Merge tag 'drm-intel-next-2025-02-24' of https://gitlab.freedesktop.org/drm/i915/kernel into drm-next

drm/i915 feature pull for v6.15:

Features and functionality:
- Enable DP 128b/132b SST DSC (Jani, Imre)
- Allow DSB to perform commits when VRR is enabled (Ville)
- Compute HDMI PLLs for SNPS/C10 PHYs for rates not in fixed tables (Ankit)
- Allow DSB usage when PSR is enabled on LNL+ (Jouni)
- Enable Panel Replay mode change without full modeset (Jouni)
- Enable async flips with compressed buffers on ICL+ (Ville)
- Support luminance based brightness control via DPCD for eDP (Suraj)
- Enable VRR enable/disable without full modeset (Mitul, Ankit)
- Add debugfs facility for force testing HDCP 1.4 (Suraj)
- Add scaler tracepoints, improve plane tracepoints (Ville)
- Improve DMC wakelock debugging facilities (Gustavo)
- Allow GuC SLPC default strategies on MTL+ for performance (Rodrigo)
- Provide more information on display faults (Ville)

Refactoring and cleanups:
- Continue conversions to struct intel_display (Ville, Jani, Suraj, Imre)
- Joiner and Y plane reorganization (Ville)
- Move HDCP debugfs to intel_hdcp.c (Jani)
- Clean up and unify LSPCON interfaces (Jani)
- Move code out of intel_display.c to reduce its size (Ville)
- Clean up and simplify DDI port enabling/disabling (Imre)
- Make LPT LP a dedicated PCH type, refactor (Jani)
- Simplify DSC range BPG offset calculation (Ankit)
- Scaler cleanups (Ville)
- Remove unused code from GVT (David Alan Gilbert)
- Improve plane debugging (Ville)
- DSB and VRR refactoring (Ville)

Fixes:
- Check if vblank is sufficient for DSC prefill and scaler (Mitul)
- Fix Mesa clear color alignment regression (Ville)
- Add missing TC DP PHY lane stagger delay (Imre)
- Fix DSB + VRR usage for PTL+ (Ville)
- Improve robustness of display VT-d workarounds (Ville)
- Fix platforms for dbuf tracker state service programming (Ravi)
- Fix DMC wakelock support conditions (Gustavo)
- Amend DMC wakelock register ranges (Gustavo)
- Disable the Common Primary Timing Generator (CMTG) (Gustavo)
- Enable C20 PHY SSC (Suraj)
- Add workaround for DKL PHY DP mode write (Nemesa)
- Fix build warnings on clamp() usage (Guenter Roeck, Ankit)
- Fix error handling while adding a connector (Imre)
- Avoid full modeset at probe on vblank delay mismatches (Ville)
- Fix encoder HDMI check for HDCP line rekeying (Suraj)
- Fix HDCP repeater authentication during topology change (Suraj)
- Handle display PHY power state reset for power savings (Mika)
- Fix typos all over the place (Nitin)
- Update HDMI TMDS C20 parameters for various platforms (Dnyaneshwar)
- Guarantee a minimum hblank time for 128b/132b and 8b/10b MST (Arun, Imre)
- Do not hardcode LSPCON settle timeout (Giedrius Statkevičius)

Xe driver changes:
- Re-use display vmas when possible (Maarten)
- Remove double pageflip (Maarten)
- Enable DP tunneling (Imre)
- Separate i915 and xe tracepoints (Ville)

DRM core changes:
- Increase DPCD eDP display control CAP size to 5 bytes (Suraj)
- Add DPCD eDP version 1.5 definition (Suraj)
- Add timeout parameter to drm_lspcon_set_mode() (Giedrius Statkevičius)

Merges:
- Backmerge drm-next (Jani)

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

From: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/87h64j7b7n.fsf@intel.com
This commit is contained in:
Dave Airlie 2025-02-27 07:13:27 +10:00
commit 16893dd23f
237 changed files with 8191 additions and 5759 deletions

View File

@ -11635,7 +11635,7 @@ F: drivers/gpio/gpio-tangier.c
F: drivers/gpio/gpio-tangier.h
INTEL GVT-g DRIVERS (Intel GPU Virtualization)
M: Zhenyu Wang <zhenyuw@linux.intel.com>
M: Zhenyu Wang <zhenyuw.linux@gmail.com>
M: Zhi Wang <zhi.wang.linux@gmail.com>
L: intel-gvt-dev@lists.freedesktop.org
L: intel-gfx@lists.freedesktop.org

View File

@ -486,16 +486,16 @@ EXPORT_SYMBOL(drm_lspcon_get_mode);
* @dev: &drm_device to use
* @adapter: I2C-over-aux adapter
* @mode: required mode of operation
* @time_out: LSPCON mode change settle timeout
*
* Returns:
* 0 on success, -error on failure/timeout
*/
int drm_lspcon_set_mode(const struct drm_device *dev, struct i2c_adapter *adapter,
enum drm_lspcon_mode mode)
enum drm_lspcon_mode mode, int time_out)
{
u8 data = 0;
int ret;
int time_out = 200;
enum drm_lspcon_mode current_mode;
if (mode == DRM_LSPCON_MODE_PCON)

View File

@ -231,6 +231,7 @@ i915-y += \
display/intel_bo.o \
display/intel_bw.o \
display/intel_cdclk.o \
display/intel_cmtg.o \
display/intel_color.o \
display/intel_combo_phy.o \
display/intel_connector.o \
@ -346,6 +347,7 @@ i915-y += \
display/intel_pps.o \
display/intel_qp_tables.o \
display/intel_sdvo.o \
display/intel_snps_hdmi_pll.o \
display/intel_snps_phy.o \
display/intel_tv.o \
display/intel_vdsc.o \

View File

@ -517,7 +517,7 @@ static enum drm_connector_status ns2501_detect(struct intel_dvo_device *dvo)
* Even if not, the detection bit of the 2501 is unreliable as
* it only works for some display types.
* It is even more unreliable as the PLL must be active for
* allowing reading from the chiop.
* allowing reading from the chip.
*/
return connector_status_connected;
}

View File

@ -51,28 +51,29 @@ static const struct dpll chv_dpll[] = {
{ .dot = 270000, .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 /* 27.0 */ },
};
const struct dpll *vlv_get_dpll(struct drm_i915_private *i915)
const struct dpll *vlv_get_dpll(struct intel_display *display)
{
return IS_CHERRYVIEW(i915) ? &chv_dpll[0] : &vlv_dpll[0];
return display->platform.cherryview ? &chv_dpll[0] : &vlv_dpll[0];
}
static void g4x_dp_set_clock(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);
const struct dpll *divisor = NULL;
int i, count = 0;
if (IS_G4X(dev_priv)) {
if (display->platform.g4x) {
divisor = g4x_dpll;
count = ARRAY_SIZE(g4x_dpll);
} else if (HAS_PCH_SPLIT(dev_priv)) {
divisor = pch_dpll;
count = ARRAY_SIZE(pch_dpll);
} else if (IS_CHERRYVIEW(dev_priv)) {
} else if (display->platform.cherryview) {
divisor = chv_dpll;
count = ARRAY_SIZE(chv_dpll);
} else if (IS_VALLEYVIEW(dev_priv)) {
} else if (display->platform.valleyview) {
divisor = vlv_dpll;
count = ARRAY_SIZE(vlv_dpll);
}
@ -129,7 +130,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder,
/* Split out the IBX/CPU vs CPT settings */
if (IS_IVYBRIDGE(dev_priv) && port == PORT_A) {
if (display->platform.ivybridge && port == PORT_A) {
if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
intel_dp->DP |= DP_SYNC_HS_HIGH;
if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
@ -148,7 +149,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder,
pipe_config->enhanced_framing ?
TRANS_DP_ENH_FRAMING : 0);
} else {
if (IS_G4X(dev_priv) && pipe_config->limited_color_range)
if (display->platform.g4x && pipe_config->limited_color_range)
intel_dp->DP |= DP_COLOR_RANGE_16_235;
if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
@ -160,7 +161,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder,
if (pipe_config->enhanced_framing)
intel_dp->DP |= DP_ENHANCED_FRAMING;
if (IS_CHERRYVIEW(dev_priv))
if (display->platform.cherryview)
intel_dp->DP |= DP_PIPE_SEL_CHV(crtc->pipe);
else
intel_dp->DP |= DP_PIPE_SEL(crtc->pipe);
@ -180,9 +181,8 @@ static void assert_dp_port(struct intel_dp *intel_dp, bool state)
}
#define assert_dp_port_disabled(d) assert_dp_port((d), false)
static void assert_edp_pll(struct drm_i915_private *dev_priv, bool state)
static void assert_edp_pll(struct intel_display *display, bool state)
{
struct intel_display *display = &dev_priv->display;
bool cur_state = intel_de_read(display, DP_A) & DP_PLL_ENABLE;
INTEL_DISPLAY_STATE_WARN(display, cur_state != state,
@ -197,11 +197,10 @@ static void ilk_edp_pll_on(struct intel_dp *intel_dp,
{
struct intel_display *display = to_intel_display(intel_dp);
struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
assert_transcoder_disabled(dev_priv, pipe_config->cpu_transcoder);
assert_transcoder_disabled(display, pipe_config->cpu_transcoder);
assert_dp_port_disabled(intel_dp);
assert_edp_pll_disabled(dev_priv);
assert_edp_pll_disabled(display);
drm_dbg_kms(display->drm, "enabling eDP PLL for clock %d\n",
pipe_config->port_clock);
@ -223,8 +222,8 @@ static void ilk_edp_pll_on(struct intel_dp *intel_dp,
* 1. Wait for the start of vertical blank on the enabled pipe going to FDI
* 2. Program DP PLL enable
*/
if (IS_IRONLAKE(dev_priv))
intel_wait_for_vblank_if_active(dev_priv, !crtc->pipe);
if (display->platform.ironlake)
intel_wait_for_vblank_if_active(display, !crtc->pipe);
intel_dp->DP |= DP_PLL_ENABLE;
@ -237,12 +236,10 @@ static void ilk_edp_pll_off(struct intel_dp *intel_dp,
const struct intel_crtc_state *old_crtc_state)
{
struct intel_display *display = to_intel_display(intel_dp);
struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
assert_transcoder_disabled(dev_priv, old_crtc_state->cpu_transcoder);
assert_transcoder_disabled(display, old_crtc_state->cpu_transcoder);
assert_dp_port_disabled(intel_dp);
assert_edp_pll_enabled(dev_priv);
assert_edp_pll_enabled(display);
drm_dbg_kms(display->drm, "disabling eDP PLL\n");
@ -253,10 +250,9 @@ static void ilk_edp_pll_off(struct intel_dp *intel_dp,
udelay(200);
}
static bool cpt_dp_port_selected(struct drm_i915_private *dev_priv,
static bool cpt_dp_port_selected(struct intel_display *display,
enum port port, enum pipe *pipe)
{
struct intel_display *display = &dev_priv->display;
enum pipe p;
for_each_pipe(display, p) {
@ -277,11 +273,11 @@ static bool cpt_dp_port_selected(struct drm_i915_private *dev_priv,
return false;
}
bool g4x_dp_port_enabled(struct drm_i915_private *dev_priv,
bool g4x_dp_port_enabled(struct intel_display *display,
i915_reg_t dp_reg, enum port port,
enum pipe *pipe)
{
struct intel_display *display = &dev_priv->display;
struct drm_i915_private *dev_priv = to_i915(display->drm);
bool ret;
u32 val;
@ -290,11 +286,11 @@ bool g4x_dp_port_enabled(struct drm_i915_private *dev_priv,
ret = val & DP_PORT_EN;
/* asserts want to know the pipe even if the port is disabled */
if (IS_IVYBRIDGE(dev_priv) && port == PORT_A)
if (display->platform.ivybridge && port == PORT_A)
*pipe = (val & DP_PIPE_SEL_MASK_IVB) >> DP_PIPE_SEL_SHIFT_IVB;
else if (HAS_PCH_CPT(dev_priv) && port != PORT_A)
ret &= cpt_dp_port_selected(dev_priv, port, pipe);
else if (IS_CHERRYVIEW(dev_priv))
ret &= cpt_dp_port_selected(display, port, pipe);
else if (display->platform.cherryview)
*pipe = (val & DP_PIPE_SEL_MASK_CHV) >> DP_PIPE_SEL_SHIFT_CHV;
else
*pipe = (val & DP_PIPE_SEL_MASK) >> DP_PIPE_SEL_SHIFT;
@ -305,20 +301,20 @@ bool g4x_dp_port_enabled(struct drm_i915_private *dev_priv,
static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
enum pipe *pipe)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_display *display = to_intel_display(encoder);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
intel_wakeref_t wakeref;
bool ret;
wakeref = intel_display_power_get_if_enabled(dev_priv,
wakeref = intel_display_power_get_if_enabled(display,
encoder->power_domain);
if (!wakeref)
return false;
ret = g4x_dp_port_enabled(dev_priv, intel_dp->output_reg,
ret = g4x_dp_port_enabled(display, intel_dp->output_reg,
encoder->port, pipe);
intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
intel_display_power_put(display, encoder->power_domain, wakeref);
return ret;
}
@ -390,7 +386,7 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
pipe_config->hw.adjusted_mode.flags |= flags;
if (IS_G4X(dev_priv) && tmp & DP_COLOR_RANGE_16_235)
if (display->platform.g4x && tmp & DP_COLOR_RANGE_16_235)
pipe_config->limited_color_range = true;
pipe_config->lane_count =
@ -432,7 +428,7 @@ intel_dp_link_down(struct intel_encoder *encoder,
drm_dbg_kms(display->drm, "\n");
if ((IS_IVYBRIDGE(dev_priv) && port == PORT_A) ||
if ((display->platform.ivybridge && port == PORT_A) ||
(HAS_PCH_CPT(dev_priv) && port != PORT_A)) {
intel_dp->DP &= ~DP_LINK_TRAIN_MASK_CPT;
intel_dp->DP |= DP_LINK_TRAIN_PAT_IDLE_CPT;
@ -457,8 +453,8 @@ intel_dp_link_down(struct intel_encoder *encoder,
* We get CPU/PCH FIFO underruns on the other pipe when
* doing the workaround. Sweep them under the rug.
*/
intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, false);
intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, false);
intel_set_cpu_fifo_underrun_reporting(display, PIPE_A, false);
intel_set_pch_fifo_underrun_reporting(display, PIPE_A, false);
/* always enable with pattern 1 (as per spec) */
intel_dp->DP &= ~(DP_PIPE_SEL_MASK | DP_LINK_TRAIN_MASK);
@ -471,14 +467,14 @@ intel_dp_link_down(struct intel_encoder *encoder,
intel_de_write(display, intel_dp->output_reg, intel_dp->DP);
intel_de_posting_read(display, intel_dp->output_reg);
intel_wait_for_vblank_if_active(dev_priv, PIPE_A);
intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, true);
intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
intel_wait_for_vblank_if_active(display, PIPE_A);
intel_set_cpu_fifo_underrun_reporting(display, PIPE_A, true);
intel_set_pch_fifo_underrun_reporting(display, PIPE_A, true);
}
msleep(intel_dp->pps.panel_power_down_delay);
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
if (display->platform.valleyview || display->platform.cherryview)
vlv_pps_port_disable(encoder, old_crtc_state);
}
@ -681,7 +677,6 @@ static void intel_enable_dp(struct intel_atomic_state *state,
const struct drm_connector_state *conn_state)
{
struct intel_display *display = to_intel_display(state);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
u32 dp_reg = intel_de_read(display, intel_dp->output_reg);
intel_wakeref_t wakeref;
@ -690,7 +685,7 @@ static void intel_enable_dp(struct intel_atomic_state *state,
return;
with_intel_pps_lock(intel_dp, wakeref) {
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
if (display->platform.valleyview || display->platform.cherryview)
vlv_pps_port_enable_unlocked(encoder, pipe_config);
intel_dp_enable_port(intel_dp, pipe_config);
@ -700,13 +695,13 @@ static void intel_enable_dp(struct intel_atomic_state *state,
intel_pps_vdd_off_unlocked(intel_dp, true);
}
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
if (display->platform.valleyview || display->platform.cherryview) {
unsigned int lane_mask = 0x0;
if (IS_CHERRYVIEW(dev_priv))
if (display->platform.cherryview)
lane_mask = intel_dp_unused_lane_mask(pipe_config->lane_count);
vlv_wait_port_ready(display, dp_to_dig_port(intel_dp), lane_mask);
vlv_wait_port_ready(encoder, lane_mask);
}
intel_dp_set_power(intel_dp, DP_SET_POWER_D0);
@ -1263,7 +1258,6 @@ static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
static void intel_dp_encoder_reset(struct drm_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder->dev);
struct drm_i915_private *dev_priv = to_i915(encoder->dev);
struct intel_dp *intel_dp = enc_to_intel_dp(to_intel_encoder(encoder));
intel_dp->DP = intel_de_read(display, intel_dp->output_reg);
@ -1271,7 +1265,7 @@ static void intel_dp_encoder_reset(struct drm_encoder *encoder)
intel_dp->reset_link_params = true;
intel_dp_invalidate_source_oui(intel_dp);
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
if (display->platform.valleyview || display->platform.cherryview)
vlv_pps_pipe_reset(intel_dp);
intel_pps_encoder_reset(intel_dp);
@ -1282,17 +1276,17 @@ static const struct drm_encoder_funcs intel_dp_enc_funcs = {
.destroy = intel_dp_encoder_destroy,
};
bool g4x_dp_init(struct drm_i915_private *dev_priv,
bool g4x_dp_init(struct intel_display *display,
i915_reg_t output_reg, enum port port)
{
struct intel_display *display = &dev_priv->display;
struct drm_i915_private *dev_priv = to_i915(display->drm);
const struct intel_bios_encoder_data *devdata;
struct intel_digital_port *dig_port;
struct intel_encoder *intel_encoder;
struct drm_encoder *encoder;
struct intel_connector *intel_connector;
if (!assert_port_valid(dev_priv, port))
if (!assert_port_valid(display, port))
return false;
devdata = intel_bios_encoder_data_lookup(display, port);
@ -1336,14 +1330,14 @@ bool g4x_dp_init(struct drm_i915_private *dev_priv,
intel_encoder->suspend = intel_dp_encoder_suspend;
intel_encoder->suspend_complete = g4x_dp_suspend_complete;
intel_encoder->shutdown = intel_dp_encoder_shutdown;
if (IS_CHERRYVIEW(dev_priv)) {
if (display->platform.cherryview) {
intel_encoder->pre_pll_enable = chv_dp_pre_pll_enable;
intel_encoder->pre_enable = chv_pre_enable_dp;
intel_encoder->enable = vlv_enable_dp;
intel_encoder->disable = vlv_disable_dp;
intel_encoder->post_disable = chv_post_disable_dp;
intel_encoder->post_pll_disable = chv_dp_post_pll_disable;
} else if (IS_VALLEYVIEW(dev_priv)) {
} else if (display->platform.valleyview) {
intel_encoder->pre_pll_enable = vlv_dp_pre_pll_enable;
intel_encoder->pre_enable = vlv_pre_enable_dp;
intel_encoder->enable = vlv_enable_dp;
@ -1358,24 +1352,24 @@ bool g4x_dp_init(struct drm_i915_private *dev_priv,
intel_encoder->audio_enable = g4x_dp_audio_enable;
intel_encoder->audio_disable = g4x_dp_audio_disable;
if ((IS_IVYBRIDGE(dev_priv) && port == PORT_A) ||
if ((display->platform.ivybridge && port == PORT_A) ||
(HAS_PCH_CPT(dev_priv) && port != PORT_A))
dig_port->dp.set_link_train = cpt_set_link_train;
else
dig_port->dp.set_link_train = g4x_set_link_train;
if (IS_CHERRYVIEW(dev_priv))
if (display->platform.cherryview)
intel_encoder->set_signal_levels = chv_set_signal_levels;
else if (IS_VALLEYVIEW(dev_priv))
else if (display->platform.valleyview)
intel_encoder->set_signal_levels = vlv_set_signal_levels;
else if (IS_IVYBRIDGE(dev_priv) && port == PORT_A)
else if (display->platform.ivybridge && port == PORT_A)
intel_encoder->set_signal_levels = ivb_cpu_edp_set_signal_levels;
else if (IS_SANDYBRIDGE(dev_priv) && port == PORT_A)
else if (display->platform.sandybridge && port == PORT_A)
intel_encoder->set_signal_levels = snb_cpu_edp_set_signal_levels;
else
intel_encoder->set_signal_levels = g4x_set_signal_levels;
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv) ||
if (display->platform.valleyview || display->platform.cherryview ||
(HAS_PCH_SPLIT(dev_priv) && port != PORT_A)) {
dig_port->dp.preemph_max = intel_dp_preemph_max_3;
dig_port->dp.voltage_max = intel_dp_voltage_max_3;
@ -1388,8 +1382,8 @@ bool g4x_dp_init(struct drm_i915_private *dev_priv,
dig_port->max_lanes = 4;
intel_encoder->type = INTEL_OUTPUT_DP;
intel_encoder->power_domain = intel_display_power_ddi_lanes_domain(dev_priv, port);
if (IS_CHERRYVIEW(dev_priv)) {
intel_encoder->power_domain = intel_display_power_ddi_lanes_domain(display, port);
if (display->platform.cherryview) {
if (port == PORT_D)
intel_encoder->pipe_mask = BIT(PIPE_C);
else
@ -1399,7 +1393,7 @@ bool g4x_dp_init(struct drm_i915_private *dev_priv,
}
intel_encoder->cloneable = 0;
intel_encoder->port = port;
intel_encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port);
intel_encoder->hpd_pin = intel_hpd_pin_default(port);
dig_port->hpd_pulse = intel_dp_hpd_pulse;

View File

@ -12,30 +12,30 @@
enum pipe;
enum port;
struct drm_i915_private;
struct intel_crtc_state;
struct intel_display;
struct intel_dp;
struct intel_encoder;
#ifdef I915
const struct dpll *vlv_get_dpll(struct drm_i915_private *i915);
bool g4x_dp_port_enabled(struct drm_i915_private *dev_priv,
const struct dpll *vlv_get_dpll(struct intel_display *display);
bool g4x_dp_port_enabled(struct intel_display *display,
i915_reg_t dp_reg, enum port port,
enum pipe *pipe);
bool g4x_dp_init(struct drm_i915_private *dev_priv,
bool g4x_dp_init(struct intel_display *display,
i915_reg_t output_reg, enum port port);
#else
static inline const struct dpll *vlv_get_dpll(struct drm_i915_private *i915)
static inline const struct dpll *vlv_get_dpll(struct intel_display *display)
{
return NULL;
}
static inline bool g4x_dp_port_enabled(struct drm_i915_private *dev_priv,
static inline bool g4x_dp_port_enabled(struct intel_display *display,
i915_reg_t dp_reg, int port,
enum pipe *pipe)
{
return false;
}
static inline bool g4x_dp_init(struct drm_i915_private *dev_priv,
static inline bool g4x_dp_init(struct intel_display *display,
i915_reg_t output_reg, int port)
{
return false;

View File

@ -27,8 +27,8 @@
static void intel_hdmi_prepare(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
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);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
@ -54,31 +54,31 @@ static void intel_hdmi_prepare(struct intel_encoder *encoder,
if (HAS_PCH_CPT(dev_priv))
hdmi_val |= SDVO_PIPE_SEL_CPT(crtc->pipe);
else if (IS_CHERRYVIEW(dev_priv))
else if (display->platform.cherryview)
hdmi_val |= SDVO_PIPE_SEL_CHV(crtc->pipe);
else
hdmi_val |= SDVO_PIPE_SEL(crtc->pipe);
intel_de_write(dev_priv, intel_hdmi->hdmi_reg, hdmi_val);
intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
intel_de_write(display, intel_hdmi->hdmi_reg, hdmi_val);
intel_de_posting_read(display, intel_hdmi->hdmi_reg);
}
static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder,
enum pipe *pipe)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_display *display = to_intel_display(encoder);
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
intel_wakeref_t wakeref;
bool ret;
wakeref = intel_display_power_get_if_enabled(dev_priv,
wakeref = intel_display_power_get_if_enabled(display,
encoder->power_domain);
if (!wakeref)
return false;
ret = intel_sdvo_port_enabled(dev_priv, intel_hdmi->hdmi_reg, pipe);
ret = intel_sdvo_port_enabled(display, intel_hdmi->hdmi_reg, pipe);
intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
intel_display_power_put(display, encoder->power_domain, wakeref);
return ret;
}
@ -131,6 +131,7 @@ static int g4x_hdmi_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->uapi.state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
@ -141,7 +142,7 @@ static int g4x_hdmi_compute_config(struct intel_encoder *encoder,
return -EINVAL;
}
if (IS_G4X(i915))
if (display->platform.g4x)
crtc_state->has_hdmi_sink = g4x_compute_has_hdmi_sink(state, crtc);
else
crtc_state->has_hdmi_sink =
@ -153,15 +154,15 @@ static int g4x_hdmi_compute_config(struct intel_encoder *encoder,
static void intel_hdmi_get_config(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(display->drm);
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
struct drm_device *dev = encoder->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
u32 tmp, flags = 0;
int dotclock;
pipe_config->output_types |= BIT(INTEL_OUTPUT_HDMI);
tmp = intel_de_read(dev_priv, intel_hdmi->hdmi_reg);
tmp = intel_de_read(display, intel_hdmi->hdmi_reg);
if (tmp & SDVO_HSYNC_ACTIVE_HIGH)
flags |= DRM_MODE_FLAG_PHSYNC;
@ -221,33 +222,32 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder,
static void g4x_hdmi_enable_port(struct intel_encoder *encoder,
const struct intel_crtc_state *pipe_config)
{
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 intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
u32 temp;
temp = intel_de_read(dev_priv, intel_hdmi->hdmi_reg);
temp = intel_de_read(display, intel_hdmi->hdmi_reg);
temp |= SDVO_ENABLE;
intel_de_write(dev_priv, intel_hdmi->hdmi_reg, temp);
intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
intel_de_write(display, intel_hdmi->hdmi_reg, temp);
intel_de_posting_read(display, intel_hdmi->hdmi_reg);
}
static void g4x_hdmi_audio_enable(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct intel_display *display = to_intel_display(encoder);
struct intel_hdmi *hdmi = enc_to_intel_hdmi(encoder);
if (!crtc_state->has_audio)
return;
drm_WARN_ON(&i915->drm, !crtc_state->has_hdmi_sink);
drm_WARN_ON(display->drm, !crtc_state->has_hdmi_sink);
/* Enable audio presence detect */
intel_de_rmw(i915, hdmi->hdmi_reg, 0, HDMI_AUDIO_ENABLE);
intel_de_rmw(display, hdmi->hdmi_reg, 0, HDMI_AUDIO_ENABLE);
intel_audio_codec_enable(encoder, crtc_state, conn_state);
}
@ -256,7 +256,7 @@ static void g4x_hdmi_audio_disable(struct intel_encoder *encoder,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state)
{
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct intel_display *display = to_intel_display(encoder);
struct intel_hdmi *hdmi = enc_to_intel_hdmi(encoder);
if (!old_crtc_state->has_audio)
@ -265,7 +265,7 @@ static void g4x_hdmi_audio_disable(struct intel_encoder *encoder,
intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
/* Disable audio presence detect */
intel_de_rmw(i915, hdmi->hdmi_reg, HDMI_AUDIO_ENABLE, 0);
intel_de_rmw(display, hdmi->hdmi_reg, HDMI_AUDIO_ENABLE, 0);
}
static void g4x_enable_hdmi(struct intel_atomic_state *state,
@ -281,12 +281,11 @@ static void ibx_enable_hdmi(struct intel_atomic_state *state,
const struct intel_crtc_state *pipe_config,
const struct drm_connector_state *conn_state)
{
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 intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
u32 temp;
temp = intel_de_read(dev_priv, intel_hdmi->hdmi_reg);
temp = intel_de_read(display, intel_hdmi->hdmi_reg);
temp |= SDVO_ENABLE;
@ -294,10 +293,10 @@ static void ibx_enable_hdmi(struct intel_atomic_state *state,
* HW workaround, need to write this twice for issue
* that may result in first write getting masked.
*/
intel_de_write(dev_priv, intel_hdmi->hdmi_reg, temp);
intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
intel_de_write(dev_priv, intel_hdmi->hdmi_reg, temp);
intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
intel_de_write(display, intel_hdmi->hdmi_reg, temp);
intel_de_posting_read(display, intel_hdmi->hdmi_reg);
intel_de_write(display, intel_hdmi->hdmi_reg, temp);
intel_de_posting_read(display, intel_hdmi->hdmi_reg);
/*
* HW workaround, need to toggle enable bit off and on
@ -308,18 +307,18 @@ static void ibx_enable_hdmi(struct intel_atomic_state *state,
*/
if (pipe_config->pipe_bpp > 24 &&
pipe_config->pixel_multiplier > 1) {
intel_de_write(dev_priv, intel_hdmi->hdmi_reg,
intel_de_write(display, intel_hdmi->hdmi_reg,
temp & ~SDVO_ENABLE);
intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
intel_de_posting_read(display, intel_hdmi->hdmi_reg);
/*
* HW workaround, need to write this twice for issue
* that may result in first write getting masked.
*/
intel_de_write(dev_priv, intel_hdmi->hdmi_reg, temp);
intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
intel_de_write(dev_priv, intel_hdmi->hdmi_reg, temp);
intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
intel_de_write(display, intel_hdmi->hdmi_reg, temp);
intel_de_posting_read(display, intel_hdmi->hdmi_reg);
intel_de_write(display, intel_hdmi->hdmi_reg, temp);
intel_de_posting_read(display, intel_hdmi->hdmi_reg);
}
}
@ -328,14 +327,13 @@ static void cpt_enable_hdmi(struct intel_atomic_state *state,
const struct intel_crtc_state *pipe_config,
const struct drm_connector_state *conn_state)
{
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 intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
enum pipe pipe = crtc->pipe;
u32 temp;
temp = intel_de_read(dev_priv, intel_hdmi->hdmi_reg);
temp = intel_de_read(display, intel_hdmi->hdmi_reg);
temp |= SDVO_ENABLE;
@ -350,24 +348,24 @@ static void cpt_enable_hdmi(struct intel_atomic_state *state,
*/
if (pipe_config->pipe_bpp > 24) {
intel_de_rmw(dev_priv, TRANS_CHICKEN1(pipe),
intel_de_rmw(display, TRANS_CHICKEN1(pipe),
0, TRANS_CHICKEN1_HDMIUNIT_GC_DISABLE);
temp &= ~SDVO_COLOR_FORMAT_MASK;
temp |= SDVO_COLOR_FORMAT_8bpc;
}
intel_de_write(dev_priv, intel_hdmi->hdmi_reg, temp);
intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
intel_de_write(display, intel_hdmi->hdmi_reg, temp);
intel_de_posting_read(display, intel_hdmi->hdmi_reg);
if (pipe_config->pipe_bpp > 24) {
temp &= ~SDVO_COLOR_FORMAT_MASK;
temp |= HDMI_COLOR_FORMAT_12bpc;
intel_de_write(dev_priv, intel_hdmi->hdmi_reg, temp);
intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
intel_de_write(display, intel_hdmi->hdmi_reg, temp);
intel_de_posting_read(display, intel_hdmi->hdmi_reg);
intel_de_rmw(dev_priv, TRANS_CHICKEN1(pipe),
intel_de_rmw(display, TRANS_CHICKEN1(pipe),
TRANS_CHICKEN1_HDMIUNIT_GC_DISABLE, 0);
}
}
@ -384,19 +382,19 @@ static void intel_disable_hdmi(struct intel_atomic_state *state,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state)
{
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);
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
struct intel_digital_port *dig_port =
hdmi_to_dig_port(intel_hdmi);
struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
u32 temp;
temp = intel_de_read(dev_priv, intel_hdmi->hdmi_reg);
temp = intel_de_read(display, intel_hdmi->hdmi_reg);
temp &= ~SDVO_ENABLE;
intel_de_write(dev_priv, intel_hdmi->hdmi_reg, temp);
intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
intel_de_write(display, intel_hdmi->hdmi_reg, temp);
intel_de_posting_read(display, intel_hdmi->hdmi_reg);
/*
* HW workaround for IBX, we need to move the port
@ -408,8 +406,8 @@ static void intel_disable_hdmi(struct intel_atomic_state *state,
* We get CPU/PCH FIFO underruns on the other pipe when
* doing the workaround. Sweep them under the rug.
*/
intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, false);
intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, false);
intel_set_cpu_fifo_underrun_reporting(display, PIPE_A, false);
intel_set_pch_fifo_underrun_reporting(display, PIPE_A, false);
temp &= ~SDVO_PIPE_SEL_MASK;
temp |= SDVO_ENABLE | SDVO_PIPE_SEL(PIPE_A);
@ -417,18 +415,18 @@ static void intel_disable_hdmi(struct intel_atomic_state *state,
* HW workaround, need to write this twice for issue
* that may result in first write getting masked.
*/
intel_de_write(dev_priv, intel_hdmi->hdmi_reg, temp);
intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
intel_de_write(dev_priv, intel_hdmi->hdmi_reg, temp);
intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
intel_de_write(display, intel_hdmi->hdmi_reg, temp);
intel_de_posting_read(display, intel_hdmi->hdmi_reg);
intel_de_write(display, intel_hdmi->hdmi_reg, temp);
intel_de_posting_read(display, intel_hdmi->hdmi_reg);
temp &= ~SDVO_ENABLE;
intel_de_write(dev_priv, intel_hdmi->hdmi_reg, temp);
intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
intel_de_write(display, intel_hdmi->hdmi_reg, temp);
intel_de_posting_read(display, intel_hdmi->hdmi_reg);
intel_wait_for_vblank_if_active(dev_priv, PIPE_A);
intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, true);
intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
intel_wait_for_vblank_if_active(display, PIPE_A);
intel_set_cpu_fifo_underrun_reporting(display, PIPE_A, true);
intel_set_pch_fifo_underrun_reporting(display, PIPE_A, true);
}
dig_port->set_infoframes(encoder,
@ -481,7 +479,6 @@ static void vlv_hdmi_pre_enable(struct intel_atomic_state *state,
const struct intel_crtc_state *pipe_config,
const struct drm_connector_state *conn_state)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
vlv_phy_pre_encoder_enable(encoder, pipe_config);
@ -497,7 +494,7 @@ static void vlv_hdmi_pre_enable(struct intel_atomic_state *state,
g4x_hdmi_enable_port(encoder, pipe_config);
vlv_wait_port_ready(display, dig_port, 0x0);
vlv_wait_port_ready(encoder, 0x0);
}
static void vlv_hdmi_pre_pll_enable(struct intel_atomic_state *state,
@ -542,8 +539,8 @@ static void chv_hdmi_post_disable(struct intel_atomic_state *state,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state)
{
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);
vlv_dpio_get(dev_priv);
@ -558,7 +555,6 @@ static void chv_hdmi_pre_enable(struct intel_atomic_state *state,
const struct intel_crtc_state *pipe_config,
const struct drm_connector_state *conn_state)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
chv_phy_pre_encoder_enable(encoder, pipe_config);
@ -573,7 +569,7 @@ static void chv_hdmi_pre_enable(struct intel_atomic_state *state,
g4x_hdmi_enable_port(encoder, pipe_config);
vlv_wait_port_ready(display, dig_port, 0x0);
vlv_wait_port_ready(encoder, 0x0);
/* Second common lane will stay alive on its own now */
chv_phy_release_cl2_override(encoder);
@ -612,7 +608,7 @@ intel_hdmi_hotplug(struct intel_encoder *encoder,
int g4x_hdmi_connector_atomic_check(struct drm_connector *connector,
struct drm_atomic_state *state)
{
struct drm_i915_private *i915 = to_i915(state->dev);
struct intel_display *display = to_intel_display(connector->dev);
struct drm_connector_list_iter conn_iter;
struct drm_connector *conn;
int ret;
@ -621,7 +617,7 @@ int g4x_hdmi_connector_atomic_check(struct drm_connector *connector,
if (ret)
return ret;
if (!IS_G4X(i915))
if (!display->platform.g4x)
return 0;
if (!intel_connector_needs_modeset(to_intel_atomic_state(state), connector))
@ -635,7 +631,7 @@ int g4x_hdmi_connector_atomic_check(struct drm_connector *connector,
*
* See also g4x_compute_has_hdmi_sink().
*/
drm_connector_list_iter_begin(&i915->drm, &conn_iter);
drm_connector_list_iter_begin(display->drm, &conn_iter);
drm_for_each_connector_iter(conn, &conn_iter) {
struct drm_connector_state *conn_state;
struct drm_crtc_state *crtc_state;
@ -644,7 +640,7 @@ int g4x_hdmi_connector_atomic_check(struct drm_connector *connector,
if (!connector_is_hdmi(conn))
continue;
drm_dbg_kms(&i915->drm, "Adding [CONNECTOR:%d:%s]\n",
drm_dbg_kms(display->drm, "Adding [CONNECTOR:%d:%s]\n",
conn->base.id, conn->name);
conn_state = drm_atomic_get_connector_state(state, conn);
@ -669,40 +665,40 @@ int g4x_hdmi_connector_atomic_check(struct drm_connector *connector,
return ret;
}
static bool is_hdmi_port_valid(struct drm_i915_private *i915, enum port port)
static bool is_hdmi_port_valid(struct intel_display *display, enum port port)
{
if (IS_G4X(i915) || IS_VALLEYVIEW(i915))
if (display->platform.g4x || display->platform.valleyview)
return port == PORT_B || port == PORT_C;
else
return port == PORT_B || port == PORT_C || port == PORT_D;
}
static bool assert_hdmi_port_valid(struct drm_i915_private *i915, enum port port)
static bool assert_hdmi_port_valid(struct intel_display *display, enum port port)
{
return !drm_WARN(&i915->drm, !is_hdmi_port_valid(i915, port),
return !drm_WARN(display->drm, !is_hdmi_port_valid(display, port),
"Platform does not support HDMI %c\n", port_name(port));
}
bool g4x_hdmi_init(struct drm_i915_private *dev_priv,
bool g4x_hdmi_init(struct intel_display *display,
i915_reg_t hdmi_reg, enum port port)
{
struct intel_display *display = &dev_priv->display;
struct drm_i915_private *dev_priv = to_i915(display->drm);
const struct intel_bios_encoder_data *devdata;
struct intel_digital_port *dig_port;
struct intel_encoder *intel_encoder;
struct intel_connector *intel_connector;
if (!assert_port_valid(dev_priv, port))
if (!assert_port_valid(display, port))
return false;
if (!assert_hdmi_port_valid(dev_priv, port))
if (!assert_hdmi_port_valid(display, port))
return false;
devdata = intel_bios_encoder_data_lookup(display, port);
/* FIXME bail? */
if (!devdata)
drm_dbg_kms(&dev_priv->drm, "No VBT child device for HDMI-%c\n",
drm_dbg_kms(display->drm, "No VBT child device for HDMI-%c\n",
port_name(port));
dig_port = kzalloc(sizeof(*dig_port), GFP_KERNEL);
@ -721,7 +717,7 @@ bool g4x_hdmi_init(struct drm_i915_private *dev_priv,
mutex_init(&dig_port->hdcp_mutex);
if (drm_encoder_init(&dev_priv->drm, &intel_encoder->base,
if (drm_encoder_init(display->drm, &intel_encoder->base,
&intel_hdmi_enc_funcs, DRM_MODE_ENCODER_TMDS,
"HDMI %c", port_name(port)))
goto err_encoder_init;
@ -736,13 +732,13 @@ bool g4x_hdmi_init(struct drm_i915_private *dev_priv,
}
intel_encoder->get_hw_state = intel_hdmi_get_hw_state;
intel_encoder->get_config = intel_hdmi_get_config;
if (IS_CHERRYVIEW(dev_priv)) {
if (display->platform.cherryview) {
intel_encoder->pre_pll_enable = chv_hdmi_pre_pll_enable;
intel_encoder->pre_enable = chv_hdmi_pre_enable;
intel_encoder->enable = vlv_enable_hdmi;
intel_encoder->post_disable = chv_hdmi_post_disable;
intel_encoder->post_pll_disable = chv_hdmi_post_pll_disable;
} else if (IS_VALLEYVIEW(dev_priv)) {
} else if (display->platform.valleyview) {
intel_encoder->pre_pll_enable = vlv_hdmi_pre_pll_enable;
intel_encoder->pre_enable = vlv_hdmi_pre_enable;
intel_encoder->enable = vlv_enable_hdmi;
@ -761,9 +757,9 @@ bool g4x_hdmi_init(struct drm_i915_private *dev_priv,
intel_encoder->shutdown = intel_hdmi_encoder_shutdown;
intel_encoder->type = INTEL_OUTPUT_HDMI;
intel_encoder->power_domain = intel_display_power_ddi_lanes_domain(dev_priv, port);
intel_encoder->power_domain = intel_display_power_ddi_lanes_domain(display, port);
intel_encoder->port = port;
if (IS_CHERRYVIEW(dev_priv)) {
if (display->platform.cherryview) {
if (port == PORT_D)
intel_encoder->pipe_mask = BIT(PIPE_C);
else
@ -772,13 +768,13 @@ bool g4x_hdmi_init(struct drm_i915_private *dev_priv,
intel_encoder->pipe_mask = ~0;
}
intel_encoder->cloneable = BIT(INTEL_OUTPUT_ANALOG);
intel_encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port);
intel_encoder->hpd_pin = intel_hpd_pin_default(port);
/*
* BSpec is unclear about HDMI+HDMI cloning on g4x, but it seems
* to work on real hardware. And since g4x can send infoframes to
* only one port anyway, nothing is lost by allowing it.
*/
if (IS_G4X(dev_priv))
if (display->platform.g4x)
intel_encoder->cloneable |= BIT(INTEL_OUTPUT_HDMI);
dig_port->hdmi.hdmi_reg = hdmi_reg;

View File

@ -13,15 +13,15 @@
enum port;
struct drm_atomic_state;
struct drm_connector;
struct drm_i915_private;
struct intel_display;
#ifdef I915
bool g4x_hdmi_init(struct drm_i915_private *dev_priv,
bool g4x_hdmi_init(struct intel_display *display,
i915_reg_t hdmi_reg, enum port port);
int g4x_hdmi_connector_atomic_check(struct drm_connector *connector,
struct drm_atomic_state *state);
#else
static inline bool g4x_hdmi_init(struct drm_i915_private *dev_priv,
static inline bool g4x_hdmi_init(struct intel_display *display,
i915_reg_t hdmi_reg, int port)
{
return false;

View File

@ -36,7 +36,7 @@ static void hsw_ips_enable(const struct intel_crtc_state *crtc_state)
if (display->ips.false_color)
val |= IPS_FALSE_COLOR;
if (IS_BROADWELL(i915)) {
if (display->platform.broadwell) {
drm_WARN_ON(display->drm,
snb_pcode_write(&i915->uncore, DISPLAY_IPS_CONTROL,
val | IPS_PCODE_CONTROL));
@ -71,7 +71,7 @@ bool hsw_ips_disable(const struct intel_crtc_state *crtc_state)
if (!crtc_state->ips_enabled)
return need_vblank_wait;
if (IS_BROADWELL(i915)) {
if (display->platform.broadwell) {
drm_WARN_ON(display->drm,
snb_pcode_write(&i915->uncore, DISPLAY_IPS_CONTROL, 0));
/*
@ -96,7 +96,7 @@ bool hsw_ips_disable(const struct intel_crtc_state *crtc_state)
static bool hsw_ips_need_disable(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
struct drm_i915_private *i915 = to_i915(state->base.dev);
struct intel_display *display = to_intel_display(state);
const struct intel_crtc_state *old_crtc_state =
intel_atomic_get_old_crtc_state(state, crtc);
const struct intel_crtc_state *new_crtc_state =
@ -114,7 +114,7 @@ static bool hsw_ips_need_disable(struct intel_atomic_state *state,
*
* Disable IPS before we program the LUT.
*/
if (IS_HASWELL(i915) &&
if (display->platform.haswell &&
intel_crtc_needs_color_update(new_crtc_state) &&
new_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)
return true;
@ -137,7 +137,7 @@ bool hsw_ips_pre_update(struct intel_atomic_state *state,
static bool hsw_ips_need_enable(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
struct drm_i915_private *i915 = to_i915(state->base.dev);
struct intel_display *display = to_intel_display(state);
const struct intel_crtc_state *old_crtc_state =
intel_atomic_get_old_crtc_state(state, crtc);
const struct intel_crtc_state *new_crtc_state =
@ -155,7 +155,7 @@ static bool hsw_ips_need_enable(struct intel_atomic_state *state,
*
* Re-enable IPS after the LUT has been programmed.
*/
if (IS_HASWELL(i915) &&
if (display->platform.haswell &&
intel_crtc_needs_color_update(new_crtc_state) &&
new_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)
return true;
@ -194,7 +194,6 @@ 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);
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
/* IPS only exists on ULT machines and is tied to pipe A. */
if (!hsw_crtc_supports_ips(crtc))
@ -213,7 +212,7 @@ static bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state
*
* Should measure whether using a lower cdclk w/o IPS
*/
if (IS_BROADWELL(i915) &&
if (display->platform.broadwell &&
crtc_state->pixel_rate > display->cdclk.max_cdclk_freq * 95 / 100)
return false;
@ -222,9 +221,9 @@ static 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)
{
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
struct intel_display *display = to_intel_display(crtc_state);
if (!IS_BROADWELL(i915))
if (!display->platform.broadwell)
return 0;
if (!hsw_crtc_state_ips_capable(crtc_state))
@ -237,7 +236,7 @@ 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)
{
struct drm_i915_private *i915 = to_i915(state->base.dev);
struct intel_display *display = to_intel_display(state);
struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
@ -259,7 +258,7 @@ int hsw_ips_compute_config(struct intel_atomic_state *state,
if (!(crtc_state->active_planes & ~BIT(PLANE_CURSOR)))
return 0;
if (IS_BROADWELL(i915)) {
if (display->platform.broadwell) {
const struct intel_cdclk_state *cdclk_state;
cdclk_state = intel_atomic_get_cdclk_state(state);
@ -280,12 +279,11 @@ void hsw_ips_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 *i915 = to_i915(crtc->base.dev);
if (!hsw_crtc_supports_ips(crtc))
return;
if (IS_HASWELL(i915)) {
if (display->platform.haswell) {
crtc_state->ips_enabled = intel_de_read(display, IPS_CTL) & IPS_ENABLE;
} else {
/*

View File

@ -109,42 +109,42 @@ static bool i965_plane_format_mod_supported(struct drm_plane *_plane,
}
}
static bool i9xx_plane_has_fbc(struct drm_i915_private *dev_priv,
static bool i9xx_plane_has_fbc(struct intel_display *display,
enum i9xx_plane_id i9xx_plane)
{
if (!HAS_FBC(dev_priv))
if (!HAS_FBC(display))
return false;
if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
if (display->platform.broadwell || display->platform.haswell)
return i9xx_plane == PLANE_A; /* tied to pipe A */
else if (IS_IVYBRIDGE(dev_priv))
else if (display->platform.ivybridge)
return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B ||
i9xx_plane == PLANE_C;
else if (DISPLAY_VER(dev_priv) >= 4)
else if (DISPLAY_VER(display) >= 4)
return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B;
else
return i9xx_plane == PLANE_A;
}
static struct intel_fbc *i9xx_plane_fbc(struct drm_i915_private *dev_priv,
static struct intel_fbc *i9xx_plane_fbc(struct intel_display *display,
enum i9xx_plane_id i9xx_plane)
{
if (i9xx_plane_has_fbc(dev_priv, i9xx_plane))
return dev_priv->display.fbc[INTEL_FBC_A];
if (i9xx_plane_has_fbc(display, i9xx_plane))
return display->fbc[INTEL_FBC_A];
else
return NULL;
}
static bool i9xx_plane_has_windowing(struct intel_plane *plane)
{
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
struct intel_display *display = to_intel_display(plane);
enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
if (IS_CHERRYVIEW(dev_priv))
if (display->platform.cherryview)
return i9xx_plane == PLANE_B;
else if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv))
else if (DISPLAY_VER(display) >= 5 || display->platform.g4x)
return false;
else if (DISPLAY_VER(dev_priv) == 4)
else if (DISPLAY_VER(display) == 4)
return i9xx_plane == PLANE_C;
else
return i9xx_plane == PLANE_B ||
@ -154,16 +154,15 @@ static bool i9xx_plane_has_windowing(struct intel_plane *plane)
static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
struct drm_i915_private *dev_priv =
to_i915(plane_state->uapi.plane->dev);
struct intel_display *display = to_intel_display(plane_state);
const struct drm_framebuffer *fb = plane_state->hw.fb;
unsigned int rotation = plane_state->hw.rotation;
u32 dspcntr;
dspcntr = DISP_ENABLE;
if (IS_G4X(dev_priv) || IS_IRONLAKE(dev_priv) ||
IS_SANDYBRIDGE(dev_priv) || IS_IVYBRIDGE(dev_priv))
if (display->platform.g4x || display->platform.ironlake ||
display->platform.sandybridge || display->platform.ivybridge)
dspcntr |= DISP_TRICKLE_FEED_DISABLE;
switch (fb->format->format) {
@ -211,7 +210,7 @@ static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,
return 0;
}
if (DISPLAY_VER(dev_priv) >= 4 &&
if (DISPLAY_VER(display) >= 4 &&
fb->modifier == I915_FORMAT_MOD_X_TILED)
dspcntr |= DISP_TILED;
@ -226,8 +225,8 @@ static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,
int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
{
struct intel_display *display = to_intel_display(plane_state);
struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
const struct drm_framebuffer *fb = plane_state->hw.fb;
int src_x, src_y, src_w;
u32 offset;
@ -245,12 +244,16 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
src_y = plane_state->uapi.src.y1 >> 16;
/* Undocumented hardware limit on i965/g4x/vlv/chv */
if (HAS_GMCH(dev_priv) && fb->format->cpp[0] == 8 && src_w > 2048)
if (HAS_GMCH(display) && fb->format->cpp[0] == 8 && src_w > 2048) {
drm_dbg_kms(display->drm,
"[PLANE:%d:%s] plane too wide (%d) for 64bpp\n",
plane->base.base.id, plane->base.name, src_w);
return -EINVAL;
}
intel_add_fb_offsets(&src_x, &src_y, plane_state, 0);
if (DISPLAY_VER(dev_priv) >= 4)
if (DISPLAY_VER(display) >= 4)
offset = intel_plane_compute_aligned_offset(&src_x, &src_y,
plane_state, 0);
else
@ -267,14 +270,15 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
* Linear surfaces seem to work just fine, even on hsw/bdw
* despite them not using the linear offset anymore.
*/
if (DISPLAY_VER(dev_priv) >= 4 && fb->modifier == I915_FORMAT_MOD_X_TILED) {
if (DISPLAY_VER(display) >= 4 && fb->modifier == I915_FORMAT_MOD_X_TILED) {
unsigned int alignment = plane->min_alignment(plane, fb, 0);
int cpp = fb->format->cpp[0];
while ((src_x + src_w) * cpp > plane_state->view.color_plane[0].mapping_stride) {
if (offset == 0) {
drm_dbg_kms(&dev_priv->drm,
"Unable to find suitable display surface offset due to X-tiling\n");
drm_dbg_kms(display->drm,
"[PLANE:%d:%s] unable to find suitable display surface offset due to X-tiling\n",
plane->base.base.id, plane->base.name);
return -EINVAL;
}
@ -291,7 +295,7 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
src_x << 16, src_y << 16);
/* HSW/BDW do this automagically in hardware */
if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)) {
if (!display->platform.haswell && !display->platform.broadwell) {
unsigned int rotation = plane_state->hw.rotation;
int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
@ -304,11 +308,11 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
}
}
if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
drm_WARN_ON(&dev_priv->drm, src_x > 8191 || src_y > 4095);
} else if (DISPLAY_VER(dev_priv) >= 4 &&
if (display->platform.haswell || display->platform.broadwell) {
drm_WARN_ON(display->drm, src_x > 8191 || src_y > 4095);
} else if (DISPLAY_VER(display) >= 4 &&
fb->modifier == I915_FORMAT_MOD_X_TILED) {
drm_WARN_ON(&dev_priv->drm, src_x > 4095 || src_y > 4095);
drm_WARN_ON(display->drm, src_x > 4095 || src_y > 4095);
}
plane_state->view.color_plane[0].offset = offset;
@ -354,8 +358,8 @@ i9xx_plane_check(struct intel_crtc_state *crtc_state,
static u32 i9xx_plane_ctl_crtc(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);
u32 dspcntr = 0;
if (crtc_state->gamma_enable)
@ -364,7 +368,7 @@ static u32 i9xx_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
if (crtc_state->csc_enable)
dspcntr |= DISP_PIPE_CSC_ENABLE;
if (DISPLAY_VER(dev_priv) < 5)
if (DISPLAY_VER(display) < 5)
dspcntr |= DISP_PIPE_SEL(crtc->pipe);
return dspcntr;
@ -422,13 +426,13 @@ static void i9xx_plane_update_noarm(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
struct intel_display *display = to_intel_display(plane);
enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
intel_de_write_fw(dev_priv, DSPSTRIDE(dev_priv, i9xx_plane),
intel_de_write_fw(display, DSPSTRIDE(display, i9xx_plane),
plane_state->view.color_plane[0].mapping_stride);
if (DISPLAY_VER(dev_priv) < 4) {
if (DISPLAY_VER(display) < 4) {
int crtc_x = plane_state->uapi.dst.x1;
int crtc_y = plane_state->uapi.dst.y1;
int crtc_w = drm_rect_width(&plane_state->uapi.dst);
@ -439,9 +443,9 @@ static void i9xx_plane_update_noarm(struct intel_dsb *dsb,
* generator but let's assume we still need to
* program whatever is there.
*/
intel_de_write_fw(dev_priv, DSPPOS(dev_priv, i9xx_plane),
intel_de_write_fw(display, DSPPOS(display, i9xx_plane),
DISP_POS_Y(crtc_y) | DISP_POS_X(crtc_x));
intel_de_write_fw(dev_priv, DSPSIZE(dev_priv, i9xx_plane),
intel_de_write_fw(display, DSPSIZE(display, i9xx_plane),
DISP_HEIGHT(crtc_h - 1) | DISP_WIDTH(crtc_w - 1));
}
}
@ -451,7 +455,7 @@ static void i9xx_plane_update_arm(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
struct intel_display *display = to_intel_display(plane);
enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
int x = plane_state->view.color_plane[0].x;
int y = plane_state->view.color_plane[0].y;
@ -466,32 +470,32 @@ static void i9xx_plane_update_arm(struct intel_dsb *dsb,
linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
if (DISPLAY_VER(dev_priv) >= 4)
if (DISPLAY_VER(display) >= 4)
dspaddr_offset = plane_state->view.color_plane[0].offset;
else
dspaddr_offset = linear_offset;
if (IS_CHERRYVIEW(dev_priv) && i9xx_plane == PLANE_B) {
if (display->platform.cherryview && i9xx_plane == PLANE_B) {
int crtc_x = plane_state->uapi.dst.x1;
int crtc_y = plane_state->uapi.dst.y1;
int crtc_w = drm_rect_width(&plane_state->uapi.dst);
int crtc_h = drm_rect_height(&plane_state->uapi.dst);
intel_de_write_fw(dev_priv, PRIMPOS(dev_priv, i9xx_plane),
intel_de_write_fw(display, PRIMPOS(display, i9xx_plane),
PRIM_POS_Y(crtc_y) | PRIM_POS_X(crtc_x));
intel_de_write_fw(dev_priv, PRIMSIZE(dev_priv, i9xx_plane),
intel_de_write_fw(display, PRIMSIZE(display, i9xx_plane),
PRIM_HEIGHT(crtc_h - 1) | PRIM_WIDTH(crtc_w - 1));
intel_de_write_fw(dev_priv,
PRIMCNSTALPHA(dev_priv, i9xx_plane), 0);
intel_de_write_fw(display,
PRIMCNSTALPHA(display, i9xx_plane), 0);
}
if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
intel_de_write_fw(dev_priv, DSPOFFSET(dev_priv, i9xx_plane),
if (display->platform.haswell || display->platform.broadwell) {
intel_de_write_fw(display, DSPOFFSET(display, i9xx_plane),
DISP_OFFSET_Y(y) | DISP_OFFSET_X(x));
} else if (DISPLAY_VER(dev_priv) >= 4) {
intel_de_write_fw(dev_priv, DSPLINOFF(dev_priv, i9xx_plane),
} else if (DISPLAY_VER(display) >= 4) {
intel_de_write_fw(display, DSPLINOFF(display, i9xx_plane),
linear_offset);
intel_de_write_fw(dev_priv, DSPTILEOFF(dev_priv, i9xx_plane),
intel_de_write_fw(display, DSPTILEOFF(display, i9xx_plane),
DISP_OFFSET_Y(y) | DISP_OFFSET_X(x));
}
@ -500,13 +504,13 @@ static void i9xx_plane_update_arm(struct intel_dsb *dsb,
* disabled. Try to make the plane enable atomic by writing
* the control register just before the surface register.
*/
intel_de_write_fw(dev_priv, DSPCNTR(dev_priv, i9xx_plane), dspcntr);
intel_de_write_fw(display, DSPCNTR(display, i9xx_plane), dspcntr);
if (DISPLAY_VER(dev_priv) >= 4)
intel_de_write_fw(dev_priv, DSPSURF(dev_priv, i9xx_plane),
if (DISPLAY_VER(display) >= 4)
intel_de_write_fw(display, DSPSURF(display, i9xx_plane),
intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
else
intel_de_write_fw(dev_priv, DSPADDR(dev_priv, i9xx_plane),
intel_de_write_fw(display, DSPADDR(display, i9xx_plane),
intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
}
@ -529,7 +533,7 @@ static void i9xx_plane_disable_arm(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
struct intel_display *display = to_intel_display(plane);
enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
u32 dspcntr;
@ -545,12 +549,46 @@ static void i9xx_plane_disable_arm(struct intel_dsb *dsb,
*/
dspcntr = i9xx_plane_ctl_crtc(crtc_state);
intel_de_write_fw(dev_priv, DSPCNTR(dev_priv, i9xx_plane), dspcntr);
intel_de_write_fw(display, DSPCNTR(display, i9xx_plane), dspcntr);
if (DISPLAY_VER(dev_priv) >= 4)
intel_de_write_fw(dev_priv, DSPSURF(dev_priv, i9xx_plane), 0);
if (DISPLAY_VER(display) >= 4)
intel_de_write_fw(display, DSPSURF(display, i9xx_plane), 0);
else
intel_de_write_fw(dev_priv, DSPADDR(dev_priv, i9xx_plane), 0);
intel_de_write_fw(display, DSPADDR(display, i9xx_plane), 0);
}
static void g4x_primary_capture_error(struct intel_crtc *crtc,
struct intel_plane *plane,
struct intel_plane_error *error)
{
struct intel_display *display = to_intel_display(plane);
enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
error->ctl = intel_de_read(display, DSPCNTR(display, i9xx_plane));
error->surf = intel_de_read(display, DSPSURF(display, i9xx_plane));
error->surflive = intel_de_read(display, DSPSURFLIVE(display, i9xx_plane));
}
static void i965_plane_capture_error(struct intel_crtc *crtc,
struct intel_plane *plane,
struct intel_plane_error *error)
{
struct intel_display *display = to_intel_display(plane);
enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
error->ctl = intel_de_read(display, DSPCNTR(display, i9xx_plane));
error->surf = intel_de_read(display, DSPSURF(display, i9xx_plane));
}
static void i8xx_plane_capture_error(struct intel_crtc *crtc,
struct intel_plane *plane,
struct intel_plane_error *error)
{
struct intel_display *display = to_intel_display(plane);
enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
error->ctl = intel_de_read(display, DSPCNTR(display, i9xx_plane));
error->surf = intel_de_read(display, DSPADDR(display, i9xx_plane));
}
static void
@ -560,7 +598,7 @@ g4x_primary_async_flip(struct intel_dsb *dsb,
const struct intel_plane_state *plane_state,
bool async_flip)
{
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
struct intel_display *display = to_intel_display(plane);
u32 dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state);
u32 dspaddr_offset = plane_state->view.color_plane[0].offset;
enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
@ -568,9 +606,9 @@ g4x_primary_async_flip(struct intel_dsb *dsb,
if (async_flip)
dspcntr |= DISP_ASYNC_FLIP;
intel_de_write_fw(dev_priv, DSPCNTR(dev_priv, i9xx_plane), dspcntr);
intel_de_write_fw(display, DSPCNTR(display, i9xx_plane), dspcntr);
intel_de_write_fw(dev_priv, DSPSURF(dev_priv, i9xx_plane),
intel_de_write_fw(display, DSPSURF(display, i9xx_plane),
intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
}
@ -581,11 +619,11 @@ vlv_primary_async_flip(struct intel_dsb *dsb,
const struct intel_plane_state *plane_state,
bool async_flip)
{
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
struct intel_display *display = to_intel_display(plane);
u32 dspaddr_offset = plane_state->view.color_plane[0].offset;
enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
intel_de_write_fw(dev_priv, DSPADDR_VLV(dev_priv, i9xx_plane),
intel_de_write_fw(display, DSPADDR_VLV(display, i9xx_plane),
intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
}
@ -673,10 +711,15 @@ vlv_primary_disable_flip_done(struct intel_plane *plane)
spin_unlock_irq(&i915->irq_lock);
}
static bool i9xx_plane_can_async_flip(u64 modifier)
{
return modifier == I915_FORMAT_MOD_X_TILED;
}
static bool i9xx_plane_get_hw_state(struct intel_plane *plane,
enum pipe *pipe)
{
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
struct intel_display *display = to_intel_display(plane);
enum intel_display_power_domain power_domain;
enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
intel_wakeref_t wakeref;
@ -689,20 +732,20 @@ static bool i9xx_plane_get_hw_state(struct intel_plane *plane,
* display power wells.
*/
power_domain = POWER_DOMAIN_PIPE(plane->pipe);
wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
wakeref = intel_display_power_get_if_enabled(display, power_domain);
if (!wakeref)
return false;
val = intel_de_read(dev_priv, DSPCNTR(dev_priv, i9xx_plane));
val = intel_de_read(display, DSPCNTR(display, i9xx_plane));
ret = val & DISP_ENABLE;
if (DISPLAY_VER(dev_priv) >= 5)
if (DISPLAY_VER(display) >= 5)
*pipe = plane->pipe;
else
*pipe = REG_FIELD_GET(DISP_PIPE_SEL_MASK, val);
intel_display_power_put(dev_priv, power_domain, wakeref);
intel_display_power_put(display, power_domain, wakeref);
return ret;
}
@ -771,16 +814,21 @@ i8xx_plane_max_stride(struct intel_plane *plane,
return 8 * 1024;
}
static unsigned int vlv_primary_min_alignment(struct intel_plane *plane,
const struct drm_framebuffer *fb,
int color_plane)
unsigned int vlv_plane_min_alignment(struct intel_plane *plane,
const struct drm_framebuffer *fb,
int color_plane)
{
struct drm_i915_private *i915 = to_i915(plane->base.dev);
struct intel_display *display = to_intel_display(plane);
if (intel_plane_can_async_flip(plane, fb->modifier))
return 256 * 1024;
/* FIXME undocumented so not sure what's actually needed */
if (intel_scanout_needs_vtd_wa(display))
return 256 * 1024;
switch (fb->modifier) {
case I915_FORMAT_MOD_X_TILED:
if (HAS_ASYNC_FLIPS(i915))
return 256 * 1024;
return 4 * 1024;
case DRM_FORMAT_MOD_LINEAR:
return 128 * 1024;
@ -794,13 +842,16 @@ static unsigned int g4x_primary_min_alignment(struct intel_plane *plane,
const struct drm_framebuffer *fb,
int color_plane)
{
struct drm_i915_private *i915 = to_i915(plane->base.dev);
struct intel_display *display = to_intel_display(plane);
if (intel_plane_can_async_flip(plane, fb->modifier))
return 256 * 1024;
if (intel_scanout_needs_vtd_wa(display))
return 256 * 1024;
switch (fb->modifier) {
case I915_FORMAT_MOD_X_TILED:
if (HAS_ASYNC_FLIPS(i915))
return 256 * 1024;
return 4 * 1024;
case DRM_FORMAT_MOD_LINEAR:
return 4 * 1024;
default:
@ -850,7 +901,7 @@ static const struct drm_plane_funcs i8xx_plane_funcs = {
};
struct intel_plane *
intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
intel_primary_plane_create(struct intel_display *display, enum pipe pipe)
{
struct intel_plane *plane;
const struct drm_plane_funcs *plane_funcs;
@ -869,20 +920,20 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
* On gen2/3 only plane A can do FBC, but the panel fitter and LVDS
* port is hooked to pipe B. Hence we want plane A feeding pipe B.
*/
if (HAS_FBC(dev_priv) && DISPLAY_VER(dev_priv) < 4 &&
INTEL_NUM_PIPES(dev_priv) == 2)
if (HAS_FBC(display) && DISPLAY_VER(display) < 4 &&
INTEL_NUM_PIPES(display) == 2)
plane->i9xx_plane = (enum i9xx_plane_id) !pipe;
else
plane->i9xx_plane = (enum i9xx_plane_id) pipe;
plane->id = PLANE_PRIMARY;
plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
intel_fbc_add_plane(i9xx_plane_fbc(dev_priv, plane->i9xx_plane), plane);
intel_fbc_add_plane(i9xx_plane_fbc(display, plane->i9xx_plane), plane);
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
if (display->platform.valleyview || display->platform.cherryview) {
formats = vlv_primary_formats;
num_formats = ARRAY_SIZE(vlv_primary_formats);
} else if (DISPLAY_VER(dev_priv) >= 4) {
} else if (DISPLAY_VER(display) >= 4) {
/*
* WaFP16GammaEnabling:ivb
* "Workaround : When using the 64-bit format, the plane
@ -896,7 +947,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
* planes, so we choose not to expose fp16 on IVB primary
* planes. HSW primary planes no longer have this problem.
*/
if (IS_IVYBRIDGE(dev_priv)) {
if (display->platform.ivybridge) {
formats = ivb_primary_formats;
num_formats = ARRAY_SIZE(ivb_primary_formats);
} else {
@ -908,44 +959,48 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
num_formats = ARRAY_SIZE(i8xx_primary_formats);
}
if (DISPLAY_VER(dev_priv) >= 4)
if (DISPLAY_VER(display) >= 4)
plane_funcs = &i965_plane_funcs;
else
plane_funcs = &i8xx_plane_funcs;
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
if (display->platform.valleyview || display->platform.cherryview)
plane->min_cdclk = vlv_plane_min_cdclk;
else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
else if (display->platform.broadwell || display->platform.haswell)
plane->min_cdclk = hsw_plane_min_cdclk;
else if (IS_IVYBRIDGE(dev_priv))
else if (display->platform.ivybridge)
plane->min_cdclk = ivb_plane_min_cdclk;
else
plane->min_cdclk = i9xx_plane_min_cdclk;
if (HAS_GMCH(dev_priv)) {
if (DISPLAY_VER(dev_priv) >= 4)
if (HAS_GMCH(display)) {
if (DISPLAY_VER(display) >= 4)
plane->max_stride = i965_plane_max_stride;
else if (DISPLAY_VER(dev_priv) == 3)
else if (DISPLAY_VER(display) == 3)
plane->max_stride = i915_plane_max_stride;
else
plane->max_stride = i8xx_plane_max_stride;
} else {
if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
if (display->platform.broadwell || display->platform.haswell)
plane->max_stride = hsw_primary_max_stride;
else
plane->max_stride = ilk_primary_max_stride;
}
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
plane->min_alignment = vlv_primary_min_alignment;
else if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv))
if (display->platform.valleyview || display->platform.cherryview)
plane->min_alignment = vlv_plane_min_alignment;
else if (DISPLAY_VER(display) >= 5 || display->platform.g4x)
plane->min_alignment = g4x_primary_min_alignment;
else if (DISPLAY_VER(dev_priv) == 4)
else if (DISPLAY_VER(display) == 4)
plane->min_alignment = i965_plane_min_alignment;
else
plane->min_alignment = i9xx_plane_min_alignment;
if (IS_I830(dev_priv) || IS_I845G(dev_priv)) {
/* FIXME undocumented for VLV/CHV so not sure what's actually needed */
if (intel_scanout_needs_vtd_wa(display))
plane->vtd_guard = 128;
if (display->platform.i830 || display->platform.i845g) {
plane->update_arm = i830_plane_update_arm;
} else {
plane->update_noarm = i9xx_plane_update_noarm;
@ -955,36 +1010,49 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
plane->get_hw_state = i9xx_plane_get_hw_state;
plane->check_plane = i9xx_plane_check;
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
plane->async_flip = vlv_primary_async_flip;
plane->enable_flip_done = vlv_primary_enable_flip_done;
plane->disable_flip_done = vlv_primary_disable_flip_done;
} else if (IS_BROADWELL(dev_priv)) {
plane->need_async_flip_toggle_wa = true;
plane->async_flip = g4x_primary_async_flip;
plane->enable_flip_done = bdw_primary_enable_flip_done;
plane->disable_flip_done = bdw_primary_disable_flip_done;
} else if (DISPLAY_VER(dev_priv) >= 7) {
plane->async_flip = g4x_primary_async_flip;
plane->enable_flip_done = ivb_primary_enable_flip_done;
plane->disable_flip_done = ivb_primary_disable_flip_done;
} else if (DISPLAY_VER(dev_priv) >= 5) {
plane->async_flip = g4x_primary_async_flip;
plane->enable_flip_done = ilk_primary_enable_flip_done;
plane->disable_flip_done = ilk_primary_disable_flip_done;
if (DISPLAY_VER(display) >= 5 || display->platform.g4x)
plane->capture_error = g4x_primary_capture_error;
else if (DISPLAY_VER(display) >= 4)
plane->capture_error = i965_plane_capture_error;
else
plane->capture_error = i8xx_plane_capture_error;
if (HAS_ASYNC_FLIPS(display)) {
if (display->platform.valleyview || display->platform.cherryview) {
plane->async_flip = vlv_primary_async_flip;
plane->enable_flip_done = vlv_primary_enable_flip_done;
plane->disable_flip_done = vlv_primary_disable_flip_done;
plane->can_async_flip = i9xx_plane_can_async_flip;
} else if (display->platform.broadwell) {
plane->need_async_flip_toggle_wa = true;
plane->async_flip = g4x_primary_async_flip;
plane->enable_flip_done = bdw_primary_enable_flip_done;
plane->disable_flip_done = bdw_primary_disable_flip_done;
plane->can_async_flip = i9xx_plane_can_async_flip;
} else if (DISPLAY_VER(display) >= 7) {
plane->async_flip = g4x_primary_async_flip;
plane->enable_flip_done = ivb_primary_enable_flip_done;
plane->disable_flip_done = ivb_primary_disable_flip_done;
plane->can_async_flip = i9xx_plane_can_async_flip;
} else if (DISPLAY_VER(display) >= 5) {
plane->async_flip = g4x_primary_async_flip;
plane->enable_flip_done = ilk_primary_enable_flip_done;
plane->disable_flip_done = ilk_primary_disable_flip_done;
plane->can_async_flip = i9xx_plane_can_async_flip;
}
}
modifiers = intel_fb_plane_get_modifiers(dev_priv, INTEL_PLANE_CAP_TILING_X);
modifiers = intel_fb_plane_get_modifiers(display, INTEL_PLANE_CAP_TILING_X);
if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv))
ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
if (DISPLAY_VER(display) >= 5 || display->platform.g4x)
ret = drm_universal_plane_init(display->drm, &plane->base,
0, plane_funcs,
formats, num_formats,
modifiers,
DRM_PLANE_TYPE_PRIMARY,
"primary %c", pipe_name(pipe));
else
ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
ret = drm_universal_plane_init(display->drm, &plane->base,
0, plane_funcs,
formats, num_formats,
modifiers,
@ -997,18 +1065,18 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
if (ret)
goto fail;
if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
if (display->platform.cherryview && pipe == PIPE_B) {
supported_rotations =
DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
DRM_MODE_REFLECT_X;
} else if (DISPLAY_VER(dev_priv) >= 4) {
} else if (DISPLAY_VER(display) >= 4) {
supported_rotations =
DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
} else {
supported_rotations = DRM_MODE_ROTATE_0;
}
if (DISPLAY_VER(dev_priv) >= 4)
if (DISPLAY_VER(display) >= 4)
drm_plane_create_rotation_property(&plane->base,
DRM_MODE_ROTATE_0,
supported_rotations);
@ -1063,8 +1131,7 @@ void
i9xx_get_initial_plane_config(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 intel_plane *plane = to_intel_plane(crtc->base.primary);
enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
enum pipe pipe;
@ -1077,21 +1144,21 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
if (!plane->get_hw_state(plane, &pipe))
return;
drm_WARN_ON(dev, pipe != crtc->pipe);
drm_WARN_ON(display->drm, pipe != crtc->pipe);
intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
if (!intel_fb) {
drm_dbg_kms(&dev_priv->drm, "failed to alloc fb\n");
drm_dbg_kms(display->drm, "failed to alloc fb\n");
return;
}
fb = &intel_fb->base;
fb->dev = dev;
fb->dev = display->drm;
val = intel_de_read(dev_priv, DSPCNTR(dev_priv, i9xx_plane));
val = intel_de_read(display, DSPCNTR(display, i9xx_plane));
if (DISPLAY_VER(dev_priv) >= 4) {
if (DISPLAY_VER(display) >= 4) {
if (val & DISP_TILED) {
plane_config->tiling = I915_TILING_X;
fb->modifier = I915_FORMAT_MOD_X_TILED;
@ -1101,50 +1168,51 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
plane_config->rotation = DRM_MODE_ROTATE_180;
}
if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B &&
val & DISP_MIRROR)
if (display->platform.cherryview &&
pipe == PIPE_B && val & DISP_MIRROR)
plane_config->rotation |= DRM_MODE_REFLECT_X;
pixel_format = val & DISP_FORMAT_MASK;
fourcc = i9xx_format_to_fourcc(pixel_format);
fb->format = drm_format_info(fourcc);
if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
offset = intel_de_read(dev_priv,
DSPOFFSET(dev_priv, i9xx_plane));
base = intel_de_read(dev_priv, DSPSURF(dev_priv, i9xx_plane)) & DISP_ADDR_MASK;
} else if (DISPLAY_VER(dev_priv) >= 4) {
if (display->platform.haswell || display->platform.broadwell) {
offset = intel_de_read(display,
DSPOFFSET(display, i9xx_plane));
base = intel_de_read(display, DSPSURF(display, i9xx_plane)) & DISP_ADDR_MASK;
} else if (DISPLAY_VER(display) >= 4) {
if (plane_config->tiling)
offset = intel_de_read(dev_priv,
DSPTILEOFF(dev_priv, i9xx_plane));
offset = intel_de_read(display,
DSPTILEOFF(display, i9xx_plane));
else
offset = intel_de_read(dev_priv,
DSPLINOFF(dev_priv, i9xx_plane));
base = intel_de_read(dev_priv, DSPSURF(dev_priv, i9xx_plane)) & DISP_ADDR_MASK;
offset = intel_de_read(display,
DSPLINOFF(display, i9xx_plane));
base = intel_de_read(display, DSPSURF(display, i9xx_plane)) & DISP_ADDR_MASK;
} else {
offset = 0;
base = intel_de_read(dev_priv, DSPADDR(dev_priv, i9xx_plane));
base = intel_de_read(display, DSPADDR(display, i9xx_plane));
}
plane_config->base = base;
drm_WARN_ON(&dev_priv->drm, offset != 0);
drm_WARN_ON(display->drm, offset != 0);
val = intel_de_read(dev_priv, PIPESRC(dev_priv, pipe));
val = intel_de_read(display, PIPESRC(display, pipe));
fb->width = REG_FIELD_GET(PIPESRC_WIDTH_MASK, val) + 1;
fb->height = REG_FIELD_GET(PIPESRC_HEIGHT_MASK, val) + 1;
val = intel_de_read(dev_priv, DSPSTRIDE(dev_priv, i9xx_plane));
val = intel_de_read(display, DSPSTRIDE(display, i9xx_plane));
fb->pitches[0] = val & 0xffffffc0;
aligned_height = intel_fb_align_height(fb, 0, fb->height);
plane_config->size = fb->pitches[0] * aligned_height;
drm_dbg_kms(&dev_priv->drm,
"%s/%s with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
crtc->base.name, plane->base.name, fb->width, fb->height,
fb->format->cpp[0] * 8, base, fb->pitches[0],
plane_config->size);
drm_dbg_kms(display->drm,
"[CRTC:%d:%s][PLANE:%d:%s] with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
crtc->base.base.id, crtc->base.name,
plane->base.base.id, plane->base.name,
fb->width, fb->height, fb->format->cpp[0] * 8,
base, fb->pitches[0], plane_config->size);
plane_config->fb = intel_fb;
}
@ -1152,7 +1220,7 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
bool i9xx_fixup_initial_plane_config(struct intel_crtc *crtc,
const struct intel_initial_plane_config *plane_config)
{
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
struct intel_display *display = to_intel_display(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);
@ -1171,10 +1239,10 @@ bool i9xx_fixup_initial_plane_config(struct intel_crtc *crtc,
if (plane_config->base == base)
return false;
if (DISPLAY_VER(dev_priv) >= 4)
intel_de_write(dev_priv, DSPSURF(dev_priv, i9xx_plane), base);
if (DISPLAY_VER(display) >= 4)
intel_de_write(display, DSPSURF(display, i9xx_plane), base);
else
intel_de_write(dev_priv, DSPADDR(dev_priv, i9xx_plane), base);
intel_de_write(display, DSPADDR(display, i9xx_plane), base);
return true;
}

View File

@ -9,8 +9,9 @@
#include <linux/types.h>
enum pipe;
struct drm_i915_private;
struct drm_framebuffer;
struct intel_crtc;
struct intel_display;
struct intel_initial_plane_config;
struct intel_plane;
struct intel_plane_state;
@ -19,10 +20,13 @@ struct intel_plane_state;
unsigned int i965_plane_max_stride(struct intel_plane *plane,
u32 pixel_format, u64 modifier,
unsigned int rotation);
unsigned int vlv_plane_min_alignment(struct intel_plane *plane,
const struct drm_framebuffer *fb,
int colot_plane);
int i9xx_check_plane_surface(struct intel_plane_state *plane_state);
struct intel_plane *
intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe);
intel_primary_plane_create(struct intel_display *display, enum pipe pipe);
void i9xx_get_initial_plane_config(struct intel_crtc *crtc,
struct intel_initial_plane_config *plane_config);
@ -40,7 +44,7 @@ static inline int i9xx_check_plane_surface(struct intel_plane_state *plane_state
return 0;
}
static inline struct intel_plane *
intel_primary_plane_create(struct drm_i915_private *dev_priv, int pipe)
intel_primary_plane_create(struct intel_display *display, int pipe)
{
return NULL;
}

View File

@ -446,7 +446,7 @@ static const struct intel_watermark_params i845_wm_info = {
* @latency: Memory wakeup latency in 0.1us units
*
* Compute the watermark using the method 1 or "small buffer"
* formula. The caller may additonally add extra cachelines
* formula. The caller may additionally add extra cachelines
* to account for TLB misses and clock crossings.
*
* This method is concerned with the short term drain rate
@ -493,7 +493,7 @@ static unsigned int intel_wm_method1(unsigned int pixel_rate,
* @latency: Memory wakeup latency in 0.1us units
*
* Compute the watermark using the method 2 or "large buffer"
* formula. The caller may additonally add extra cachelines
* formula. The caller may additionally add extra cachelines
* to account for TLB misses and clock crossings.
*
* This method is concerned with the long term drain rate
@ -1562,7 +1562,7 @@ static int vlv_compute_fifo(struct intel_crtc_state *crtc_state)
/*
* When enabling sprite0 after sprite1 has already been enabled
* we tend to get an underrun unless sprite0 already has some
* FIFO space allcoated. Hence we always allocate at least one
* FIFO space allocated. Hence we always allocate at least one
* cacheline for sprite0 whenever sprite1 is enabled.
*
* All other plane enable sequences appear immune to this problem.

View File

@ -31,8 +31,8 @@
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_probe_helper.h>
#include "i915_drv.h"
#include "i915_reg.h"
#include "i915_utils.h"
#include "icl_dsi.h"
#include "icl_dsi_regs.h"
#include "intel_atomic.h"
@ -243,7 +243,7 @@ static void dsi_program_swing_and_deemphasis(struct intel_encoder *encoder)
for_each_dsi_phy(phy, intel_dsi->phys) {
/*
* Program voltage swing and pre-emphasis level values as per
* table in BSPEC under DDI buffer programing
* table in BSPEC under DDI buffer programming.
*/
mask = SCALING_MODE_SEL_MASK | RTERM_SELECT_MASK;
val = SCALING_MODE_SEL(0x2) | TAP2_DISABLE | TAP3_DISABLE |
@ -345,7 +345,6 @@ static void gen11_dsi_program_esc_clk_div(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
enum port port;
int afe_clk_khz;
@ -354,7 +353,7 @@ static void gen11_dsi_program_esc_clk_div(struct intel_encoder *encoder,
afe_clk_khz = afe_clk(encoder, crtc_state);
if (IS_ALDERLAKE_S(dev_priv) || IS_ALDERLAKE_P(dev_priv)) {
if (display->platform.alderlake_s || display->platform.alderlake_p) {
theo_word_clk = DIV_ROUND_UP(afe_clk_khz, 8 * DSI_MAX_ESC_CLK);
act_word_clk = max(3, theo_word_clk + (theo_word_clk + 1) % 2);
esc_clk_div_m = act_word_clk * 8;
@ -375,7 +374,7 @@ static void gen11_dsi_program_esc_clk_div(struct intel_encoder *encoder,
intel_de_posting_read(display, ICL_DPHY_ESC_CLK_DIV(port));
}
if (IS_ALDERLAKE_S(dev_priv) || IS_ALDERLAKE_P(dev_priv)) {
if (display->platform.alderlake_s || display->platform.alderlake_p) {
for_each_dsi_port(port, intel_dsi->ports) {
intel_de_write(display, ADL_MIPIO_DW(port, 8),
esc_clk_div_m_phy & TX_ESC_CLK_DIV_PHY);
@ -387,13 +386,12 @@ static void gen11_dsi_program_esc_clk_div(struct intel_encoder *encoder,
static void get_dsi_io_power_domains(struct intel_dsi *intel_dsi)
{
struct intel_display *display = to_intel_display(&intel_dsi->base);
struct drm_i915_private *dev_priv = to_i915(display->drm);
enum port port;
for_each_dsi_port(port, intel_dsi->ports) {
drm_WARN_ON(display->drm, intel_dsi->io_wakeref[port]);
intel_dsi->io_wakeref[port] =
intel_display_power_get(dev_priv,
intel_display_power_get(display,
port == PORT_A ?
POWER_DOMAIN_PORT_DDI_IO_A :
POWER_DOMAIN_PORT_DDI_IO_B);
@ -415,19 +413,18 @@ static void gen11_dsi_enable_io_power(struct intel_encoder *encoder)
static void gen11_dsi_power_up_lanes(struct intel_encoder *encoder)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_display *display = to_intel_display(encoder);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
enum phy phy;
for_each_dsi_phy(phy, intel_dsi->phys)
intel_combo_phy_power_up_lanes(dev_priv, phy, true,
intel_combo_phy_power_up_lanes(display, phy, true,
intel_dsi->lane_count, false);
}
static void gen11_dsi_config_phy_lanes_sequence(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
enum phy phy;
u32 tmp;
@ -452,7 +449,7 @@ static void gen11_dsi_config_phy_lanes_sequence(struct intel_encoder *encoder)
intel_de_write(display, ICL_PORT_TX_DW2_GRP(phy), tmp);
/* For EHL, TGL, set latency optimization for PCS_DW1 lanes */
if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv) ||
if (display->platform.jasperlake || display->platform.elkhartlake ||
(DISPLAY_VER(display) >= 12)) {
intel_de_rmw(display, ICL_PORT_PCS_DW1_AUX(phy),
LATENCY_OPTIM_MASK, LATENCY_OPTIM_VAL(0));
@ -534,7 +531,6 @@ gen11_dsi_setup_dphy_timings(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
enum port port;
enum phy phy;
@ -564,7 +560,7 @@ gen11_dsi_setup_dphy_timings(struct intel_encoder *encoder,
}
}
if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) {
if (display->platform.jasperlake || display->platform.elkhartlake) {
for_each_dsi_phy(phy, intel_dsi->phys)
intel_de_rmw(display, ICL_DPHY_CHKN(phy),
0, ICL_DPHY_CHKN_AFE_OVER_PPI_STRAP);
@ -961,7 +957,7 @@ gen11_dsi_set_transcoder_timings(struct intel_encoder *encoder,
for_each_dsi_port(port, intel_dsi->ports) {
dsi_trans = dsi_port_to_transcoder(port);
/*
* FIXME: Programing this by assuming progressive mode, since
* FIXME: Programming this by assuming progressive mode, since
* non-interlaced info from VBT is not saved inside
* struct drm_display_mode.
* For interlace mode: program required pixel minus 2
@ -1385,7 +1381,6 @@ static void gen11_dsi_disable_port(struct intel_encoder *encoder)
static void gen11_dsi_disable_io_power(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
enum port port;
@ -1393,7 +1388,7 @@ static void gen11_dsi_disable_io_power(struct intel_encoder *encoder)
intel_wakeref_t wakeref;
wakeref = fetch_and_zero(&intel_dsi->io_wakeref[port]);
intel_display_power_put(dev_priv,
intel_display_power_put(display,
port == PORT_A ?
POWER_DOMAIN_PORT_DDI_IO_A :
POWER_DOMAIN_PORT_DDI_IO_B,
@ -1462,10 +1457,10 @@ static void gen11_dsi_post_disable(struct intel_atomic_state *state,
static enum drm_mode_status gen11_dsi_mode_valid(struct drm_connector *connector,
const struct drm_display_mode *mode)
{
struct drm_i915_private *i915 = to_i915(connector->dev);
struct intel_display *display = to_intel_display(connector->dev);
enum drm_mode_status status;
status = intel_cpu_transcoder_mode_valid(i915, mode);
status = intel_cpu_transcoder_mode_valid(display, mode);
if (status != MODE_OK)
return status;
@ -1697,7 +1692,6 @@ static bool gen11_dsi_get_hw_state(struct intel_encoder *encoder,
enum pipe *pipe)
{
struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
enum transcoder dsi_trans;
intel_wakeref_t wakeref;
@ -1705,7 +1699,7 @@ static bool gen11_dsi_get_hw_state(struct intel_encoder *encoder,
bool ret = false;
u32 tmp;
wakeref = intel_display_power_get_if_enabled(dev_priv,
wakeref = intel_display_power_get_if_enabled(display,
encoder->power_domain);
if (!wakeref)
return false;
@ -1736,7 +1730,7 @@ static bool gen11_dsi_get_hw_state(struct intel_encoder *encoder,
ret = tmp & TRANSCONF_ENABLE;
}
out:
intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
intel_display_power_put(display, encoder->power_domain, wakeref);
return ret;
}

View File

@ -52,6 +52,7 @@
#include "intel_fb.h"
#include "intel_fb_pin.h"
#include "skl_scaler.h"
#include "skl_universal_plane.h"
#include "skl_watermark.h"
static void intel_plane_state_reset(struct intel_plane_state *plane_state,
@ -92,6 +93,19 @@ void intel_plane_free(struct intel_plane *plane)
kfree(plane);
}
/**
* intel_plane_destroy - destroy a plane
* @plane: plane to destroy
*
* Common destruction function for all types of planes (primary, cursor,
* sprite).
*/
void intel_plane_destroy(struct drm_plane *plane)
{
drm_plane_cleanup(plane);
kfree(to_intel_plane(plane));
}
/**
* intel_plane_duplicate_state - duplicate plane state
* @plane: drm plane
@ -156,6 +170,11 @@ bool intel_plane_needs_physical(struct intel_plane *plane)
DISPLAY_INFO(i915)->cursor_needs_physical;
}
bool intel_plane_can_async_flip(struct intel_plane *plane, u64 modifier)
{
return plane->can_async_flip && plane->can_async_flip(modifier);
}
unsigned int intel_adjusted_rate(const struct drm_rect *src,
const struct drm_rect *dst,
unsigned int rate)
@ -663,7 +682,7 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_
old_plane_state, new_plane_state);
}
static struct intel_plane *
struct intel_plane *
intel_crtc_get_plane(struct intel_crtc *crtc, enum plane_id plane_id)
{
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
@ -767,7 +786,7 @@ void intel_plane_update_noarm(struct intel_dsb *dsb,
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
trace_intel_plane_update_noarm(plane, crtc);
trace_intel_plane_update_noarm(plane_state, crtc);
if (plane->update_noarm)
plane->update_noarm(dsb, plane, crtc_state, plane_state);
@ -797,7 +816,7 @@ void intel_plane_update_arm(struct intel_dsb *dsb,
return;
}
trace_intel_plane_update_arm(plane, crtc);
trace_intel_plane_update_arm(plane_state, crtc);
plane->update_arm(dsb, plane, crtc_state, plane_state);
}
@ -836,7 +855,7 @@ void intel_crtc_planes_update_noarm(struct intel_dsb *dsb,
/* TODO: for mailbox updates this should be skipped */
if (new_plane_state->uapi.visible ||
new_plane_state->planar_slave)
new_plane_state->is_y_plane)
intel_plane_update_noarm(dsb, plane,
new_crtc_state, new_plane_state);
}
@ -869,7 +888,7 @@ static void skl_crtc_planes_update_arm(struct intel_dsb *dsb,
* would have to be called here as well.
*/
if (new_plane_state->uapi.visible ||
new_plane_state->planar_slave)
new_plane_state->is_y_plane)
intel_plane_update_arm(dsb, plane, new_crtc_state, new_plane_state);
else
intel_plane_disable_arm(dsb, plane, new_crtc_state);
@ -921,6 +940,7 @@ int intel_atomic_plane_check_clipping(struct intel_plane_state *plane_state,
bool can_position)
{
struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
struct drm_framebuffer *fb = plane_state->hw.fb;
struct drm_rect *src = &plane_state->uapi.src;
struct drm_rect *dst = &plane_state->uapi.dst;
@ -939,9 +959,10 @@ int intel_atomic_plane_check_clipping(struct intel_plane_state *plane_state,
hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale);
vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale);
if (hscale < 0 || vscale < 0) {
drm_dbg_kms(&i915->drm, "Invalid scaling of plane\n");
drm_rect_debug_print("src: ", src, true);
drm_rect_debug_print("dst: ", dst, false);
drm_dbg_kms(&i915->drm,
"[PLANE:%d:%s] invalid scaling "DRM_RECT_FP_FMT " -> " DRM_RECT_FMT "\n",
plane->base.base.id, plane->base.name,
DRM_RECT_FP_ARG(src), DRM_RECT_ARG(dst));
return -ERANGE;
}
@ -955,9 +976,10 @@ int intel_atomic_plane_check_clipping(struct intel_plane_state *plane_state,
if (!can_position && plane_state->uapi.visible &&
!drm_rect_equals(dst, clip)) {
drm_dbg_kms(&i915->drm, "Plane must cover entire CRTC\n");
drm_rect_debug_print("dst: ", dst, false);
drm_rect_debug_print("clip: ", clip, false);
drm_dbg_kms(&i915->drm,
"[PLANE:%d:%s] plane (" DRM_RECT_FMT ") must cover entire CRTC (" DRM_RECT_FMT ")\n",
plane->base.base.id, plane->base.name,
DRM_RECT_ARG(dst), DRM_RECT_ARG(clip));
return -EINVAL;
}
@ -970,6 +992,7 @@ int intel_atomic_plane_check_clipping(struct intel_plane_state *plane_state,
int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
{
struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
const struct drm_framebuffer *fb = plane_state->hw.fb;
struct drm_rect *src = &plane_state->uapi.src;
u32 src_x, src_y, src_w, src_h, hsub, vsub;
@ -1025,13 +1048,17 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
hsub = vsub = max(hsub, vsub);
if (src_x % hsub || src_w % hsub) {
drm_dbg_kms(&i915->drm, "src x/w (%u, %u) must be a multiple of %u (rotated: %s)\n",
drm_dbg_kms(&i915->drm,
"[PLANE:%d:%s] src x/w (%u, %u) must be a multiple of %u (rotated: %s)\n",
plane->base.base.id, plane->base.name,
src_x, src_w, hsub, str_yes_no(rotated));
return -EINVAL;
}
if (src_y % vsub || src_h % vsub) {
drm_dbg_kms(&i915->drm, "src y/h (%u, %u) must be a multiple of %u (rotated: %s)\n",
drm_dbg_kms(&i915->drm,
"[PLANE:%d:%s] src y/h (%u, %u) must be a multiple of %u (rotated: %s)\n",
plane->base.base.id, plane->base.name,
src_y, src_h, vsub, str_yes_no(rotated));
return -EINVAL;
}
@ -1119,7 +1146,7 @@ intel_prepare_plane_fb(struct drm_plane *_plane,
* This should only fail upon a hung GPU, in which case we
* can safely continue.
*/
if (new_crtc_state && intel_crtc_needs_modeset(new_crtc_state)) {
if (intel_crtc_needs_modeset(new_crtc_state)) {
ret = add_dma_resv_fences(old_obj->resv,
&new_plane_state->uapi);
if (ret < 0)
@ -1130,7 +1157,7 @@ intel_prepare_plane_fb(struct drm_plane *_plane,
if (!obj)
return 0;
ret = intel_plane_pin_fb(new_plane_state);
ret = intel_plane_pin_fb(new_plane_state, old_plane_state);
if (ret)
return ret;
@ -1210,3 +1237,298 @@ void intel_plane_init_cursor_vblank_work(struct intel_plane_state *old_plane_sta
drm_vblank_work_init(&old_plane_state->unpin_work, old_plane_state->uapi.crtc,
intel_cursor_unpin_work);
}
static void link_nv12_planes(struct intel_crtc_state *crtc_state,
struct intel_plane_state *uv_plane_state,
struct intel_plane_state *y_plane_state)
{
struct intel_display *display = to_intel_display(uv_plane_state);
struct intel_plane *uv_plane = to_intel_plane(uv_plane_state->uapi.plane);
struct intel_plane *y_plane = to_intel_plane(y_plane_state->uapi.plane);
drm_dbg_kms(display->drm, "UV plane [PLANE:%d:%s] using Y plane [PLANE:%d:%s]\n",
uv_plane->base.base.id, uv_plane->base.name,
y_plane->base.base.id, y_plane->base.name);
uv_plane_state->planar_linked_plane = y_plane;
y_plane_state->is_y_plane = true;
y_plane_state->planar_linked_plane = uv_plane;
crtc_state->enabled_planes |= BIT(y_plane->id);
crtc_state->active_planes |= BIT(y_plane->id);
crtc_state->update_planes |= BIT(y_plane->id);
crtc_state->data_rate[y_plane->id] = crtc_state->data_rate_y[uv_plane->id];
crtc_state->rel_data_rate[y_plane->id] = crtc_state->rel_data_rate_y[uv_plane->id];
/* Copy parameters to Y plane */
intel_plane_copy_hw_state(y_plane_state, uv_plane_state);
y_plane_state->uapi.src = uv_plane_state->uapi.src;
y_plane_state->uapi.dst = uv_plane_state->uapi.dst;
y_plane_state->ctl = uv_plane_state->ctl;
y_plane_state->color_ctl = uv_plane_state->color_ctl;
y_plane_state->view = uv_plane_state->view;
y_plane_state->decrypt = uv_plane_state->decrypt;
icl_link_nv12_planes(uv_plane_state, y_plane_state);
}
static void unlink_nv12_plane(struct intel_crtc_state *crtc_state,
struct intel_plane_state *plane_state)
{
struct intel_display *display = to_intel_display(plane_state);
struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
plane_state->planar_linked_plane = NULL;
if (!plane_state->is_y_plane)
return;
drm_WARN_ON(display->drm, plane_state->uapi.visible);
plane_state->is_y_plane = false;
crtc_state->enabled_planes &= ~BIT(plane->id);
crtc_state->active_planes &= ~BIT(plane->id);
crtc_state->update_planes |= BIT(plane->id);
crtc_state->data_rate[plane->id] = 0;
crtc_state->rel_data_rate[plane->id] = 0;
}
static int icl_check_nv12_planes(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
struct intel_display *display = to_intel_display(state);
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
struct intel_plane_state *plane_state;
struct intel_plane *plane;
int i;
if (DISPLAY_VER(dev_priv) < 11)
return 0;
/*
* Destroy all old plane links and make the Y plane invisible
* in the crtc_state->active_planes mask.
*/
for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
if (plane->pipe != crtc->pipe)
continue;
if (plane_state->planar_linked_plane)
unlink_nv12_plane(crtc_state, plane_state);
}
if (!crtc_state->nv12_planes)
return 0;
for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
struct intel_plane_state *y_plane_state = NULL;
struct intel_plane *y_plane;
if (plane->pipe != crtc->pipe)
continue;
if ((crtc_state->nv12_planes & BIT(plane->id)) == 0)
continue;
for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, y_plane) {
if (!icl_is_nv12_y_plane(display, y_plane->id))
continue;
if (crtc_state->active_planes & BIT(y_plane->id))
continue;
y_plane_state = intel_atomic_get_plane_state(state, y_plane);
if (IS_ERR(y_plane_state))
return PTR_ERR(y_plane_state);
break;
}
if (!y_plane_state) {
drm_dbg_kms(&dev_priv->drm,
"[CRTC:%d:%s] need %d free Y planes for planar YUV\n",
crtc->base.base.id, crtc->base.name,
hweight8(crtc_state->nv12_planes));
return -EINVAL;
}
link_nv12_planes(crtc_state, plane_state, y_plane_state);
}
return 0;
}
static int intel_crtc_add_planes_to_state(struct intel_atomic_state *state,
struct intel_crtc *crtc,
u8 plane_ids_mask)
{
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
struct intel_plane *plane;
for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) {
struct intel_plane_state *plane_state;
if ((plane_ids_mask & BIT(plane->id)) == 0)
continue;
plane_state = intel_atomic_get_plane_state(state, plane);
if (IS_ERR(plane_state))
return PTR_ERR(plane_state);
}
return 0;
}
int intel_atomic_add_affected_planes(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
const struct intel_crtc_state *old_crtc_state =
intel_atomic_get_old_crtc_state(state, crtc);
const struct intel_crtc_state *new_crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
return intel_crtc_add_planes_to_state(state, crtc,
old_crtc_state->enabled_planes |
new_crtc_state->enabled_planes);
}
static bool active_planes_affects_min_cdclk(struct drm_i915_private *dev_priv)
{
/* See {hsw,vlv,ivb}_plane_ratio() */
return IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv) ||
IS_CHERRYVIEW(dev_priv) || IS_VALLEYVIEW(dev_priv) ||
IS_IVYBRIDGE(dev_priv);
}
static u8 intel_joiner_affected_planes(struct intel_atomic_state *state,
u8 joined_pipes)
{
const struct intel_plane_state *plane_state;
struct intel_plane *plane;
u8 affected_planes = 0;
int i;
for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
struct intel_plane *linked = plane_state->planar_linked_plane;
if ((joined_pipes & BIT(plane->pipe)) == 0)
continue;
affected_planes |= BIT(plane->id);
if (linked)
affected_planes |= BIT(linked->id);
}
return affected_planes;
}
static int intel_joiner_add_affected_planes(struct intel_atomic_state *state,
u8 joined_pipes)
{
u8 prev_affected_planes, affected_planes = 0;
/*
* We want all the joined pipes to have the same
* set of planes in the atomic state, to make sure
* state copying always works correctly, and the
* UV<->Y plane linkage is always up to date.
* Keep pulling planes in until we've determined
* the full set of affected planes. A bit complicated
* on account of each pipe being capable of selecting
* their own Y planes independently of the other pipes,
* and the selection being done from the set of
* inactive planes.
*/
do {
struct intel_crtc *crtc;
for_each_intel_crtc_in_pipe_mask(state->base.dev, crtc, joined_pipes) {
int ret;
ret = intel_crtc_add_planes_to_state(state, crtc, affected_planes);
if (ret)
return ret;
}
prev_affected_planes = affected_planes;
affected_planes = intel_joiner_affected_planes(state, joined_pipes);
} while (affected_planes != prev_affected_planes);
return 0;
}
static int intel_add_affected_planes(struct intel_atomic_state *state)
{
const struct intel_crtc_state *crtc_state;
struct intel_crtc *crtc;
int i;
for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
int ret;
ret = intel_joiner_add_affected_planes(state, intel_crtc_joined_pipe_mask(crtc_state));
if (ret)
return ret;
}
return 0;
}
int intel_atomic_check_planes(struct intel_atomic_state *state)
{
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
struct intel_crtc_state *old_crtc_state, *new_crtc_state;
struct intel_plane_state __maybe_unused *plane_state;
struct intel_plane *plane;
struct intel_crtc *crtc;
int i, ret;
ret = intel_add_affected_planes(state);
if (ret)
return ret;
for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
ret = intel_plane_atomic_check(state, plane);
if (ret) {
drm_dbg_atomic(&dev_priv->drm,
"[PLANE:%d:%s] atomic driver check failed\n",
plane->base.base.id, plane->base.name);
return ret;
}
}
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
u8 old_active_planes, new_active_planes;
ret = icl_check_nv12_planes(state, crtc);
if (ret)
return ret;
/*
* On some platforms the number of active planes affects
* the planes' minimum cdclk calculation. Add such planes
* to the state before we compute the minimum cdclk.
*/
if (!active_planes_affects_min_cdclk(dev_priv))
continue;
old_active_planes = old_crtc_state->active_planes & ~BIT(PLANE_CURSOR);
new_active_planes = new_crtc_state->active_planes & ~BIT(PLANE_CURSOR);
if (hweight8(old_active_planes) == hweight8(new_active_planes))
continue;
ret = intel_crtc_add_planes_to_state(state, crtc, new_active_planes);
if (ret)
return ret;
}
return 0;
}

View File

@ -19,6 +19,9 @@ struct intel_plane;
struct intel_plane_state;
enum plane_id;
struct intel_plane *
intel_crtc_get_plane(struct intel_crtc *crtc, enum plane_id plane_id);
bool intel_plane_can_async_flip(struct intel_plane *plane, u64 modifier);
unsigned int intel_adjusted_rate(const struct drm_rect *src,
const struct drm_rect *dst,
unsigned int rate);
@ -51,6 +54,7 @@ void intel_plane_disable_arm(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state);
struct intel_plane *intel_plane_alloc(void);
void intel_plane_free(struct intel_plane *plane);
void intel_plane_destroy(struct drm_plane *plane);
struct drm_plane_state *intel_plane_duplicate_state(struct drm_plane *plane);
void intel_plane_destroy_state(struct drm_plane *plane,
struct drm_plane_state *state);
@ -80,5 +84,8 @@ void intel_plane_helper_add(struct intel_plane *plane);
bool intel_plane_needs_physical(struct intel_plane *plane);
void intel_plane_init_cursor_vblank_work(struct intel_plane_state *old_plane_state,
struct intel_plane_state *new_plane_state);
int intel_atomic_add_affected_planes(struct intel_atomic_state *state,
struct intel_crtc *crtc);
int intel_atomic_check_planes(struct intel_atomic_state *state);
#endif /* __INTEL_ATOMIC_PLANE_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -9,11 +9,11 @@
#include <linux/types.h>
struct drm_connector_state;
struct drm_i915_private;
struct intel_crtc_state;
struct intel_display;
struct intel_encoder;
void intel_audio_hooks_init(struct drm_i915_private *dev_priv);
void intel_audio_hooks_init(struct intel_display *display);
bool intel_audio_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state);
@ -25,12 +25,12 @@ void intel_audio_codec_disable(struct intel_encoder *encoder,
const struct drm_connector_state *old_conn_state);
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);
void intel_audio_cdclk_change_pre(struct intel_display *display);
void intel_audio_cdclk_change_post(struct intel_display *display);
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);
void intel_audio_init(struct intel_display *display);
void intel_audio_register(struct intel_display *display);
void intel_audio_deinit(struct intel_display *display);
void intel_audio_sdp_split_update(const struct intel_crtc_state *crtc_state);
#endif /* __INTEL_AUDIO_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -314,27 +314,26 @@ static unsigned int intel_hpll_vco(struct intel_display *display)
[4] = 2666667,
[5] = 4266667,
};
struct drm_i915_private *dev_priv = to_i915(display->drm);
const unsigned int *vco_table;
unsigned int vco;
u8 tmp = 0;
/* FIXME other chipsets? */
if (IS_GM45(dev_priv))
if (display->platform.gm45)
vco_table = ctg_vco;
else if (IS_G45(dev_priv))
else if (display->platform.g45)
vco_table = elk_vco;
else if (IS_I965GM(dev_priv))
else if (display->platform.i965gm)
vco_table = cl_vco;
else if (IS_PINEVIEW(dev_priv))
else if (display->platform.pineview)
vco_table = pnv_vco;
else if (IS_G33(dev_priv))
else if (display->platform.g33)
vco_table = blb_vco;
else
return 0;
tmp = intel_de_read(display,
IS_PINEVIEW(dev_priv) || IS_MOBILE(dev_priv) ? HPLLVCO_MOBILE : HPLLVCO);
tmp = intel_de_read(display, display->platform.pineview ||
display->platform.mobile ? HPLLVCO_MOBILE : HPLLVCO);
vco = vco_table[tmp & 0x7];
if (vco == 0)
@ -508,7 +507,6 @@ static void gm45_get_cdclk(struct intel_display *display,
static void hsw_get_cdclk(struct intel_display *display,
struct intel_cdclk_config *cdclk_config)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
u32 lcpll = intel_de_read(display, LCPLL_CTL);
u32 freq = lcpll & LCPLL_CLK_FREQ_MASK;
@ -518,7 +516,7 @@ static void hsw_get_cdclk(struct intel_display *display,
cdclk_config->cdclk = 450000;
else if (freq == LCPLL_CLK_FREQ_450)
cdclk_config->cdclk = 450000;
else if (IS_HASWELL_ULT(dev_priv))
else if (display->platform.haswell_ult)
cdclk_config->cdclk = 337500;
else
cdclk_config->cdclk = 540000;
@ -535,7 +533,7 @@ static int vlv_calc_cdclk(struct intel_display *display, int min_cdclk)
* Not sure what's wrong. For now use 200MHz only when all pipes
* are off.
*/
if (IS_VALLEYVIEW(dev_priv) && min_cdclk > freq_320)
if (display->platform.valleyview && min_cdclk > freq_320)
return 400000;
else if (min_cdclk > 266667)
return freq_320;
@ -549,7 +547,7 @@ static u8 vlv_calc_voltage_level(struct intel_display *display, int cdclk)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
if (IS_VALLEYVIEW(dev_priv)) {
if (display->platform.valleyview) {
if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */
return 2;
else if (cdclk >= 266667)
@ -585,7 +583,7 @@ static void vlv_get_cdclk(struct intel_display *display,
vlv_iosf_sb_put(dev_priv,
BIT(VLV_IOSF_SB_CCK) | BIT(VLV_IOSF_SB_PUNIT));
if (IS_VALLEYVIEW(dev_priv))
if (display->platform.valleyview)
cdclk_config->voltage_level = (val & DSPFREQGUAR_MASK) >>
DSPFREQGUAR_SHIFT;
else
@ -598,14 +596,14 @@ static void vlv_program_pfi_credits(struct intel_display *display)
struct drm_i915_private *dev_priv = to_i915(display->drm);
unsigned int credits, default_credits;
if (IS_CHERRYVIEW(dev_priv))
if (display->platform.cherryview)
default_credits = PFI_CREDIT(12);
else
default_credits = PFI_CREDIT(8);
if (display->cdclk.hw.cdclk >= dev_priv->czclk_freq) {
/* CHV suggested value is 31 or 63 */
if (IS_CHERRYVIEW(dev_priv))
if (display->platform.cherryview)
credits = PFI_CREDIT_63;
else
credits = PFI_CREDIT(15);
@ -658,7 +656,7 @@ static void vlv_set_cdclk(struct intel_display *display,
* a system suspend. So grab the display core domain, which covers
* the HW blocks needed for the following programming.
*/
wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_DISPLAY_CORE);
wakeref = intel_display_power_get(display, POWER_DOMAIN_DISPLAY_CORE);
vlv_iosf_sb_get(dev_priv,
BIT(VLV_IOSF_SB_CCK) |
@ -718,7 +716,7 @@ static void vlv_set_cdclk(struct intel_display *display,
vlv_program_pfi_credits(display);
intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
intel_display_power_put(display, POWER_DOMAIN_DISPLAY_CORE, wakeref);
}
static void chv_set_cdclk(struct intel_display *display,
@ -747,7 +745,7 @@ static void chv_set_cdclk(struct intel_display *display,
* a system suspend. So grab the display core domain, which covers
* the HW blocks needed for the following programming.
*/
wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_DISPLAY_CORE);
wakeref = intel_display_power_get(display, POWER_DOMAIN_DISPLAY_CORE);
vlv_punit_get(dev_priv);
val = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM);
@ -767,7 +765,7 @@ static void chv_set_cdclk(struct intel_display *display,
vlv_program_pfi_credits(display);
intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
intel_display_power_put(display, POWER_DOMAIN_DISPLAY_CORE, wakeref);
}
static int bdw_calc_cdclk(int min_cdclk)
@ -1142,7 +1140,7 @@ static void skl_set_cdclk(struct intel_display *display,
* minimum 308MHz CDCLK.
*/
drm_WARN_ON_ONCE(display->drm,
IS_SKYLAKE(dev_priv) && vco == 8640000);
display->platform.skylake && vco == 8640000);
ret = skl_pcode_request(&dev_priv->uncore, SKL_PCODE_CDCLK_CONTROL,
SKL_CDCLK_PREPARE_FOR_CHANGE,
@ -1662,10 +1660,9 @@ static void icl_readout_refclk(struct intel_display *display,
static void bxt_de_pll_readout(struct intel_display *display,
struct intel_cdclk_config *cdclk_config)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
u32 val, ratio;
if (IS_DG2(dev_priv))
if (display->platform.dg2)
cdclk_config->ref = 38400;
else if (DISPLAY_VER(display) >= 11)
icl_readout_refclk(display, cdclk_config);
@ -2057,11 +2054,9 @@ static bool cdclk_compute_crawl_and_squash_midpoint(struct intel_display *displa
static bool pll_enable_wa_needed(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
return (DISPLAY_VERx100(display) == 2000 ||
DISPLAY_VERx100(display) == 1400 ||
IS_DG2(dev_priv)) &&
display->platform.dg2) &&
display->cdclk.hw.vco > 0;
}
@ -2069,7 +2064,6 @@ static u32 bxt_cdclk_ctl(struct intel_display *display,
const struct intel_cdclk_config *cdclk_config,
enum pipe pipe)
{
struct drm_i915_private *i915 = to_i915(display->drm);
int cdclk = cdclk_config->cdclk;
int vco = cdclk_config->vco;
u16 waveform;
@ -2084,7 +2078,7 @@ static u32 bxt_cdclk_ctl(struct intel_display *display,
* Disable SSA Precharge when CD clock frequency < 500 MHz,
* enable otherwise.
*/
if ((IS_GEMINILAKE(i915) || IS_BROXTON(i915)) &&
if ((display->platform.geminilake || display->platform.broxton) &&
cdclk >= 500000)
val |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
@ -2144,8 +2138,8 @@ static void bxt_set_cdclk(struct intel_display *display,
* mailbox communication, skip
* this step.
*/
if (DISPLAY_VER(display) >= 14 || IS_DG2(dev_priv))
/* NOOP */;
if (DISPLAY_VER(display) >= 14 || display->platform.dg2)
; /* NOOP */
else if (DISPLAY_VER(display) >= 11)
ret = skl_pcode_request(&dev_priv->uncore, SKL_PCODE_CDCLK_CONTROL,
SKL_CDCLK_PREPARE_FOR_CHANGE,
@ -2186,7 +2180,7 @@ static void bxt_set_cdclk(struct intel_display *display,
* NOOP - No Pcode communication needed for
* Display versions 14 and beyond
*/;
else if (DISPLAY_VER(display) >= 11 && !IS_DG2(dev_priv))
else if (DISPLAY_VER(display) >= 11 && !display->platform.dg2)
ret = snb_pcode_write(&dev_priv->uncore, SKL_PCODE_CDCLK_CONTROL,
cdclk_config->voltage_level);
if (DISPLAY_VER(display) < 11) {
@ -2250,7 +2244,7 @@ static void bxt_sanitize_cdclk(struct intel_display *display)
/*
* Let's ignore the pipe field, since BIOS could have configured the
* dividers both synching to an active pipe, or asynchronously
* dividers both syncing to an active pipe, or asynchronously
* (PIPE_NONE).
*/
cdctl &= ~bxt_cdclk_cd2x_pipe(display, INVALID_PIPE);
@ -2318,9 +2312,7 @@ static void bxt_cdclk_uninit_hw(struct intel_display *display)
*/
void intel_cdclk_init_hw(struct intel_display *display)
{
struct drm_i915_private *i915 = to_i915(display->drm);
if (DISPLAY_VER(display) >= 10 || IS_BROXTON(i915))
if (DISPLAY_VER(display) >= 10 || display->platform.broxton)
bxt_cdclk_init_hw(display);
else if (DISPLAY_VER(display) == 9)
skl_cdclk_init_hw(display);
@ -2335,9 +2327,7 @@ void intel_cdclk_init_hw(struct intel_display *display)
*/
void intel_cdclk_uninit_hw(struct intel_display *display)
{
struct drm_i915_private *i915 = to_i915(display->drm);
if (DISPLAY_VER(display) >= 10 || IS_BROXTON(i915))
if (DISPLAY_VER(display) >= 10 || display->platform.broxton)
bxt_cdclk_uninit_hw(display);
else if (DISPLAY_VER(display) == 9)
skl_cdclk_uninit_hw(display);
@ -2438,10 +2428,8 @@ static bool intel_cdclk_can_cd2x_update(struct intel_display *display,
const struct intel_cdclk_config *a,
const struct intel_cdclk_config *b)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
/* Older hw doesn't have the capability */
if (DISPLAY_VER(display) < 10 && !IS_BROXTON(dev_priv))
if (DISPLAY_VER(display) < 10 && !display->platform.broxton)
return false;
/*
@ -2495,7 +2483,7 @@ static void intel_pcode_notify(struct intel_display *display,
int ret;
u32 update_mask = 0;
if (!IS_DG2(i915))
if (!display->platform.dg2)
return;
update_mask = DISPLAY_TO_PCODE_UPDATE_MASK(cdclk, active_pipe_count, voltage_level);
@ -2521,7 +2509,6 @@ static void intel_set_cdclk(struct intel_display *display,
const struct intel_cdclk_config *cdclk_config,
enum pipe pipe, const char *context)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct intel_encoder *encoder;
if (!intel_cdclk_changed(&display->cdclk.hw, cdclk_config))
@ -2538,7 +2525,7 @@ static void intel_set_cdclk(struct intel_display *display,
intel_psr_pause(intel_dp);
}
intel_audio_cdclk_change_pre(dev_priv);
intel_audio_cdclk_change_pre(display);
/*
* Lock aux/gmbus while we change cdclk in case those
@ -2568,7 +2555,7 @@ static void intel_set_cdclk(struct intel_display *display,
intel_psr_resume(intel_dp);
}
intel_audio_cdclk_change_post(dev_priv);
intel_audio_cdclk_change_post(display);
if (drm_WARN(display->drm,
intel_cdclk_changed(&display->cdclk.hw, cdclk_config),
@ -2682,7 +2669,6 @@ void
intel_set_cdclk_pre_plane_update(struct intel_atomic_state *state)
{
struct intel_display *display = to_intel_display(state);
struct drm_i915_private *i915 = to_i915(display->drm);
const struct intel_cdclk_state *old_cdclk_state =
intel_atomic_get_old_cdclk_state(state);
const struct intel_cdclk_state *new_cdclk_state =
@ -2694,7 +2680,7 @@ intel_set_cdclk_pre_plane_update(struct intel_atomic_state *state)
&new_cdclk_state->actual))
return;
if (IS_DG2(i915))
if (display->platform.dg2)
intel_cdclk_pcode_pre_notify(state);
if (new_cdclk_state->disable_pipes) {
@ -2736,7 +2722,6 @@ void
intel_set_cdclk_post_plane_update(struct intel_atomic_state *state)
{
struct intel_display *display = to_intel_display(state);
struct drm_i915_private *i915 = to_i915(display->drm);
const struct intel_cdclk_state *old_cdclk_state =
intel_atomic_get_old_cdclk_state(state);
const struct intel_cdclk_state *new_cdclk_state =
@ -2747,7 +2732,7 @@ intel_set_cdclk_post_plane_update(struct intel_atomic_state *state)
&new_cdclk_state->actual))
return;
if (IS_DG2(i915))
if (display->platform.dg2)
intel_cdclk_pcode_post_notify(state);
if (!new_cdclk_state->disable_pipes &&
@ -2771,12 +2756,10 @@ static int intel_cdclk_ppc(struct intel_display *display, bool double_wide)
/* 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))
display->platform.broadwell || display->platform.haswell)
return 100;
else if (IS_CHERRYVIEW(dev_priv))
else if (display->platform.cherryview)
return 95;
else
return 90;
@ -2879,7 +2862,7 @@ static int intel_compute_min_cdclk(struct intel_atomic_state *state)
* by changing the cd2x divider (see glk_cdclk_table[]) and
* thus a full modeset won't be needed then.
*/
if (IS_GEMINILAKE(dev_priv) && cdclk_state->active_pipes &&
if (display->platform.geminilake && cdclk_state->active_pipes &&
!is_power_of_2(cdclk_state->active_pipes))
min_cdclk = max(min_cdclk, 2 * 96000);
@ -3233,7 +3216,6 @@ static bool intel_cdclk_need_serialize(struct intel_display *display,
const struct intel_cdclk_state *old_cdclk_state,
const struct intel_cdclk_state *new_cdclk_state)
{
struct drm_i915_private *i915 = to_i915(display->drm);
bool power_well_cnt_changed = hweight8(old_cdclk_state->active_pipes) !=
hweight8(new_cdclk_state->active_pipes);
bool cdclk_changed = intel_cdclk_changed(&old_cdclk_state->actual,
@ -3242,7 +3224,7 @@ static bool intel_cdclk_need_serialize(struct intel_display *display,
* We need to poke hw for gen >= 12, because we notify PCode if
* pipe power well count changes.
*/
return cdclk_changed || (IS_DG2(i915) && power_well_cnt_changed);
return cdclk_changed || (display->platform.dg2 && power_well_cnt_changed);
}
int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
@ -3377,11 +3359,9 @@ static int intel_compute_max_dotclk(struct intel_display *display)
*/
void intel_update_max_cdclk(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
if (DISPLAY_VER(display) >= 30) {
display->cdclk.max_cdclk_freq = 691200;
} else if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) {
} else if (display->platform.jasperlake || display->platform.elkhartlake) {
if (display->cdclk.hw.ref == 24000)
display->cdclk.max_cdclk_freq = 552000;
else
@ -3391,9 +3371,9 @@ void intel_update_max_cdclk(struct intel_display *display)
display->cdclk.max_cdclk_freq = 648000;
else
display->cdclk.max_cdclk_freq = 652800;
} else if (IS_GEMINILAKE(dev_priv)) {
} else if (display->platform.geminilake) {
display->cdclk.max_cdclk_freq = 316800;
} else if (IS_BROXTON(dev_priv)) {
} else if (display->platform.broxton) {
display->cdclk.max_cdclk_freq = 624000;
} else if (DISPLAY_VER(display) == 9) {
u32 limit = intel_de_read(display, SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK;
@ -3417,7 +3397,7 @@ void intel_update_max_cdclk(struct intel_display *display)
max_cdclk = 308571;
display->cdclk.max_cdclk_freq = skl_calc_cdclk(max_cdclk, vco);
} else if (IS_BROADWELL(dev_priv)) {
} else if (display->platform.broadwell) {
/*
* FIXME with extra cooling we can allow
* 540 MHz for ULX and 675 Mhz for ULT.
@ -3426,15 +3406,15 @@ void intel_update_max_cdclk(struct intel_display *display)
*/
if (intel_de_read(display, FUSE_STRAP) & HSW_CDCLK_LIMIT)
display->cdclk.max_cdclk_freq = 450000;
else if (IS_BROADWELL_ULX(dev_priv))
else if (display->platform.broadwell_ulx)
display->cdclk.max_cdclk_freq = 450000;
else if (IS_BROADWELL_ULT(dev_priv))
else if (display->platform.broadwell_ult)
display->cdclk.max_cdclk_freq = 540000;
else
display->cdclk.max_cdclk_freq = 675000;
} else if (IS_CHERRYVIEW(dev_priv)) {
} else if (display->platform.cherryview) {
display->cdclk.max_cdclk_freq = 320000;
} else if (IS_VALLEYVIEW(dev_priv)) {
} else if (display->platform.valleyview) {
display->cdclk.max_cdclk_freq = 400000;
} else {
/* otherwise assume cdclk is fixed */
@ -3458,8 +3438,6 @@ void intel_update_max_cdclk(struct intel_display *display)
*/
void intel_update_cdclk(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
intel_cdclk_get_cdclk(display, &display->cdclk.hw);
/*
@ -3468,7 +3446,7 @@ void intel_update_cdclk(struct intel_display *display)
* of cdclk that generates 4MHz reference clock freq which is used to
* generate GMBus clock. This will vary with the cdclk freq.
*/
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
if (display->platform.valleyview || display->platform.cherryview)
intel_de_write(display, GMBUSFREQ_VLV,
DIV_ROUND_UP(display->cdclk.hw.cdclk, 1000));
}
@ -3562,7 +3540,7 @@ u32 intel_read_rawclk(struct intel_display *display)
freq = cnp_rawclk(display);
else if (HAS_PCH_SPLIT(dev_priv))
freq = pch_rawclk(display);
else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
else if (display->platform.valleyview || display->platform.cherryview)
freq = vlv_hrawclk(display);
else if (DISPLAY_VER(display) >= 3)
freq = i9xx_hrawclk(display);
@ -3743,8 +3721,6 @@ static const struct intel_cdclk_funcs i830_cdclk_funcs = {
*/
void intel_init_cdclk_hooks(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
if (DISPLAY_VER(display) >= 30) {
display->funcs.cdclk = &xe3lpd_cdclk_funcs;
display->cdclk.table = xe3lpd_cdclk_table;
@ -3757,80 +3733,80 @@ void intel_init_cdclk_hooks(struct intel_display *display)
} else if (DISPLAY_VER(display) >= 14) {
display->funcs.cdclk = &rplu_cdclk_funcs;
display->cdclk.table = mtl_cdclk_table;
} else if (IS_DG2(dev_priv)) {
} else if (display->platform.dg2) {
display->funcs.cdclk = &tgl_cdclk_funcs;
display->cdclk.table = dg2_cdclk_table;
} else if (IS_ALDERLAKE_P(dev_priv)) {
} else if (display->platform.alderlake_p) {
/* Wa_22011320316:adl-p[a0] */
if (IS_ALDERLAKE_P(dev_priv) && IS_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) {
if (display->platform.alderlake_p && IS_DISPLAY_STEP(display, STEP_A0, STEP_B0)) {
display->cdclk.table = adlp_a_step_cdclk_table;
display->funcs.cdclk = &tgl_cdclk_funcs;
} else if (IS_RAPTORLAKE_U(dev_priv)) {
} else if (display->platform.alderlake_p_raptorlake_u) {
display->cdclk.table = rplu_cdclk_table;
display->funcs.cdclk = &rplu_cdclk_funcs;
} else {
display->cdclk.table = adlp_cdclk_table;
display->funcs.cdclk = &tgl_cdclk_funcs;
}
} else if (IS_ROCKETLAKE(dev_priv)) {
} else if (display->platform.rocketlake) {
display->funcs.cdclk = &tgl_cdclk_funcs;
display->cdclk.table = rkl_cdclk_table;
} else if (DISPLAY_VER(display) >= 12) {
display->funcs.cdclk = &tgl_cdclk_funcs;
display->cdclk.table = icl_cdclk_table;
} else if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) {
} else if (display->platform.jasperlake || display->platform.elkhartlake) {
display->funcs.cdclk = &ehl_cdclk_funcs;
display->cdclk.table = icl_cdclk_table;
} else if (DISPLAY_VER(display) >= 11) {
display->funcs.cdclk = &icl_cdclk_funcs;
display->cdclk.table = icl_cdclk_table;
} else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
} else if (display->platform.geminilake || display->platform.broxton) {
display->funcs.cdclk = &bxt_cdclk_funcs;
if (IS_GEMINILAKE(dev_priv))
if (display->platform.geminilake)
display->cdclk.table = glk_cdclk_table;
else
display->cdclk.table = bxt_cdclk_table;
} else if (DISPLAY_VER(display) == 9) {
display->funcs.cdclk = &skl_cdclk_funcs;
} else if (IS_BROADWELL(dev_priv)) {
} else if (display->platform.broadwell) {
display->funcs.cdclk = &bdw_cdclk_funcs;
} else if (IS_HASWELL(dev_priv)) {
} else if (display->platform.haswell) {
display->funcs.cdclk = &hsw_cdclk_funcs;
} else if (IS_CHERRYVIEW(dev_priv)) {
} else if (display->platform.cherryview) {
display->funcs.cdclk = &chv_cdclk_funcs;
} else if (IS_VALLEYVIEW(dev_priv)) {
} else if (display->platform.valleyview) {
display->funcs.cdclk = &vlv_cdclk_funcs;
} else if (IS_SANDYBRIDGE(dev_priv) || IS_IVYBRIDGE(dev_priv)) {
} else if (display->platform.sandybridge || display->platform.ivybridge) {
display->funcs.cdclk = &fixed_400mhz_cdclk_funcs;
} else if (IS_IRONLAKE(dev_priv)) {
} else if (display->platform.ironlake) {
display->funcs.cdclk = &ilk_cdclk_funcs;
} else if (IS_GM45(dev_priv)) {
} else if (display->platform.gm45) {
display->funcs.cdclk = &gm45_cdclk_funcs;
} else if (IS_G45(dev_priv)) {
} else if (display->platform.g45) {
display->funcs.cdclk = &g33_cdclk_funcs;
} else if (IS_I965GM(dev_priv)) {
} else if (display->platform.i965gm) {
display->funcs.cdclk = &i965gm_cdclk_funcs;
} else if (IS_I965G(dev_priv)) {
} else if (display->platform.i965g) {
display->funcs.cdclk = &fixed_400mhz_cdclk_funcs;
} else if (IS_PINEVIEW(dev_priv)) {
} else if (display->platform.pineview) {
display->funcs.cdclk = &pnv_cdclk_funcs;
} else if (IS_G33(dev_priv)) {
} else if (display->platform.g33) {
display->funcs.cdclk = &g33_cdclk_funcs;
} else if (IS_I945GM(dev_priv)) {
} else if (display->platform.i945gm) {
display->funcs.cdclk = &i945gm_cdclk_funcs;
} else if (IS_I945G(dev_priv)) {
} else if (display->platform.i945g) {
display->funcs.cdclk = &fixed_400mhz_cdclk_funcs;
} else if (IS_I915GM(dev_priv)) {
} else if (display->platform.i915gm) {
display->funcs.cdclk = &i915gm_cdclk_funcs;
} else if (IS_I915G(dev_priv)) {
} else if (display->platform.i915g) {
display->funcs.cdclk = &i915g_cdclk_funcs;
} else if (IS_I865G(dev_priv)) {
} else if (display->platform.i865g) {
display->funcs.cdclk = &i865g_cdclk_funcs;
} else if (IS_I85X(dev_priv)) {
} else if (display->platform.i85x) {
display->funcs.cdclk = &i85x_cdclk_funcs;
} else if (IS_I845G(dev_priv)) {
} else if (display->platform.i845g) {
display->funcs.cdclk = &i845g_cdclk_funcs;
} else if (IS_I830(dev_priv)) {
} else if (display->platform.i830) {
display->funcs.cdclk = &i830_cdclk_funcs;
}

View File

@ -0,0 +1,189 @@
// SPDX-License-Identifier: MIT
/*
* Copyright (C) 2025 Intel Corporation
*/
#include <linux/string_choices.h>
#include <linux/types.h>
#include <drm/drm_device.h>
#include <drm/drm_print.h>
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_crtc.h"
#include "intel_cmtg.h"
#include "intel_cmtg_regs.h"
#include "intel_de.h"
#include "intel_display_device.h"
#include "intel_display_power.h"
/**
* DOC: Common Primary Timing Generator (CMTG)
*
* The CMTG is a timing generator that runs in parallel to transcoders timing
* generators (TG) to provide a synchronization mechanism where CMTG acts as
* primary and transcoders TGs act as secondary to the CMTG. The CMTG outputs
* its TG start and frame sync signals to the transcoders that are configured
* as secondary, which use those signals to synchronize their own timing with
* the CMTG's.
*
* The CMTG can be used only with eDP or MIPI command mode and supports the
* following use cases:
*
* - Dual eDP: The CMTG can be used to keep two eDP TGs in sync when on a
* dual eDP configuration (with or without PSR/PSR2 enabled).
*
* - Single eDP as secondary: It is also possible to use a single eDP
* configuration with the transcoder TG as secondary to the CMTG. That would
* allow a flow that would not require a modeset on the existing eDP when a
* new eDP is added for a dual eDP configuration with CMTG.
*
* - DC6v: In DC6v, the transcoder might be off but the CMTG keeps running to
* maintain frame timings. When exiting DC6v, the transcoder TG then is
* synced back the CMTG.
*
* Currently, the driver does not use the CMTG, but we need to make sure that
* we disable it in case we inherit a display configuration with it enabled.
*/
/*
* We describe here only the minimum data required to allow us to properly
* disable the CMTG if necessary.
*/
struct intel_cmtg_config {
bool cmtg_a_enable;
/*
* Xe2_LPD adds a second CMTG that can be used for dual eDP async mode.
*/
bool cmtg_b_enable;
bool trans_a_secondary;
bool trans_b_secondary;
};
static bool intel_cmtg_has_cmtg_b(struct intel_display *display)
{
return DISPLAY_VER(display) >= 20;
}
static bool intel_cmtg_has_clock_sel(struct intel_display *display)
{
return DISPLAY_VER(display) >= 14;
}
static void intel_cmtg_dump_config(struct intel_display *display,
struct intel_cmtg_config *cmtg_config)
{
drm_dbg_kms(display->drm,
"CMTG readout: CMTG A: %s, CMTG B: %s, Transcoder A secondary: %s, Transcoder B secondary: %s\n",
str_enabled_disabled(cmtg_config->cmtg_a_enable),
intel_cmtg_has_cmtg_b(display) ? str_enabled_disabled(cmtg_config->cmtg_b_enable) : "n/a",
str_yes_no(cmtg_config->trans_a_secondary),
str_yes_no(cmtg_config->trans_b_secondary));
}
static bool intel_cmtg_transcoder_is_secondary(struct intel_display *display,
enum transcoder trans)
{
enum intel_display_power_domain power_domain;
intel_wakeref_t wakeref;
u32 val = 0;
if (!HAS_TRANSCODER(display, trans))
return false;
power_domain = POWER_DOMAIN_TRANSCODER(trans);
with_intel_display_power_if_enabled(display, power_domain, wakeref)
val = intel_de_read(display, TRANS_DDI_FUNC_CTL2(display, trans));
return val & CMTG_SECONDARY_MODE;
}
static void intel_cmtg_get_config(struct intel_display *display,
struct intel_cmtg_config *cmtg_config)
{
u32 val;
val = intel_de_read(display, TRANS_CMTG_CTL_A);
cmtg_config->cmtg_a_enable = val & CMTG_ENABLE;
if (intel_cmtg_has_cmtg_b(display)) {
val = intel_de_read(display, TRANS_CMTG_CTL_B);
cmtg_config->cmtg_b_enable = val & CMTG_ENABLE;
}
cmtg_config->trans_a_secondary = intel_cmtg_transcoder_is_secondary(display, TRANSCODER_A);
cmtg_config->trans_b_secondary = intel_cmtg_transcoder_is_secondary(display, TRANSCODER_B);
}
static bool intel_cmtg_disable_requires_modeset(struct intel_display *display,
struct intel_cmtg_config *cmtg_config)
{
if (DISPLAY_VER(display) >= 20)
return false;
return cmtg_config->trans_a_secondary || cmtg_config->trans_b_secondary;
}
static void intel_cmtg_disable(struct intel_display *display,
struct intel_cmtg_config *cmtg_config)
{
u32 clk_sel_clr = 0;
u32 clk_sel_set = 0;
if (cmtg_config->trans_a_secondary)
intel_de_rmw(display, TRANS_DDI_FUNC_CTL2(display, TRANSCODER_A),
CMTG_SECONDARY_MODE, 0);
if (cmtg_config->trans_b_secondary)
intel_de_rmw(display, TRANS_DDI_FUNC_CTL2(display, TRANSCODER_B),
CMTG_SECONDARY_MODE, 0);
if (cmtg_config->cmtg_a_enable) {
drm_dbg_kms(display->drm, "Disabling CMTG A\n");
intel_de_rmw(display, TRANS_CMTG_CTL_A, CMTG_ENABLE, 0);
clk_sel_clr |= CMTG_CLK_SEL_A_MASK;
clk_sel_set |= CMTG_CLK_SEL_A_DISABLED;
}
if (cmtg_config->cmtg_b_enable) {
drm_dbg_kms(display->drm, "Disabling CMTG B\n");
intel_de_rmw(display, TRANS_CMTG_CTL_B, CMTG_ENABLE, 0);
clk_sel_clr |= CMTG_CLK_SEL_B_MASK;
clk_sel_set |= CMTG_CLK_SEL_B_DISABLED;
}
if (intel_cmtg_has_clock_sel(display) && clk_sel_clr)
intel_de_rmw(display, CMTG_CLK_SEL, clk_sel_clr, clk_sel_set);
}
/*
* Read out CMTG configuration and, on platforms that allow disabling it without
* a modeset, do it.
*
* This function must be called before any port PLL is disabled in the general
* sanitization process, because we need whatever port PLL that is providing the
* clock for CMTG to be on before accessing CMTG registers.
*/
void intel_cmtg_sanitize(struct intel_display *display)
{
struct intel_cmtg_config cmtg_config = {};
if (!HAS_CMTG(display))
return;
intel_cmtg_get_config(display, &cmtg_config);
intel_cmtg_dump_config(display, &cmtg_config);
/*
* FIXME: The driver is not prepared to handle cases where a modeset is
* required for disabling the CMTG: we need a proper way of tracking
* CMTG state and do the right syncronization with respect to triggering
* the modeset as part of the disable sequence.
*/
if (intel_cmtg_disable_requires_modeset(display, &cmtg_config))
return;
intel_cmtg_disable(display, &cmtg_config);
}

View File

@ -0,0 +1,13 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright (C) 2025 Intel Corporation
*/
#ifndef __INTEL_CMTG_H__
#define __INTEL_CMTG_H__
struct intel_display;
void intel_cmtg_sanitize(struct intel_display *display);
#endif /* __INTEL_CMTG_H__ */

View File

@ -0,0 +1,21 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright (C) 2025 Intel Corporation
*/
#ifndef __INTEL_CMTG_REGS_H__
#define __INTEL_CMTG_REGS_H__
#include "i915_reg_defs.h"
#define CMTG_CLK_SEL _MMIO(0x46160)
#define CMTG_CLK_SEL_A_MASK REG_GENMASK(31, 29)
#define CMTG_CLK_SEL_A_DISABLED REG_FIELD_PREP(CMTG_CLK_SEL_A_MASK, 0)
#define CMTG_CLK_SEL_B_MASK REG_GENMASK(15, 13)
#define CMTG_CLK_SEL_B_DISABLED REG_FIELD_PREP(CMTG_CLK_SEL_B_MASK, 0)
#define TRANS_CMTG_CTL_A _MMIO(0x6fa88)
#define TRANS_CMTG_CTL_B _MMIO(0x6fb88)
#define CMTG_ENABLE REG_BIT(31)
#endif /* __INTEL_CMTG_REGS_H__ */

View File

@ -29,6 +29,7 @@
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dsb.h"
#include "intel_vrr.h"
struct intel_color_funcs {
int (*color_check)(struct intel_atomic_state *state,
@ -998,7 +999,7 @@ static void skl_color_commit_noarm(struct intel_dsb *dsb,
* output all black (until CSC_MODE is rearmed and properly latched).
* Once PSR exit (and proper register latching) has occurred the
* danger is over. Thus when PSR is enabled the CSC coeff/offset
* register programming will be peformed from skl_color_commit_arm()
* register programming will be performed from skl_color_commit_arm()
* which is called after PSR exit.
*/
if (!crtc_state->has_psr)
@ -1987,8 +1988,12 @@ void intel_color_prepare_commit(struct intel_atomic_state *state,
display->funcs.color->load_luts(crtc_state);
intel_dsb_wait_vblank_delay(state, crtc_state->dsb_color_vblank);
intel_dsb_interrupt(crtc_state->dsb_color_vblank);
if (crtc_state->use_dsb) {
intel_vrr_send_push(crtc_state->dsb_color_vblank, crtc_state);
intel_dsb_wait_vblank_delay(state, crtc_state->dsb_color_vblank);
intel_vrr_check_push_sent(crtc_state->dsb_color_vblank, crtc_state);
intel_dsb_interrupt(crtc_state->dsb_color_vblank);
}
intel_dsb_finish(crtc_state->dsb_color_vblank);
}

View File

@ -3,20 +3,20 @@
* Copyright © 2018 Intel Corporation
*/
#include "i915_drv.h"
#include "i915_reg.h"
#include "i915_utils.h"
#include "intel_combo_phy.h"
#include "intel_combo_phy_regs.h"
#include "intel_de.h"
#include "intel_display_types.h"
#define for_each_combo_phy(__dev_priv, __phy) \
#define for_each_combo_phy(__display, __phy) \
for ((__phy) = PHY_A; (__phy) < I915_MAX_PHYS; (__phy)++) \
for_each_if(intel_phy_is_combo(__dev_priv, __phy))
for_each_if(intel_phy_is_combo(__display, __phy))
#define for_each_combo_phy_reverse(__dev_priv, __phy) \
#define for_each_combo_phy_reverse(__display, __phy) \
for ((__phy) = I915_MAX_PHYS; (__phy)-- > PHY_A;) \
for_each_if(intel_phy_is_combo(__dev_priv, __phy))
for_each_if(intel_phy_is_combo(__display, __phy))
enum {
PROCMON_0_85V_DOT_0,
@ -53,11 +53,11 @@ static const struct icl_procmon {
};
static const struct icl_procmon *
icl_get_procmon_ref_values(struct drm_i915_private *dev_priv, enum phy phy)
icl_get_procmon_ref_values(struct intel_display *display, enum phy phy)
{
u32 val;
val = intel_de_read(dev_priv, ICL_PORT_COMP_DW3(phy));
val = intel_de_read(display, ICL_PORT_COMP_DW3(phy));
switch (val & (PROCESS_INFO_MASK | VOLTAGE_INFO_MASK)) {
default:
MISSING_CASE(val);
@ -75,57 +75,57 @@ icl_get_procmon_ref_values(struct drm_i915_private *dev_priv, enum phy phy)
}
}
static void icl_set_procmon_ref_values(struct drm_i915_private *dev_priv,
static void icl_set_procmon_ref_values(struct intel_display *display,
enum phy phy)
{
const struct icl_procmon *procmon;
procmon = icl_get_procmon_ref_values(dev_priv, phy);
procmon = icl_get_procmon_ref_values(display, phy);
intel_de_rmw(dev_priv, ICL_PORT_COMP_DW1(phy),
intel_de_rmw(display, ICL_PORT_COMP_DW1(phy),
(0xff << 16) | 0xff, procmon->dw1);
intel_de_write(dev_priv, ICL_PORT_COMP_DW9(phy), procmon->dw9);
intel_de_write(dev_priv, ICL_PORT_COMP_DW10(phy), procmon->dw10);
intel_de_write(display, ICL_PORT_COMP_DW9(phy), procmon->dw9);
intel_de_write(display, ICL_PORT_COMP_DW10(phy), procmon->dw10);
}
static bool check_phy_reg(struct drm_i915_private *dev_priv,
static bool check_phy_reg(struct intel_display *display,
enum phy phy, i915_reg_t reg, u32 mask,
u32 expected_val)
{
u32 val = intel_de_read(dev_priv, reg);
u32 val = intel_de_read(display, reg);
if ((val & mask) != expected_val) {
drm_dbg(&dev_priv->drm,
"Combo PHY %c reg %08x state mismatch: "
"current %08x mask %08x expected %08x\n",
phy_name(phy),
reg.reg, val, mask, expected_val);
drm_dbg_kms(display->drm,
"Combo PHY %c reg %08x state mismatch: "
"current %08x mask %08x expected %08x\n",
phy_name(phy),
reg.reg, val, mask, expected_val);
return false;
}
return true;
}
static bool icl_verify_procmon_ref_values(struct drm_i915_private *dev_priv,
static bool icl_verify_procmon_ref_values(struct intel_display *display,
enum phy phy)
{
const struct icl_procmon *procmon;
bool ret;
procmon = icl_get_procmon_ref_values(dev_priv, phy);
procmon = icl_get_procmon_ref_values(display, phy);
ret = check_phy_reg(dev_priv, phy, ICL_PORT_COMP_DW1(phy),
ret = check_phy_reg(display, phy, ICL_PORT_COMP_DW1(phy),
(0xff << 16) | 0xff, procmon->dw1);
ret &= check_phy_reg(dev_priv, phy, ICL_PORT_COMP_DW9(phy),
ret &= check_phy_reg(display, phy, ICL_PORT_COMP_DW9(phy),
-1U, procmon->dw9);
ret &= check_phy_reg(dev_priv, phy, ICL_PORT_COMP_DW10(phy),
ret &= check_phy_reg(display, phy, ICL_PORT_COMP_DW10(phy),
-1U, procmon->dw10);
return ret;
}
static bool has_phy_misc(struct drm_i915_private *i915, enum phy phy)
static bool has_phy_misc(struct intel_display *display, enum phy phy)
{
/*
* Some platforms only expect PHY_MISC to be programmed for PHY-A and
@ -136,32 +136,30 @@ static bool has_phy_misc(struct drm_i915_private *i915, enum phy phy)
* that we program it for PHY A.
*/
if (IS_ALDERLAKE_S(i915))
if (display->platform.alderlake_s)
return phy == PHY_A;
else if ((IS_JASPERLAKE(i915) || IS_ELKHARTLAKE(i915)) ||
IS_ROCKETLAKE(i915) ||
IS_DG1(i915))
else if ((display->platform.jasperlake || display->platform.elkhartlake) ||
display->platform.rocketlake ||
display->platform.dg1)
return phy < PHY_C;
return true;
}
static bool icl_combo_phy_enabled(struct drm_i915_private *dev_priv,
static bool icl_combo_phy_enabled(struct intel_display *display,
enum phy phy)
{
/* The PHY C added by EHL has no PHY_MISC register */
if (!has_phy_misc(dev_priv, phy))
return intel_de_read(dev_priv, ICL_PORT_COMP_DW0(phy)) & COMP_INIT;
if (!has_phy_misc(display, phy))
return intel_de_read(display, ICL_PORT_COMP_DW0(phy)) & COMP_INIT;
else
return !(intel_de_read(dev_priv, ICL_PHY_MISC(phy)) &
return !(intel_de_read(display, ICL_PHY_MISC(phy)) &
ICL_PHY_MISC_DE_IO_COMP_PWR_DOWN) &&
(intel_de_read(dev_priv, ICL_PORT_COMP_DW0(phy)) & COMP_INIT);
(intel_de_read(display, ICL_PORT_COMP_DW0(phy)) & COMP_INIT);
}
static bool ehl_vbt_ddi_d_present(struct drm_i915_private *i915)
static bool ehl_vbt_ddi_d_present(struct intel_display *display)
{
struct intel_display *display = &i915->display;
bool ddi_a_present = intel_bios_is_port_present(display, PORT_A);
bool ddi_d_present = intel_bios_is_port_present(display, PORT_D);
bool dsi_present = intel_bios_is_dsi_present(display, NULL);
@ -181,13 +179,13 @@ static bool ehl_vbt_ddi_d_present(struct drm_i915_private *i915)
* in the log and let the internal display win.
*/
if (ddi_d_present)
drm_err(&i915->drm,
drm_err(display->drm,
"VBT claims to have both internal and external displays on PHY A. Configuring for internal.\n");
return false;
}
static bool phy_is_master(struct drm_i915_private *dev_priv, enum phy phy)
static bool phy_is_master(struct intel_display *display, enum phy phy)
{
/*
* Certain PHYs are connected to compensation resistors and act
@ -207,64 +205,64 @@ static bool phy_is_master(struct drm_i915_private *dev_priv, enum phy phy)
*/
if (phy == PHY_A)
return true;
else if (IS_ALDERLAKE_S(dev_priv))
else if (display->platform.alderlake_s)
return phy == PHY_D;
else if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv))
else if (display->platform.dg1 || display->platform.rocketlake)
return phy == PHY_C;
return false;
}
static bool icl_combo_phy_verify_state(struct drm_i915_private *dev_priv,
static bool icl_combo_phy_verify_state(struct intel_display *display,
enum phy phy)
{
bool ret = true;
u32 expected_val = 0;
if (!icl_combo_phy_enabled(dev_priv, phy))
if (!icl_combo_phy_enabled(display, phy))
return false;
if (DISPLAY_VER(dev_priv) >= 12) {
ret &= check_phy_reg(dev_priv, phy, ICL_PORT_TX_DW8_LN(0, phy),
if (DISPLAY_VER(display) >= 12) {
ret &= check_phy_reg(display, phy, ICL_PORT_TX_DW8_LN(0, phy),
ICL_PORT_TX_DW8_ODCC_CLK_SEL |
ICL_PORT_TX_DW8_ODCC_CLK_DIV_SEL_MASK,
ICL_PORT_TX_DW8_ODCC_CLK_SEL |
ICL_PORT_TX_DW8_ODCC_CLK_DIV_SEL_DIV2);
ret &= check_phy_reg(dev_priv, phy, ICL_PORT_PCS_DW1_LN(0, phy),
ret &= check_phy_reg(display, phy, ICL_PORT_PCS_DW1_LN(0, phy),
DCC_MODE_SELECT_MASK, RUN_DCC_ONCE);
}
ret &= icl_verify_procmon_ref_values(dev_priv, phy);
ret &= icl_verify_procmon_ref_values(display, phy);
if (phy_is_master(dev_priv, phy)) {
ret &= check_phy_reg(dev_priv, phy, ICL_PORT_COMP_DW8(phy),
if (phy_is_master(display, phy)) {
ret &= check_phy_reg(display, phy, ICL_PORT_COMP_DW8(phy),
IREFGEN, IREFGEN);
if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) {
if (ehl_vbt_ddi_d_present(dev_priv))
if (display->platform.jasperlake || display->platform.elkhartlake) {
if (ehl_vbt_ddi_d_present(display))
expected_val = ICL_PHY_MISC_MUX_DDID;
ret &= check_phy_reg(dev_priv, phy, ICL_PHY_MISC(phy),
ret &= check_phy_reg(display, phy, ICL_PHY_MISC(phy),
ICL_PHY_MISC_MUX_DDID,
expected_val);
}
}
ret &= check_phy_reg(dev_priv, phy, ICL_PORT_CL_DW5(phy),
ret &= check_phy_reg(display, phy, ICL_PORT_CL_DW5(phy),
CL_POWER_DOWN_ENABLE, CL_POWER_DOWN_ENABLE);
return ret;
}
void intel_combo_phy_power_up_lanes(struct drm_i915_private *dev_priv,
void intel_combo_phy_power_up_lanes(struct intel_display *display,
enum phy phy, bool is_dsi,
int lane_count, bool lane_reversal)
{
u8 lane_mask;
if (is_dsi) {
drm_WARN_ON(&dev_priv->drm, lane_reversal);
drm_WARN_ON(display->drm, lane_reversal);
switch (lane_count) {
case 1:
@ -302,28 +300,28 @@ void intel_combo_phy_power_up_lanes(struct drm_i915_private *dev_priv,
}
}
intel_de_rmw(dev_priv, ICL_PORT_CL_DW10(phy),
intel_de_rmw(display, ICL_PORT_CL_DW10(phy),
PWR_DOWN_LN_MASK, lane_mask);
}
static void icl_combo_phys_init(struct drm_i915_private *dev_priv)
static void icl_combo_phys_init(struct intel_display *display)
{
enum phy phy;
for_each_combo_phy(dev_priv, phy) {
for_each_combo_phy(display, phy) {
const struct icl_procmon *procmon;
u32 val;
if (icl_combo_phy_verify_state(dev_priv, phy))
if (icl_combo_phy_verify_state(display, phy))
continue;
procmon = icl_get_procmon_ref_values(dev_priv, phy);
procmon = icl_get_procmon_ref_values(display, phy);
drm_dbg(&dev_priv->drm,
"Initializing combo PHY %c (Voltage/Process Info : %s)\n",
phy_name(phy), procmon->name);
drm_dbg_kms(display->drm,
"Initializing combo PHY %c (Voltage/Process Info : %s)\n",
phy_name(phy), procmon->name);
if (!has_phy_misc(dev_priv, phy))
if (!has_phy_misc(display, phy))
goto skip_phy_misc;
/*
@ -334,84 +332,84 @@ static void icl_combo_phys_init(struct drm_i915_private *dev_priv)
* based on whether our VBT indicates the presence of any
* "internal" child devices.
*/
val = intel_de_read(dev_priv, ICL_PHY_MISC(phy));
if ((IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) &&
val = intel_de_read(display, ICL_PHY_MISC(phy));
if ((display->platform.jasperlake || display->platform.elkhartlake) &&
phy == PHY_A) {
val &= ~ICL_PHY_MISC_MUX_DDID;
if (ehl_vbt_ddi_d_present(dev_priv))
if (ehl_vbt_ddi_d_present(display))
val |= ICL_PHY_MISC_MUX_DDID;
}
val &= ~ICL_PHY_MISC_DE_IO_COMP_PWR_DOWN;
intel_de_write(dev_priv, ICL_PHY_MISC(phy), val);
intel_de_write(display, ICL_PHY_MISC(phy), val);
skip_phy_misc:
if (DISPLAY_VER(dev_priv) >= 12) {
val = intel_de_read(dev_priv, ICL_PORT_TX_DW8_LN(0, phy));
if (DISPLAY_VER(display) >= 12) {
val = intel_de_read(display, ICL_PORT_TX_DW8_LN(0, phy));
val &= ~ICL_PORT_TX_DW8_ODCC_CLK_DIV_SEL_MASK;
val |= ICL_PORT_TX_DW8_ODCC_CLK_SEL;
val |= ICL_PORT_TX_DW8_ODCC_CLK_DIV_SEL_DIV2;
intel_de_write(dev_priv, ICL_PORT_TX_DW8_GRP(phy), val);
intel_de_write(display, ICL_PORT_TX_DW8_GRP(phy), val);
val = intel_de_read(dev_priv, ICL_PORT_PCS_DW1_LN(0, phy));
val = intel_de_read(display, ICL_PORT_PCS_DW1_LN(0, phy));
val &= ~DCC_MODE_SELECT_MASK;
val |= RUN_DCC_ONCE;
intel_de_write(dev_priv, ICL_PORT_PCS_DW1_GRP(phy), val);
intel_de_write(display, ICL_PORT_PCS_DW1_GRP(phy), val);
}
icl_set_procmon_ref_values(dev_priv, phy);
icl_set_procmon_ref_values(display, phy);
if (phy_is_master(dev_priv, phy))
intel_de_rmw(dev_priv, ICL_PORT_COMP_DW8(phy),
if (phy_is_master(display, phy))
intel_de_rmw(display, ICL_PORT_COMP_DW8(phy),
0, IREFGEN);
intel_de_rmw(dev_priv, ICL_PORT_COMP_DW0(phy), 0, COMP_INIT);
intel_de_rmw(dev_priv, ICL_PORT_CL_DW5(phy),
intel_de_rmw(display, ICL_PORT_COMP_DW0(phy), 0, COMP_INIT);
intel_de_rmw(display, ICL_PORT_CL_DW5(phy),
0, CL_POWER_DOWN_ENABLE);
}
}
static void icl_combo_phys_uninit(struct drm_i915_private *dev_priv)
static void icl_combo_phys_uninit(struct intel_display *display)
{
enum phy phy;
for_each_combo_phy_reverse(dev_priv, phy) {
for_each_combo_phy_reverse(display, phy) {
if (phy == PHY_A &&
!icl_combo_phy_verify_state(dev_priv, phy)) {
if (IS_TIGERLAKE(dev_priv) || IS_DG1(dev_priv)) {
!icl_combo_phy_verify_state(display, phy)) {
if (display->platform.tigerlake || display->platform.dg1) {
/*
* A known problem with old ifwi:
* https://gitlab.freedesktop.org/drm/intel/-/issues/2411
* Suppress the warning for CI. Remove ASAP!
*/
drm_dbg_kms(&dev_priv->drm,
drm_dbg_kms(display->drm,
"Combo PHY %c HW state changed unexpectedly\n",
phy_name(phy));
} else {
drm_warn(&dev_priv->drm,
drm_warn(display->drm,
"Combo PHY %c HW state changed unexpectedly\n",
phy_name(phy));
}
}
if (!has_phy_misc(dev_priv, phy))
if (!has_phy_misc(display, phy))
goto skip_phy_misc;
intel_de_rmw(dev_priv, ICL_PHY_MISC(phy), 0,
intel_de_rmw(display, ICL_PHY_MISC(phy), 0,
ICL_PHY_MISC_DE_IO_COMP_PWR_DOWN);
skip_phy_misc:
intel_de_rmw(dev_priv, ICL_PORT_COMP_DW0(phy), COMP_INIT, 0);
intel_de_rmw(display, ICL_PORT_COMP_DW0(phy), COMP_INIT, 0);
}
}
void intel_combo_phy_init(struct drm_i915_private *i915)
void intel_combo_phy_init(struct intel_display *display)
{
icl_combo_phys_init(i915);
icl_combo_phys_init(display);
}
void intel_combo_phy_uninit(struct drm_i915_private *i915)
void intel_combo_phy_uninit(struct intel_display *display)
{
icl_combo_phys_uninit(i915);
icl_combo_phys_uninit(display);
}

View File

@ -8,12 +8,12 @@
#include <linux/types.h>
struct drm_i915_private;
enum phy;
struct intel_display;
void intel_combo_phy_init(struct drm_i915_private *dev_priv);
void intel_combo_phy_uninit(struct drm_i915_private *dev_priv);
void intel_combo_phy_power_up_lanes(struct drm_i915_private *dev_priv,
void intel_combo_phy_init(struct intel_display *display);
void intel_combo_phy_uninit(struct intel_display *display);
void intel_combo_phy_power_up_lanes(struct intel_display *display,
enum phy phy, bool is_dsi,
int lane_count, bool lane_reversal);

View File

@ -28,6 +28,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_edid.h>
#include <drm/drm_probe_helper.h>
#include "i915_drv.h"
#include "intel_backlight.h"
@ -37,6 +38,44 @@
#include "intel_hdcp.h"
#include "intel_panel.h"
static void intel_connector_modeset_retry_work_fn(struct work_struct *work)
{
struct intel_connector *connector = container_of(work, typeof(*connector),
modeset_retry_work);
struct intel_display *display = to_intel_display(connector);
drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s]\n", connector->base.base.id,
connector->base.name);
/* Grab the locks before changing connector property*/
mutex_lock(&display->drm->mode_config.mutex);
/* Set connector link status to BAD and send a Uevent to notify
* userspace to do a modeset.
*/
drm_connector_set_link_status_property(&connector->base,
DRM_MODE_LINK_STATUS_BAD);
mutex_unlock(&display->drm->mode_config.mutex);
/* Send Hotplug uevent so userspace can reprobe */
drm_kms_helper_connector_hotplug_event(&connector->base);
drm_connector_put(&connector->base);
}
void intel_connector_queue_modeset_retry_work(struct intel_connector *connector)
{
struct drm_i915_private *i915 = to_i915(connector->base.dev);
drm_connector_get(&connector->base);
if (!queue_work(i915->unordered_wq, &connector->modeset_retry_work))
drm_connector_put(&connector->base);
}
void intel_connector_cancel_modeset_retry_work(struct intel_connector *connector)
{
if (cancel_work_sync(&connector->modeset_retry_work))
drm_connector_put(&connector->base);
}
int intel_connector_init(struct intel_connector *connector)
{
struct intel_digital_connector_state *conn_state;
@ -56,6 +95,9 @@ int intel_connector_init(struct intel_connector *connector)
intel_panel_init_alloc(connector);
INIT_WORK(&connector->modeset_retry_work,
intel_connector_modeset_retry_work_fn);
return 0;
}

View File

@ -33,5 +33,7 @@ void intel_attach_aspect_ratio_property(struct drm_connector *connector);
void intel_attach_hdmi_colorspace_property(struct drm_connector *connector);
void intel_attach_dp_colorspace_property(struct drm_connector *connector);
void intel_attach_scaling_mode_property(struct drm_connector *connector);
void intel_connector_queue_modeset_retry_work(struct intel_connector *connector);
void intel_connector_cancel_modeset_retry_work(struct intel_connector *connector);
#endif /* __INTEL_CONNECTOR_H__ */

View File

@ -108,19 +108,18 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
enum pipe *pipe)
{
struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_crt *crt = intel_encoder_to_crt(encoder);
intel_wakeref_t wakeref;
bool ret;
wakeref = intel_display_power_get_if_enabled(dev_priv,
wakeref = intel_display_power_get_if_enabled(display,
encoder->power_domain);
if (!wakeref)
return false;
ret = intel_crt_port_enabled(display, crt->adpa_reg, pipe);
intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
intel_display_power_put(display, encoder->power_domain, wakeref);
return ret;
}
@ -251,11 +250,10 @@ static void hsw_disable_crt(struct intel_atomic_state *state,
const struct drm_connector_state *old_conn_state)
{
struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
drm_WARN_ON(display->drm, !old_crtc_state->has_pch_encoder);
intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, false);
intel_set_pch_fifo_underrun_reporting(display, PIPE_A, false);
}
static void hsw_post_disable_crt(struct intel_atomic_state *state,
@ -265,7 +263,6 @@ static void hsw_post_disable_crt(struct intel_atomic_state *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);
intel_crtc_vblank_off(old_crtc_state);
@ -285,7 +282,7 @@ static void hsw_post_disable_crt(struct intel_atomic_state *state,
drm_WARN_ON(display->drm, !old_crtc_state->has_pch_encoder);
intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
intel_set_pch_fifo_underrun_reporting(display, PIPE_A, true);
}
static void hsw_pre_pll_enable_crt(struct intel_atomic_state *state,
@ -294,11 +291,10 @@ static void hsw_pre_pll_enable_crt(struct intel_atomic_state *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);
drm_WARN_ON(display->drm, !crtc_state->has_pch_encoder);
intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, false);
intel_set_pch_fifo_underrun_reporting(display, PIPE_A, false);
}
static void hsw_pre_enable_crt(struct intel_atomic_state *state,
@ -307,13 +303,12 @@ static void hsw_pre_enable_crt(struct intel_atomic_state *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_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
enum pipe pipe = crtc->pipe;
drm_WARN_ON(display->drm, !crtc_state->has_pch_encoder);
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
intel_set_cpu_fifo_underrun_reporting(display, pipe, false);
hsw_fdi_link_train(encoder, crtc_state);
@ -326,7 +321,6 @@ static void hsw_enable_crt(struct intel_atomic_state *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_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
enum pipe pipe = crtc->pipe;
@ -344,8 +338,8 @@ static void hsw_enable_crt(struct intel_atomic_state *state,
intel_crtc_wait_for_next_vblank(crtc);
intel_crtc_wait_for_next_vblank(crtc);
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
intel_set_cpu_fifo_underrun_reporting(display, pipe, true);
intel_set_pch_fifo_underrun_reporting(display, PIPE_A, true);
}
static void intel_enable_crt(struct intel_atomic_state *state,
@ -366,7 +360,7 @@ intel_crt_mode_valid(struct drm_connector *connector,
enum drm_mode_status status;
int max_clock;
status = intel_cpu_transcoder_mode_valid(dev_priv, mode);
status = intel_cpu_transcoder_mode_valid(display, mode);
if (status != MODE_OK)
return status;
@ -745,8 +739,10 @@ intel_crt_load_detect(struct intel_crt *crt, enum pipe pipe)
transconf | TRANSCONF_FORCE_BORDER);
intel_de_posting_read(display,
TRANSCONF(display, cpu_transcoder));
/* Wait for next Vblank to substitue
* border color for Color info */
/*
* Wait for next Vblank to substitute
* border color for Color info.
*/
intel_crtc_wait_for_next_vblank(intel_crtc_for_pipe(display, pipe));
st00 = intel_de_read8(display, _VGA_MSR_WRITE);
status = ((st00 & (1 << 4)) != 0) ?
@ -856,7 +852,6 @@ intel_crt_detect(struct drm_connector *connector,
bool force)
{
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 *encoder = &crt->base;
struct drm_atomic_state *state;
@ -874,7 +869,7 @@ intel_crt_detect(struct drm_connector *connector,
return connector->status;
if (display->params.load_detect_test) {
wakeref = intel_display_power_get(dev_priv, encoder->power_domain);
wakeref = intel_display_power_get(display, encoder->power_domain);
goto load_detect;
}
@ -882,7 +877,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, encoder->power_domain);
wakeref = intel_display_power_get(display, encoder->power_domain);
if (I915_HAS_HOTPLUG(display)) {
/* We can not rely on the HPD pin always being correctly wired
@ -939,7 +934,7 @@ intel_crt_detect(struct drm_connector *connector,
}
out:
intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
intel_display_power_put(display, encoder->power_domain, wakeref);
return status;
}
@ -957,7 +952,7 @@ static int intel_crt_get_modes(struct drm_connector *connector)
if (!intel_display_driver_check_access(display))
return drm_edid_connector_add_modes(connector);
wakeref = intel_display_power_get(dev_priv, encoder->power_domain);
wakeref = intel_display_power_get(display, encoder->power_domain);
ret = intel_crt_ddc_get_modes(connector, connector->ddc);
if (ret || !IS_G4X(dev_priv))
@ -968,7 +963,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, encoder->power_domain, wakeref);
intel_display_power_put(display, encoder->power_domain, wakeref);
return ret;
}
@ -1099,7 +1094,7 @@ void intel_crt_init(struct intel_display *display)
connector->base.polled = connector->polled;
if (HAS_DDI(display)) {
assert_port_valid(dev_priv, PORT_E);
assert_port_valid(display, PORT_E);
crt->base.port = PORT_E;
crt->base.get_config = hsw_crt_get_config;

View File

@ -45,9 +45,9 @@ static void assert_vblank_disabled(struct drm_crtc *crtc)
drm_crtc_vblank_put(crtc);
}
struct intel_crtc *intel_first_crtc(struct drm_i915_private *i915)
struct intel_crtc *intel_first_crtc(struct intel_display *display)
{
return to_intel_crtc(drm_crtc_from_index(&i915->drm, 0));
return to_intel_crtc(drm_crtc_from_index(display->drm, 0));
}
struct intel_crtc *intel_crtc_for_pipe(struct intel_display *display,
@ -68,10 +68,9 @@ void intel_crtc_wait_for_next_vblank(struct intel_crtc *crtc)
drm_crtc_wait_one_vblank(&crtc->base);
}
void intel_wait_for_vblank_if_active(struct drm_i915_private *i915,
void intel_wait_for_vblank_if_active(struct intel_display *display,
enum pipe pipe)
{
struct intel_display *display = &i915->display;
struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe);
if (crtc->active)
@ -93,10 +92,10 @@ u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc)
u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
struct intel_display *display = to_intel_display(crtc_state);
/*
* From Gen 11, In case of dsi cmd mode, frame counter wouldnt
* From Gen 11, in case of dsi cmd mode, frame counter wouldn't
* have updated at the beginning of TE, if we want to use
* the hw counter, then we would find it updated in only
* the next TE, hence switching to sw counter.
@ -109,13 +108,13 @@ u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state)
* On i965gm the hardware frame counter reads
* zero when the TV encoder is enabled :(
*/
if (IS_I965GM(dev_priv) &&
if (display->platform.i965gm &&
(crtc_state->output_types & BIT(INTEL_OUTPUT_TVOUT)))
return 0;
if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv))
if (DISPLAY_VER(display) >= 5 || display->platform.g4x)
return 0xffffffff; /* full 32 bit counter */
else if (DISPLAY_VER(dev_priv) >= 3)
else if (DISPLAY_VER(display) >= 3)
return 0xffffff; /* only 24 bits of frame count */
else
return 0; /* Gen2 doesn't have a hardware frame counter */
@ -142,8 +141,8 @@ void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state)
void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct intel_display *display = to_intel_display(crtc);
/*
* Should really happen exactly when we disable the pipe
@ -304,8 +303,9 @@ static const struct drm_crtc_funcs i8xx_crtc_funcs = {
.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
};
int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
int intel_crtc_init(struct intel_display *display, enum pipe pipe)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct intel_plane *primary, *cursor;
const struct drm_crtc_funcs *funcs;
struct intel_crtc *crtc;
@ -316,27 +316,27 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
return PTR_ERR(crtc);
crtc->pipe = pipe;
crtc->num_scalers = DISPLAY_RUNTIME_INFO(dev_priv)->num_scalers[pipe];
crtc->num_scalers = DISPLAY_RUNTIME_INFO(display)->num_scalers[pipe];
if (DISPLAY_VER(dev_priv) >= 9)
primary = skl_universal_plane_create(dev_priv, pipe, PLANE_1);
if (DISPLAY_VER(display) >= 9)
primary = skl_universal_plane_create(display, pipe, PLANE_1);
else
primary = intel_primary_plane_create(dev_priv, pipe);
primary = intel_primary_plane_create(display, pipe);
if (IS_ERR(primary)) {
ret = PTR_ERR(primary);
goto fail;
}
crtc->plane_ids_mask |= BIT(primary->id);
intel_init_fifo_underrun_reporting(dev_priv, crtc, false);
intel_init_fifo_underrun_reporting(display, crtc, false);
for_each_sprite(dev_priv, pipe, sprite) {
for_each_sprite(display, pipe, sprite) {
struct intel_plane *plane;
if (DISPLAY_VER(dev_priv) >= 9)
plane = skl_universal_plane_create(dev_priv, pipe, PLANE_2 + sprite);
plane = skl_universal_plane_create(display, pipe, PLANE_2 + sprite);
else
plane = intel_sprite_plane_create(dev_priv, pipe, sprite);
plane = intel_sprite_plane_create(display, pipe, sprite);
if (IS_ERR(plane)) {
ret = PTR_ERR(plane);
goto fail;
@ -344,39 +344,41 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
crtc->plane_ids_mask |= BIT(plane->id);
}
cursor = intel_cursor_plane_create(dev_priv, pipe);
cursor = intel_cursor_plane_create(display, pipe);
if (IS_ERR(cursor)) {
ret = PTR_ERR(cursor);
goto fail;
}
crtc->plane_ids_mask |= BIT(cursor->id);
if (HAS_GMCH(dev_priv)) {
if (IS_CHERRYVIEW(dev_priv) ||
IS_VALLEYVIEW(dev_priv) || IS_G4X(dev_priv))
if (HAS_GMCH(display)) {
if (display->platform.cherryview ||
display->platform.valleyview ||
display->platform.g4x)
funcs = &g4x_crtc_funcs;
else if (DISPLAY_VER(dev_priv) == 4)
else if (DISPLAY_VER(display) == 4)
funcs = &i965_crtc_funcs;
else if (IS_I945GM(dev_priv) || IS_I915GM(dev_priv))
else if (display->platform.i945gm ||
display->platform.i915gm)
funcs = &i915gm_crtc_funcs;
else if (DISPLAY_VER(dev_priv) == 3)
else if (DISPLAY_VER(display) == 3)
funcs = &i915_crtc_funcs;
else
funcs = &i8xx_crtc_funcs;
} else {
if (DISPLAY_VER(dev_priv) >= 8)
if (DISPLAY_VER(display) >= 8)
funcs = &bdw_crtc_funcs;
else
funcs = &ilk_crtc_funcs;
}
ret = drm_crtc_init_with_planes(&dev_priv->drm, &crtc->base,
ret = drm_crtc_init_with_planes(display->drm, &crtc->base,
&primary->base, &cursor->base,
funcs, "pipe %c", pipe_name(pipe));
if (ret)
goto fail;
if (DISPLAY_VER(dev_priv) >= 11)
if (DISPLAY_VER(display) >= 11)
drm_crtc_create_scaling_filter_property(&crtc->base,
BIT(DRM_SCALING_FILTER_DEFAULT) |
BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
@ -387,7 +389,7 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
cpu_latency_qos_add_request(&crtc->vblank_pm_qos, PM_QOS_DEFAULT_VALUE);
drm_WARN_ON(&dev_priv->drm, drm_crtc_index(&crtc->base) != crtc->pipe);
drm_WARN_ON(display->drm, drm_crtc_index(&crtc->base) != crtc->pipe);
return 0;
@ -512,7 +514,7 @@ int intel_scanlines_to_usecs(const struct drm_display_mode *adjusted_mode,
void intel_pipe_update_start(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
struct intel_display *display = to_intel_display(state);
const struct intel_crtc_state *old_crtc_state =
intel_atomic_get_old_crtc_state(state, crtc);
struct intel_crtc_state *new_crtc_state =
@ -520,6 +522,8 @@ void intel_pipe_update_start(struct intel_atomic_state *state,
struct intel_vblank_evade_ctx evade;
int scanline;
drm_WARN_ON(display->drm, new_crtc_state->use_dsb);
intel_psr_lock(new_crtc_state);
if (new_crtc_state->do_async_flip) {
@ -546,7 +550,7 @@ void intel_pipe_update_start(struct intel_atomic_state *state,
intel_vblank_evade_init(old_crtc_state, new_crtc_state, &evade);
if (drm_WARN_ON(&dev_priv->drm, drm_crtc_vblank_get(&crtc->base)))
if (drm_WARN_ON(display->drm, drm_crtc_vblank_get(&crtc->base)))
goto irq_disable;
/*
@ -649,6 +653,7 @@ void intel_crtc_prepare_vblank_event(struct intel_crtc_state *crtc_state,
void intel_pipe_update_end(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
struct intel_display *display = to_intel_display(state);
struct intel_crtc_state *new_crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
enum pipe pipe = crtc->pipe;
@ -657,6 +662,8 @@ void intel_pipe_update_end(struct intel_atomic_state *state,
ktime_t end_vbl_time = ktime_get();
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
drm_WARN_ON(display->drm, new_crtc_state->use_dsb);
if (new_crtc_state->do_async_flip)
goto out;
@ -666,7 +673,7 @@ void intel_pipe_update_end(struct intel_atomic_state *state,
* Incase of mipi dsi command mode, we need to set frame update
* request for every commit.
*/
if (DISPLAY_VER(dev_priv) >= 11 &&
if (DISPLAY_VER(display) >= 11 &&
intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI))
icl_dsi_frame_update(new_crtc_state);
@ -714,7 +721,8 @@ void intel_pipe_update_end(struct intel_atomic_state *state,
* which would cause the next frame to terminate already at vmin
* vblank start instead of vmax vblank start.
*/
intel_vrr_send_push(new_crtc_state);
if (!state->base.legacy_cursor_update)
intel_vrr_send_push(NULL, new_crtc_state);
local_irq_enable();
@ -723,7 +731,7 @@ void intel_pipe_update_end(struct intel_atomic_state *state,
if (crtc->debug.start_vbl_count &&
crtc->debug.start_vbl_count != end_vbl_count) {
drm_err(&dev_priv->drm,
drm_err(display->drm,
"Atomic update failure on pipe %c (start=%u end=%u) time %lld us, min %d, max %d, scanline start %d, end %d\n",
pipe_name(pipe), crtc->debug.start_vbl_count,
end_vbl_count,

View File

@ -13,7 +13,6 @@ enum pipe;
struct drm_device;
struct drm_display_mode;
struct drm_file;
struct drm_i915_private;
struct drm_pending_vblank_event;
struct intel_atomic_state;
struct intel_crtc;
@ -38,7 +37,7 @@ void intel_crtc_arm_vblank_event(struct intel_crtc_state *crtc_state);
void intel_crtc_prepare_vblank_event(struct intel_crtc_state *crtc_state,
struct drm_pending_vblank_event **event);
u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state);
int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe);
int intel_crtc_init(struct intel_display *display, enum pipe pipe);
int intel_crtc_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc);
@ -52,10 +51,10 @@ void intel_pipe_update_start(struct intel_atomic_state *state,
void intel_pipe_update_end(struct intel_atomic_state *state,
struct intel_crtc *crtc);
void intel_wait_for_vblank_workers(struct intel_atomic_state *state);
struct intel_crtc *intel_first_crtc(struct drm_i915_private *i915);
struct intel_crtc *intel_first_crtc(struct intel_display *display);
struct intel_crtc *intel_crtc_for_pipe(struct intel_display *display,
enum pipe pipe);
void intel_wait_for_vblank_if_active(struct drm_i915_private *i915,
void intel_wait_for_vblank_if_active(struct intel_display *display,
enum pipe pipe);
void intel_crtc_wait_for_next_vblank(struct intel_crtc *crtc);

View File

@ -10,6 +10,7 @@
#include "intel_crtc_state_dump.h"
#include "intel_display_types.h"
#include "intel_hdmi.h"
#include "intel_vblank.h"
#include "intel_vdsc.h"
#include "intel_vrr.h"
@ -175,6 +176,7 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config,
struct intel_atomic_state *state,
const char *context)
{
struct intel_display *display = to_intel_display(pipe_config);
struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
const struct intel_plane_state *plane_state;
@ -248,11 +250,9 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config,
str_enabled_disabled(pipe_config->has_sel_update),
str_enabled_disabled(pipe_config->has_panel_replay),
str_enabled_disabled(pipe_config->enable_psr2_sel_fetch));
drm_printf(&p, "minimum HBlank: %d\n", pipe_config->min_hblank);
}
drm_printf(&p, "framestart delay: %d, MSA timing delay: %d\n",
pipe_config->framestart_delay, pipe_config->msa_timing_delay);
drm_printf(&p, "audio: %i, infoframes: %i, infoframes enabled: 0x%x\n",
pipe_config->has_audio, pipe_config->has_infoframe,
pipe_config->infoframes.enable);
@ -286,13 +286,23 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config,
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",
drm_printf(&p, "scanline offset: %d\n",
intel_crtc_scanline_offset(pipe_config));
drm_printf(&p, "vblank delay: %d, framestart delay: %d, MSA timing delay: %d\n",
pipe_config->hw.adjusted_mode.crtc_vblank_start -
pipe_config->hw.adjusted_mode.crtc_vdisplay,
pipe_config->framestart_delay, pipe_config->msa_timing_delay);
drm_printf(&p, "vrr: %s, vmin: %d, vmax: %d, flipline: %d, pipeline full: %d, guardband: %d vsync start: %d, vsync end: %d\n",
str_yes_no(pipe_config->vrr.enable),
pipe_config->vrr.vmin, pipe_config->vrr.vmax,
pipe_config->vrr.vmin, pipe_config->vrr.vmax, pipe_config->vrr.flipline,
pipe_config->vrr.pipeline_full, pipe_config->vrr.guardband,
pipe_config->vrr.flipline,
intel_vrr_vmin_vblank_start(pipe_config),
intel_vrr_vmax_vblank_start(pipe_config));
pipe_config->vrr.vsync_start, pipe_config->vrr.vsync_end);
drm_printf(&p, "vrr: vmin vblank: %d, vmax vblank: %d, vmin vtotal: %d, vmax vtotal: %d\n",
intel_vrr_vmin_vblank_start(pipe_config), intel_vrr_vmax_vblank_start(pipe_config),
intel_vrr_vmin_vtotal(pipe_config), intel_vrr_vmax_vtotal(pipe_config));
drm_printf(&p, "requested mode: " DRM_MODE_FMT "\n",
DRM_MODE_ARG(&pipe_config->hw.mode));
@ -331,7 +341,7 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config,
pipe_config->ips_enabled, pipe_config->double_wide,
pipe_config->has_drrs);
intel_dpll_dump_hw_state(i915, &p, &pipe_config->dpll_hw_state);
intel_dpll_dump_hw_state(display, &p, &pipe_config->dpll_hw_state);
if (IS_CHERRYVIEW(i915))
drm_printf(&p, "cgm_mode: 0x%x gamma_mode: 0x%x gamma_enable: %d csc_enable: %d\n",

View File

@ -35,11 +35,10 @@ static const u32 intel_cursor_formats[] = {
static u32 intel_cursor_base(const struct intel_plane_state *plane_state)
{
struct drm_i915_private *dev_priv =
to_i915(plane_state->uapi.plane->dev);
struct intel_display *display = to_intel_display(plane_state);
u32 base;
if (DISPLAY_INFO(dev_priv)->cursor_needs_physical)
if (DISPLAY_INFO(display)->cursor_needs_physical)
base = plane_state->phys_dma_addr;
else
base = intel_plane_ggtt_offset(plane_state);
@ -92,8 +91,8 @@ static bool intel_cursor_size_ok(const struct intel_plane_state *plane_state)
static int intel_cursor_check_surface(struct intel_plane_state *plane_state)
{
struct drm_i915_private *dev_priv =
to_i915(plane_state->uapi.plane->dev);
struct intel_display *display = to_intel_display(plane_state);
struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
unsigned int rotation = plane_state->hw.rotation;
int src_x, src_y;
u32 offset;
@ -114,8 +113,9 @@ static int intel_cursor_check_surface(struct intel_plane_state *plane_state)
plane_state, 0);
if (src_x != 0 || src_y != 0) {
drm_dbg_kms(&dev_priv->drm,
"Arbitrary cursor panning not supported\n");
drm_dbg_kms(display->drm,
"[PLANE:%d:%s] arbitrary cursor panning not supported\n",
plane->base.base.id, plane->base.name);
return -EINVAL;
}
@ -127,7 +127,7 @@ static int intel_cursor_check_surface(struct intel_plane_state *plane_state)
src_x << 16, src_y << 16);
/* ILK+ do this automagically in hardware */
if (HAS_GMCH(dev_priv) && rotation & DRM_MODE_ROTATE_180) {
if (HAS_GMCH(display) && rotation & DRM_MODE_ROTATE_180) {
const struct drm_framebuffer *fb = plane_state->hw.fb;
int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
@ -145,14 +145,16 @@ static int intel_cursor_check_surface(struct intel_plane_state *plane_state)
static int intel_check_cursor(struct intel_crtc_state *crtc_state,
struct intel_plane_state *plane_state)
{
struct intel_display *display = to_intel_display(plane_state);
struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
const struct drm_framebuffer *fb = plane_state->hw.fb;
struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
const struct drm_rect src = plane_state->uapi.src;
const struct drm_rect dst = plane_state->uapi.dst;
int ret;
if (fb && fb->modifier != DRM_FORMAT_MOD_LINEAR) {
drm_dbg_kms(&i915->drm, "cursor cannot be tiled\n");
drm_dbg_kms(display->drm, "[PLANE:%d:%s] cursor cannot be tiled\n",
plane->base.base.id, plane->base.name);
return -EINVAL;
}
@ -233,8 +235,9 @@ static bool i845_cursor_size_ok(const struct intel_plane_state *plane_state)
static int i845_check_cursor(struct intel_crtc_state *crtc_state,
struct intel_plane_state *plane_state)
{
struct intel_display *display = to_intel_display(plane_state);
struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
const struct drm_framebuffer *fb = plane_state->hw.fb;
struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
int ret;
ret = intel_check_cursor(crtc_state, plane_state);
@ -247,14 +250,15 @@ static int i845_check_cursor(struct intel_crtc_state *crtc_state,
/* Check for which cursor types we support */
if (!i845_cursor_size_ok(plane_state)) {
drm_dbg_kms(&i915->drm,
"Cursor dimension %dx%d not supported\n",
drm_dbg_kms(display->drm,
"[PLANE:%d:%s] cursor dimension %dx%d not supported\n",
plane->base.base.id, plane->base.name,
drm_rect_width(&plane_state->uapi.dst),
drm_rect_height(&plane_state->uapi.dst));
return -EINVAL;
}
drm_WARN_ON(&i915->drm, plane_state->uapi.visible &&
drm_WARN_ON(display->drm, plane_state->uapi.visible &&
plane_state->view.color_plane[0].mapping_stride != fb->pitches[0]);
switch (fb->pitches[0]) {
@ -264,7 +268,8 @@ static int i845_check_cursor(struct intel_crtc_state *crtc_state,
case 2048:
break;
default:
drm_dbg_kms(&i915->drm, "Invalid cursor stride (%u)\n",
drm_dbg_kms(display->drm, "[PLANE:%d:%s] invalid cursor stride (%u)\n",
plane->base.base.id, plane->base.name,
fb->pitches[0]);
return -EINVAL;
}
@ -280,7 +285,7 @@ static void i845_cursor_update_arm(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
struct intel_display *display = to_intel_display(plane);
u32 cntl = 0, base = 0, pos = 0, size = 0;
if (plane_state && plane_state->uapi.visible) {
@ -302,17 +307,17 @@ static void i845_cursor_update_arm(struct intel_dsb *dsb,
if (plane->cursor.base != base ||
plane->cursor.size != size ||
plane->cursor.cntl != cntl) {
intel_de_write_fw(dev_priv, CURCNTR(dev_priv, PIPE_A), 0);
intel_de_write_fw(dev_priv, CURBASE(dev_priv, PIPE_A), base);
intel_de_write_fw(dev_priv, CURSIZE(dev_priv, PIPE_A), size);
intel_de_write_fw(dev_priv, CURPOS(dev_priv, PIPE_A), pos);
intel_de_write_fw(dev_priv, CURCNTR(dev_priv, PIPE_A), cntl);
intel_de_write_fw(display, CURCNTR(display, PIPE_A), 0);
intel_de_write_fw(display, CURBASE(display, PIPE_A), base);
intel_de_write_fw(display, CURSIZE(display, PIPE_A), size);
intel_de_write_fw(display, CURPOS(display, PIPE_A), pos);
intel_de_write_fw(display, CURCNTR(display, PIPE_A), cntl);
plane->cursor.base = base;
plane->cursor.size = size;
plane->cursor.cntl = cntl;
} else {
intel_de_write_fw(dev_priv, CURPOS(dev_priv, PIPE_A), pos);
intel_de_write_fw(display, CURPOS(display, PIPE_A), pos);
}
}
@ -326,21 +331,21 @@ static void i845_cursor_disable_arm(struct intel_dsb *dsb,
static bool i845_cursor_get_hw_state(struct intel_plane *plane,
enum pipe *pipe)
{
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
struct intel_display *display = to_intel_display(plane);
enum intel_display_power_domain power_domain;
intel_wakeref_t wakeref;
bool ret;
power_domain = POWER_DOMAIN_PIPE(PIPE_A);
wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
wakeref = intel_display_power_get_if_enabled(display, power_domain);
if (!wakeref)
return false;
ret = intel_de_read(dev_priv, CURCNTR(dev_priv, PIPE_A)) & CURSOR_ENABLE;
ret = intel_de_read(display, CURCNTR(display, PIPE_A)) & CURSOR_ENABLE;
*pipe = PIPE_A;
intel_display_power_put(dev_priv, power_domain, wakeref);
intel_display_power_put(display, power_domain, wakeref);
return ret;
}
@ -372,16 +377,21 @@ static unsigned int i9xx_cursor_min_alignment(struct intel_plane *plane,
const struct drm_framebuffer *fb,
int color_plane)
{
struct intel_display *display = to_intel_display(plane);
if (intel_scanout_needs_vtd_wa(display))
return 64 * 1024;
return 4 * 1024; /* physical for i915/i945 */
}
static u32 i9xx_cursor_ctl_crtc(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);
u32 cntl = 0;
if (DISPLAY_VER(dev_priv) >= 11)
if (DISPLAY_VER(display) >= 11)
return cntl;
if (crtc_state->gamma_enable)
@ -390,7 +400,7 @@ static u32 i9xx_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
if (crtc_state->csc_enable)
cntl |= MCURSOR_PIPE_CSC_ENABLE;
if (DISPLAY_VER(dev_priv) < 5 && !IS_G4X(dev_priv))
if (DISPLAY_VER(display) < 5 && !display->platform.g4x)
cntl |= MCURSOR_PIPE_SEL(crtc->pipe);
return cntl;
@ -399,11 +409,10 @@ static u32 i9xx_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
struct drm_i915_private *dev_priv =
to_i915(plane_state->uapi.plane->dev);
struct intel_display *display = to_intel_display(plane_state);
u32 cntl = 0;
if (IS_SANDYBRIDGE(dev_priv) || IS_IVYBRIDGE(dev_priv))
if (display->platform.sandybridge || display->platform.ivybridge)
cntl |= MCURSOR_TRICKLE_FEED_DISABLE;
switch (drm_rect_width(&plane_state->uapi.dst)) {
@ -425,7 +434,7 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
cntl |= MCURSOR_ROTATE_180;
/* Wa_22012358565:adl-p */
if (DISPLAY_VER(dev_priv) == 13)
if (DISPLAY_VER(display) == 13)
cntl |= MCURSOR_ARB_SLOTS(1);
return cntl;
@ -433,8 +442,7 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state)
{
struct drm_i915_private *dev_priv =
to_i915(plane_state->uapi.plane->dev);
struct intel_display *display = to_intel_display(plane_state);
int width = drm_rect_width(&plane_state->uapi.dst);
int height = drm_rect_height(&plane_state->uapi.dst);
@ -457,7 +465,7 @@ static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state)
* cursor is not rotated. Everything else requires square
* cursors.
*/
if (HAS_CUR_FBC(dev_priv) &&
if (HAS_CUR_FBC(display) &&
plane_state->hw.rotation & DRM_MODE_ROTATE_0) {
if (height < 8 || height > width)
return false;
@ -472,8 +480,8 @@ static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state)
static int i9xx_check_cursor(struct intel_crtc_state *crtc_state,
struct intel_plane_state *plane_state)
{
struct intel_display *display = to_intel_display(plane_state);
struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
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;
int ret;
@ -488,22 +496,23 @@ static int i9xx_check_cursor(struct intel_crtc_state *crtc_state,
/* Check for which cursor types we support */
if (!i9xx_cursor_size_ok(plane_state)) {
drm_dbg(&dev_priv->drm,
"Cursor dimension %dx%d not supported\n",
drm_rect_width(&plane_state->uapi.dst),
drm_rect_height(&plane_state->uapi.dst));
drm_dbg_kms(display->drm,
"[PLANE:%d:%s] cursor dimension %dx%d not supported\n",
plane->base.base.id, plane->base.name,
drm_rect_width(&plane_state->uapi.dst),
drm_rect_height(&plane_state->uapi.dst));
return -EINVAL;
}
drm_WARN_ON(&dev_priv->drm, plane_state->uapi.visible &&
drm_WARN_ON(display->drm, plane_state->uapi.visible &&
plane_state->view.color_plane[0].mapping_stride != fb->pitches[0]);
if (fb->pitches[0] !=
drm_rect_width(&plane_state->uapi.dst) * fb->format->cpp[0]) {
drm_dbg_kms(&dev_priv->drm,
"Invalid cursor stride (%u) (cursor width %d)\n",
fb->pitches[0],
drm_rect_width(&plane_state->uapi.dst));
drm_dbg_kms(display->drm,
"[PLANE:%d:%s] invalid cursor stride (%u) (cursor width %d)\n",
plane->base.base.id, plane->base.name,
fb->pitches[0], drm_rect_width(&plane_state->uapi.dst));
return -EINVAL;
}
@ -517,10 +526,11 @@ static int i9xx_check_cursor(struct intel_crtc_state *crtc_state,
* display power well must be turned off and on again.
* Refuse the put the cursor into that compromised position.
*/
if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_C &&
if (display->platform.cherryview && pipe == PIPE_C &&
plane_state->uapi.visible && plane_state->uapi.dst.x1 < 0) {
drm_dbg_kms(&dev_priv->drm,
"CHV cursor C not allowed to straddle the left screen edge\n");
drm_dbg_kms(display->drm,
"[PLANE:%d:%s] cursor not allowed to straddle the left screen edge\n",
plane->base.base.id, plane->base.name);
return -EINVAL;
}
@ -533,7 +543,7 @@ static void i9xx_cursor_disable_sel_fetch_arm(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(plane->base.dev);
struct intel_display *display = to_intel_display(plane);
enum pipe pipe = plane->pipe;
if (!crtc_state->enable_psr2_sel_fetch)
@ -547,8 +557,7 @@ static void wa_16021440873(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
struct intel_display *display = to_intel_display(plane->base.dev);
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
struct intel_display *display = to_intel_display(plane);
u32 ctl = plane_state->ctl;
int et_y_position = drm_rect_height(&crtc_state->pipe_src) + 1;
enum pipe pipe = plane->pipe;
@ -558,7 +567,7 @@ static void wa_16021440873(struct intel_dsb *dsb,
intel_de_write_dsb(display, dsb, SEL_FETCH_CUR_CTL(pipe), ctl);
intel_de_write_dsb(display, dsb, CURPOS_ERLY_TPT(dev_priv, pipe),
intel_de_write_dsb(display, dsb, CURPOS_ERLY_TPT(display, pipe),
CURSOR_POS_Y(et_y_position));
}
@ -567,8 +576,7 @@ static void i9xx_cursor_update_sel_fetch_arm(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
struct intel_display *display = to_intel_display(plane->base.dev);
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
struct intel_display *display = to_intel_display(plane);
enum pipe pipe = plane->pipe;
if (!crtc_state->enable_psr2_sel_fetch)
@ -579,7 +587,7 @@ static void i9xx_cursor_update_sel_fetch_arm(struct intel_dsb *dsb,
u32 val = intel_cursor_position(crtc_state, plane_state,
true);
intel_de_write_dsb(display, dsb, CURPOS_ERLY_TPT(dev_priv, pipe), val);
intel_de_write_dsb(display, dsb, CURPOS_ERLY_TPT(display, pipe), val);
}
intel_de_write_dsb(display, dsb, SEL_FETCH_CUR_CTL(pipe), plane_state->ctl);
@ -653,8 +661,7 @@ static void i9xx_cursor_update_arm(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
struct intel_display *display = to_intel_display(plane->base.dev);
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
struct intel_display *display = to_intel_display(plane);
enum pipe pipe = plane->pipe;
u32 cntl = 0, base = 0, pos = 0, fbc_ctl = 0;
@ -680,7 +687,7 @@ static void i9xx_cursor_update_arm(struct intel_dsb *dsb,
* CURPOS.
*
* On other platforms CURPOS always requires the
* CURBASE write to arm the update. Additonally
* CURBASE write to arm the update. Additionally
* a write to any of the cursor register will cancel
* an already armed cursor update. Thus leaving out
* the CURBASE write after CURPOS could lead to a
@ -692,7 +699,7 @@ static void i9xx_cursor_update_arm(struct intel_dsb *dsb,
* the CURCNTR write arms the update.
*/
if (DISPLAY_VER(dev_priv) >= 9)
if (DISPLAY_VER(display) >= 9)
skl_write_cursor_wm(dsb, plane, crtc_state);
if (plane_state)
@ -703,18 +710,18 @@ static void i9xx_cursor_update_arm(struct intel_dsb *dsb,
if (plane->cursor.base != base ||
plane->cursor.size != fbc_ctl ||
plane->cursor.cntl != cntl) {
if (HAS_CUR_FBC(dev_priv))
intel_de_write_dsb(display, dsb, CUR_FBC_CTL(dev_priv, pipe), fbc_ctl);
intel_de_write_dsb(display, dsb, CURCNTR(dev_priv, pipe), cntl);
intel_de_write_dsb(display, dsb, CURPOS(dev_priv, pipe), pos);
intel_de_write_dsb(display, dsb, CURBASE(dev_priv, pipe), base);
if (HAS_CUR_FBC(display))
intel_de_write_dsb(display, dsb, CUR_FBC_CTL(display, pipe), fbc_ctl);
intel_de_write_dsb(display, dsb, CURCNTR(display, pipe), cntl);
intel_de_write_dsb(display, dsb, CURPOS(display, pipe), pos);
intel_de_write_dsb(display, dsb, CURBASE(display, pipe), base);
plane->cursor.base = base;
plane->cursor.size = fbc_ctl;
plane->cursor.cntl = cntl;
} else {
intel_de_write_dsb(display, dsb, CURPOS(dev_priv, pipe), pos);
intel_de_write_dsb(display, dsb, CURBASE(dev_priv, pipe), base);
intel_de_write_dsb(display, dsb, CURPOS(display, pipe), pos);
intel_de_write_dsb(display, dsb, CURBASE(display, pipe), base);
}
}
@ -728,7 +735,7 @@ static void i9xx_cursor_disable_arm(struct intel_dsb *dsb,
static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
enum pipe *pipe)
{
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
struct intel_display *display = to_intel_display(plane);
enum intel_display_power_domain power_domain;
intel_wakeref_t wakeref;
bool ret;
@ -740,24 +747,45 @@ static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
* display power wells.
*/
power_domain = POWER_DOMAIN_PIPE(plane->pipe);
wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
wakeref = intel_display_power_get_if_enabled(display, power_domain);
if (!wakeref)
return false;
val = intel_de_read(dev_priv, CURCNTR(dev_priv, plane->pipe));
val = intel_de_read(display, CURCNTR(display, plane->pipe));
ret = val & MCURSOR_MODE_MASK;
if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv))
if (DISPLAY_VER(display) >= 5 || display->platform.g4x)
*pipe = plane->pipe;
else
*pipe = REG_FIELD_GET(MCURSOR_PIPE_SEL_MASK, val);
intel_display_power_put(dev_priv, power_domain, wakeref);
intel_display_power_put(display, power_domain, wakeref);
return ret;
}
static void g4x_cursor_capture_error(struct intel_crtc *crtc,
struct intel_plane *plane,
struct intel_plane_error *error)
{
struct intel_display *display = to_intel_display(plane);
error->ctl = intel_de_read(display, CURCNTR(display, crtc->pipe));
error->surf = intel_de_read(display, CURBASE(display, crtc->pipe));
error->surflive = intel_de_read(display, CURSURFLIVE(display, crtc->pipe));
}
static void i9xx_cursor_capture_error(struct intel_crtc *crtc,
struct intel_plane *plane,
struct intel_plane_error *error)
{
struct intel_display *display = to_intel_display(plane);
error->ctl = intel_de_read(display, CURCNTR(display, crtc->pipe));
error->surf = intel_de_read(display, CURBASE(display, crtc->pipe));
}
static bool intel_cursor_format_mod_supported(struct drm_plane *_plane,
u32 format, u64 modifier)
{
@ -790,7 +818,7 @@ intel_legacy_cursor_update(struct drm_plane *_plane,
{
struct intel_plane *plane = to_intel_plane(_plane);
struct intel_crtc *crtc = to_intel_crtc(_crtc);
struct drm_i915_private *i915 = to_i915(plane->base.dev);
struct intel_display *display = to_intel_display(plane);
struct intel_plane_state *old_plane_state =
to_intel_plane_state(plane->base.state);
struct intel_plane_state *new_plane_state;
@ -865,7 +893,7 @@ intel_legacy_cursor_update(struct drm_plane *_plane,
if (ret)
goto out_free;
ret = intel_plane_pin_fb(new_plane_state);
ret = intel_plane_pin_fb(new_plane_state, old_plane_state);
if (ret)
goto out_free;
@ -894,7 +922,7 @@ intel_legacy_cursor_update(struct drm_plane *_plane,
intel_psr_lock(crtc_state);
if (!drm_WARN_ON(&i915->drm, drm_crtc_vblank_get(&crtc->base))) {
if (!drm_WARN_ON(display->drm, drm_crtc_vblank_get(&crtc->base))) {
/*
* TODO: maybe check if we're still in PSR
* and skip the vblank evasion entirely?
@ -960,8 +988,8 @@ static const struct drm_plane_funcs intel_cursor_plane_funcs = {
static void intel_cursor_add_size_hints_property(struct intel_plane *plane)
{
struct drm_i915_private *i915 = to_i915(plane->base.dev);
const struct drm_mode_config *config = &i915->drm.mode_config;
struct intel_display *display = to_intel_display(plane);
const struct drm_mode_config *config = &display->drm->mode_config;
struct drm_plane_size_hint hints[4];
int size, max_size, num_hints = 0;
@ -969,7 +997,7 @@ static void intel_cursor_add_size_hints_property(struct intel_plane *plane)
/* for simplicity only enumerate the supported square+POT sizes */
for (size = 64; size <= max_size; size *= 2) {
if (drm_WARN_ON(&i915->drm, num_hints >= ARRAY_SIZE(hints)))
if (drm_WARN_ON(display->drm, num_hints >= ARRAY_SIZE(hints)))
break;
hints[num_hints].width = size;
@ -981,7 +1009,7 @@ static void intel_cursor_add_size_hints_property(struct intel_plane *plane)
}
struct intel_plane *
intel_cursor_plane_create(struct drm_i915_private *dev_priv,
intel_cursor_plane_create(struct intel_display *display,
enum pipe pipe)
{
struct intel_plane *cursor;
@ -997,7 +1025,7 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv,
cursor->id = PLANE_CURSOR;
cursor->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, cursor->id);
if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) {
if (display->platform.i845g || display->platform.i865g) {
cursor->max_stride = i845_cursor_max_stride;
cursor->min_alignment = i845_cursor_min_alignment;
cursor->update_arm = i845_cursor_update_arm;
@ -1007,28 +1035,36 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv,
} else {
cursor->max_stride = i9xx_cursor_max_stride;
if (IS_I830(dev_priv))
if (display->platform.i830)
cursor->min_alignment = i830_cursor_min_alignment;
else if (IS_I85X(dev_priv))
else if (display->platform.i85x)
cursor->min_alignment = i85x_cursor_min_alignment;
else
cursor->min_alignment = i9xx_cursor_min_alignment;
if (intel_scanout_needs_vtd_wa(display))
cursor->vtd_guard = 2;
cursor->update_arm = i9xx_cursor_update_arm;
cursor->disable_arm = i9xx_cursor_disable_arm;
cursor->get_hw_state = i9xx_cursor_get_hw_state;
cursor->check_plane = i9xx_check_cursor;
}
if (DISPLAY_VER(display) >= 5 || display->platform.g4x)
cursor->capture_error = g4x_cursor_capture_error;
else
cursor->capture_error = i9xx_cursor_capture_error;
cursor->cursor.base = ~0;
cursor->cursor.cntl = ~0;
if (IS_I845G(dev_priv) || IS_I865G(dev_priv) || HAS_CUR_FBC(dev_priv))
if (display->platform.i845g || display->platform.i865g || HAS_CUR_FBC(display))
cursor->cursor.size = ~0;
modifiers = intel_fb_plane_get_modifiers(dev_priv, INTEL_PLANE_CAP_NONE);
modifiers = intel_fb_plane_get_modifiers(display, INTEL_PLANE_CAP_NONE);
ret = drm_universal_plane_init(&dev_priv->drm, &cursor->base,
ret = drm_universal_plane_init(display->drm, &cursor->base,
0, &intel_cursor_plane_funcs,
intel_cursor_formats,
ARRAY_SIZE(intel_cursor_formats),
@ -1041,7 +1077,7 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv,
if (ret)
goto fail;
if (DISPLAY_VER(dev_priv) >= 4)
if (DISPLAY_VER(display) >= 4)
drm_plane_create_rotation_property(&cursor->base,
DRM_MODE_ROTATE_0,
DRM_MODE_ROTATE_0 |
@ -1049,10 +1085,10 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv,
intel_cursor_add_size_hints_property(cursor);
zpos = DISPLAY_RUNTIME_INFO(dev_priv)->num_sprites[pipe] + 1;
zpos = DISPLAY_RUNTIME_INFO(display)->num_sprites[pipe] + 1;
drm_plane_create_zpos_immutable_property(&cursor->base, zpos);
if (DISPLAY_VER(dev_priv) >= 12)
if (DISPLAY_VER(display) >= 12)
drm_plane_enable_fb_damage_clips(&cursor->base);
intel_plane_helper_add(cursor);

View File

@ -7,12 +7,12 @@
#define _INTEL_CURSOR_H_
enum pipe;
struct drm_i915_private;
struct intel_display;
struct intel_plane;
struct kthread_work;
struct intel_plane *
intel_cursor_plane_create(struct drm_i915_private *dev_priv,
intel_cursor_plane_create(struct intel_display *display,
enum pipe pipe);
void intel_cursor_unpin_work(struct kthread_work *base);

View File

@ -18,6 +18,7 @@
#include "intel_hdmi.h"
#include "intel_panel.h"
#include "intel_psr.h"
#include "intel_snps_hdmi_pll.h"
#include "intel_tc.h"
#define MB_WRITE_COMMITTED true
@ -33,13 +34,13 @@
bool intel_encoder_is_c10phy(struct intel_encoder *encoder)
{
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct intel_display *display = to_intel_display(encoder);
enum phy phy = intel_encoder_to_phy(encoder);
if (IS_PANTHERLAKE(i915) && phy == PHY_A)
if (display->platform.pantherlake && phy == PHY_A)
return true;
if ((IS_LUNARLAKE(i915) || IS_METEORLAKE(i915)) && phy < PHY_C)
if ((display->platform.lunarlake || display->platform.meteorlake) && phy < PHY_C)
return true;
return false;
@ -72,10 +73,9 @@ static u8 intel_cx0_get_owned_lane_mask(struct intel_encoder *encoder)
static void
assert_dc_off(struct intel_display *display)
{
struct drm_i915_private *i915 = to_i915(display->drm);
bool enabled;
enabled = intel_display_power_is_enabled(i915, POWER_DOMAIN_DC_OFF);
enabled = intel_display_power_is_enabled(display, POWER_DOMAIN_DC_OFF);
drm_WARN_ON(display->drm, !enabled);
}
@ -102,12 +102,12 @@ static void intel_cx0_program_msgbus_timer(struct intel_encoder *encoder)
*/
static intel_wakeref_t intel_cx0_phy_transaction_begin(struct intel_encoder *encoder)
{
intel_wakeref_t wakeref;
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct intel_display *display = to_intel_display(encoder);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
intel_wakeref_t wakeref;
intel_psr_pause(intel_dp);
wakeref = intel_display_power_get(i915, POWER_DOMAIN_DC_OFF);
wakeref = intel_display_power_get(display, POWER_DOMAIN_DC_OFF);
intel_cx0_program_msgbus_timer(encoder);
return wakeref;
@ -115,11 +115,11 @@ static intel_wakeref_t intel_cx0_phy_transaction_begin(struct intel_encoder *enc
static void intel_cx0_phy_transaction_end(struct intel_encoder *encoder, intel_wakeref_t wakeref)
{
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct intel_display *display = to_intel_display(encoder);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
intel_psr_resume(intel_dp);
intel_display_power_put(i915, POWER_DOMAIN_DC_OFF, wakeref);
intel_display_power_put(display, POWER_DOMAIN_DC_OFF, wakeref);
}
static void intel_clear_response_ready_flag(struct intel_encoder *encoder,
@ -2003,19 +2003,6 @@ static const struct intel_c20pll_state * const mtl_c20_hdmi_tables[] = {
NULL,
};
static int intel_c10_phy_check_hdmi_link_rate(int clock)
{
const struct intel_c10pll_state * const *tables = mtl_c10_hdmi_tables;
int i;
for (i = 0; tables[i]; i++) {
if (clock == tables[i]->clock)
return MODE_OK;
}
return MODE_CLOCK_RANGE;
}
static const struct intel_c10pll_state * const *
intel_c10pll_tables_get(struct intel_crtc_state *crtc_state,
struct intel_encoder *encoder)
@ -2033,21 +2020,25 @@ intel_c10pll_tables_get(struct intel_crtc_state *crtc_state,
return NULL;
}
static void intel_c10pll_update_pll(struct intel_crtc_state *crtc_state,
struct intel_encoder *encoder)
static void intel_cx0pll_update_ssc(struct intel_encoder *encoder,
struct intel_cx0pll_state *pll_state, bool is_dp)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_cx0pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll;
int i;
if (intel_crtc_has_dp_encoder(crtc_state)) {
if (is_dp) {
if (intel_panel_use_ssc(display)) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
pll_state->ssc_enabled =
(intel_dp->dpcd[DP_MAX_DOWNSPREAD] & DP_MAX_DOWNSPREAD_0_5);
}
}
}
static void intel_c10pll_update_pll(struct intel_encoder *encoder,
struct intel_cx0pll_state *pll_state)
{
struct intel_display *display = to_intel_display(encoder);
int i;
if (pll_state->ssc_enabled)
return;
@ -2057,21 +2048,19 @@ static void intel_c10pll_update_pll(struct intel_crtc_state *crtc_state,
pll_state->c10.pll[i] = 0;
}
static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state,
struct intel_encoder *encoder)
static int intel_c10pll_calc_state_from_table(struct intel_encoder *encoder,
const struct intel_c10pll_state * const *tables,
bool is_dp, int port_clock,
struct intel_cx0pll_state *pll_state)
{
const struct intel_c10pll_state * const *tables;
int i;
tables = intel_c10pll_tables_get(crtc_state, encoder);
if (!tables)
return -EINVAL;
for (i = 0; tables[i]; i++) {
if (crtc_state->port_clock == tables[i]->clock) {
crtc_state->dpll_hw_state.cx0pll.c10 = *tables[i];
intel_c10pll_update_pll(crtc_state, encoder);
crtc_state->dpll_hw_state.cx0pll.use_c10 = true;
if (port_clock == tables[i]->clock) {
pll_state->c10 = *tables[i];
intel_cx0pll_update_ssc(encoder, pll_state, is_dp);
intel_c10pll_update_pll(encoder, pll_state);
pll_state->use_c10 = true;
return 0;
}
@ -2080,6 +2069,34 @@ static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state,
return -EINVAL;
}
static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state,
struct intel_encoder *encoder)
{
const struct intel_c10pll_state * const *tables;
int err;
tables = intel_c10pll_tables_get(crtc_state, encoder);
if (!tables)
return -EINVAL;
err = intel_c10pll_calc_state_from_table(encoder, tables,
intel_crtc_has_dp_encoder(crtc_state),
crtc_state->port_clock,
&crtc_state->dpll_hw_state.cx0pll);
if (err == 0 || !intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
return err;
/* For HDMI PLLs try SNPS PHY algorithm, if there are no precomputed tables */
intel_snps_hdmi_pll_compute_c10pll(&crtc_state->dpll_hw_state.cx0pll.c10,
crtc_state->port_clock);
intel_c10pll_update_pll(encoder,
&crtc_state->dpll_hw_state.cx0pll);
crtc_state->dpll_hw_state.cx0pll.use_c10 = true;
return 0;
}
static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder,
struct intel_c10pll_state *pll_state)
{
@ -2107,10 +2124,9 @@ static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder,
}
static void intel_c10_pll_program(struct intel_display *display,
const struct intel_crtc_state *crtc_state,
struct intel_encoder *encoder)
struct intel_encoder *encoder,
const struct intel_c10pll_state *pll_state)
{
const struct intel_c10pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll.c10;
int i;
intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1),
@ -2173,9 +2189,47 @@ static void intel_c10pll_dump_hw_state(struct intel_display *display,
i + 2, hw_state->pll[i + 2], i + 3, hw_state->pll[i + 3]);
}
static int intel_c20_compute_hdmi_tmds_pll(struct intel_crtc_state *crtc_state)
/*
* Some ARLs SoCs have the same drm PCI IDs, so need a helper to differentiate based
* on the host bridge device ID to get the correct txx_mics value.
*/
static bool is_arrowlake_s_by_host_bridge(void)
{
struct pci_dev *pdev = NULL;
u16 host_bridge_pci_dev_id;
while ((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST << 8, pdev)))
host_bridge_pci_dev_id = pdev->device;
return pdev && IS_ARROWLAKE_S_BY_HOST_BRIDGE_ID(host_bridge_pci_dev_id);
}
static u16 intel_c20_hdmi_tmds_tx_cgf_1(struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
u16 tx_misc;
u16 tx_dcc_cal_dac_ctrl_range = 8;
u16 tx_term_ctrl = 2;
if (DISPLAY_VER(display) >= 20) {
tx_misc = 5;
tx_term_ctrl = 4;
} else if (display->platform.battlemage) {
tx_misc = 0;
} else if (display->platform.meteorlake_u ||
is_arrowlake_s_by_host_bridge()) {
tx_misc = 3;
} else {
tx_misc = 7;
}
return (C20_PHY_TX_MISC(tx_misc) |
C20_PHY_TX_DCC_CAL_RANGE(tx_dcc_cal_dac_ctrl_range) |
C20_PHY_TX_DCC_BYPASS | C20_PHY_TX_TERM_CTL(tx_term_ctrl));
}
static int intel_c20_compute_hdmi_tmds_pll(struct intel_crtc_state *crtc_state)
{
struct intel_c20pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll.c20;
u64 datarate;
u64 mpll_tx_clk_div;
@ -2185,7 +2239,6 @@ static int intel_c20_compute_hdmi_tmds_pll(struct intel_crtc_state *crtc_state)
u64 mpll_multiplier;
u64 mpll_fracn_quot;
u64 mpll_fracn_rem;
u16 tx_misc;
u8 mpllb_ana_freq_vco;
u8 mpll_div_multiplier;
@ -2205,11 +2258,6 @@ static int intel_c20_compute_hdmi_tmds_pll(struct intel_crtc_state *crtc_state)
mpll_div_multiplier = min_t(u8, div64_u64((vco_freq * 16 + (datarate >> 1)),
datarate), 255);
if (DISPLAY_VER(display) >= 20)
tx_misc = 0x5;
else
tx_misc = 0x0;
if (vco_freq <= DATARATE_3000000000)
mpllb_ana_freq_vco = MPLLB_ANA_FREQ_VCO_3;
else if (vco_freq <= DATARATE_3500000000)
@ -2221,7 +2269,7 @@ static int intel_c20_compute_hdmi_tmds_pll(struct intel_crtc_state *crtc_state)
pll_state->clock = crtc_state->port_clock;
pll_state->tx[0] = 0xbe88;
pll_state->tx[1] = 0x9800 | C20_PHY_TX_MISC(tx_misc);
pll_state->tx[1] = intel_c20_hdmi_tmds_tx_cgf_1(crtc_state);
pll_state->tx[2] = 0x0000;
pll_state->cmn[0] = 0x0500;
pll_state->cmn[1] = 0x0005;
@ -2249,31 +2297,6 @@ static int intel_c20_compute_hdmi_tmds_pll(struct intel_crtc_state *crtc_state)
return 0;
}
static int intel_c20_phy_check_hdmi_link_rate(int clock)
{
const struct intel_c20pll_state * const *tables = mtl_c20_hdmi_tables;
int i;
for (i = 0; tables[i]; i++) {
if (clock == tables[i]->clock)
return MODE_OK;
}
if (clock >= 25175 && clock <= 594000)
return MODE_OK;
return MODE_CLOCK_RANGE;
}
int intel_cx0_phy_check_hdmi_link_rate(struct intel_hdmi *hdmi, int clock)
{
struct intel_digital_port *dig_port = hdmi_to_dig_port(hdmi);
if (intel_encoder_is_c10phy(&dig_port->base))
return intel_c10_phy_check_hdmi_link_rate(clock);
return intel_c20_phy_check_hdmi_link_rate(clock);
}
static const struct intel_c20pll_state * const *
intel_c20_pll_tables_get(struct intel_crtc_state *crtc_state,
struct intel_encoder *encoder)
@ -2322,6 +2345,9 @@ static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state,
for (i = 0; tables[i]; i++) {
if (crtc_state->port_clock == tables[i]->clock) {
crtc_state->dpll_hw_state.cx0pll.c20 = *tables[i];
intel_cx0pll_update_ssc(encoder,
&crtc_state->dpll_hw_state.cx0pll,
intel_crtc_has_dp_encoder(crtc_state));
crtc_state->dpll_hw_state.cx0pll.use_c10 = false;
return 0;
}
@ -2587,19 +2613,14 @@ static int intel_get_c20_custom_width(u32 clock, bool dp)
}
static void intel_c20_pll_program(struct intel_display *display,
const struct intel_crtc_state *crtc_state,
struct intel_encoder *encoder)
struct intel_encoder *encoder,
const struct intel_c20pll_state *pll_state,
bool is_dp, int port_clock)
{
const struct intel_c20pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll.c20;
bool dp = false;
u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(encoder);
u32 clock = crtc_state->port_clock;
bool cntx;
int i;
if (intel_crtc_has_dp_encoder(crtc_state))
dp = true;
/* 1. Read current context selection */
cntx = intel_cx0_read(encoder, INTEL_CX0_LANE0, PHY_C20_VDR_CUSTOM_SERDES_RATE) & BIT(0);
@ -2667,23 +2688,23 @@ static void intel_c20_pll_program(struct intel_display *display,
/* 4. Program custom width to match the link protocol */
intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_WIDTH,
PHY_C20_CUSTOM_WIDTH_MASK,
PHY_C20_CUSTOM_WIDTH(intel_get_c20_custom_width(clock, dp)),
PHY_C20_CUSTOM_WIDTH(intel_get_c20_custom_width(port_clock, is_dp)),
MB_WRITE_COMMITTED);
/* 5. For DP or 6. For HDMI */
if (dp) {
if (is_dp) {
intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_SERDES_RATE,
BIT(6) | PHY_C20_CUSTOM_SERDES_MASK,
BIT(6) | PHY_C20_CUSTOM_SERDES(intel_c20_get_dp_rate(clock)),
BIT(6) | PHY_C20_CUSTOM_SERDES(intel_c20_get_dp_rate(port_clock)),
MB_WRITE_COMMITTED);
} else {
intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_SERDES_RATE,
BIT(7) | PHY_C20_CUSTOM_SERDES_MASK,
is_hdmi_frl(clock) ? BIT(7) : 0,
is_hdmi_frl(port_clock) ? BIT(7) : 0,
MB_WRITE_COMMITTED);
intel_cx0_write(encoder, INTEL_CX0_BOTH_LANES, PHY_C20_VDR_HDMI_RATE,
intel_c20_get_hdmi_rate(clock),
intel_c20_get_hdmi_rate(port_clock),
MB_WRITE_COMMITTED);
}
@ -2723,7 +2744,8 @@ static int intel_c10pll_calc_port_clock(struct intel_encoder *encoder,
}
static void intel_program_port_clock_ctl(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
const struct intel_cx0pll_state *pll_state,
bool is_dp, int port_clock,
bool lane_reversal)
{
struct intel_display *display = to_intel_display(encoder);
@ -2738,18 +2760,17 @@ static void intel_program_port_clock_ctl(struct intel_encoder *encoder,
val |= XELPDP_FORWARD_CLOCK_UNGATE;
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) &&
is_hdmi_frl(crtc_state->port_clock))
if (!is_dp && is_hdmi_frl(port_clock))
val |= XELPDP_DDI_CLOCK_SELECT(XELPDP_DDI_CLOCK_SELECT_DIV18CLK);
else
val |= XELPDP_DDI_CLOCK_SELECT(XELPDP_DDI_CLOCK_SELECT_MAXPCLK);
/* TODO: HDMI FRL */
/* DP2.0 10G and 20G rates enable MPLLA*/
if (crtc_state->port_clock == 1000000 || crtc_state->port_clock == 2000000)
val |= crtc_state->dpll_hw_state.cx0pll.ssc_enabled ? XELPDP_SSC_ENABLE_PLLA : 0;
if (port_clock == 1000000 || port_clock == 2000000)
val |= pll_state->ssc_enabled ? XELPDP_SSC_ENABLE_PLLA : 0;
else
val |= crtc_state->dpll_hw_state.cx0pll.ssc_enabled ? XELPDP_SSC_ENABLE_PLLB : 0;
val |= pll_state->ssc_enabled ? XELPDP_SSC_ENABLE_PLLB : 0;
intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port),
XELPDP_LANE1_PHY_CLOCK_SELECT | XELPDP_FORWARD_CLOCK_UNGATE |
@ -2979,8 +3000,9 @@ static u32 intel_cx0_get_pclk_pll_ack(u8 lane_mask)
return val;
}
static void intel_cx0pll_enable(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
static void __intel_cx0pll_enable(struct intel_encoder *encoder,
const struct intel_cx0pll_state *pll_state,
bool is_dp, int port_clock, int lane_count)
{
struct intel_display *display = to_intel_display(encoder);
enum phy phy = intel_encoder_to_phy(encoder);
@ -2994,7 +3016,7 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder,
* 1. Program PORT_CLOCK_CTL REGISTER to configure
* clock muxes, gating and SSC
*/
intel_program_port_clock_ctl(encoder, crtc_state, lane_reversal);
intel_program_port_clock_ctl(encoder, pll_state, is_dp, port_clock, lane_reversal);
/* 2. Bring PHY out of reset. */
intel_cx0_phy_lane_reset(encoder, lane_reversal);
@ -3014,15 +3036,15 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder,
/* 5. Program PHY internal PLL internal registers. */
if (intel_encoder_is_c10phy(encoder))
intel_c10_pll_program(display, crtc_state, encoder);
intel_c10_pll_program(display, encoder, &pll_state->c10);
else
intel_c20_pll_program(display, crtc_state, encoder);
intel_c20_pll_program(display, encoder, &pll_state->c20, is_dp, port_clock);
/*
* 6. Program the enabled and disabled owned PHY lane
* transmitters over message bus
*/
intel_cx0_program_phy_lane(encoder, crtc_state->lane_count, lane_reversal);
intel_cx0_program_phy_lane(encoder, lane_count, lane_reversal);
/*
* 7. Follow the Display Voltage Frequency Switching - Sequence
@ -3033,8 +3055,7 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder,
* 8. Program DDI_CLK_VALFREQ to match intended DDI
* clock frequency.
*/
intel_de_write(display, DDI_CLK_VALFREQ(encoder->port),
crtc_state->port_clock);
intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), port_clock);
/*
* 9. Set PORT_CLOCK_CTL register PCLK PLL Request
@ -3061,6 +3082,14 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder,
intel_cx0_phy_transaction_end(encoder, wakeref);
}
static void intel_cx0pll_enable(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
__intel_cx0pll_enable(encoder, &crtc_state->dpll_hw_state.cx0pll,
intel_crtc_has_dp_encoder(crtc_state),
crtc_state->port_clock, crtc_state->lane_count);
}
int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder);
@ -3203,12 +3232,11 @@ void intel_mtl_pll_enable(struct intel_encoder *encoder,
static u8 cx0_power_control_disable_val(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
if (intel_encoder_is_c10phy(encoder))
return CX0_P2PG_STATE_DISABLE;
if ((IS_BATTLEMAGE(i915) && encoder->port == PORT_A) ||
if ((display->platform.battlemage && encoder->port == PORT_A) ||
(DISPLAY_VER(display) >= 30 && encoder->type == INTEL_OUTPUT_EDP))
return CX0_P2PG_STATE_DISABLE;
@ -3266,6 +3294,16 @@ static void intel_cx0pll_disable(struct intel_encoder *encoder)
intel_cx0_phy_transaction_end(encoder, wakeref);
}
static bool intel_cx0_pll_is_enabled(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
u8 lane = dig_port->lane_reversal ? INTEL_CX0_LANE1 : INTEL_CX0_LANE0;
return intel_de_read(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port)) &
intel_cx0_get_pclk_pll_request(lane);
}
static void intel_mtl_tbt_pll_disable(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder);
@ -3527,3 +3565,54 @@ void intel_cx0pll_state_verify(struct intel_atomic_state *state,
else
intel_c20pll_state_verify(new_crtc_state, crtc, encoder, &mpll_hw_state.c20);
}
/*
* WA 14022081154
* The dedicated display PHYs reset to a power state that blocks S0ix, increasing idle
* system power. After a system reset (cold boot, S3/4/5, warm reset) if a dedicated
* PHY is not being brought up shortly, use these steps to move the PHY to the lowest
* power state to save power. For PTL the workaround is needed only for port A. Port B
* is not connected.
*
* 1. Follow the PLL Enable Sequence, using any valid frequency such as DP 1.62 GHz.
* This brings lanes out of reset and enables the PLL to allow powerdown to be moved
* to the Disable state.
* 2. Follow PLL Disable Sequence. This moves powerdown to the Disable state and disables the PLL.
*/
void intel_cx0_pll_power_save_wa(struct intel_display *display)
{
struct intel_encoder *encoder;
if (DISPLAY_VER(display) != 30)
return;
for_each_intel_encoder(display->drm, encoder) {
struct intel_cx0pll_state pll_state = {};
int port_clock = 162000;
if (!intel_encoder_is_dig_port(encoder))
continue;
if (!intel_encoder_is_c10phy(encoder))
continue;
if (intel_cx0_pll_is_enabled(encoder))
continue;
if (intel_c10pll_calc_state_from_table(encoder,
mtl_c10_edp_tables,
true, port_clock,
&pll_state) < 0) {
drm_WARN_ON(display->drm,
"Unable to calc C10 state from the tables\n");
continue;
}
drm_dbg_kms(display->drm,
"[ENCODER:%d:%s] Applying power saving workaround on disabled PLL\n",
encoder->base.base.id, encoder->base.name);
__intel_cx0pll_enable(encoder, &pll_state, true, port_clock, 4);
intel_cx0pll_disable(encoder);
}
}

View File

@ -41,7 +41,7 @@ bool intel_cx0pll_compare_hw_state(const struct intel_cx0pll_state *a,
const struct intel_cx0pll_state *b);
void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
int intel_cx0_phy_check_hdmi_link_rate(struct intel_hdmi *hdmi, int clock);
int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder);
void intel_cx0_pll_power_save_wa(struct intel_display *display);
#endif /* __INTEL_CX0_PHY_H__ */

View File

@ -110,7 +110,8 @@
#define XELPDP_TCSS_POWER_REQUEST REG_BIT(5)
#define XELPDP_TCSS_POWER_STATE REG_BIT(4)
#define XELPDP_PORT_WIDTH_MASK REG_GENMASK(3, 1)
#define XELPDP_PORT_WIDTH(val) REG_FIELD_PREP(XELPDP_PORT_WIDTH_MASK, val)
#define XELPDP_PORT_WIDTH(width) REG_FIELD_PREP(XELPDP_PORT_WIDTH_MASK, \
((width) == 3 ? 4 : (width) - 1))
#define _XELPDP_PORT_BUF_CTL2(idx) _MMIO(_PICK_EVEN_2RANGES(idx, PORT_TC1, \
_XELPDP_PORT_BUF_CTL1_LN0_A, \
@ -218,10 +219,34 @@
/* C10 Vendor Registers */
#define PHY_C10_VDR_PLL(idx) (0xC00 + (idx))
#define C10_PLL0_SSC_EN REG_BIT8(0)
#define C10_PLL0_DIVCLK_EN REG_BIT8(1)
#define C10_PLL0_DIV5CLK_EN REG_BIT8(2)
#define C10_PLL0_WORDDIV2_EN REG_BIT8(3)
#define C10_PLL0_FRACEN REG_BIT8(4)
#define C10_PLL0_PMIX_EN REG_BIT8(5)
#define C10_PLL0_ANA_FREQ_VCO_MASK REG_GENMASK8(7, 6)
#define C10_PLL1_DIV_MULTIPLIER_MASK REG_GENMASK8(7, 0)
#define C10_PLL2_MULTIPLIERL_MASK REG_GENMASK8(7, 0)
#define C10_PLL3_MULTIPLIERH_MASK REG_GENMASK8(3, 0)
#define C10_PLL8_SSC_UP_SPREAD REG_BIT8(5)
#define C10_PLL9_FRACN_DENL_MASK REG_GENMASK8(7, 0)
#define C10_PLL10_FRACN_DENH_MASK REG_GENMASK8(7, 0)
#define C10_PLL11_FRACN_QUOT_L_MASK REG_GENMASK8(7, 0)
#define C10_PLL12_FRACN_QUOT_H_MASK REG_GENMASK8(7, 0)
#define C10_PLL13_FRACN_REM_L_MASK REG_GENMASK8(7, 0)
#define C10_PLL14_FRACN_REM_H_MASK REG_GENMASK8(7, 0)
#define C10_PLL15_TXCLKDIV_MASK REG_GENMASK8(2, 0)
#define C10_PLL15_HDMIDIV_MASK REG_GENMASK8(5, 3)
#define C10_PLL15_PIXELCLKDIV_MASK REG_GENMASK8(7, 6)
#define C10_PLL16_ANA_CPINT REG_GENMASK8(6, 0)
#define C10_PLL16_ANA_CPINTGS_L REG_BIT8(7)
#define C10_PLL17_ANA_CPINTGS_H_MASK REG_GENMASK8(5, 0)
#define C10_PLL17_ANA_CPPROP_L_MASK REG_GENMASK8(7, 6)
#define C10_PLL18_ANA_CPPROP_H_MASK REG_GENMASK8(4, 0)
#define C10_PLL18_ANA_CPPROPGS_L_MASK REG_GENMASK8(7, 5)
#define C10_PLL19_ANA_CPPROPGS_H_MASK REG_GENMASK8(3, 0)
#define C10_PLL19_ANA_V2I_MASK REG_GENMASK8(5, 4)
#define PHY_C10_VDR_CMN(idx) (0xC20 + (idx))
#define C10_CMN0_REF_RANGE REG_FIELD_PREP(REG_GENMASK(4, 0), 1)
@ -298,6 +323,12 @@
#define C20_PHY_TX_RATE REG_GENMASK(2, 0)
#define C20_PHY_TX_MISC_MASK REG_GENMASK16(7, 0)
#define C20_PHY_TX_MISC(val) REG_FIELD_PREP16(C20_PHY_TX_MISC_MASK, (val))
#define C20_PHY_TX_DCC_CAL_RANGE_MASK REG_GENMASK16(11, 8)
#define C20_PHY_TX_DCC_CAL_RANGE(val) \
REG_FIELD_PREP16(C20_PHY_TX_DCC_CAL_RANGE_MASK, (val))
#define C20_PHY_TX_DCC_BYPASS REG_BIT(12)
#define C20_PHY_TX_TERM_CTL_MASK REG_GENMASK16(15, 13)
#define C20_PHY_TX_TERM_CTL(val) REG_FIELD_PREP16(C20_PHY_TX_TERM_CTL_MASK, (val))
#define PHY_C20_A_CMN_CNTX_CFG(i915, idx) \
((_IS_XE2HPD_C20(i915) ? _XE2HPD_C20_A_CMN_CNTX_CFG : _MTL_C20_A_CMN_CNTX_CFG) - (idx))

File diff suppressed because it is too large Load Diff

View File

@ -3,13 +3,13 @@
* Copyright © 2020 Intel Corporation
*/
#include "i915_drv.h"
#include "i915_utils.h"
#include "intel_cx0_phy.h"
#include "intel_ddi.h"
#include "intel_ddi_buf_trans.h"
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_cx0_phy.h"
/* HDMI/DVI modes ignore everything but the last 2 items. So we share
* them for both DP and FDI transports, allowing those ports to
@ -1407,10 +1407,10 @@ tgl_get_combo_buf_trans_dp(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_display *display = to_intel_display(encoder);
if (crtc_state->port_clock > 270000) {
if (IS_TIGERLAKE_UY(dev_priv)) {
if (display->platform.tigerlake_uy) {
return intel_get_buf_trans(&tgl_uy_combo_phy_trans_dp_hbr2,
n_entries);
} else {
@ -1709,59 +1709,67 @@ mtl_get_c20_buf_trans(struct intel_encoder *encoder,
void intel_ddi_buf_trans_init(struct intel_encoder *encoder)
{
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct intel_display *display = to_intel_display(encoder);
if (DISPLAY_VER(i915) >= 14) {
if (DISPLAY_VER(display) >= 14) {
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)) {
} else if (display->platform.dg2) {
encoder->get_buf_trans = dg2_get_snps_buf_trans;
} else if (IS_ALDERLAKE_P(i915)) {
} else if (display->platform.alderlake_p) {
if (intel_encoder_is_combo(encoder))
encoder->get_buf_trans = adlp_get_combo_buf_trans;
else
encoder->get_buf_trans = adlp_get_dkl_buf_trans;
} else if (IS_ALDERLAKE_S(i915)) {
} else if (display->platform.alderlake_s) {
encoder->get_buf_trans = adls_get_combo_buf_trans;
} else if (IS_ROCKETLAKE(i915)) {
} else if (display->platform.rocketlake) {
encoder->get_buf_trans = rkl_get_combo_buf_trans;
} else if (IS_DG1(i915)) {
} else if (display->platform.dg1) {
encoder->get_buf_trans = dg1_get_combo_buf_trans;
} else if (DISPLAY_VER(i915) >= 12) {
} else if (DISPLAY_VER(display) >= 12) {
if (intel_encoder_is_combo(encoder))
encoder->get_buf_trans = tgl_get_combo_buf_trans;
else
encoder->get_buf_trans = tgl_get_dkl_buf_trans;
} else if (DISPLAY_VER(i915) == 11) {
if (IS_JASPERLAKE(i915))
} else if (DISPLAY_VER(display) == 11) {
if (display->platform.jasperlake)
encoder->get_buf_trans = jsl_get_combo_buf_trans;
else if (IS_ELKHARTLAKE(i915))
else if (display->platform.elkhartlake)
encoder->get_buf_trans = ehl_get_combo_buf_trans;
else if (intel_encoder_is_combo(encoder))
encoder->get_buf_trans = icl_get_combo_buf_trans;
else
encoder->get_buf_trans = icl_get_mg_buf_trans;
} else if (IS_GEMINILAKE(i915) || IS_BROXTON(i915)) {
} else if (display->platform.geminilake || display->platform.broxton) {
encoder->get_buf_trans = bxt_get_buf_trans;
} else if (IS_COMETLAKE_ULX(i915) || IS_COFFEELAKE_ULX(i915) || IS_KABYLAKE_ULX(i915)) {
} else if (display->platform.cometlake_ulx ||
display->platform.coffeelake_ulx ||
display->platform.kabylake_ulx) {
encoder->get_buf_trans = kbl_y_get_buf_trans;
} else if (IS_COMETLAKE_ULT(i915) || IS_COFFEELAKE_ULT(i915) || IS_KABYLAKE_ULT(i915)) {
} else if (display->platform.cometlake_ult ||
display->platform.coffeelake_ult ||
display->platform.kabylake_ult) {
encoder->get_buf_trans = kbl_u_get_buf_trans;
} else if (IS_COMETLAKE(i915) || IS_COFFEELAKE(i915) || IS_KABYLAKE(i915)) {
} else if (display->platform.cometlake ||
display->platform.coffeelake ||
display->platform.kabylake) {
encoder->get_buf_trans = kbl_get_buf_trans;
} else if (IS_SKYLAKE_ULX(i915)) {
} else if (display->platform.skylake_ulx) {
encoder->get_buf_trans = skl_y_get_buf_trans;
} else if (IS_SKYLAKE_ULT(i915)) {
} else if (display->platform.skylake_ult) {
encoder->get_buf_trans = skl_u_get_buf_trans;
} else if (IS_SKYLAKE(i915)) {
} else if (display->platform.skylake) {
encoder->get_buf_trans = skl_get_buf_trans;
} else if (IS_BROADWELL(i915)) {
} else if (display->platform.broadwell) {
encoder->get_buf_trans = bdw_get_buf_trans;
} else if (IS_HASWELL(i915)) {
} else if (display->platform.haswell) {
encoder->get_buf_trans = hsw_get_buf_trans;
} else {
MISSING_CASE(INTEL_INFO(i915)->platform);
struct pci_dev *pdev = to_pci_dev(display->drm->dev);
MISSING_CASE(pdev->device);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -59,8 +59,6 @@ struct intel_link_m_n;
struct intel_plane;
struct intel_plane_state;
struct intel_power_domain_mask;
struct intel_remapped_info;
struct intel_rotation_info;
struct pci_dev;
struct work_struct;
@ -413,22 +411,20 @@ enum phy_fia {
i)
int intel_atomic_check(struct drm_device *dev, struct drm_atomic_state *state);
int intel_atomic_add_affected_planes(struct intel_atomic_state *state,
struct intel_crtc *crtc);
u8 intel_calc_active_pipes(struct intel_atomic_state *state,
u8 active_pipes);
void intel_link_compute_m_n(u16 bpp, int nlanes,
int pixel_clock, int link_clock,
int bw_overhead,
struct intel_link_m_n *m_n);
u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv,
u32 intel_plane_fb_max_stride(struct drm_device *drm,
u32 pixel_format, u64 modifier);
enum drm_mode_status
intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
intel_mode_valid_max_plane_size(struct intel_display *display,
const struct drm_display_mode *mode,
int num_joined_pipes);
enum drm_mode_status
intel_cpu_transcoder_mode_valid(struct drm_i915_private *i915,
intel_cpu_transcoder_mode_valid(struct intel_display *display,
const struct drm_display_mode *mode);
enum phy intel_port_to_phy(struct drm_i915_private *i915, enum port port);
bool is_trans_port_sync_mode(const struct intel_crtc_state *state);
@ -450,7 +446,6 @@ bool intel_pipe_config_compare(const struct intel_crtc_state *current_config,
const struct intel_crtc_state *pipe_config,
bool fastset);
void intel_plane_destroy(struct drm_plane *plane);
void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state);
void ilk_set_pipeconf(const struct intel_crtc_state *crtc_state);
void intel_enable_transcoder(const struct intel_crtc_state *new_crtc_state);
@ -463,20 +458,13 @@ int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
const char *name, u32 reg);
void intel_init_display_hooks(struct drm_i915_private *dev_priv);
unsigned int intel_fb_xy_to_linear(int x, int y,
const struct intel_plane_state *state,
int plane);
void intel_add_fb_offsets(int *x, int *y,
const struct intel_plane_state *state, int plane);
unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info);
unsigned int intel_remapped_info_size(const struct intel_remapped_info *rem_info);
bool intel_has_pending_fb_unpin(struct drm_i915_private *dev_priv);
void intel_encoder_destroy(struct drm_encoder *encoder);
struct drm_display_mode *
intel_encoder_current_mode(struct intel_encoder *encoder);
void intel_encoder_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state);
bool intel_phy_is_combo(struct drm_i915_private *dev_priv, enum phy phy);
bool intel_phy_is_combo(struct intel_display *display, enum phy phy);
bool intel_phy_is_tc(struct drm_i915_private *dev_priv, enum phy phy);
bool intel_phy_is_snps(struct drm_i915_private *dev_priv, enum phy phy);
enum tc_port intel_port_to_tc(struct drm_i915_private *dev_priv,
@ -489,9 +477,6 @@ bool intel_encoder_is_tc(struct intel_encoder *encoder);
enum tc_port intel_encoder_to_tc(struct intel_encoder *encoder);
int ilk_get_lanes_required(int target_clock, int link_bw, int bpp);
void vlv_wait_port_ready(struct intel_display *display,
struct intel_digital_port *dig_port,
unsigned int expected_mask);
bool intel_fuzzy_clock_check(int clock1, int clock2);
@ -530,8 +515,6 @@ void ilk_pfit_disable(const struct intel_crtc_state *old_crtc_state);
int bdw_get_pipe_misc_bpp(struct intel_crtc *crtc);
unsigned int intel_plane_fence_y_offset(const struct intel_plane_state *plane_state);
bool intel_plane_uses_fence(const struct intel_plane_state *plane_state);
struct intel_encoder *
intel_get_crtc_new_encoder(const struct intel_atomic_state *state,
const struct intel_crtc_state *crtc_state);
@ -571,15 +554,13 @@ enum drm_mode_status intel_mode_valid(struct drm_device *dev,
int intel_atomic_commit(struct drm_device *dev, struct drm_atomic_state *_state,
bool nonblock);
void intel_hpd_poll_fini(struct drm_i915_private *i915);
/* modesetting asserts */
void assert_transcoder(struct drm_i915_private *dev_priv,
void assert_transcoder(struct intel_display *display,
enum transcoder cpu_transcoder, bool state);
#define assert_transcoder_enabled(d, t) assert_transcoder(d, t, true)
#define assert_transcoder_disabled(d, t) assert_transcoder(d, t, false)
bool assert_port_valid(struct drm_i915_private *i915, enum port port);
bool assert_port_valid(struct intel_display *display, enum port port);
/*
* Use INTEL_DISPLAY_STATE_WARN(x) (rather than WARN() and WARN_ON()) for hw
@ -596,7 +577,7 @@ bool assert_port_valid(struct drm_i915_private *i915, enum port port);
unlikely(__ret_warn_on); \
})
bool intel_scanout_needs_vtd_wa(struct drm_i915_private *i915);
bool intel_scanout_needs_vtd_wa(struct intel_display *display);
int intel_crtc_num_joined_pipes(const struct intel_crtc_state *crtc_state);
#endif

View File

@ -68,17 +68,17 @@ static int intel_display_caps(struct seq_file *m, void *data)
static int i915_frontbuffer_tracking(struct seq_file *m, void *unused)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
struct intel_display *display = node_to_intel_display(m->private);
spin_lock(&dev_priv->display.fb_tracking.lock);
spin_lock(&display->fb_tracking.lock);
seq_printf(m, "FB tracking busy bits: 0x%08x\n",
dev_priv->display.fb_tracking.busy_bits);
display->fb_tracking.busy_bits);
seq_printf(m, "FB tracking flip bits: 0x%08x\n",
dev_priv->display.fb_tracking.flip_bits);
display->fb_tracking.flip_bits);
spin_unlock(&dev_priv->display.fb_tracking.lock);
spin_unlock(&display->fb_tracking.lock);
return 0;
}
@ -86,26 +86,27 @@ static int i915_frontbuffer_tracking(struct seq_file *m, void *unused)
static int i915_sr_status(struct seq_file *m, void *unused)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
struct intel_display *display = node_to_intel_display(m->private);
intel_wakeref_t wakeref;
bool sr_enabled = false;
wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
wakeref = intel_display_power_get(display, POWER_DOMAIN_INIT);
if (DISPLAY_VER(dev_priv) >= 9)
if (DISPLAY_VER(display) >= 9)
/* no global SR status; inspect per-plane WM */;
else if (HAS_PCH_SPLIT(dev_priv))
sr_enabled = intel_de_read(dev_priv, WM1_LP_ILK) & WM_LP_ENABLE;
else if (IS_I965GM(dev_priv) || IS_G4X(dev_priv) ||
IS_I945G(dev_priv) || IS_I945GM(dev_priv))
sr_enabled = intel_de_read(dev_priv, FW_BLC_SELF) & FW_BLC_SELF_EN;
else if (IS_I915GM(dev_priv))
sr_enabled = intel_de_read(dev_priv, INSTPM) & INSTPM_SELF_EN;
else if (IS_PINEVIEW(dev_priv))
sr_enabled = intel_de_read(dev_priv, DSPFW3(dev_priv)) & PINEVIEW_SELF_REFRESH_EN;
else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
sr_enabled = intel_de_read(dev_priv, FW_BLC_SELF_VLV) & FW_CSPWRDWNEN;
sr_enabled = intel_de_read(display, WM1_LP_ILK) & WM_LP_ENABLE;
else if (display->platform.i965gm || display->platform.g4x ||
display->platform.i945g || display->platform.i945gm)
sr_enabled = intel_de_read(display, FW_BLC_SELF) & FW_BLC_SELF_EN;
else if (display->platform.i915gm)
sr_enabled = intel_de_read(display, INSTPM) & INSTPM_SELF_EN;
else if (display->platform.pineview)
sr_enabled = intel_de_read(display, DSPFW3(dev_priv)) & PINEVIEW_SELF_REFRESH_EN;
else if (display->platform.valleyview || display->platform.cherryview)
sr_enabled = intel_de_read(display, FW_BLC_SELF_VLV) & FW_CSPWRDWNEN;
intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, wakeref);
intel_display_power_put(display, POWER_DOMAIN_INIT, wakeref);
seq_printf(m, "self-refresh: %s\n", str_enabled_disabled(sr_enabled));
@ -114,12 +115,12 @@ static int i915_sr_status(struct seq_file *m, void *unused)
static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
struct intel_display *display = node_to_intel_display(m->private);
struct intel_framebuffer *fbdev_fb = NULL;
struct drm_framebuffer *drm_fb;
#ifdef CONFIG_DRM_FBDEV_EMULATION
fbdev_fb = intel_fbdev_framebuffer(dev_priv->display.fbdev.fbdev);
fbdev_fb = intel_fbdev_framebuffer(display->fbdev.fbdev);
if (fbdev_fb) {
seq_printf(m, "fbcon size: %d x %d, depth %d, %d bpp, modifier 0x%llx, refcount %d, obj ",
fbdev_fb->base.width,
@ -133,8 +134,8 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
}
#endif
mutex_lock(&dev_priv->drm.mode_config.fb_lock);
drm_for_each_fb(drm_fb, &dev_priv->drm) {
mutex_lock(&display->drm->mode_config.fb_lock);
drm_for_each_fb(drm_fb, display->drm) {
struct intel_framebuffer *fb = to_intel_framebuffer(drm_fb);
if (fb == fbdev_fb)
continue;
@ -149,7 +150,7 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
intel_bo_describe(m, intel_fb_bo(&fb->base));
seq_putc(m, '\n');
}
mutex_unlock(&dev_priv->drm.mode_config.fb_lock);
mutex_unlock(&display->drm->mode_config.fb_lock);
return 0;
}
@ -157,8 +158,9 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
static int i915_power_domain_info(struct seq_file *m, void *unused)
{
struct drm_i915_private *i915 = node_to_i915(m->private);
struct intel_display *display = &i915->display;
intel_display_power_debug(i915, m);
intel_display_power_debug(display, m);
return 0;
}
@ -178,14 +180,14 @@ static void intel_encoder_info(struct seq_file *m,
struct intel_crtc *crtc,
struct intel_encoder *encoder)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
struct intel_display *display = node_to_intel_display(m->private);
struct drm_connector_list_iter conn_iter;
struct drm_connector *connector;
seq_printf(m, "\t[ENCODER:%d:%s]: connectors:\n",
encoder->base.base.id, encoder->base.name);
drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
drm_connector_list_iter_begin(display->drm, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter) {
const struct drm_connector_state *conn_state =
connector->state;
@ -213,38 +215,6 @@ static void intel_panel_info(struct seq_file *m,
intel_seq_print_mode(m, 2, fixed_mode);
}
static void intel_hdcp_info(struct seq_file *m,
struct intel_connector *intel_connector,
bool remote_req)
{
bool hdcp_cap = false, hdcp2_cap = false;
if (!intel_connector->hdcp.shim) {
seq_puts(m, "No Connector Support");
goto out;
}
if (remote_req) {
intel_hdcp_get_remote_capability(intel_connector,
&hdcp_cap,
&hdcp2_cap);
} else {
hdcp_cap = intel_hdcp_get_capability(intel_connector);
hdcp2_cap = intel_hdcp2_get_capability(intel_connector);
}
if (hdcp_cap)
seq_puts(m, "HDCP1.4 ");
if (hdcp2_cap)
seq_puts(m, "HDCP2.2 ");
if (!hdcp_cap && !hdcp2_cap)
seq_puts(m, "None");
out:
seq_puts(m, "\n");
}
static void intel_dp_info(struct seq_file *m, struct intel_connector *connector)
{
struct intel_encoder *intel_encoder = intel_attached_encoder(connector);
@ -309,12 +279,7 @@ static void intel_connector_info(struct seq_file *m,
break;
}
seq_puts(m, "\tHDCP version: ");
if (intel_connector->mst_port) {
intel_hdcp_info(m, intel_connector, true);
seq_puts(m, "\tMST Hub HDCP version: ");
}
intel_hdcp_info(m, intel_connector, false);
intel_hdcp_info(m, intel_connector);
seq_printf(m, "\tmax bpc: %u\n", connector->display_info.bpc);
@ -365,8 +330,8 @@ static const char *plane_visibility(const struct intel_plane_state *plane_state)
if (plane_state->uapi.visible)
return "visible";
if (plane_state->planar_slave)
return "planar-slave";
if (plane_state->is_y_plane)
return "Y plane";
return "hidden";
}
@ -399,7 +364,7 @@ static void intel_plane_uapi_info(struct seq_file *m, struct intel_plane *plane)
if (plane_state->planar_linked_plane)
seq_printf(m, "\t\tplanar: Linked to [PLANE:%d:%s] as a %s\n",
plane_state->planar_linked_plane->base.base.id, plane_state->planar_linked_plane->base.name,
plane_state->planar_slave ? "slave" : "master");
plane_state->is_y_plane ? "Y plane" : "UV plane");
}
static void intel_plane_hw_info(struct seq_file *m, struct intel_plane *plane)
@ -427,10 +392,10 @@ static void intel_plane_hw_info(struct seq_file *m, struct intel_plane *plane)
static void intel_plane_info(struct seq_file *m, struct intel_crtc *crtc)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
struct intel_display *display = node_to_intel_display(m->private);
struct intel_plane *plane;
for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) {
for_each_intel_plane_on_crtc(display->drm, crtc, plane) {
seq_printf(m, "\t[PLANE:%d:%s]: type=%s\n",
plane->base.base.id, plane->base.name,
plane_type(plane->base.type));
@ -573,7 +538,7 @@ static void crtc_updates_add(struct intel_crtc *crtc)
static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
struct intel_display *display = node_to_intel_display(m->private);
struct drm_printer p = drm_seq_file_printer(m);
const struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
@ -607,7 +572,7 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc)
intel_vdsc_state_dump(&p, 1, crtc_state);
for_each_intel_encoder_mask(&dev_priv->drm, encoder,
for_each_intel_encoder_mask(display->drm, encoder,
crtc_state->uapi.encoder_mask)
intel_encoder_info(m, crtc, encoder);
@ -622,6 +587,7 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc)
static int i915_display_info(struct seq_file *m, void *unused)
{
struct intel_display *display = node_to_intel_display(m->private);
struct drm_i915_private *dev_priv = node_to_i915(m->private);
struct intel_crtc *crtc;
struct drm_connector *connector;
@ -630,22 +596,22 @@ static int i915_display_info(struct seq_file *m, void *unused)
wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm);
drm_modeset_lock_all(&dev_priv->drm);
drm_modeset_lock_all(display->drm);
seq_printf(m, "CRTC info\n");
seq_printf(m, "---------\n");
for_each_intel_crtc(&dev_priv->drm, crtc)
for_each_intel_crtc(display->drm, crtc)
intel_crtc_info(m, crtc);
seq_printf(m, "\n");
seq_printf(m, "Connector info\n");
seq_printf(m, "--------------\n");
drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
drm_connector_list_iter_begin(display->drm, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter)
intel_connector_info(m, connector);
drm_connector_list_iter_end(&conn_iter);
drm_modeset_unlock_all(&dev_priv->drm);
drm_modeset_unlock_all(display->drm);
intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
@ -654,56 +620,56 @@ static int i915_display_info(struct seq_file *m, void *unused)
static int i915_display_capabilities(struct seq_file *m, void *unused)
{
struct drm_i915_private *i915 = node_to_i915(m->private);
struct intel_display *display = node_to_intel_display(m->private);
struct drm_printer p = drm_seq_file_printer(m);
intel_display_device_info_print(DISPLAY_INFO(i915),
DISPLAY_RUNTIME_INFO(i915), &p);
intel_display_device_info_print(DISPLAY_INFO(display),
DISPLAY_RUNTIME_INFO(display), &p);
return 0;
}
static int i915_shared_dplls_info(struct seq_file *m, void *unused)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
struct intel_display *display = node_to_intel_display(m->private);
struct drm_printer p = drm_seq_file_printer(m);
struct intel_shared_dpll *pll;
int i;
drm_modeset_lock_all(&dev_priv->drm);
drm_modeset_lock_all(display->drm);
drm_printf(&p, "PLL refclks: non-SSC: %d kHz, SSC: %d kHz\n",
dev_priv->display.dpll.ref_clks.nssc,
dev_priv->display.dpll.ref_clks.ssc);
display->dpll.ref_clks.nssc,
display->dpll.ref_clks.ssc);
for_each_shared_dpll(dev_priv, pll, i) {
for_each_shared_dpll(display, pll, i) {
drm_printf(&p, "DPLL%i: %s, id: %i\n", pll->index,
pll->info->name, pll->info->id);
drm_printf(&p, " pipe_mask: 0x%x, active: 0x%x, on: %s\n",
pll->state.pipe_mask, pll->active_mask,
str_yes_no(pll->on));
drm_printf(&p, " tracked hardware state:\n");
intel_dpll_dump_hw_state(dev_priv, &p, &pll->state.hw_state);
intel_dpll_dump_hw_state(display, &p, &pll->state.hw_state);
}
drm_modeset_unlock_all(&dev_priv->drm);
drm_modeset_unlock_all(display->drm);
return 0;
}
static int i915_ddb_info(struct seq_file *m, void *unused)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
struct intel_display *display = node_to_intel_display(m->private);
struct skl_ddb_entry *entry;
struct intel_crtc *crtc;
if (DISPLAY_VER(dev_priv) < 9)
if (DISPLAY_VER(display) < 9)
return -ENODEV;
drm_modeset_lock_all(&dev_priv->drm);
drm_modeset_lock_all(display->drm);
seq_printf(m, "%-15s%8s%8s%8s\n", "", "Start", "End", "Size");
for_each_intel_crtc(&dev_priv->drm, crtc) {
for_each_intel_crtc(display->drm, crtc) {
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
enum pipe pipe = crtc->pipe;
@ -723,16 +689,16 @@ static int i915_ddb_info(struct seq_file *m, void *unused)
entry->end, skl_ddb_entry_size(entry));
}
drm_modeset_unlock_all(&dev_priv->drm);
drm_modeset_unlock_all(display->drm);
return 0;
}
static bool
intel_lpsp_power_well_enabled(struct drm_i915_private *i915,
intel_lpsp_power_well_enabled(struct intel_display *display,
enum i915_power_well_id power_well_id)
{
struct intel_display *display = &i915->display;
struct drm_i915_private *i915 = to_i915(display->drm);
intel_wakeref_t wakeref;
bool is_enabled;
@ -746,15 +712,16 @@ intel_lpsp_power_well_enabled(struct drm_i915_private *i915,
static int i915_lpsp_status(struct seq_file *m, void *unused)
{
struct intel_display *display = node_to_intel_display(m->private);
struct drm_i915_private *i915 = node_to_i915(m->private);
bool lpsp_enabled = false;
if (DISPLAY_VER(i915) >= 13 || IS_DISPLAY_VER(i915, 9, 10)) {
lpsp_enabled = !intel_lpsp_power_well_enabled(i915, SKL_DISP_PW_2);
} else if (IS_DISPLAY_VER(i915, 11, 12)) {
lpsp_enabled = !intel_lpsp_power_well_enabled(i915, ICL_DISP_PW_3);
if (DISPLAY_VER(display) >= 13 || IS_DISPLAY_VER(display, 9, 10)) {
lpsp_enabled = !intel_lpsp_power_well_enabled(display, SKL_DISP_PW_2);
} else if (IS_DISPLAY_VER(display, 11, 12)) {
lpsp_enabled = !intel_lpsp_power_well_enabled(display, ICL_DISP_PW_3);
} else if (IS_HASWELL(i915) || IS_BROADWELL(i915)) {
lpsp_enabled = !intel_lpsp_power_well_enabled(i915, HSW_DISP_PW_GLOBAL);
lpsp_enabled = !intel_lpsp_power_well_enabled(display, HSW_DISP_PW_GLOBAL);
} else {
seq_puts(m, "LPSP: not supported\n");
return 0;
@ -767,13 +734,13 @@ static int i915_lpsp_status(struct seq_file *m, void *unused)
static int i915_dp_mst_info(struct seq_file *m, void *unused)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
struct intel_display *display = node_to_intel_display(m->private);
struct intel_encoder *intel_encoder;
struct intel_digital_port *dig_port;
struct drm_connector *connector;
struct drm_connector_list_iter conn_iter;
drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
drm_connector_list_iter_begin(display->drm, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter) {
if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort)
continue;
@ -801,7 +768,7 @@ i915_fifo_underrun_reset_write(struct file *filp,
const char __user *ubuf,
size_t cnt, loff_t *ppos)
{
struct drm_i915_private *dev_priv = filp->private_data;
struct intel_display *display = filp->private_data;
struct intel_crtc *crtc;
int ret;
bool reset;
@ -813,7 +780,7 @@ i915_fifo_underrun_reset_write(struct file *filp,
if (!reset)
return cnt;
for_each_intel_crtc(&dev_priv->drm, crtc) {
for_each_intel_crtc(display->drm, crtc) {
struct drm_crtc_commit *commit;
struct intel_crtc_state *crtc_state;
@ -830,7 +797,7 @@ i915_fifo_underrun_reset_write(struct file *filp,
}
if (!ret && crtc_state->hw.active) {
drm_dbg_kms(&dev_priv->drm,
drm_dbg_kms(display->drm,
"Re-arming FIFO underruns on pipe %c\n",
pipe_name(crtc->pipe));
@ -843,7 +810,7 @@ i915_fifo_underrun_reset_write(struct file *filp,
return ret;
}
intel_fbc_reset_underrun(&dev_priv->display);
intel_fbc_reset_underrun(display);
return cnt;
}
@ -875,7 +842,7 @@ void intel_display_debugfs_register(struct drm_i915_private *i915)
struct drm_minor *minor = i915->drm.primary;
debugfs_create_file("i915_fifo_underrun_reset", 0644, minor->debugfs_root,
to_i915(minor->dev), &i915_fifo_underrun_reset_ops);
display, &i915_fifo_underrun_reset_ops);
drm_debugfs_create_files(intel_display_debugfs_list,
ARRAY_SIZE(intel_display_debugfs_list),
@ -893,38 +860,12 @@ void intel_display_debugfs_register(struct drm_i915_private *i915)
intel_display_debugfs_params(display);
}
static int i915_hdcp_sink_capability_show(struct seq_file *m, void *data)
{
struct intel_connector *connector = m->private;
struct drm_i915_private *i915 = to_i915(connector->base.dev);
int ret;
ret = drm_modeset_lock_single_interruptible(&i915->drm.mode_config.connection_mutex);
if (ret)
return ret;
if (!connector->base.encoder ||
connector->base.status != connector_status_connected) {
ret = -ENODEV;
goto out;
}
seq_printf(m, "%s:%d HDCP version: ", connector->base.name,
connector->base.base.id);
intel_hdcp_info(m, connector, false);
out:
drm_modeset_unlock(&i915->drm.mode_config.connection_mutex);
return ret;
}
DEFINE_SHOW_ATTRIBUTE(i915_hdcp_sink_capability);
static int i915_lpsp_capability_show(struct seq_file *m, void *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);
struct intel_encoder *encoder = intel_attached_encoder(connector);
struct drm_i915_private *i915 = to_i915(connector->base.dev);
int connector_type = connector->base.connector_type;
bool lpsp_capable = false;
@ -934,19 +875,19 @@ static int i915_lpsp_capability_show(struct seq_file *m, void *data)
if (connector->base.status != connector_status_connected)
return -ENODEV;
if (DISPLAY_VER(i915) >= 13)
if (DISPLAY_VER(display) >= 13)
lpsp_capable = encoder->port <= PORT_B;
else if (DISPLAY_VER(i915) >= 12)
else if (DISPLAY_VER(display) >= 12)
/*
* Actually TGL can drive LPSP on port till DDI_C
* but there is no physical connected DDI_C on TGL sku's,
* even driver is not initilizing DDI_C port for gen12.
* even driver is not initializing DDI_C port for gen12.
*/
lpsp_capable = encoder->port <= PORT_B;
else if (DISPLAY_VER(i915) == 11)
else if (DISPLAY_VER(display) == 11)
lpsp_capable = (connector_type == DRM_MODE_CONNECTOR_DSI ||
connector_type == DRM_MODE_CONNECTOR_eDP);
else if (IS_DISPLAY_VER(i915, 9, 10))
else if (IS_DISPLAY_VER(display, 9, 10))
lpsp_capable = (encoder->port == PORT_A &&
(connector_type == DRM_MODE_CONNECTOR_DSI ||
connector_type == DRM_MODE_CONNECTOR_eDP ||
@ -963,7 +904,7 @@ DEFINE_SHOW_ATTRIBUTE(i915_lpsp_capability);
static int i915_dsc_fec_support_show(struct seq_file *m, void *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);
struct drm_crtc *crtc;
struct intel_dp *intel_dp;
struct drm_modeset_acquire_ctx ctx;
@ -975,7 +916,7 @@ static int i915_dsc_fec_support_show(struct seq_file *m, void *data)
do {
try_again = false;
ret = drm_modeset_lock(&i915->drm.mode_config.connection_mutex,
ret = drm_modeset_lock(&display->drm->mode_config.connection_mutex,
&ctx);
if (ret) {
if (ret == -EDEADLK && !drm_modeset_backoff(&ctx)) {
@ -1036,7 +977,7 @@ static ssize_t i915_dsc_fec_support_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);
struct intel_encoder *encoder = intel_attached_encoder(connector);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
bool dsc_enable = false;
@ -1045,14 +986,14 @@ static ssize_t i915_dsc_fec_support_write(struct file *file,
if (len == 0)
return 0;
drm_dbg(&i915->drm,
drm_dbg(display->drm,
"Copied %zu bytes from user to force DSC\n", len);
ret = kstrtobool_from_user(ubuf, len, &dsc_enable);
if (ret < 0)
return ret;
drm_dbg(&i915->drm, "Got %s for DSC Enable\n",
drm_dbg(display->drm, "Got %s for DSC Enable\n",
(dsc_enable) ? "true" : "false");
intel_dp->force_dsc_en = dsc_enable;
@ -1079,7 +1020,7 @@ static const struct file_operations i915_dsc_fec_support_fops = {
static int i915_dsc_bpc_show(struct seq_file *m, void *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);
struct intel_encoder *encoder = intel_attached_encoder(connector);
struct drm_crtc *crtc;
struct intel_crtc_state *crtc_state;
@ -1088,7 +1029,7 @@ static int i915_dsc_bpc_show(struct seq_file *m, void *data)
if (!encoder)
return -ENODEV;
ret = drm_modeset_lock_single_interruptible(&i915->drm.mode_config.connection_mutex);
ret = drm_modeset_lock_single_interruptible(&display->drm->mode_config.connection_mutex);
if (ret)
return ret;
@ -1101,7 +1042,7 @@ static int i915_dsc_bpc_show(struct seq_file *m, void *data)
crtc_state = to_intel_crtc_state(crtc->state);
seq_printf(m, "Input_BPC: %d\n", crtc_state->dsc.config.bits_per_component);
out: drm_modeset_unlock(&i915->drm.mode_config.connection_mutex);
out: drm_modeset_unlock(&display->drm->mode_config.connection_mutex);
return ret;
}
@ -1145,7 +1086,7 @@ static const struct file_operations i915_dsc_bpc_fops = {
static int i915_dsc_output_format_show(struct seq_file *m, void *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);
struct intel_encoder *encoder = intel_attached_encoder(connector);
struct drm_crtc *crtc;
struct intel_crtc_state *crtc_state;
@ -1154,7 +1095,7 @@ static int i915_dsc_output_format_show(struct seq_file *m, void *data)
if (!encoder)
return -ENODEV;
ret = drm_modeset_lock_single_interruptible(&i915->drm.mode_config.connection_mutex);
ret = drm_modeset_lock_single_interruptible(&display->drm->mode_config.connection_mutex);
if (ret)
return ret;
@ -1168,7 +1109,7 @@ static int i915_dsc_output_format_show(struct seq_file *m, void *data)
seq_printf(m, "DSC_Output_Format: %s\n",
intel_output_format_name(crtc_state->output_format));
out: drm_modeset_unlock(&i915->drm.mode_config.connection_mutex);
out: drm_modeset_unlock(&display->drm->mode_config.connection_mutex);
return ret;
}
@ -1212,7 +1153,7 @@ static const struct file_operations i915_dsc_output_format_fops = {
static int i915_dsc_fractional_bpp_show(struct seq_file *m, void *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);
struct intel_encoder *encoder = intel_attached_encoder(connector);
struct drm_crtc *crtc;
struct intel_dp *intel_dp;
@ -1221,7 +1162,7 @@ static int i915_dsc_fractional_bpp_show(struct seq_file *m, void *data)
if (!encoder)
return -ENODEV;
ret = drm_modeset_lock_single_interruptible(&i915->drm.mode_config.connection_mutex);
ret = drm_modeset_lock_single_interruptible(&display->drm->mode_config.connection_mutex);
if (ret)
return ret;
@ -1236,7 +1177,7 @@ static int i915_dsc_fractional_bpp_show(struct seq_file *m, void *data)
str_yes_no(intel_dp->force_dsc_fractional_bpp_en));
out:
drm_modeset_unlock(&i915->drm.mode_config.connection_mutex);
drm_modeset_unlock(&display->drm->mode_config.connection_mutex);
return ret;
}
@ -1247,8 +1188,8 @@ static ssize_t i915_dsc_fractional_bpp_write(struct file *file,
{
struct seq_file *m = file->private_data;
struct intel_connector *connector = m->private;
struct intel_display *display = to_intel_display(connector);
struct intel_encoder *encoder = intel_attached_encoder(connector);
struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
bool dsc_fractional_bpp_enable = false;
int ret;
@ -1256,14 +1197,14 @@ static ssize_t i915_dsc_fractional_bpp_write(struct file *file,
if (len == 0)
return 0;
drm_dbg(&i915->drm,
drm_dbg(display->drm,
"Copied %zu bytes from user to force fractional bpp for DSC\n", len);
ret = kstrtobool_from_user(ubuf, len, &dsc_fractional_bpp_enable);
if (ret < 0)
return ret;
drm_dbg(&i915->drm, "Got %s for DSC Fractional BPP Enable\n",
drm_dbg(display->drm, "Got %s for DSC Fractional BPP Enable\n",
(dsc_fractional_bpp_enable) ? "true" : "false");
intel_dp->force_dsc_fractional_bpp_en = dsc_fractional_bpp_enable;
@ -1392,7 +1333,7 @@ static const struct file_operations i915_joiner_fops = {
*/
void intel_connector_debugfs_add(struct intel_connector *connector)
{
struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_display *display = to_intel_display(connector);
struct dentry *root = connector->base.debugfs_entry;
int connector_type = connector->base.connector_type;
@ -1401,19 +1342,13 @@ void intel_connector_debugfs_add(struct intel_connector *connector)
return;
intel_drrs_connector_debugfs_add(connector);
intel_hdcp_connector_debugfs_add(connector);
intel_pps_connector_debugfs_add(connector);
intel_psr_connector_debugfs_add(connector);
intel_alpm_lobf_debugfs_add(connector);
intel_dp_link_training_debugfs_add(connector);
if (connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
connector_type == DRM_MODE_CONNECTOR_HDMIA ||
connector_type == DRM_MODE_CONNECTOR_HDMIB) {
debugfs_create_file("i915_hdcp_sink_capability", 0444, root,
connector, &i915_hdcp_sink_capability_fops);
}
if (DISPLAY_VER(i915) >= 11 &&
if (DISPLAY_VER(display) >= 11 &&
((connector_type == DRM_MODE_CONNECTOR_DisplayPort && !connector->mst_port) ||
connector_type == DRM_MODE_CONNECTOR_eDP)) {
debugfs_create_file("i915_dsc_fec_support", 0644, root,

View File

@ -1357,6 +1357,12 @@ static const struct intel_display_device_info xe2_hpd_display = {
BIT(PORT_TC1) | BIT(PORT_TC2) | BIT(PORT_TC3) | BIT(PORT_TC4),
};
static const u16 mtl_u_ids[] = {
INTEL_MTL_U_IDS(ID),
INTEL_ARL_U_IDS(ID),
0
};
/*
* Do not initialize the .info member of the platform desc for GMD ID based
* platforms. Their display will be probed automatically based on the IP version
@ -1364,6 +1370,13 @@ static const struct intel_display_device_info xe2_hpd_display = {
*/
static const struct platform_desc mtl_desc = {
PLATFORM(meteorlake),
.subplatforms = (const struct subplatform_desc[]) {
{
SUBPLATFORM(meteorlake, u),
.pciidlist = mtl_u_ids,
},
{},
}
};
static const struct platform_desc lnl_desc = {

View File

@ -96,6 +96,7 @@ struct pci_dev;
func(dg2_g12) \
/* Display ver 14 (based on GMD ID) */ \
func(meteorlake) \
func(meteorlake_u) \
/* Display ver 20 (based on GMD ID) */ \
func(lunarlake) \
/* Display ver 14.1 (based on GMD ID) */ \
@ -145,6 +146,7 @@ struct intel_display_platforms {
#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_CMTG(__display) (!(__display)->platform.dg2 && DISPLAY_VER(__display) >= 13)
#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)
@ -233,6 +235,17 @@ struct intel_display_platforms {
(drm_WARN_ON(__to_intel_display(__display)->drm, INTEL_DISPLAY_STEP(__display) == STEP_NONE), \
INTEL_DISPLAY_STEP(__display) >= (since) && INTEL_DISPLAY_STEP(__display) < (until))
#define ARLS_HOST_BRIDGE_PCI_ID1 0x7D1C
#define ARLS_HOST_BRIDGE_PCI_ID2 0x7D2D
#define ARLS_HOST_BRIDGE_PCI_ID3 0x7D2E
#define ARLS_HOST_BRIDGE_PCI_ID4 0x7D2F
#define IS_ARROWLAKE_S_BY_HOST_BRIDGE_ID(id) \
(((id) == ARLS_HOST_BRIDGE_PCI_ID1) || \
((id) == ARLS_HOST_BRIDGE_PCI_ID2) || \
((id) == ARLS_HOST_BRIDGE_PCI_ID3) || \
((id) == ARLS_HOST_BRIDGE_PCI_ID4))
struct intel_display_runtime_info {
struct intel_display_ip_ver {
u16 ver;

View File

@ -197,7 +197,7 @@ void intel_display_driver_early_probe(struct intel_display *display)
intel_dkl_phy_init(i915);
intel_color_init_hooks(display);
intel_init_cdclk_hooks(display);
intel_audio_hooks_init(i915);
intel_audio_hooks_init(display);
intel_dpll_init_clock_hook(i915);
intel_init_display_hooks(i915);
intel_fdi_init_hook(i915);
@ -442,18 +442,18 @@ int intel_display_driver_probe_nogem(struct intel_display *display)
INTEL_NUM_PIPES(display) > 1 ? "s" : "");
for_each_pipe(display, pipe) {
ret = intel_crtc_init(i915, pipe);
ret = intel_crtc_init(display, pipe);
if (ret)
goto err_mode_config;
}
intel_plane_possible_crtcs_init(display);
intel_shared_dpll_init(i915);
intel_shared_dpll_init(display);
intel_fdi_pll_freq_update(i915);
intel_update_czclk(i915);
intel_display_driver_init_hw(display);
intel_dpll_update_ref_clks(i915);
intel_dpll_update_ref_clks(display);
if (display->cdclk.max_cdclk_freq == 0)
intel_update_max_cdclk(display);
@ -544,11 +544,11 @@ void intel_display_driver_register(struct intel_display *display)
intel_opregion_register(display);
intel_acpi_video_register(display);
intel_audio_init(i915);
intel_audio_init(display);
intel_display_driver_enable_user_access(display);
intel_audio_register(i915);
intel_audio_register(display);
intel_display_debugfs_register(i915);
@ -636,8 +636,6 @@ void intel_display_driver_remove_nogem(struct intel_display *display)
void intel_display_driver_unregister(struct intel_display *display)
{
struct drm_i915_private *i915 = to_i915(display->drm);
if (!HAS_DISPLAY(display))
return;
@ -652,7 +650,7 @@ void intel_display_driver_unregister(struct intel_display *display)
intel_display_driver_disable_user_access(display);
intel_audio_deinit(i915);
intel_audio_deinit(display);
drm_atomic_helper_shutdown(display->drm);

File diff suppressed because it is too large Load Diff

View File

@ -11,8 +11,9 @@
#include "intel_display_limits.h"
enum pipe;
struct drm_i915_private;
struct drm_crtc;
struct drm_i915_private;
struct intel_display;
void valleyview_enable_display_irqs(struct drm_i915_private *i915);
void valleyview_disable_display_irqs(struct drm_i915_private *i915);
@ -64,7 +65,7 @@ void gen8_de_irq_postinstall(struct drm_i915_private *i915);
void gen11_de_irq_postinstall(struct drm_i915_private *i915);
void dg1_de_irq_postinstall(struct drm_i915_private *i915);
u32 i915_pipestat_enable_mask(struct drm_i915_private *i915, enum pipe pipe);
u32 i915_pipestat_enable_mask(struct intel_display *display, enum pipe pipe);
void i915_enable_pipestat(struct drm_i915_private *i915, enum pipe pipe, u32 status_mask);
void i915_disable_pipestat(struct drm_i915_private *i915, enum pipe pipe, u32 status_mask);
void i915_enable_asle_pipestat(struct drm_i915_private *i915);
@ -75,6 +76,9 @@ void i915_pipestat_irq_handler(struct drm_i915_private *i915, u32 iir, u32 pipe_
void i965_pipestat_irq_handler(struct drm_i915_private *i915, u32 iir, u32 pipe_stats[I915_MAX_PIPES]);
void valleyview_pipestat_irq_handler(struct drm_i915_private *i915, u32 pipe_stats[I915_MAX_PIPES]);
void vlv_display_error_irq_ack(struct intel_display *display, u32 *eir, u32 *dpinvgtt);
void vlv_display_error_irq_handler(struct intel_display *display, u32 eir, u32 dpinvgtt);
void intel_display_irq_init(struct drm_i915_private *i915);
void i915gm_irq_cstate_wa(struct drm_i915_private *i915, bool enable);

View File

@ -130,7 +130,7 @@ intel_display_param_named_unsafe(enable_psr2_sel_fetch, bool, 0400,
intel_display_param_named_unsafe(enable_dmc_wl, int, 0400,
"Enable DMC wakelock "
"(-1=use per-chip default, 0=disabled, 1=enabled) "
"(-1=use per-chip default, 0=disabled, 1=enabled, 2=match any register, 3=always locked) "
"Default: -1");
__maybe_unused

View File

@ -224,7 +224,7 @@ static bool __intel_display_power_is_enabled(struct intel_display *display,
/**
* intel_display_power_is_enabled - check for a power domain
* @dev_priv: i915 device instance
* @display: display device instance
* @domain: power domain to check
*
* This function can be used to check the hw power domain state. It is mostly
@ -239,10 +239,9 @@ static bool __intel_display_power_is_enabled(struct intel_display *display,
* Returns:
* True when the power domain is enabled, false otherwise.
*/
bool intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
bool intel_display_power_is_enabled(struct intel_display *display,
enum intel_display_power_domain domain)
{
struct intel_display *display = &dev_priv->display;
struct i915_power_domains *power_domains = &display->power.domains;
bool ret;
@ -500,7 +499,7 @@ __intel_display_power_get_domain(struct intel_display *display,
/**
* intel_display_power_get - grab a power domain reference
* @dev_priv: i915 device instance
* @display: display device instance
* @domain: power domain to reference
*
* This function grabs a power domain reference for @domain and ensures that the
@ -510,10 +509,10 @@ __intel_display_power_get_domain(struct intel_display *display,
* Any power domain reference obtained by this function must have a symmetric
* call to intel_display_power_put() to release the reference again.
*/
intel_wakeref_t intel_display_power_get(struct drm_i915_private *dev_priv,
intel_wakeref_t intel_display_power_get(struct intel_display *display,
enum intel_display_power_domain domain)
{
struct intel_display *display = &dev_priv->display;
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct i915_power_domains *power_domains = &display->power.domains;
intel_wakeref_t wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm);
@ -526,7 +525,7 @@ intel_wakeref_t intel_display_power_get(struct drm_i915_private *dev_priv,
/**
* intel_display_power_get_if_enabled - grab a reference for an enabled display power domain
* @dev_priv: i915 device instance
* @display: display device instance
* @domain: power domain to reference
*
* This function grabs a power domain reference for @domain and ensures that the
@ -537,10 +536,10 @@ intel_wakeref_t intel_display_power_get(struct drm_i915_private *dev_priv,
* call to intel_display_power_put() to release the reference again.
*/
intel_wakeref_t
intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
intel_display_power_get_if_enabled(struct intel_display *display,
enum intel_display_power_domain domain)
{
struct intel_display *display = &dev_priv->display;
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct i915_power_domains *power_domains = &display->power.domains;
intel_wakeref_t wakeref;
bool is_enabled;
@ -696,7 +695,7 @@ intel_display_power_put_async_work(struct work_struct *work)
/**
* __intel_display_power_put_async - release a power domain reference asynchronously
* @i915: i915 device instance
* @display: display device instance
* @domain: power domain to reference
* @wakeref: wakeref acquired for the reference that is being released
* @delay_ms: delay of powering down the power domain
@ -707,12 +706,12 @@ intel_display_power_put_async_work(struct work_struct *work)
* The power down is delayed by @delay_ms if this is >= 0, or by a default
* 100 ms otherwise.
*/
void __intel_display_power_put_async(struct drm_i915_private *i915,
void __intel_display_power_put_async(struct intel_display *display,
enum intel_display_power_domain domain,
intel_wakeref_t wakeref,
int delay_ms)
{
struct intel_display *display = &i915->display;
struct drm_i915_private *i915 = to_i915(display->drm);
struct i915_power_domains *power_domains = &display->power.domains;
struct intel_runtime_pm *rpm = &i915->runtime_pm;
intel_wakeref_t work_wakeref = intel_runtime_pm_get_raw(rpm);
@ -754,7 +753,7 @@ void __intel_display_power_put_async(struct drm_i915_private *i915,
/**
* intel_display_power_flush_work - flushes the async display power disabling work
* @i915: i915 device instance
* @display: display device instance
*
* Flushes any pending work that was scheduled by a preceding
* intel_display_power_put_async() call, completing the disabling of the
@ -764,9 +763,9 @@ void __intel_display_power_put_async(struct drm_i915_private *i915,
* function returns; to ensure that the work handler isn't running use
* intel_display_power_flush_work_sync() instead.
*/
void intel_display_power_flush_work(struct drm_i915_private *i915)
void intel_display_power_flush_work(struct intel_display *display)
{
struct intel_display *display = &i915->display;
struct drm_i915_private *i915 = to_i915(display->drm);
struct i915_power_domains *power_domains = &display->power.domains;
struct intel_power_domain_mask async_put_mask;
intel_wakeref_t work_wakeref;
@ -800,10 +799,9 @@ void intel_display_power_flush_work(struct drm_i915_private *i915)
static void
intel_display_power_flush_work_sync(struct intel_display *display)
{
struct drm_i915_private *i915 = to_i915(display->drm);
struct i915_power_domains *power_domains = &display->power.domains;
intel_display_power_flush_work(i915);
intel_display_power_flush_work(display);
cancel_async_put_work(power_domains, true);
verify_async_put_domains_state(power_domains);
@ -814,7 +812,7 @@ intel_display_power_flush_work_sync(struct intel_display *display)
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
/**
* intel_display_power_put - release a power domain reference
* @dev_priv: i915 device instance
* @display: display device instance
* @domain: power domain to reference
* @wakeref: wakeref acquired for the reference that is being released
*
@ -822,11 +820,11 @@ intel_display_power_flush_work_sync(struct intel_display *display)
* intel_display_power_get() and might power down the corresponding hardware
* block right away if this is the last reference.
*/
void intel_display_power_put(struct drm_i915_private *dev_priv,
void intel_display_power_put(struct intel_display *display,
enum intel_display_power_domain domain,
intel_wakeref_t wakeref)
{
struct intel_display *display = &dev_priv->display;
struct drm_i915_private *dev_priv = to_i915(display->drm);
__intel_display_power_put(display, domain);
intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
@ -834,7 +832,7 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
#else
/**
* intel_display_power_put_unchecked - release an unchecked power domain reference
* @dev_priv: i915 device instance
* @display: display device instance
* @domain: power domain to reference
*
* This function drops the power domain reference obtained by
@ -842,13 +840,13 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
* block right away if this is the last reference.
*
* This function is only for the power domain code's internal use to suppress wakeref
* tracking when the correspondig debug kconfig option is disabled, should not
* tracking when the corresponding debug kconfig option is disabled, should not
* be used otherwise.
*/
void intel_display_power_put_unchecked(struct drm_i915_private *dev_priv,
void intel_display_power_put_unchecked(struct intel_display *display,
enum intel_display_power_domain domain)
{
struct intel_display *display = &dev_priv->display;
struct drm_i915_private *dev_priv = to_i915(display->drm);
__intel_display_power_put(display, domain);
intel_runtime_pm_put_unchecked(&dev_priv->runtime_pm);
@ -856,16 +854,15 @@ void intel_display_power_put_unchecked(struct drm_i915_private *dev_priv,
#endif
void
intel_display_power_get_in_set(struct drm_i915_private *i915,
intel_display_power_get_in_set(struct intel_display *display,
struct intel_display_power_domain_set *power_domain_set,
enum intel_display_power_domain domain)
{
struct intel_display *display = &i915->display;
intel_wakeref_t __maybe_unused wf;
drm_WARN_ON(display->drm, test_bit(domain, power_domain_set->mask.bits));
wf = intel_display_power_get(i915, domain);
wf = intel_display_power_get(display, domain);
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
power_domain_set->wakerefs[domain] = wf;
#endif
@ -873,16 +870,15 @@ intel_display_power_get_in_set(struct drm_i915_private *i915,
}
bool
intel_display_power_get_in_set_if_enabled(struct drm_i915_private *i915,
intel_display_power_get_in_set_if_enabled(struct intel_display *display,
struct intel_display_power_domain_set *power_domain_set,
enum intel_display_power_domain domain)
{
struct intel_display *display = &i915->display;
intel_wakeref_t wf;
drm_WARN_ON(display->drm, test_bit(domain, power_domain_set->mask.bits));
wf = intel_display_power_get_if_enabled(i915, domain);
wf = intel_display_power_get_if_enabled(display, domain);
if (!wf)
return false;
@ -895,11 +891,10 @@ intel_display_power_get_in_set_if_enabled(struct drm_i915_private *i915,
}
void
intel_display_power_put_mask_in_set(struct drm_i915_private *i915,
intel_display_power_put_mask_in_set(struct intel_display *display,
struct intel_display_power_domain_set *power_domain_set,
struct intel_power_domain_mask *mask)
{
struct intel_display *display = &i915->display;
enum intel_display_power_domain domain;
drm_WARN_ON(display->drm,
@ -911,7 +906,7 @@ intel_display_power_put_mask_in_set(struct drm_i915_private *i915,
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
wf = fetch_and_zero(&power_domain_set->wakerefs[domain]);
#endif
intel_display_power_put(i915, domain, wf);
intel_display_power_put(display, domain, wf);
clear_bit(domain, power_domain_set->mask.bits);
}
}
@ -999,7 +994,7 @@ static u32 get_allowed_dc_mask(struct intel_display *display, int enable_dc)
* intel_power_domains_init - initializes the power domain structures
* @display: display device instance
*
* Initializes the power domain structures for @dev_priv depending upon the
* Initializes the power domain structures for @display depending upon the
* supported platform.
*/
int intel_power_domains_init(struct intel_display *display)
@ -1061,10 +1056,9 @@ static void gen9_dbuf_slice_set(struct intel_display *display,
slice, str_enable_disable(enable));
}
void gen9_dbuf_slices_update(struct drm_i915_private *dev_priv,
void gen9_dbuf_slices_update(struct intel_display *display,
u8 req_slices)
{
struct intel_display *display = &dev_priv->display;
struct i915_power_domains *power_domains = &display->power.domains;
u8 slice_mask = DISPLAY_INFO(display)->dbuf.slice_mask;
enum dbuf_slice slice;
@ -1095,10 +1089,9 @@ void gen9_dbuf_slices_update(struct drm_i915_private *dev_priv,
static void gen9_dbuf_enable(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
u8 slices_mask;
display->dbuf.enabled_slices = intel_enabled_dbuf_slices_mask(dev_priv);
display->dbuf.enabled_slices = intel_enabled_dbuf_slices_mask(display);
slices_mask = BIT(DBUF_S1) | display->dbuf.enabled_slices;
@ -1109,14 +1102,12 @@ static void gen9_dbuf_enable(struct intel_display *display)
* Just power up at least 1 slice, we will
* figure out later which slices we have and what we need.
*/
gen9_dbuf_slices_update(dev_priv, slices_mask);
gen9_dbuf_slices_update(display, slices_mask);
}
static void gen9_dbuf_disable(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
gen9_dbuf_slices_update(dev_priv, 0);
gen9_dbuf_slices_update(display, 0);
if (DISPLAY_VER(display) >= 14)
intel_pmdemand_program_dbuf(display, 0);
@ -1126,9 +1117,6 @@ static void gen12_dbuf_slices_config(struct intel_display *display)
{
enum dbuf_slice slice;
if (display->platform.alderlake_p)
return;
for_each_dbuf_slice(display, slice)
intel_de_rmw(display, DBUF_CTL_S(slice),
DBUF_TRACKER_STATE_SERVICE_MASK,
@ -1663,7 +1651,7 @@ static void icl_display_core_init(struct intel_display *display,
return;
/* 2. Initialize all combo phys */
intel_combo_phy_init(dev_priv);
intel_combo_phy_init(display);
/*
* 3. Enable Power Well 1 (PG1).
@ -1681,7 +1669,7 @@ static void icl_display_core_init(struct intel_display *display,
/* 4. Enable CDCLK. */
intel_cdclk_init_hw(display);
if (DISPLAY_VER(display) >= 12)
if (DISPLAY_VER(display) == 12 || display->platform.dg2)
gen12_dbuf_slices_config(display);
/* 5. Enable DBUF. */
@ -1726,7 +1714,6 @@ static void icl_display_core_init(struct intel_display *display,
static void icl_display_core_uninit(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct i915_power_domains *power_domains = &display->power.domains;
struct i915_power_well *well;
@ -1736,7 +1723,7 @@ static void icl_display_core_uninit(struct intel_display *display)
gen9_disable_dc_states(display);
intel_dmc_disable_program(display);
/* 1. Disable all display engine functions -> aready done */
/* 1. Disable all display engine functions -> already done */
/* 2. Disable DBUF */
gen9_dbuf_disable(display);
@ -1759,7 +1746,7 @@ static void icl_display_core_uninit(struct intel_display *display)
mutex_unlock(&power_domains->lock);
/* 5. */
intel_combo_phy_uninit(dev_priv);
intel_combo_phy_uninit(display);
}
static void chv_phy_control_init(struct intel_display *display)
@ -1966,12 +1953,12 @@ void intel_power_domains_init_hw(struct intel_display *display, bool resume)
*/
drm_WARN_ON(display->drm, power_domains->init_wakeref);
power_domains->init_wakeref =
intel_display_power_get(i915, POWER_DOMAIN_INIT);
intel_display_power_get(display, POWER_DOMAIN_INIT);
/* Disable power support if the user asked so. */
if (!display->params.disable_power_well) {
drm_WARN_ON(display->drm, power_domains->disable_wakeref);
display->power.domains.disable_wakeref = intel_display_power_get(i915,
display->power.domains.disable_wakeref = intel_display_power_get(display,
POWER_DOMAIN_INIT);
}
intel_power_domains_sync_hw(display);
@ -1998,7 +1985,7 @@ void intel_power_domains_driver_remove(struct intel_display *display)
/* Remove the refcount we took to keep power well support disabled. */
if (!display->params.disable_power_well)
intel_display_power_put(i915, POWER_DOMAIN_INIT,
intel_display_power_put(display, POWER_DOMAIN_INIT,
fetch_and_zero(&display->power.domains.disable_wakeref));
intel_display_power_flush_work_sync(display);
@ -2054,11 +2041,10 @@ void intel_power_domains_sanitize_state(struct intel_display *display)
*/
void intel_power_domains_enable(struct intel_display *display)
{
struct drm_i915_private *i915 = to_i915(display->drm);
intel_wakeref_t wakeref __maybe_unused =
fetch_and_zero(&display->power.domains.init_wakeref);
intel_display_power_put(i915, POWER_DOMAIN_INIT, wakeref);
intel_display_power_put(display, POWER_DOMAIN_INIT, wakeref);
intel_power_domains_verify_state(display);
}
@ -2071,12 +2057,11 @@ void intel_power_domains_enable(struct intel_display *display)
*/
void intel_power_domains_disable(struct intel_display *display)
{
struct drm_i915_private *i915 = to_i915(display->drm);
struct i915_power_domains *power_domains = &display->power.domains;
drm_WARN_ON(display->drm, power_domains->init_wakeref);
power_domains->init_wakeref =
intel_display_power_get(i915, POWER_DOMAIN_INIT);
intel_display_power_get(display, POWER_DOMAIN_INIT);
intel_power_domains_verify_state(display);
}
@ -2094,12 +2079,11 @@ void intel_power_domains_disable(struct intel_display *display)
*/
void intel_power_domains_suspend(struct intel_display *display, bool s2idle)
{
struct drm_i915_private *i915 = to_i915(display->drm);
struct i915_power_domains *power_domains = &display->power.domains;
intel_wakeref_t wakeref __maybe_unused =
fetch_and_zero(&power_domains->init_wakeref);
intel_display_power_put(i915, POWER_DOMAIN_INIT, wakeref);
intel_display_power_put(display, POWER_DOMAIN_INIT, wakeref);
/*
* In case of suspend-to-idle (aka S0ix) on a DMC platform without DC9
@ -2110,7 +2094,7 @@ void intel_power_domains_suspend(struct intel_display *display, bool s2idle)
*/
if (!(power_domains->allowed_dc_mask & DC_STATE_EN_DC9) && s2idle &&
intel_dmc_has_payload(display)) {
intel_display_power_flush_work(i915);
intel_display_power_flush_work(display);
intel_power_domains_verify_state(display);
return;
}
@ -2120,10 +2104,10 @@ void intel_power_domains_suspend(struct intel_display *display, bool s2idle)
* power wells if power domains must be deinitialized for suspend.
*/
if (!display->params.disable_power_well)
intel_display_power_put(i915, POWER_DOMAIN_INIT,
intel_display_power_put(display, POWER_DOMAIN_INIT,
fetch_and_zero(&display->power.domains.disable_wakeref));
intel_display_power_flush_work(i915);
intel_display_power_flush_work(display);
intel_power_domains_verify_state(display);
if (DISPLAY_VER(display) >= 11)
@ -2148,7 +2132,6 @@ void intel_power_domains_suspend(struct intel_display *display, bool s2idle)
*/
void intel_power_domains_resume(struct intel_display *display)
{
struct drm_i915_private *i915 = to_i915(display->drm);
struct i915_power_domains *power_domains = &display->power.domains;
if (power_domains->display_core_suspended) {
@ -2157,7 +2140,7 @@ void intel_power_domains_resume(struct intel_display *display)
} else {
drm_WARN_ON(display->drm, power_domains->init_wakeref);
power_domains->init_wakeref =
intel_display_power_get(i915, POWER_DOMAIN_INIT);
intel_display_power_get(display, POWER_DOMAIN_INIT);
}
intel_power_domains_verify_state(display);
@ -2327,9 +2310,8 @@ void intel_display_power_resume(struct intel_display *display)
}
}
void intel_display_power_debug(struct drm_i915_private *i915, struct seq_file *m)
void intel_display_power_debug(struct intel_display *display, struct seq_file *m)
{
struct intel_display *display = &i915->display;
struct i915_power_domains *power_domains = &display->power.domains;
int i;
@ -2510,9 +2492,8 @@ intel_port_domains_for_port(struct intel_display *display, enum port port)
}
enum intel_display_power_domain
intel_display_power_ddi_io_domain(struct drm_i915_private *i915, enum port port)
intel_display_power_ddi_io_domain(struct intel_display *display, enum port port)
{
struct intel_display *display = &i915->display;
const struct intel_ddi_port_domains *domains = intel_port_domains_for_port(display, port);
if (drm_WARN_ON(display->drm, !domains || domains->ddi_io == POWER_DOMAIN_INVALID))
@ -2522,9 +2503,8 @@ intel_display_power_ddi_io_domain(struct drm_i915_private *i915, enum port port)
}
enum intel_display_power_domain
intel_display_power_ddi_lanes_domain(struct drm_i915_private *i915, enum port port)
intel_display_power_ddi_lanes_domain(struct intel_display *display, enum port port)
{
struct intel_display *display = &i915->display;
const struct intel_ddi_port_domains *domains = intel_port_domains_for_port(display, port);
if (drm_WARN_ON(display->drm, !domains || domains->ddi_lanes == POWER_DOMAIN_INVALID))
@ -2549,9 +2529,8 @@ intel_port_domains_for_aux_ch(struct intel_display *display, enum aux_ch aux_ch)
}
enum intel_display_power_domain
intel_display_power_aux_io_domain(struct drm_i915_private *i915, enum aux_ch aux_ch)
intel_display_power_aux_io_domain(struct intel_display *display, enum aux_ch aux_ch)
{
struct intel_display *display = &i915->display;
const struct intel_ddi_port_domains *domains = intel_port_domains_for_aux_ch(display, aux_ch);
if (drm_WARN_ON(display->drm, !domains || domains->aux_io == POWER_DOMAIN_INVALID))
@ -2561,9 +2540,8 @@ intel_display_power_aux_io_domain(struct drm_i915_private *i915, enum aux_ch aux
}
enum intel_display_power_domain
intel_display_power_legacy_aux_domain(struct drm_i915_private *i915, enum aux_ch aux_ch)
intel_display_power_legacy_aux_domain(struct intel_display *display, enum aux_ch aux_ch)
{
struct intel_display *display = &i915->display;
const struct intel_ddi_port_domains *domains = intel_port_domains_for_aux_ch(display, aux_ch);
if (drm_WARN_ON(display->drm, !domains || domains->aux_legacy_usbc == POWER_DOMAIN_INVALID))
@ -2573,9 +2551,8 @@ intel_display_power_legacy_aux_domain(struct drm_i915_private *i915, enum aux_ch
}
enum intel_display_power_domain
intel_display_power_tbt_aux_domain(struct drm_i915_private *i915, enum aux_ch aux_ch)
intel_display_power_tbt_aux_domain(struct intel_display *display, enum aux_ch aux_ch)
{
struct intel_display *display = &i915->display;
const struct intel_ddi_port_domains *domains = intel_port_domains_for_aux_ch(display, aux_ch);
if (drm_WARN_ON(display->drm, !domains || domains->aux_tbt == POWER_DOMAIN_INVALID))

View File

@ -13,7 +13,6 @@
enum aux_ch;
enum port;
struct drm_i915_private;
struct i915_power_well;
struct intel_display;
struct intel_encoder;
@ -184,102 +183,102 @@ 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,
bool intel_display_power_is_enabled(struct intel_display *display,
enum intel_display_power_domain domain);
intel_wakeref_t intel_display_power_get(struct drm_i915_private *dev_priv,
intel_wakeref_t intel_display_power_get(struct intel_display *display,
enum intel_display_power_domain domain);
intel_wakeref_t
intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
intel_display_power_get_if_enabled(struct intel_display *display,
enum intel_display_power_domain domain);
void __intel_display_power_put_async(struct drm_i915_private *i915,
void __intel_display_power_put_async(struct intel_display *display,
enum intel_display_power_domain domain,
intel_wakeref_t wakeref,
int delay_ms);
void intel_display_power_flush_work(struct drm_i915_private *i915);
void intel_display_power_flush_work(struct intel_display *display);
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
void intel_display_power_put(struct drm_i915_private *dev_priv,
void intel_display_power_put(struct intel_display *display,
enum intel_display_power_domain domain,
intel_wakeref_t wakeref);
static inline void
intel_display_power_put_async(struct drm_i915_private *i915,
intel_display_power_put_async(struct intel_display *display,
enum intel_display_power_domain domain,
intel_wakeref_t wakeref)
{
__intel_display_power_put_async(i915, domain, wakeref, -1);
__intel_display_power_put_async(display, domain, wakeref, -1);
}
static inline void
intel_display_power_put_async_delay(struct drm_i915_private *i915,
intel_display_power_put_async_delay(struct intel_display *display,
enum intel_display_power_domain domain,
intel_wakeref_t wakeref,
int delay_ms)
{
__intel_display_power_put_async(i915, domain, wakeref, delay_ms);
__intel_display_power_put_async(display, domain, wakeref, delay_ms);
}
#else
void intel_display_power_put_unchecked(struct drm_i915_private *dev_priv,
void intel_display_power_put_unchecked(struct intel_display *display,
enum intel_display_power_domain domain);
static inline void
intel_display_power_put(struct drm_i915_private *i915,
intel_display_power_put(struct intel_display *display,
enum intel_display_power_domain domain,
intel_wakeref_t wakeref)
{
intel_display_power_put_unchecked(i915, domain);
intel_display_power_put_unchecked(display, domain);
}
static inline void
intel_display_power_put_async(struct drm_i915_private *i915,
intel_display_power_put_async(struct intel_display *display,
enum intel_display_power_domain domain,
intel_wakeref_t wakeref)
{
__intel_display_power_put_async(i915, domain, INTEL_WAKEREF_DEF, -1);
__intel_display_power_put_async(display, domain, INTEL_WAKEREF_DEF, -1);
}
static inline void
intel_display_power_put_async_delay(struct drm_i915_private *i915,
intel_display_power_put_async_delay(struct intel_display *display,
enum intel_display_power_domain domain,
intel_wakeref_t wakeref,
int delay_ms)
{
__intel_display_power_put_async(i915, domain, INTEL_WAKEREF_DEF, delay_ms);
__intel_display_power_put_async(display, domain, INTEL_WAKEREF_DEF, delay_ms);
}
#endif
void
intel_display_power_get_in_set(struct drm_i915_private *i915,
intel_display_power_get_in_set(struct intel_display *display,
struct intel_display_power_domain_set *power_domain_set,
enum intel_display_power_domain domain);
bool
intel_display_power_get_in_set_if_enabled(struct drm_i915_private *i915,
intel_display_power_get_in_set_if_enabled(struct intel_display *display,
struct intel_display_power_domain_set *power_domain_set,
enum intel_display_power_domain domain);
void
intel_display_power_put_mask_in_set(struct drm_i915_private *i915,
intel_display_power_put_mask_in_set(struct intel_display *display,
struct intel_display_power_domain_set *power_domain_set,
struct intel_power_domain_mask *mask);
static inline void
intel_display_power_put_all_in_set(struct drm_i915_private *i915,
intel_display_power_put_all_in_set(struct intel_display *display,
struct intel_display_power_domain_set *power_domain_set)
{
intel_display_power_put_mask_in_set(i915, power_domain_set, &power_domain_set->mask);
intel_display_power_put_mask_in_set(display, power_domain_set, &power_domain_set->mask);
}
void intel_display_power_debug(struct drm_i915_private *i915, struct seq_file *m);
void intel_display_power_debug(struct intel_display *display, struct seq_file *m);
enum intel_display_power_domain
intel_display_power_ddi_lanes_domain(struct drm_i915_private *i915, enum port port);
intel_display_power_ddi_lanes_domain(struct intel_display *display, enum port port);
enum intel_display_power_domain
intel_display_power_ddi_io_domain(struct drm_i915_private *i915, enum port port);
intel_display_power_ddi_io_domain(struct intel_display *display, enum port port);
enum intel_display_power_domain
intel_display_power_aux_io_domain(struct drm_i915_private *i915, enum aux_ch aux_ch);
intel_display_power_aux_io_domain(struct intel_display *display, enum aux_ch aux_ch);
enum intel_display_power_domain
intel_display_power_legacy_aux_domain(struct drm_i915_private *i915, enum aux_ch aux_ch);
intel_display_power_legacy_aux_domain(struct intel_display *display, enum aux_ch aux_ch);
enum intel_display_power_domain
intel_display_power_tbt_aux_domain(struct drm_i915_private *i915, enum aux_ch aux_ch);
intel_display_power_tbt_aux_domain(struct intel_display *display, enum aux_ch aux_ch);
/*
* FIXME: We should probably switch this to a 0-based scheme to be consistent
@ -293,15 +292,15 @@ enum dbuf_slice {
I915_MAX_DBUF_SLICES
};
void gen9_dbuf_slices_update(struct drm_i915_private *dev_priv,
void gen9_dbuf_slices_update(struct intel_display *display,
u8 req_slices);
#define with_intel_display_power(i915, domain, wf) \
for ((wf) = intel_display_power_get((i915), (domain)); (wf); \
intel_display_power_put_async((i915), (domain), (wf)), (wf) = NULL)
#define with_intel_display_power(display, domain, wf) \
for ((wf) = intel_display_power_get((display), (domain)); (wf); \
intel_display_power_put_async((display), (domain), (wf)), (wf) = NULL)
#define with_intel_display_power_if_enabled(i915, domain, wf) \
for ((wf) = intel_display_power_get_if_enabled((i915), (domain)); (wf); \
intel_display_power_put_async((i915), (domain), (wf)), (wf) = NULL)
#define with_intel_display_power_if_enabled(display, domain, wf) \
for ((wf) = intel_display_power_get_if_enabled((display), (domain)); (wf); \
intel_display_power_put_async((display), (domain), (wf)), (wf) = NULL)
#endif /* __INTEL_DISPLAY_POWER_H__ */

View File

@ -507,7 +507,6 @@ static void
icl_tc_phy_aux_power_well_enable(struct intel_display *display,
struct i915_power_well *power_well)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
enum aux_ch aux_ch = icl_aux_pw_to_ch(power_well);
struct intel_digital_port *dig_port = aux_ch_to_digital_port(display, aux_ch);
const struct i915_power_well_regs *regs = power_well->desc->ops->regs;
@ -539,7 +538,7 @@ icl_tc_phy_aux_power_well_enable(struct intel_display *display,
tc_port = TGL_AUX_PW_TO_TC_PORT(i915_power_well_instance(power_well)->hsw.idx);
if (wait_for(intel_dkl_phy_read(dev_priv, DKL_CMN_UC_DW_27(tc_port)) &
if (wait_for(intel_dkl_phy_read(display, DKL_CMN_UC_DW_27(tc_port)) &
DKL_CMN_UC_DW27_UC_HEALTH, 1))
drm_warn(display->drm,
"Timeout waiting TC uC health\n");
@ -962,8 +961,7 @@ static bool gen9_dc_off_power_well_enabled(struct intel_display *display,
static void gen9_assert_dbuf_enabled(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
u8 hw_enabled_dbuf_slices = intel_enabled_dbuf_slices_mask(dev_priv);
u8 hw_enabled_dbuf_slices = intel_enabled_dbuf_slices_mask(display);
u8 enabled_dbuf_slices = display->dbuf.enabled_slices;
drm_WARN(display->drm,
@ -975,7 +973,6 @@ static void gen9_assert_dbuf_enabled(struct intel_display *display)
void gen9_disable_dc_states(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct i915_power_domains *power_domains = &display->power.domains;
struct intel_cdclk_config cdclk_config = {};
u32 old_state = power_domains->dc_state;
@ -1015,7 +1012,7 @@ void gen9_disable_dc_states(struct intel_display *display)
* PHY's HW context for port B is lost after DC transitions,
* so we need to restore it manually.
*/
intel_combo_phy_init(dev_priv);
intel_combo_phy_init(display);
}
static void gen9_dc_off_power_well_enable(struct intel_display *display,
@ -1314,11 +1311,10 @@ static void vlv_dpio_cmn_power_well_enable(struct intel_display *display,
static void vlv_dpio_cmn_power_well_disable(struct intel_display *display,
struct i915_power_well *power_well)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
enum pipe pipe;
for_each_pipe(display, pipe)
assert_pll_disabled(dev_priv, pipe);
assert_pll_disabled(display, pipe);
/* Assert common reset */
intel_de_rmw(display, DPIO_CTL, DPIO_CMNRST, 0);
@ -1500,7 +1496,6 @@ static void chv_dpio_cmn_power_well_enable(struct intel_display *display,
static void chv_dpio_cmn_power_well_disable(struct intel_display *display,
struct i915_power_well *power_well)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
enum i915_power_well_id id = i915_power_well_instance(power_well)->id;
enum dpio_phy phy;
@ -1510,11 +1505,11 @@ static void chv_dpio_cmn_power_well_disable(struct intel_display *display,
if (id == VLV_DISP_PW_DPIO_CMN_BC) {
phy = DPIO_PHY0;
assert_pll_disabled(dev_priv, PIPE_A);
assert_pll_disabled(dev_priv, PIPE_B);
assert_pll_disabled(display, PIPE_A);
assert_pll_disabled(display, PIPE_B);
} else {
phy = DPIO_PHY1;
assert_pll_disabled(dev_priv, PIPE_C);
assert_pll_disabled(display, PIPE_C);
}
display->power.chv_phy_control &= ~PHY_COM_LANE_RESET_DEASSERT(phy);

View File

@ -60,7 +60,7 @@ struct i915_power_well_instance {
/* unique identifier for this power well */
enum i915_power_well_id id;
/*
* Arbitraty data associated with this power well. Platform and power
* Arbitrary data associated with this power well. Platform and power
* well specific.
*/
union {
@ -77,7 +77,7 @@ struct i915_power_well_instance {
struct {
/*
* request/status flag index in the power well
* constrol/status registers.
* control/status registers.
*/
u8 idx;
} hsw;

View File

@ -7,6 +7,7 @@
#include "i915_drv.h"
#include "intel_clock_gating.h"
#include "intel_cx0_phy.h"
#include "intel_display_driver.h"
#include "intel_display_reset.h"
#include "intel_display_types.h"
@ -116,6 +117,7 @@ void intel_display_reset_finish(struct drm_i915_private *i915)
intel_pps_unlock_regs_wa(display);
intel_display_driver_init_hw(display);
intel_clock_gating_init(i915);
intel_cx0_pll_power_save_wa(display);
intel_hpd_init(i915);
ret = __intel_display_driver_resume(display, state, ctx);

View File

@ -4,7 +4,11 @@
*/
#undef TRACE_SYSTEM
#ifdef I915
#define TRACE_SYSTEM i915
#else
#define TRACE_SYSTEM xe
#endif
#if !defined(__INTEL_DISPLAY_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ)
#define __INTEL_DISPLAY_TRACE_H__
@ -21,6 +25,7 @@
#include "intel_vblank.h"
#define __dev_name_display(display) dev_name((display)->drm->dev)
#define __dev_name_drm(obj) dev_name((obj)->dev->dev)
#define __dev_name_kms(obj) dev_name((obj)->base.dev->dev)
/*
@ -397,23 +402,24 @@ TRACE_EVENT(intel_plane_async_flip,
__entry->async_flip = async_flip;
),
TP_printk("dev %s, pipe %c, plane %s, frame=%u, scanline=%u, async_flip=%s",
TP_printk("dev %s, pipe %c, %s, frame=%u, scanline=%u, async_flip=%s",
__get_str(dev), __entry->pipe_name, __get_str(name),
__entry->frame, __entry->scanline, str_yes_no(__entry->async_flip))
);
TRACE_EVENT(intel_plane_update_noarm,
TP_PROTO(struct intel_plane *plane, struct intel_crtc *crtc),
TP_ARGS(plane, crtc),
TP_PROTO(const struct intel_plane_state *plane_state, struct intel_crtc *crtc),
TP_ARGS(plane_state, crtc),
TP_STRUCT__entry(
__string(dev, __dev_name_kms(plane))
__string(dev, __dev_name_drm(plane_state->uapi.plane))
__field(char, pipe_name)
__field(u32, frame)
__field(u32, scanline)
__field(u32, format)
__array(int, src, 4)
__array(int, dst, 4)
__string(name, plane->base.name)
__string(name, plane_state->uapi.plane->name)
),
TP_fast_assign(
@ -422,29 +428,31 @@ TRACE_EVENT(intel_plane_update_noarm,
__entry->pipe_name = pipe_name(crtc->pipe);
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
memcpy(__entry->src, &plane->base.state->src, sizeof(__entry->src));
memcpy(__entry->dst, &plane->base.state->dst, sizeof(__entry->dst));
__entry->format = plane_state->hw.fb->format->format;
memcpy(__entry->src, &plane_state->uapi.src, sizeof(__entry->src));
memcpy(__entry->dst, &plane_state->uapi.dst, sizeof(__entry->dst));
),
TP_printk("dev %s, pipe %c, plane %s, frame=%u, scanline=%u, " DRM_RECT_FP_FMT " -> " DRM_RECT_FMT,
TP_printk("dev %s, pipe %c, %s, frame=%u, scanline=%u, format=%p4cc, " DRM_RECT_FP_FMT " -> " DRM_RECT_FMT,
__get_str(dev), __entry->pipe_name, __get_str(name),
__entry->frame, __entry->scanline,
__entry->frame, __entry->scanline, &__entry->format,
DRM_RECT_FP_ARG((const struct drm_rect *)__entry->src),
DRM_RECT_ARG((const struct drm_rect *)__entry->dst))
);
TRACE_EVENT(intel_plane_update_arm,
TP_PROTO(struct intel_plane *plane, struct intel_crtc *crtc),
TP_ARGS(plane, crtc),
TP_PROTO(const struct intel_plane_state *plane_state, struct intel_crtc *crtc),
TP_ARGS(plane_state, crtc),
TP_STRUCT__entry(
__string(dev, __dev_name_kms(plane))
__string(dev, __dev_name_drm(plane_state->uapi.plane))
__field(char, pipe_name)
__field(u32, frame)
__field(u32, scanline)
__field(u32, format)
__array(int, src, 4)
__array(int, dst, 4)
__string(name, plane->base.name)
__string(name, plane_state->uapi.plane->name)
),
TP_fast_assign(
@ -453,13 +461,14 @@ TRACE_EVENT(intel_plane_update_arm,
__entry->pipe_name = pipe_name(crtc->pipe);
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
memcpy(__entry->src, &plane->base.state->src, sizeof(__entry->src));
memcpy(__entry->dst, &plane->base.state->dst, sizeof(__entry->dst));
__entry->format = plane_state->hw.fb->format->format;
memcpy(__entry->src, &plane_state->uapi.src, sizeof(__entry->src));
memcpy(__entry->dst, &plane_state->uapi.dst, sizeof(__entry->dst));
),
TP_printk("dev %s, pipe %c, plane %s, frame=%u, scanline=%u, " DRM_RECT_FP_FMT " -> " DRM_RECT_FMT,
TP_printk("dev %s, pipe %c, %s, frame=%u, scanline=%u, format=%p4cc, " DRM_RECT_FP_FMT " -> " DRM_RECT_FMT,
__get_str(dev), __entry->pipe_name, __get_str(name),
__entry->frame, __entry->scanline,
__entry->frame, __entry->scanline, &__entry->format,
DRM_RECT_FP_ARG((const struct drm_rect *)__entry->src),
DRM_RECT_ARG((const struct drm_rect *)__entry->dst))
);
@ -484,11 +493,110 @@ TRACE_EVENT(intel_plane_disable_arm,
__entry->scanline = intel_get_crtc_scanline(crtc);
),
TP_printk("dev %s, pipe %c, plane %s, frame=%u, scanline=%u",
TP_printk("dev %s, pipe %c, %s, frame=%u, scanline=%u",
__get_str(dev), __entry->pipe_name, __get_str(name),
__entry->frame, __entry->scanline)
);
TRACE_EVENT(intel_plane_scaler_update_arm,
TP_PROTO(struct intel_plane *plane,
int scaler_id, int x, int y, int w, int h),
TP_ARGS(plane, scaler_id, x, y, w, h),
TP_STRUCT__entry(
__string(dev, __dev_name_kms(plane))
__field(char, pipe_name)
__field(int, scaler_id)
__field(u32, frame)
__field(u32, scanline)
__field(int, x)
__field(int, y)
__field(int, w)
__field(int, h)
__string(name, plane->base.name)
),
TP_fast_assign(
struct intel_display *display = to_intel_display(plane);
struct intel_crtc *crtc = intel_crtc_for_pipe(display, plane->pipe);
__assign_str(dev);
__assign_str(name);
__entry->pipe_name = pipe_name(crtc->pipe);
__entry->scaler_id = scaler_id;
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
__entry->x = x;
__entry->y = y;
__entry->w = w;
__entry->h = h;
),
TP_printk("dev %s, pipe %c, scaler %d, plane %s, frame=%u, scanline=%u, " DRM_RECT_FMT,
__get_str(dev), __entry->pipe_name, __entry->scaler_id,
__get_str(name), __entry->frame, __entry->scanline,
__entry->w, __entry->h, __entry->x, __entry->y)
);
TRACE_EVENT(intel_pipe_scaler_update_arm,
TP_PROTO(struct intel_crtc *crtc, int scaler_id,
int x, int y, int w, int h),
TP_ARGS(crtc, scaler_id, x, y, w, h),
TP_STRUCT__entry(
__string(dev, __dev_name_kms(crtc))
__field(char, pipe_name)
__field(int, scaler_id)
__field(u32, frame)
__field(u32, scanline)
__field(int, x)
__field(int, y)
__field(int, w)
__field(int, h)
),
TP_fast_assign(
__assign_str(dev);
__entry->pipe_name = pipe_name(crtc->pipe);
__entry->scaler_id = scaler_id;
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
__entry->x = x;
__entry->y = y;
__entry->w = w;
__entry->h = h;
),
TP_printk("dev %s, pipe %c, scaler %d frame=%u, scanline=%u, " DRM_RECT_FMT,
__get_str(dev), __entry->pipe_name, __entry->scaler_id,
__entry->frame, __entry->scanline,
__entry->w, __entry->h, __entry->x, __entry->y)
);
TRACE_EVENT(intel_scaler_disable_arm,
TP_PROTO(struct intel_crtc *crtc, int scaler_id),
TP_ARGS(crtc, scaler_id),
TP_STRUCT__entry(
__string(dev, __dev_name_kms(crtc))
__field(char, pipe_name)
__field(int, scaler_id)
__field(u32, frame)
__field(u32, scanline)
),
TP_fast_assign(
__assign_str(dev);
__entry->pipe_name = pipe_name(crtc->pipe);
__entry->scaler_id = scaler_id;
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
),
TP_printk("dev %s, pipe %c, scaler %d, frame=%u, scanline=%u",
__get_str(dev), __entry->pipe_name, __entry->scaler_id,
__entry->frame, __entry->scanline)
);
TRACE_EVENT(intel_fbc_activate,
TP_PROTO(struct intel_plane *plane),
TP_ARGS(plane),
@ -512,7 +620,7 @@ TRACE_EVENT(intel_fbc_activate,
__entry->scanline = intel_get_crtc_scanline(crtc);
),
TP_printk("dev %s, pipe %c, plane %s, frame=%u, scanline=%u",
TP_printk("dev %s, pipe %c, %s, frame=%u, scanline=%u",
__get_str(dev), __entry->pipe_name, __get_str(name),
__entry->frame, __entry->scanline)
);
@ -540,7 +648,7 @@ TRACE_EVENT(intel_fbc_deactivate,
__entry->scanline = intel_get_crtc_scanline(crtc);
),
TP_printk("dev %s, pipe %c, plane %s, frame=%u, scanline=%u",
TP_printk("dev %s, pipe %c, %s, frame=%u, scanline=%u",
__get_str(dev), __entry->pipe_name, __get_str(name),
__entry->frame, __entry->scanline)
);
@ -568,7 +676,7 @@ TRACE_EVENT(intel_fbc_nuke,
__entry->scanline = intel_get_crtc_scanline(crtc);
),
TP_printk("dev %s, pipe %c, plane %s, frame=%u, scanline=%u",
TP_printk("dev %s, pipe %c, %s, frame=%u, scanline=%u",
__get_str(dev), __entry->pipe_name, __get_str(name),
__entry->frame, __entry->scanline)
);

View File

@ -144,6 +144,7 @@ struct intel_framebuffer {
struct i915_address_space *dpt_vm;
unsigned int min_alignment;
unsigned int vtd_guard;
};
enum intel_hotplug_state {
@ -412,6 +413,7 @@ struct intel_panel {
union {
struct {
struct drm_edp_backlight_info info;
bool luminance_control_support;
} vesa;
struct {
bool sdr_uses_aux;
@ -494,6 +496,8 @@ struct intel_hdcp {
enum transcoder cpu_transcoder;
/* Only used for DP MST stream encryption */
enum transcoder stream_transcoder;
/* Used to force HDCP 1.4 bypassing HDCP 2.x */
bool force_hdcp14;
};
struct intel_connector {
@ -638,6 +642,9 @@ struct intel_plane_state {
/* Plane state to display black pixels when pxp is borked */
bool force_black;
/* Acting as Y plane for another UV plane? */
bool is_y_plane;
/* plane control register */
u32 ctl;
@ -677,16 +684,6 @@ struct intel_plane_state {
*/
struct intel_plane *planar_linked_plane;
/*
* planar_slave:
* If set don't update use the linked plane's state for updating
* this plane during atomic commit with the update_slave() callback.
*
* It's also used by the watermark code to ignore wm calculations on
* this plane. They're calculated by the linked plane's wm code.
*/
u32 planar_slave;
struct drm_intel_sprite_colorkey ckey;
struct drm_rect psr2_sel_fetch_area;
@ -711,6 +708,8 @@ struct intel_initial_plane_config {
struct intel_scaler {
u32 mode;
bool in_use;
int hscale;
int vscale;
};
struct intel_crtc_scaler_state {
@ -732,7 +731,7 @@ struct intel_crtc_scaler_state {
*
* intel_atomic_setup_scalers will setup available scalers to users
* requesting scalers. It will gracefully fail if request exceeds
* avilability.
* availability.
*/
#define SKL_CRTC_INDEX 31
unsigned scaler_users;
@ -1095,6 +1094,7 @@ struct intel_crtc_state {
int max_link_bpp_x16; /* in 1/16 bpp units */
int pipe_bpp; /* in 1 bpp units */
int min_hblank;
struct intel_link_m_n dp_m_n;
/* m2_n2 for eDP downclock */
@ -1113,7 +1113,7 @@ struct intel_crtc_state {
u16 su_y_granularity;
/*
* Frequence the dpll for the port should run at. Differs from the
* Frequency the dpll for the port should run at. Differs from the
* adjusted dotclock e.g. for DP or 10/12bpc hdmi mode. This is also
* already multiplied by pixel_multiplier.
*/
@ -1439,12 +1439,17 @@ struct intel_crtc {
bool block_dc_for_vblank;
};
struct intel_plane_error {
u32 ctl, surf, surflive;
};
struct intel_plane {
struct drm_plane base;
enum i9xx_plane_id i9xx_plane;
enum plane_id id;
enum pipe pipe;
bool need_async_flip_toggle_wa;
u8 vtd_guard;
u32 frontbuffer_bit;
struct {
@ -1474,6 +1479,7 @@ struct intel_plane {
unsigned int (*max_stride)(struct intel_plane *plane,
u32 pixel_format, u64 modifier,
unsigned int rotation);
bool (*can_async_flip)(u64 modifier);
/* Write all non-self arming plane registers */
void (*update_noarm)(struct intel_dsb *dsb,
struct intel_plane *plane,
@ -1488,6 +1494,9 @@ struct intel_plane {
void (*disable_arm)(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state);
void (*capture_error)(struct intel_crtc *crtc,
struct intel_plane *plane,
struct intel_plane_error *error);
bool (*get_hw_state)(struct intel_plane *plane, enum pipe *pipe);
int (*check_plane)(struct intel_crtc_state *crtc_state,
struct intel_plane_state *plane_state);
@ -1979,24 +1988,12 @@ static inline bool intel_encoder_is_hdmi(struct intel_encoder *encoder)
}
}
static inline struct intel_lspcon *
enc_to_intel_lspcon(struct intel_encoder *encoder)
{
return &enc_to_dig_port(encoder)->lspcon;
}
static inline struct intel_digital_port *
dp_to_dig_port(struct intel_dp *intel_dp)
{
return container_of(intel_dp, struct intel_digital_port, dp);
}
static inline struct intel_lspcon *
dp_to_lspcon(struct intel_dp *intel_dp)
{
return &dp_to_dig_port(intel_dp)->lspcon;
}
static inline struct intel_digital_port *
hdmi_to_dig_port(struct intel_hdmi *intel_hdmi)
{

View File

@ -20,20 +20,20 @@ void intel_dkl_phy_init(struct drm_i915_private *i915)
}
static void
dkl_phy_set_hip_idx(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg)
dkl_phy_set_hip_idx(struct intel_display *display, struct intel_dkl_phy_reg reg)
{
enum tc_port tc_port = DKL_REG_TC_PORT(reg);
drm_WARN_ON(&i915->drm, tc_port < TC_PORT_1 || tc_port >= I915_MAX_TC_PORTS);
drm_WARN_ON(display->drm, tc_port < TC_PORT_1 || tc_port >= I915_MAX_TC_PORTS);
intel_de_write(i915,
intel_de_write(display,
HIP_INDEX_REG(tc_port),
HIP_INDEX_VAL(tc_port, reg.bank_idx));
}
/**
* intel_dkl_phy_read - read a Dekel PHY register
* @i915: i915 device instance
* @display: intel_display device instance
* @reg: Dekel PHY register
*
* Read the @reg Dekel PHY register.
@ -41,42 +41,42 @@ dkl_phy_set_hip_idx(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg)
* Returns the read value.
*/
u32
intel_dkl_phy_read(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg)
intel_dkl_phy_read(struct intel_display *display, struct intel_dkl_phy_reg reg)
{
u32 val;
spin_lock(&i915->display.dkl.phy_lock);
spin_lock(&display->dkl.phy_lock);
dkl_phy_set_hip_idx(i915, reg);
val = intel_de_read(i915, DKL_REG_MMIO(reg));
dkl_phy_set_hip_idx(display, reg);
val = intel_de_read(display, DKL_REG_MMIO(reg));
spin_unlock(&i915->display.dkl.phy_lock);
spin_unlock(&display->dkl.phy_lock);
return val;
}
/**
* intel_dkl_phy_write - write a Dekel PHY register
* @i915: i915 device instance
* @display: intel_display device instance
* @reg: Dekel PHY register
* @val: value to write
*
* Write @val to the @reg Dekel PHY register.
*/
void
intel_dkl_phy_write(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg, u32 val)
intel_dkl_phy_write(struct intel_display *display, struct intel_dkl_phy_reg reg, u32 val)
{
spin_lock(&i915->display.dkl.phy_lock);
spin_lock(&display->dkl.phy_lock);
dkl_phy_set_hip_idx(i915, reg);
intel_de_write(i915, DKL_REG_MMIO(reg), val);
dkl_phy_set_hip_idx(display, reg);
intel_de_write(display, DKL_REG_MMIO(reg), val);
spin_unlock(&i915->display.dkl.phy_lock);
spin_unlock(&display->dkl.phy_lock);
}
/**
* intel_dkl_phy_rmw - read-modify-write a Dekel PHY register
* @i915: i915 device instance
* @display: display device instance
* @reg: Dekel PHY register
* @clear: mask to clear
* @set: mask to set
@ -85,30 +85,30 @@ intel_dkl_phy_write(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg,
* this value back to the register if the value differs from the read one.
*/
void
intel_dkl_phy_rmw(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg, u32 clear, u32 set)
intel_dkl_phy_rmw(struct intel_display *display, struct intel_dkl_phy_reg reg, u32 clear, u32 set)
{
spin_lock(&i915->display.dkl.phy_lock);
spin_lock(&display->dkl.phy_lock);
dkl_phy_set_hip_idx(i915, reg);
intel_de_rmw(i915, DKL_REG_MMIO(reg), clear, set);
dkl_phy_set_hip_idx(display, reg);
intel_de_rmw(display, DKL_REG_MMIO(reg), clear, set);
spin_unlock(&i915->display.dkl.phy_lock);
spin_unlock(&display->dkl.phy_lock);
}
/**
* intel_dkl_phy_posting_read - do a posting read from a Dekel PHY register
* @i915: i915 device instance
* @display: display device instance
* @reg: Dekel PHY register
*
* Read the @reg Dekel PHY register without returning the read value.
*/
void
intel_dkl_phy_posting_read(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg)
intel_dkl_phy_posting_read(struct intel_display *display, struct intel_dkl_phy_reg reg)
{
spin_lock(&i915->display.dkl.phy_lock);
spin_lock(&display->dkl.phy_lock);
dkl_phy_set_hip_idx(i915, reg);
intel_de_posting_read(i915, DKL_REG_MMIO(reg));
dkl_phy_set_hip_idx(display, reg);
intel_de_posting_read(display, DKL_REG_MMIO(reg));
spin_unlock(&i915->display.dkl.phy_lock);
spin_unlock(&display->dkl.phy_lock);
}

View File

@ -11,15 +11,16 @@
#include "intel_dkl_phy_regs.h"
struct drm_i915_private;
struct intel_display;
void intel_dkl_phy_init(struct drm_i915_private *i915);
u32
intel_dkl_phy_read(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg);
intel_dkl_phy_read(struct intel_display *display, struct intel_dkl_phy_reg reg);
void
intel_dkl_phy_write(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg, u32 val);
intel_dkl_phy_write(struct intel_display *display, struct intel_dkl_phy_reg reg, u32 val);
void
intel_dkl_phy_rmw(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg, u32 clear, u32 set);
intel_dkl_phy_rmw(struct intel_display *display, struct intel_dkl_phy_reg reg, u32 clear, u32 set);
void
intel_dkl_phy_posting_read(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg);
intel_dkl_phy_posting_read(struct intel_display *display, struct intel_dkl_phy_reg reg);
#endif /* __INTEL_DKL_PHY_H__ */

View File

@ -992,19 +992,16 @@ static int parse_dmc_fw(struct intel_dmc *dmc, const struct firmware *fw)
static void intel_dmc_runtime_pm_get(struct intel_display *display)
{
struct drm_i915_private *i915 = to_i915(display->drm);
drm_WARN_ON(display->drm, display->dmc.wakeref);
display->dmc.wakeref = intel_display_power_get(i915, POWER_DOMAIN_INIT);
display->dmc.wakeref = intel_display_power_get(display, POWER_DOMAIN_INIT);
}
static void intel_dmc_runtime_pm_put(struct intel_display *display)
{
struct drm_i915_private *i915 = to_i915(display->drm);
intel_wakeref_t wakeref __maybe_unused =
fetch_and_zero(&display->dmc.wakeref);
intel_display_power_put(i915, POWER_DOMAIN_INIT, wakeref);
intel_display_power_put(display, POWER_DOMAIN_INIT, wakeref);
}
static const char *dmc_fallback_path(struct intel_display *display)

View File

@ -10,7 +10,6 @@
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_de.h"
#include "intel_dmc.h"
#include "intel_dmc_regs.h"
#include "intel_dmc_wl.h"
@ -50,12 +49,24 @@
#define DMC_WAKELOCK_CTL_TIMEOUT_US 5000
#define DMC_WAKELOCK_HOLD_TIME 50
/*
* Possible non-negative values for the enable_dmc_wl param.
*/
enum {
ENABLE_DMC_WL_DISABLED,
ENABLE_DMC_WL_ENABLED,
ENABLE_DMC_WL_ANY_REGISTER,
ENABLE_DMC_WL_ALWAYS_LOCKED,
ENABLE_DMC_WL_MAX,
};
struct intel_dmc_wl_range {
u32 start;
u32 end;
};
static const struct intel_dmc_wl_range powered_off_ranges[] = {
{ .start = 0x44400, .end = 0x4447f }, /* PIPE interrupt registers */
{ .start = 0x60000, .end = 0x7ffff },
{},
};
@ -90,6 +101,7 @@ static const struct intel_dmc_wl_range xe3lpd_dc5_dc6_dmc_ranges[] = {
{ .start = 0x42088 }, /* CHICKEN_MISC_3 */
{ .start = 0x46160 }, /* CMTG_CLK_SEL */
{ .start = 0x8f000, .end = 0x8ffff }, /* Main DMC registers */
{ .start = 0x45230 }, /* INITIATE_PM_DMD_REQ */
{},
};
@ -230,10 +242,15 @@ static bool intel_dmc_wl_reg_in_range(i915_reg_t reg,
return false;
}
static bool intel_dmc_wl_check_range(i915_reg_t reg, u32 dc_state)
static bool intel_dmc_wl_check_range(struct intel_display *display,
i915_reg_t reg,
u32 dc_state)
{
const struct intel_dmc_wl_range *ranges;
if (display->params.enable_dmc_wl == ENABLE_DMC_WL_ANY_REGISTER)
return true;
/*
* Check that the offset is in one of the ranges for which
* registers are powered off during DC states.
@ -265,20 +282,48 @@ static bool intel_dmc_wl_check_range(i915_reg_t reg, u32 dc_state)
static bool __intel_dmc_wl_supported(struct intel_display *display)
{
return display->params.enable_dmc_wl && intel_dmc_has_payload(display);
return display->params.enable_dmc_wl;
}
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;
const char *desc;
drm_dbg_kms(display->drm, "Sanitized enable_dmc_wl value: %d\n",
display->params.enable_dmc_wl);
if (!HAS_DMC_WAKELOCK(display)) {
display->params.enable_dmc_wl = ENABLE_DMC_WL_DISABLED;
} else if (display->params.enable_dmc_wl < 0) {
if (DISPLAY_VER(display) >= 30)
display->params.enable_dmc_wl = ENABLE_DMC_WL_ENABLED;
else
display->params.enable_dmc_wl = ENABLE_DMC_WL_DISABLED;
} else if (display->params.enable_dmc_wl >= ENABLE_DMC_WL_MAX) {
display->params.enable_dmc_wl = ENABLE_DMC_WL_ENABLED;
}
drm_WARN_ON(display->drm,
display->params.enable_dmc_wl < 0 ||
display->params.enable_dmc_wl >= ENABLE_DMC_WL_MAX);
switch (display->params.enable_dmc_wl) {
case ENABLE_DMC_WL_DISABLED:
desc = "disabled";
break;
case ENABLE_DMC_WL_ENABLED:
desc = "enabled";
break;
case ENABLE_DMC_WL_ANY_REGISTER:
desc = "match any register";
break;
case ENABLE_DMC_WL_ALWAYS_LOCKED:
desc = "always locked";
break;
default:
desc = "unknown";
break;
}
drm_dbg_kms(display->drm, "Sanitized enable_dmc_wl value: %d (%s)\n",
display->params.enable_dmc_wl, desc);
}
void intel_dmc_wl_init(struct intel_display *display)
@ -292,7 +337,8 @@ void intel_dmc_wl_init(struct intel_display *display)
INIT_DELAYED_WORK(&wl->work, intel_dmc_wl_work);
spin_lock_init(&wl->lock);
refcount_set(&wl->refcount, 0);
refcount_set(&wl->refcount,
display->params.enable_dmc_wl == ENABLE_DMC_WL_ALWAYS_LOCKED ? 1 : 0);
}
/* Must only be called as part of enabling dynamic DC states. */
@ -398,7 +444,8 @@ void intel_dmc_wl_get(struct intel_display *display, i915_reg_t reg)
spin_lock_irqsave(&wl->lock, flags);
if (i915_mmio_reg_valid(reg) && !intel_dmc_wl_check_range(reg, wl->dc_state))
if (i915_mmio_reg_valid(reg) &&
!intel_dmc_wl_check_range(display, reg, wl->dc_state))
goto out_unlock;
if (!wl->enabled) {
@ -430,7 +477,8 @@ void intel_dmc_wl_put(struct intel_display *display, i915_reg_t reg)
spin_lock_irqsave(&wl->lock, flags);
if (i915_mmio_reg_valid(reg) && !intel_dmc_wl_check_range(reg, wl->dc_state))
if (i915_mmio_reg_valid(reg) &&
!intel_dmc_wl_check_range(display, reg, wl->dc_state))
goto out_unlock;
if (WARN_RATELIMIT(!refcount_read(&wl->refcount),

View File

@ -1075,7 +1075,7 @@ static bool source_can_output(struct intel_dp *intel_dp,
/*
* No YCbCr output support on gmch platforms.
* Also, ILK doesn't seem capable of DP YCbCr output.
* The displayed image is severly corrupted. SNB+ is fine.
* The displayed image is severely corrupted. SNB+ is fine.
*/
return !HAS_GMCH(display) && !display->platform.ironlake;
@ -1396,7 +1396,6 @@ intel_dp_mode_valid(struct drm_connector *_connector,
struct intel_display *display = to_intel_display(_connector->dev);
struct intel_connector *connector = to_intel_connector(_connector);
struct intel_dp *intel_dp = intel_attached_dp(connector);
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
const struct drm_display_mode *fixed_mode;
int target_clock = mode->clock;
int max_rate, mode_rate, max_lanes, max_link_clock;
@ -1407,7 +1406,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
bool dsc = false;
int num_joined_pipes;
status = intel_cpu_transcoder_mode_valid(dev_priv, mode);
status = intel_cpu_transcoder_mode_valid(display, mode);
if (status != MODE_OK)
return status;
@ -1496,7 +1495,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
if (status != MODE_OK)
return status;
return intel_mode_valid_max_plane_size(dev_priv, mode, num_joined_pipes);
return intel_mode_valid_max_plane_size(display, mode, num_joined_pipes);
}
bool intel_dp_source_supports_tps3(struct intel_display *display)
@ -1926,7 +1925,7 @@ static bool intel_dp_dsc_supports_format(const struct intel_connector *connector
return drm_dp_dsc_sink_supports_format(connector->dp.dsc_dpcd, sink_dsc_format);
}
static bool is_bw_sufficient_for_dsc_config(u16 compressed_bppx16, u32 link_clock,
static bool is_bw_sufficient_for_dsc_config(int dsc_bpp_x16, u32 link_clock,
u32 lane_count, u32 mode_clock,
enum intel_output_format output_format,
int timeslots)
@ -1934,15 +1933,16 @@ static bool is_bw_sufficient_for_dsc_config(u16 compressed_bppx16, u32 link_cloc
u32 available_bw, required_bw;
available_bw = (link_clock * lane_count * timeslots * 16) / 8;
required_bw = compressed_bppx16 * (intel_dp_mode_to_fec_clock(mode_clock));
required_bw = dsc_bpp_x16 * (intel_dp_mode_to_fec_clock(mode_clock));
return available_bw > required_bw;
}
static int dsc_compute_link_config(struct intel_dp *intel_dp,
struct intel_crtc_state *pipe_config,
struct link_config_limits *limits,
u16 compressed_bppx16,
struct drm_connector_state *conn_state,
const struct link_config_limits *limits,
int dsc_bpp_x16,
int timeslots)
{
const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
@ -1957,15 +1957,37 @@ static int dsc_compute_link_config(struct intel_dp *intel_dp,
for (lane_count = limits->min_lane_count;
lane_count <= limits->max_lane_count;
lane_count <<= 1) {
if (!is_bw_sufficient_for_dsc_config(compressed_bppx16, link_rate,
lane_count, adjusted_mode->clock,
pipe_config->output_format,
timeslots))
continue;
/*
* FIXME: intel_dp_mtp_tu_compute_config() requires
* ->lane_count and ->port_clock set before we know
* they'll work. If we end up failing altogether,
* they'll remain in crtc state. This shouldn't matter,
* as we'd then bail out from compute config, but it's
* just ugly.
*/
pipe_config->lane_count = lane_count;
pipe_config->port_clock = link_rate;
if (drm_dp_is_uhbr_rate(link_rate)) {
int ret;
ret = intel_dp_mtp_tu_compute_config(intel_dp,
pipe_config,
conn_state,
dsc_bpp_x16,
dsc_bpp_x16,
0, true);
if (ret)
continue;
} else {
if (!is_bw_sufficient_for_dsc_config(dsc_bpp_x16, link_rate,
lane_count, adjusted_mode->clock,
pipe_config->output_format,
timeslots))
continue;
}
return 0;
}
}
@ -2055,111 +2077,66 @@ static int dsc_src_max_compressed_bpp(struct intel_dp *intel_dp)
}
/*
* From a list of valid compressed bpps try different compressed bpp and find a
* suitable link configuration that can support it.
* Note: for pre-13 display you still need to check the validity of each step.
*/
static int
icl_dsc_compute_link_config(struct intel_dp *intel_dp,
struct intel_crtc_state *pipe_config,
struct link_config_limits *limits,
int dsc_max_bpp,
int dsc_min_bpp,
int pipe_bpp,
int timeslots)
static int intel_dp_dsc_bpp_step_x16(const struct intel_connector *connector)
{
int i, ret;
struct intel_display *display = to_intel_display(connector);
u8 incr = drm_dp_dsc_sink_bpp_incr(connector->dp.dsc_dpcd);
/* Compressed BPP should be less than the Input DSC bpp */
dsc_max_bpp = min(dsc_max_bpp, pipe_bpp - 1);
if (DISPLAY_VER(display) < 14 || !incr)
return fxp_q4_from_int(1);
for (i = ARRAY_SIZE(valid_dsc_bpp) - 1; i >= 0; i--) {
if (valid_dsc_bpp[i] < dsc_min_bpp ||
valid_dsc_bpp[i] > dsc_max_bpp)
continue;
/* fxp q4 */
return fxp_q4_from_int(1) / incr;
}
ret = dsc_compute_link_config(intel_dp,
pipe_config,
limits,
valid_dsc_bpp[i] << 4,
timeslots);
if (ret == 0) {
pipe_config->dsc.compressed_bpp_x16 =
fxp_q4_from_int(valid_dsc_bpp[i]);
return 0;
}
/* Note: This is not universally usable! */
static bool intel_dp_dsc_valid_bpp(struct intel_dp *intel_dp, int bpp_x16)
{
struct intel_display *display = to_intel_display(intel_dp);
int i;
if (DISPLAY_VER(display) >= 13) {
if (intel_dp->force_dsc_fractional_bpp_en && !fxp_q4_to_frac(bpp_x16))
return false;
return true;
}
return -EINVAL;
if (fxp_q4_to_frac(bpp_x16))
return false;
for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp); i++) {
if (fxp_q4_to_int(bpp_x16) == valid_dsc_bpp[i])
return true;
}
return false;
}
/*
* From XE_LPD onwards we supports compression bpps in steps of 1 up to
* uncompressed bpp-1. So we start from max compressed bpp and see if any
* link configuration is able to support that compressed bpp, if not we
* step down and check for lower compressed bpp.
* Find the max compressed BPP we can find a link configuration for. The BPPs to
* try depend on the source (platform) and sink.
*/
static int
xelpd_dsc_compute_link_config(struct intel_dp *intel_dp,
const struct intel_connector *connector,
struct intel_crtc_state *pipe_config,
struct link_config_limits *limits,
int dsc_max_bpp,
int dsc_min_bpp,
int pipe_bpp,
int timeslots)
{
struct intel_display *display = to_intel_display(intel_dp);
u8 bppx16_incr = drm_dp_dsc_sink_bpp_incr(connector->dp.dsc_dpcd);
u16 compressed_bppx16;
u8 bppx16_step;
int ret;
if (DISPLAY_VER(display) < 14 || bppx16_incr <= 1)
bppx16_step = 16;
else
bppx16_step = 16 / bppx16_incr;
/* Compressed BPP should be less than the Input DSC bpp */
dsc_max_bpp = min(dsc_max_bpp << 4, (pipe_bpp << 4) - bppx16_step);
dsc_min_bpp = dsc_min_bpp << 4;
for (compressed_bppx16 = dsc_max_bpp;
compressed_bppx16 >= dsc_min_bpp;
compressed_bppx16 -= bppx16_step) {
if (intel_dp->force_dsc_fractional_bpp_en &&
!fxp_q4_to_frac(compressed_bppx16))
continue;
ret = dsc_compute_link_config(intel_dp,
pipe_config,
limits,
compressed_bppx16,
timeslots);
if (ret == 0) {
pipe_config->dsc.compressed_bpp_x16 = compressed_bppx16;
if (intel_dp->force_dsc_fractional_bpp_en &&
fxp_q4_to_frac(compressed_bppx16))
drm_dbg_kms(display->drm,
"Forcing DSC fractional bpp\n");
return 0;
}
}
return -EINVAL;
}
static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp,
const struct intel_connector *connector,
struct intel_crtc_state *pipe_config,
struct link_config_limits *limits,
struct drm_connector_state *conn_state,
const struct link_config_limits *limits,
int pipe_bpp,
int timeslots)
{
struct intel_display *display = to_intel_display(intel_dp);
const struct intel_connector *connector = to_intel_connector(conn_state->connector);
const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
int output_bpp;
int dsc_min_bpp;
int dsc_max_bpp;
int min_bpp_x16, max_bpp_x16, bpp_step_x16;
int dsc_joiner_max_bpp;
int num_joined_pipes = intel_crtc_num_joined_pipes(pipe_config);
int bpp_x16;
int ret;
dsc_min_bpp = fxp_q4_to_int_roundup(limits->link.min_bpp_x16);
@ -2168,11 +2145,38 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp,
num_joined_pipes);
dsc_max_bpp = min(dsc_joiner_max_bpp, fxp_q4_to_int(limits->link.max_bpp_x16));
if (DISPLAY_VER(display) >= 13)
return xelpd_dsc_compute_link_config(intel_dp, connector, pipe_config, limits,
dsc_max_bpp, dsc_min_bpp, pipe_bpp, timeslots);
return icl_dsc_compute_link_config(intel_dp, pipe_config, limits,
dsc_max_bpp, dsc_min_bpp, pipe_bpp, timeslots);
/* FIXME: remove the round trip via integers */
min_bpp_x16 = fxp_q4_from_int(dsc_min_bpp);
max_bpp_x16 = fxp_q4_from_int(dsc_max_bpp);
bpp_step_x16 = intel_dp_dsc_bpp_step_x16(connector);
/* Compressed BPP should be less than the Input DSC bpp */
output_bpp = intel_dp_output_bpp(pipe_config->output_format, pipe_bpp);
max_bpp_x16 = min(max_bpp_x16, fxp_q4_from_int(output_bpp) - bpp_step_x16);
for (bpp_x16 = max_bpp_x16; bpp_x16 >= min_bpp_x16; bpp_x16 -= bpp_step_x16) {
if (!intel_dp_dsc_valid_bpp(intel_dp, bpp_x16))
continue;
ret = dsc_compute_link_config(intel_dp,
pipe_config,
conn_state,
limits,
bpp_x16,
timeslots);
if (ret == 0) {
pipe_config->dsc.compressed_bpp_x16 = bpp_x16;
if (intel_dp->force_dsc_fractional_bpp_en &&
fxp_q4_to_frac(bpp_x16))
drm_dbg_kms(display->drm,
"Forcing DSC fractional bpp\n");
return 0;
}
}
return -EINVAL;
}
int intel_dp_dsc_min_src_input_bpc(void)
@ -2182,7 +2186,7 @@ int intel_dp_dsc_min_src_input_bpc(void)
}
static
bool is_dsc_pipe_bpp_sufficient(struct link_config_limits *limits,
bool is_dsc_pipe_bpp_sufficient(const struct link_config_limits *limits,
int pipe_bpp)
{
return pipe_bpp >= limits->pipe.min_bpp &&
@ -2191,7 +2195,7 @@ bool is_dsc_pipe_bpp_sufficient(struct link_config_limits *limits,
static
int intel_dp_force_dsc_pipe_bpp(struct intel_dp *intel_dp,
struct link_config_limits *limits)
const struct link_config_limits *limits)
{
struct intel_display *display = to_intel_display(intel_dp);
int forced_bpp;
@ -2217,13 +2221,11 @@ int intel_dp_force_dsc_pipe_bpp(struct intel_dp *intel_dp,
static int intel_dp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state,
struct link_config_limits *limits,
const struct link_config_limits *limits,
int timeslots)
{
const struct intel_connector *connector =
to_intel_connector(conn_state->connector);
int dsc_max_bpp;
int dsc_min_bpp;
u8 dsc_bpc[3] = {};
int forced_bpp, pipe_bpp;
int num_bpc, i, ret;
@ -2231,7 +2233,7 @@ static int intel_dp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp,
forced_bpp = intel_dp_force_dsc_pipe_bpp(intel_dp, limits);
if (forced_bpp) {
ret = dsc_compute_compressed_bpp(intel_dp, connector, pipe_config,
ret = dsc_compute_compressed_bpp(intel_dp, pipe_config, conn_state,
limits, forced_bpp, timeslots);
if (ret == 0) {
pipe_config->pipe_bpp = forced_bpp;
@ -2239,9 +2241,6 @@ static int intel_dp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp,
}
}
dsc_max_bpp = limits->pipe.max_bpp;
dsc_min_bpp = limits->pipe.min_bpp;
/*
* Get the maximum DSC bpc that will be supported by any valid
* link configuration and compressed bpp.
@ -2249,11 +2248,10 @@ static int intel_dp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp,
num_bpc = drm_dp_dsc_sink_supported_input_bpcs(connector->dp.dsc_dpcd, dsc_bpc);
for (i = 0; i < num_bpc; i++) {
pipe_bpp = dsc_bpc[i] * 3;
if (pipe_bpp < dsc_min_bpp)
break;
if (pipe_bpp > dsc_max_bpp)
if (pipe_bpp < limits->pipe.min_bpp || pipe_bpp > limits->pipe.max_bpp)
continue;
ret = dsc_compute_compressed_bpp(intel_dp, connector, pipe_config,
ret = dsc_compute_compressed_bpp(intel_dp, pipe_config, conn_state,
limits, pipe_bpp, timeslots);
if (ret == 0) {
pipe_config->pipe_bpp = pipe_bpp;
@ -2267,7 +2265,7 @@ static int intel_dp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp,
static int intel_edp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state,
struct link_config_limits *limits)
const struct link_config_limits *limits)
{
struct intel_display *display = to_intel_display(intel_dp);
struct intel_connector *connector =
@ -2332,9 +2330,8 @@ static void intel_dp_fec_compute_config(struct intel_dp *intel_dp,
int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state,
struct link_config_limits *limits,
int timeslots,
bool compute_pipe_bpp)
const struct link_config_limits *limits,
int timeslots)
{
struct intel_display *display = to_intel_display(intel_dp);
const struct intel_connector *connector =
@ -2342,6 +2339,7 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
const struct drm_display_mode *adjusted_mode =
&pipe_config->hw.adjusted_mode;
int num_joined_pipes = intel_crtc_num_joined_pipes(pipe_config);
bool is_mst = intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST);
int ret;
intel_dp_fec_compute_config(intel_dp, pipe_config);
@ -2350,12 +2348,10 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
return -EINVAL;
/*
* compute pipe bpp is set to false for DP MST DSC case
* and compressed_bpp is calculated same time once
* vpci timeslots are allocated, because overall bpp
* calculation procedure is bit different for MST case.
* Link parameters, pipe bpp and compressed bpp have already been
* figured out for DP MST DSC.
*/
if (compute_pipe_bpp) {
if (!is_mst) {
if (intel_dp_is_edp(intel_dp))
ret = intel_edp_dsc_compute_pipe_bpp(intel_dp, pipe_config,
conn_state, limits);
@ -2518,9 +2514,6 @@ intel_dp_compute_config_limits(struct intel_dp *intel_dp,
limits->min_rate = intel_dp_min_link_rate(intel_dp);
limits->max_rate = intel_dp_max_link_rate(intel_dp);
/* FIXME 128b/132b SST+DSC support missing */
if (!is_mst && dsc)
limits->max_rate = min(limits->max_rate, 810000);
limits->min_rate = min(limits->min_rate, limits->max_rate);
limits->min_lane_count = intel_dp_min_lane_count(intel_dp);
@ -2640,9 +2633,9 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
if (!ret && intel_dp_is_uhbr(pipe_config))
ret = intel_dp_mtp_tu_compute_config(intel_dp,
pipe_config,
pipe_config->pipe_bpp,
pipe_config->pipe_bpp,
conn_state,
fxp_q4_from_int(pipe_config->pipe_bpp),
fxp_q4_from_int(pipe_config->pipe_bpp),
0, false);
if (ret)
dsc_needed = true;
@ -2666,7 +2659,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
return -EINVAL;
ret = intel_dp_dsc_compute_config(intel_dp, pipe_config,
conn_state, &limits, 64, true);
conn_state, &limits, 64);
if (ret < 0)
return ret;
}
@ -2831,15 +2824,14 @@ static void intel_dp_compute_as_sdp(struct intel_dp *intel_dp,
as_sdp->sdp_type = DP_SDP_ADAPTIVE_SYNC;
as_sdp->length = 0x9;
as_sdp->duration_incr_ms = 0;
as_sdp->vtotal = intel_vrr_vmin_vtotal(crtc_state);
if (crtc_state->cmrr.enable) {
as_sdp->mode = DP_AS_SDP_FAVT_TRR_REACHED;
as_sdp->vtotal = adjusted_mode->vtotal;
as_sdp->target_rr = drm_mode_vrefresh(adjusted_mode);
as_sdp->target_rr_divider = true;
} else {
as_sdp->mode = DP_AS_SDP_AVT_DYNAMIC_VTOTAL;
as_sdp->vtotal = adjusted_mode->vtotal;
as_sdp->target_rr = 0;
}
}
@ -3064,15 +3056,6 @@ intel_dp_audio_compute_config(struct intel_encoder *encoder,
intel_dp_is_uhbr(pipe_config);
}
static void intel_dp_queue_modeset_retry_work(struct intel_connector *connector)
{
struct drm_i915_private *i915 = to_i915(connector->base.dev);
drm_connector_get(&connector->base);
if (!queue_work(i915->unordered_wq, &connector->modeset_retry_work))
drm_connector_put(&connector->base);
}
void
intel_dp_queue_modeset_retry_for_link(struct intel_atomic_state *state,
struct intel_encoder *encoder,
@ -3089,7 +3072,7 @@ intel_dp_queue_modeset_retry_for_link(struct intel_atomic_state *state,
intel_dp->needs_modeset_retry = true;
if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) {
intel_dp_queue_modeset_retry_work(intel_dp->attached_connector);
intel_connector_queue_modeset_retry_work(intel_dp->attached_connector);
return;
}
@ -3099,7 +3082,7 @@ intel_dp_queue_modeset_retry_for_link(struct intel_atomic_state *state,
continue;
if (connector->mst_port == intel_dp)
intel_dp_queue_modeset_retry_work(connector);
intel_connector_queue_modeset_retry_work(connector);
}
}
@ -3526,9 +3509,9 @@ void intel_dp_set_power(struct intel_dp *intel_dp, u8 mode)
ret = drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, mode);
} else {
struct intel_lspcon *lspcon = dp_to_lspcon(intel_dp);
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
lspcon_resume(dp_to_dig_port(intel_dp));
intel_lspcon_resume(dig_port);
/* Write the source OUI as early as possible */
intel_dp_init_source_oui(intel_dp);
@ -3544,8 +3527,8 @@ void intel_dp_set_power(struct intel_dp *intel_dp, u8 mode)
msleep(1);
}
if (ret == 1 && lspcon->active)
lspcon_wait_pcon_mode(lspcon);
if (ret == 1 && intel_lspcon_active(dig_port))
intel_lspcon_wait_pcon_mode(dig_port);
}
if (ret != 1)
@ -5395,7 +5378,7 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp)
if (drm_WARN_ON(display->drm, intel_dp_is_edp(intel_dp)))
return connector_status_connected;
lspcon_resume(dig_port);
intel_lspcon_resume(dig_port);
if (!intel_dp_get_dpcd(intel_dp))
return connector_status_disconnected;
@ -5477,13 +5460,13 @@ void intel_digital_port_unlock(struct intel_encoder *encoder)
*/
bool intel_digital_port_connected_locked(struct intel_encoder *encoder)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_display *display = to_intel_display(encoder);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
bool is_glitch_free = intel_tc_port_handles_hpd_glitches(dig_port);
bool is_connected = false;
intel_wakeref_t wakeref;
with_intel_display_power(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref) {
with_intel_display_power(display, POWER_DOMAIN_DISPLAY_CORE, wakeref) {
unsigned long wait_expires = jiffies + msecs_to_jiffies_timeout(4);
do {
@ -5595,7 +5578,7 @@ intel_dp_update_420(struct intel_dp *intel_dp)
intel_dp->downstream_ports);
/* on-board LSPCON always assumed to support 4:4:4->4:2:0 conversion */
intel_dp->dfp.ycbcr_444_to_420 =
dp_to_dig_port(intel_dp)->lspcon.active ||
intel_lspcon_active(dp_to_dig_port(intel_dp)) ||
drm_dp_downstream_444_to_420_conversion(intel_dp->dpcd,
intel_dp->downstream_ports);
intel_dp->dfp.rgb_to_ycbcr =
@ -5869,7 +5852,6 @@ intel_dp_connector_register(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_lspcon *lspcon = &dig_port->lspcon;
int ret;
ret = intel_connector_register(connector);
@ -5891,9 +5873,8 @@ intel_dp_connector_register(struct drm_connector *connector)
* ToDo: Clean this up to handle lspcon init and resume more
* efficiently and streamlined.
*/
if (lspcon_init(dig_port)) {
lspcon_detect_hdr_capability(lspcon);
if (lspcon->hdr_supported)
if (intel_lspcon_init(dig_port)) {
if (intel_lspcon_detect_hdr_capability(dig_port))
drm_connector_attach_hdr_output_metadata_property(connector);
}
@ -6495,35 +6476,6 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
return false;
}
static void intel_dp_modeset_retry_work_fn(struct work_struct *work)
{
struct intel_connector *connector = container_of(work, typeof(*connector),
modeset_retry_work);
struct intel_display *display = to_intel_display(connector);
drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s]\n", connector->base.base.id,
connector->base.name);
/* Grab the locks before changing connector property*/
mutex_lock(&display->drm->mode_config.mutex);
/* Set connector link status to BAD and send a Uevent to notify
* userspace to do a modeset.
*/
drm_connector_set_link_status_property(&connector->base,
DRM_MODE_LINK_STATUS_BAD);
mutex_unlock(&display->drm->mode_config.mutex);
/* Send Hotplug uevent so userspace can reprobe */
drm_kms_helper_connector_hotplug_event(&connector->base);
drm_connector_put(&connector->base);
}
void intel_dp_init_modeset_retry_work(struct intel_connector *connector)
{
INIT_WORK(&connector->modeset_retry_work,
intel_dp_modeset_retry_work_fn);
}
bool
intel_dp_init_connector(struct intel_digital_port *dig_port,
struct intel_connector *connector)
@ -6532,13 +6484,9 @@ intel_dp_init_connector(struct intel_digital_port *dig_port,
struct intel_dp *intel_dp = &dig_port->dp;
struct intel_encoder *encoder = &dig_port->base;
struct drm_device *dev = encoder->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
enum port port = encoder->port;
int type;
/* Initialize the work for modeset in case of link train failure */
intel_dp_init_modeset_retry_work(connector);
if (drm_WARN(dev, dig_port->max_lanes < 1,
"Not enough lanes (%d) for DP on [ENCODER:%d:%s]\n",
dig_port->max_lanes, encoder->base.base.id,
@ -6632,7 +6580,7 @@ intel_dp_init_connector(struct intel_digital_port *dig_port,
return true;
fail:
intel_display_power_flush_work(dev_priv);
intel_display_power_flush_work(display);
drm_connector_cleanup(&connector->base);
return false;

View File

@ -75,9 +75,8 @@ int intel_dp_compute_config(struct intel_encoder *encoder,
int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state,
struct link_config_limits *limits,
int timeslots,
bool recompute_pipe_bpp);
const struct link_config_limits *limits,
int timeslots);
void intel_dp_audio_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state);

View File

@ -243,7 +243,6 @@ intel_dp_aux_xfer(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);
struct intel_encoder *encoder = &dig_port->base;
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
i915_reg_t ch_ctl, ch_data[5];
u32 aux_clock_divider;
enum intel_display_power_domain aux_domain;
@ -272,7 +271,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
aux_domain = intel_aux_power_domain(dig_port);
aux_wakeref = intel_display_power_get(i915, aux_domain);
aux_wakeref = intel_display_power_get(display, aux_domain);
pps_wakeref = intel_pps_lock(intel_dp);
/*
@ -432,7 +431,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
intel_pps_vdd_off_unlocked(intel_dp, false);
intel_pps_unlock(intel_dp, pps_wakeref);
intel_display_power_put_async(i915, aux_domain, aux_wakeref);
intel_display_power_put_async(display, aux_domain, aux_wakeref);
out_unlock:
intel_digital_port_unlock(encoder);

View File

@ -451,9 +451,54 @@ intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pi
/* VESA backlight callbacks */
static u32 intel_dp_aux_vesa_get_backlight(struct intel_connector *connector, enum pipe unused)
{
struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
struct intel_panel *panel = &connector->panel;
u8 buf[3];
u32 val = 0;
int ret;
if (panel->backlight.edp.vesa.luminance_control_support) {
ret = drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_PANEL_TARGET_LUMINANCE_VALUE, buf,
sizeof(buf));
if (ret < 0) {
drm_err(intel_dp->aux.drm_dev,
"[CONNECTOR:%d:%s] Failed to read Luminance from DPCD\n",
connector->base.base.id, connector->base.name);
return 0;
}
val |= buf[0] | buf[1] << 8 | buf[2] << 16;
return val / 1000;
}
return connector->panel.backlight.level;
}
static int
intel_dp_aux_vesa_set_luminance(struct intel_connector *connector, u32 level)
{
struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
u8 buf[3];
int ret;
level = level * 1000;
level &= 0xffffff;
buf[0] = (level & 0x0000ff);
buf[1] = (level & 0x00ff00) >> 8;
buf[2] = (level & 0xff0000) >> 16;
ret = drm_dp_dpcd_write(&intel_dp->aux, DP_EDP_PANEL_TARGET_LUMINANCE_VALUE,
buf, sizeof(buf));
if (ret != sizeof(buf)) {
drm_err(intel_dp->aux.drm_dev,
"%s: Failed to set VESA Aux Luminance: %d\n",
intel_dp->aux.name, ret);
return -EINVAL;
} else {
return 0;
}
}
static void
intel_dp_aux_vesa_set_backlight(const struct drm_connector_state *conn_state, u32 level)
{
@ -461,6 +506,11 @@ intel_dp_aux_vesa_set_backlight(const struct drm_connector_state *conn_state, u3
struct intel_panel *panel = &connector->panel;
struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
if (panel->backlight.edp.vesa.luminance_control_support) {
if (!intel_dp_aux_vesa_set_luminance(connector, level))
return;
}
if (!panel->backlight.edp.vesa.info.aux_set) {
const u32 pwm_level = intel_backlight_level_to_pwm(connector, level);
@ -477,6 +527,18 @@ intel_dp_aux_vesa_enable_backlight(const struct intel_crtc_state *crtc_state,
struct intel_connector *connector = to_intel_connector(conn_state->connector);
struct intel_panel *panel = &connector->panel;
struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
int ret;
if (panel->backlight.edp.vesa.luminance_control_support) {
ret = drm_dp_dpcd_writeb(&intel_dp->aux, DP_EDP_BACKLIGHT_MODE_SET_REGISTER,
DP_EDP_PANEL_LUMINANCE_CONTROL_ENABLE);
if (ret == 1)
return;
if (!intel_dp_aux_vesa_set_luminance(connector, level))
return;
}
if (!panel->backlight.edp.vesa.info.aux_enable) {
u32 pwm_level;
@ -500,6 +562,9 @@ static void intel_dp_aux_vesa_disable_backlight(const struct drm_connector_state
struct intel_panel *panel = &connector->panel;
struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
if (panel->backlight.edp.vesa.luminance_control_support)
return;
drm_edp_backlight_disable(&intel_dp->aux, &panel->backlight.edp.vesa.info);
if (!panel->backlight.edp.vesa.info.aux_enable)
@ -510,56 +575,75 @@ static void intel_dp_aux_vesa_disable_backlight(const struct drm_connector_state
static int intel_dp_aux_vesa_setup_backlight(struct intel_connector *connector, enum pipe pipe)
{
struct intel_display *display = to_intel_display(connector);
struct drm_luminance_range_info *luminance_range =
&connector->base.display_info.luminance_range;
struct intel_dp *intel_dp = intel_attached_dp(connector);
struct intel_panel *panel = &connector->panel;
u16 current_level;
u8 current_mode;
int ret;
ret = drm_edp_backlight_init(&intel_dp->aux, &panel->backlight.edp.vesa.info,
panel->vbt.backlight.pwm_freq_hz, intel_dp->edp_dpcd,
&current_level, &current_mode);
if (ret < 0)
return ret;
drm_dbg_kms(display->drm,
"[CONNECTOR:%d:%s] AUX VESA backlight enable is controlled through %s\n",
connector->base.base.id, connector->base.name,
dpcd_vs_pwm_str(panel->backlight.edp.vesa.info.aux_enable));
drm_dbg_kms(display->drm,
"[CONNECTOR:%d:%s] AUX VESA backlight level is controlled through %s\n",
connector->base.base.id, connector->base.name,
dpcd_vs_pwm_str(panel->backlight.edp.vesa.info.aux_set));
if (!panel->backlight.edp.vesa.info.aux_set || !panel->backlight.edp.vesa.info.aux_enable) {
ret = panel->backlight.pwm_funcs->setup(connector, pipe);
if (ret < 0) {
drm_err(display->drm,
"[CONNECTOR:%d:%s] Failed to setup PWM backlight controls for eDP backlight: %d\n",
connector->base.base.id, connector->base.name, ret);
return ret;
}
}
if (panel->backlight.edp.vesa.info.aux_set) {
panel->backlight.max = panel->backlight.edp.vesa.info.max;
panel->backlight.min = 0;
if (current_mode == DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD) {
panel->backlight.level = current_level;
panel->backlight.enabled = panel->backlight.level != 0;
if (panel->backlight.edp.vesa.luminance_control_support) {
if (luminance_range->max_luminance) {
panel->backlight.max = luminance_range->max_luminance;
panel->backlight.min = luminance_range->min_luminance;
} else {
panel->backlight.level = panel->backlight.max;
panel->backlight.enabled = false;
panel->backlight.max = 512;
panel->backlight.min = 0;
}
panel->backlight.level = intel_dp_aux_vesa_get_backlight(connector, 0);
panel->backlight.enabled = panel->backlight.level != 0;
drm_dbg_kms(display->drm,
"[CONNECTOR:%d:%s] AUX VESA Nits backlight level is controlled through DPCD\n",
connector->base.base.id, connector->base.name);
} else {
panel->backlight.max = panel->backlight.pwm_level_max;
panel->backlight.min = panel->backlight.pwm_level_min;
if (current_mode == DP_EDP_BACKLIGHT_CONTROL_MODE_PWM) {
panel->backlight.level = panel->backlight.pwm_funcs->get(connector, pipe);
panel->backlight.enabled = panel->backlight.pwm_enabled;
ret = drm_edp_backlight_init(&intel_dp->aux, &panel->backlight.edp.vesa.info,
panel->vbt.backlight.pwm_freq_hz, intel_dp->edp_dpcd,
&current_level, &current_mode);
if (ret < 0)
return ret;
drm_dbg_kms(display->drm,
"[CONNECTOR:%d:%s] AUX VESA backlight enable is controlled through %s\n",
connector->base.base.id, connector->base.name,
dpcd_vs_pwm_str(panel->backlight.edp.vesa.info.aux_enable));
drm_dbg_kms(display->drm,
"[CONNECTOR:%d:%s] AUX VESA backlight level is controlled through %s\n",
connector->base.base.id, connector->base.name,
dpcd_vs_pwm_str(panel->backlight.edp.vesa.info.aux_set));
if (!panel->backlight.edp.vesa.info.aux_set ||
!panel->backlight.edp.vesa.info.aux_enable) {
ret = panel->backlight.pwm_funcs->setup(connector, pipe);
if (ret < 0) {
drm_err(display->drm,
"[CONNECTOR:%d:%s] Failed to setup PWM backlight controls for eDP backlight: %d\n",
connector->base.base.id, connector->base.name, ret);
return ret;
}
}
if (panel->backlight.edp.vesa.info.aux_set) {
panel->backlight.max = panel->backlight.edp.vesa.info.max;
panel->backlight.min = 0;
if (current_mode == DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD) {
panel->backlight.level = current_level;
panel->backlight.enabled = panel->backlight.level != 0;
} else {
panel->backlight.level = panel->backlight.max;
panel->backlight.enabled = false;
}
} else {
panel->backlight.level = panel->backlight.max;
panel->backlight.enabled = false;
panel->backlight.max = panel->backlight.pwm_level_max;
panel->backlight.min = panel->backlight.pwm_level_min;
if (current_mode == DP_EDP_BACKLIGHT_CONTROL_MODE_PWM) {
panel->backlight.level =
panel->backlight.pwm_funcs->get(connector, pipe);
panel->backlight.enabled = panel->backlight.pwm_enabled;
} else {
panel->backlight.level = panel->backlight.max;
panel->backlight.enabled = false;
}
}
}
@ -575,6 +659,15 @@ intel_dp_aux_supports_vesa_backlight(struct intel_connector *connector)
{
struct intel_display *display = to_intel_display(connector);
struct intel_dp *intel_dp = intel_attached_dp(connector);
struct intel_panel *panel = &connector->panel;
if ((intel_dp->edp_dpcd[3] & DP_EDP_PANEL_LUMINANCE_CONTROL_CAPABLE)) {
drm_dbg_kms(display->drm,
"[CONNECTOR:%d:%s] AUX Luminance Based Backlight Control Supported!\n",
connector->base.base.id, connector->base.name);
panel->backlight.edp.vesa.luminance_control_support = true;
return true;
}
if (drm_edp_backlight_supported(intel_dp->edp_dpcd)) {
drm_dbg_kms(display->drm,
@ -604,6 +697,7 @@ static const struct intel_panel_bl_funcs intel_dp_vesa_bl_funcs = {
int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector)
{
struct intel_display *display = to_intel_display(connector);
struct intel_dp *intel_dp = intel_attached_dp(connector);
struct drm_device *dev = connector->base.dev;
struct intel_panel *panel = &connector->panel;
bool try_intel_interface = false, try_vesa_interface = false;
@ -640,6 +734,10 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector)
break;
}
/* For eDP 1.5 and above we are supposed to use VESA interface for brightness control */
if (intel_dp->edp_dpcd[0] >= DP_EDP_15)
try_vesa_interface = true;
/*
* Since Intel has their own backlight control interface, the majority of machines out there
* using DPCD backlight controls with Intel GPUs will be using this interface as opposed to
@ -653,7 +751,8 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector)
* backlight interface at all. This means that the only sensible way for us to detect both
* interfaces is to probe for Intel's first, and VESA's second.
*/
if (try_intel_interface && intel_dp_aux_supports_hdr_backlight(connector)) {
if (try_intel_interface && intel_dp_aux_supports_hdr_backlight(connector) &&
intel_dp->edp_dpcd[0] <= DP_EDP_14b) {
drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Using Intel proprietary eDP backlight controls\n",
connector->base.base.id, connector->base.name);
panel->backlight.funcs = &intel_dp_hdr_bl_funcs;

View File

@ -783,7 +783,7 @@ intel_dp_prepare_link_train(struct intel_dp *intel_dp,
/*
* WaEdpLinkRateDataReload
*
* Parade PS8461E MUX (used on varius TGL+ laptops) needs
* Parade PS8461E MUX (used on various TGL+ laptops) needs
* to snoop the link rates reported by the sink when we
* use LINK_RATE_SET in order to operate in jitter cleaning
* mode (as opposed to redriver mode). Unfortunately it
@ -1642,7 +1642,7 @@ void intel_dp_start_link_train(struct intel_atomic_state *state,
/*
* Ignore the link failure in CI
*
* In fixed enviroments like CI, sometimes unexpected long HPDs are
* In fixed environments like CI, sometimes unexpected long HPDs are
* generated by the displays. If ignore_long_hpd flag is set, such long
* HPDs are ignored. And probably as a consequence of these ignored
* long HPDs, subsequent link trainings are failed resulting into CI

View File

@ -111,7 +111,7 @@ static int intel_dp_mst_max_dpt_bpp(const struct intel_crtc_state *crtc_state,
&crtc_state->hw.adjusted_mode;
if (!intel_dp_is_uhbr(crtc_state) || DISPLAY_VER(display) >= 20 || !dsc)
return INT_MAX;
return 0;
/*
* DSC->DPT interface width:
@ -209,22 +209,56 @@ static int intel_dp_mst_dsc_get_slice_count(const struct intel_connector *connec
num_joined_pipes);
}
static void intel_dp_mst_compute_min_hblank(struct intel_crtc_state *crtc_state,
int bpp_x16)
{
struct intel_display *display = to_intel_display(crtc_state);
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;
int symbol_size = intel_dp_is_uhbr(crtc_state) ? 32 : 8;
int hblank;
if (DISPLAY_VER(display) < 20)
return;
/* Calculate min Hblank Link Layer Symbol Cycle Count for 8b/10b MST & 128b/132b */
hblank = DIV_ROUND_UP((DIV_ROUND_UP
(adjusted_mode->htotal - adjusted_mode->hdisplay, 4) * bpp_x16),
symbol_size);
crtc_state->min_hblank = hblank;
}
int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state,
int max_bpp, int min_bpp,
struct drm_connector_state *conn_state,
int step, bool dsc)
int min_bpp_x16, int max_bpp_x16, int bpp_step_x16, bool dsc)
{
struct intel_display *display = to_intel_display(intel_dp);
struct drm_atomic_state *state = crtc_state->uapi.state;
struct drm_dp_mst_topology_state *mst_state = NULL;
struct intel_connector *connector =
to_intel_connector(conn_state->connector);
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;
fixed20_12 pbn_div;
int bpp, slots = -EINVAL;
bool is_mst = intel_dp->is_mst;
int bpp_x16, slots = -EINVAL;
int dsc_slice_count = 0;
int max_dpt_bpp;
int max_dpt_bpp_x16;
/* shouldn't happen, sanity check */
drm_WARN_ON(display->drm, !dsc && (fxp_q4_to_frac(min_bpp_x16) ||
fxp_q4_to_frac(max_bpp_x16) ||
fxp_q4_to_frac(bpp_step_x16)));
if (is_mst) {
mst_state = drm_atomic_get_mst_topology_state(state, &intel_dp->mst_mgr);
if (IS_ERR(mst_state))
return PTR_ERR(mst_state);
mst_state->pbn_div = drm_dp_get_vc_payload_bw(crtc_state->port_clock,
crtc_state->lane_count);
}
if (dsc) {
if (!intel_dp_supports_fec(intel_dp, connector, crtc_state))
@ -233,18 +267,15 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp,
crtc_state->fec_enable = !intel_dp_is_uhbr(crtc_state);
}
pbn_div = drm_dp_get_vc_payload_bw(crtc_state->port_clock,
crtc_state->lane_count);
max_dpt_bpp = intel_dp_mst_max_dpt_bpp(crtc_state, dsc);
if (max_bpp > max_dpt_bpp) {
drm_dbg_kms(display->drm, "Limiting bpp to max DPT bpp (%d -> %d)\n",
max_bpp, max_dpt_bpp);
max_bpp = max_dpt_bpp;
max_dpt_bpp_x16 = fxp_q4_from_int(intel_dp_mst_max_dpt_bpp(crtc_state, dsc));
if (max_dpt_bpp_x16 && max_bpp_x16 > max_dpt_bpp_x16) {
drm_dbg_kms(display->drm, "Limiting bpp to max DPT bpp (" FXP_Q4_FMT " -> " FXP_Q4_FMT ")\n",
FXP_Q4_ARGS(max_bpp_x16), FXP_Q4_ARGS(max_dpt_bpp_x16));
max_bpp_x16 = max_dpt_bpp_x16;
}
drm_dbg_kms(display->drm, "Looking for slots in range min bpp %d max bpp %d\n",
min_bpp, max_bpp);
drm_dbg_kms(display->drm, "Looking for slots in range min bpp " FXP_Q4_FMT " max bpp " FXP_Q4_FMT "\n",
FXP_Q4_ARGS(min_bpp_x16), FXP_Q4_ARGS(max_bpp_x16));
if (dsc) {
dsc_slice_count = intel_dp_mst_dsc_get_slice_count(connector, crtc_state);
@ -255,23 +286,27 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp,
}
}
for (bpp = max_bpp; bpp >= min_bpp; bpp -= step) {
for (bpp_x16 = max_bpp_x16; bpp_x16 >= min_bpp_x16; bpp_x16 -= bpp_step_x16) {
int local_bw_overhead;
int link_bpp_x16;
drm_dbg_kms(display->drm, "Trying bpp %d\n", bpp);
drm_dbg_kms(display->drm, "Trying bpp " FXP_Q4_FMT "\n", FXP_Q4_ARGS(bpp_x16));
link_bpp_x16 = fxp_q4_from_int(dsc ? bpp :
intel_dp_output_bpp(crtc_state->output_format, bpp));
link_bpp_x16 = dsc ? bpp_x16 :
fxp_q4_from_int(intel_dp_output_bpp(crtc_state->output_format,
fxp_q4_to_int(bpp_x16)));
local_bw_overhead = intel_dp_mst_bw_overhead(crtc_state,
false, dsc_slice_count, link_bpp_x16);
intel_dp_mst_compute_min_hblank(crtc_state, link_bpp_x16);
intel_dp_mst_compute_m_n(crtc_state,
local_bw_overhead,
link_bpp_x16,
&crtc_state->dp_m_n);
if (intel_dp->is_mst) {
if (is_mst) {
int remote_bw_overhead;
int remote_tu;
fixed20_12 pbn;
@ -296,7 +331,7 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp,
pbn.full = dfixed_const(intel_dp_mst_calc_pbn(adjusted_mode->crtc_clock,
link_bpp_x16,
remote_bw_overhead));
remote_tu = DIV_ROUND_UP(pbn.full, pbn_div.full);
remote_tu = DIV_ROUND_UP(pbn.full, mst_state->pbn_div.full);
/*
* Aligning the TUs ensures that symbols consisting of multiple
@ -314,7 +349,7 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp,
* allocated for the whole path and the TUs allocated for the
* first branch device's link also applies here.
*/
pbn.full = remote_tu * pbn_div.full;
pbn.full = remote_tu * mst_state->pbn_div.full;
drm_WARN_ON(display->drm, remote_tu < crtc_state->dp_m_n.tu);
crtc_state->dp_m_n.tu = remote_tu;
@ -343,7 +378,7 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp,
}
/* Allow using zero step to indicate one try */
if (!step)
if (!bpp_step_x16)
break;
}
@ -354,65 +389,42 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp,
}
if (!dsc)
crtc_state->pipe_bpp = bpp;
crtc_state->pipe_bpp = fxp_q4_to_int(bpp_x16);
else
crtc_state->dsc.compressed_bpp_x16 = fxp_q4_from_int(bpp);
crtc_state->dsc.compressed_bpp_x16 = bpp_x16;
drm_dbg_kms(display->drm, "Got %d slots for pipe bpp %d dsc %d\n",
slots, bpp, dsc);
drm_dbg_kms(display->drm, "Got %d slots for pipe bpp " FXP_Q4_FMT " dsc %d\n",
slots, FXP_Q4_ARGS(bpp_x16), dsc);
return 0;
}
static int mst_stream_find_vcpi_slots_for_bpp(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state,
int max_bpp, int min_bpp,
struct link_config_limits *limits,
struct drm_connector_state *conn_state,
int step, bool dsc)
{
struct drm_atomic_state *state = crtc_state->uapi.state;
struct drm_dp_mst_topology_state *mst_state;
mst_state = drm_atomic_get_mst_topology_state(state, &intel_dp->mst_mgr);
if (IS_ERR(mst_state))
return PTR_ERR(mst_state);
crtc_state->lane_count = limits->max_lane_count;
crtc_state->port_clock = limits->max_rate;
mst_state->pbn_div = drm_dp_get_vc_payload_bw(crtc_state->port_clock,
crtc_state->lane_count);
return intel_dp_mtp_tu_compute_config(intel_dp, crtc_state,
max_bpp, min_bpp,
conn_state, step, dsc);
}
static int mst_stream_compute_link_config(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state,
struct link_config_limits *limits)
const struct link_config_limits *limits)
{
crtc_state->lane_count = limits->max_lane_count;
crtc_state->port_clock = limits->max_rate;
/*
* FIXME: allocate the BW according to link_bpp, which in the case of
* YUV420 is only half of the pipe bpp value.
*/
return mst_stream_find_vcpi_slots_for_bpp(intel_dp, crtc_state,
fxp_q4_to_int(limits->link.max_bpp_x16),
fxp_q4_to_int(limits->link.min_bpp_x16),
limits,
conn_state, 2 * 3, false);
return intel_dp_mtp_tu_compute_config(intel_dp, crtc_state, conn_state,
limits->link.min_bpp_x16,
limits->link.max_bpp_x16,
fxp_q4_from_int(2 * 3), false);
}
static int mst_stream_dsc_compute_link_config(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state,
struct link_config_limits *limits)
const struct link_config_limits *limits)
{
struct intel_display *display = to_intel_display(intel_dp);
struct intel_connector *connector = to_intel_connector(conn_state->connector);
int i, num_bpc;
int num_bpc;
u8 dsc_bpc[3] = {};
int min_bpp, max_bpp, sink_min_bpp, sink_max_bpp;
int min_compressed_bpp, max_compressed_bpp;
@ -426,15 +438,8 @@ static int mst_stream_dsc_compute_link_config(struct intel_dp *intel_dp,
drm_dbg_kms(display->drm, "DSC Source supported min bpp %d max bpp %d\n",
min_bpp, max_bpp);
sink_max_bpp = dsc_bpc[0] * 3;
sink_min_bpp = sink_max_bpp;
for (i = 1; i < num_bpc; i++) {
if (sink_min_bpp > dsc_bpc[i] * 3)
sink_min_bpp = dsc_bpc[i] * 3;
if (sink_max_bpp < dsc_bpc[i] * 3)
sink_max_bpp = dsc_bpc[i] * 3;
}
sink_min_bpp = min_array(dsc_bpc, num_bpc) * 3;
sink_max_bpp = max_array(dsc_bpc, num_bpc) * 3;
drm_dbg_kms(display->drm, "DSC Sink supported min bpp %d max bpp %d\n",
sink_min_bpp, sink_max_bpp);
@ -459,9 +464,13 @@ static int mst_stream_dsc_compute_link_config(struct intel_dp *intel_dp,
min_compressed_bpp = intel_dp_dsc_nearest_valid_bpp(display, min_compressed_bpp,
crtc_state->pipe_bpp);
return mst_stream_find_vcpi_slots_for_bpp(intel_dp, crtc_state, max_compressed_bpp,
min_compressed_bpp, limits,
conn_state, 1, true);
crtc_state->lane_count = limits->max_lane_count;
crtc_state->port_clock = limits->max_rate;
return intel_dp_mtp_tu_compute_config(intel_dp, crtc_state, conn_state,
fxp_q4_from_int(min_compressed_bpp),
fxp_q4_from_int(max_compressed_bpp),
fxp_q4_from_int(1), true);
}
static int mst_stream_update_slots(struct intel_dp *intel_dp,
@ -683,7 +692,7 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
ret = intel_dp_dsc_compute_config(intel_dp, pipe_config,
conn_state, &limits,
pipe_config->dp_m_n.tu, false);
pipe_config->dp_m_n.tu);
}
if (ret)
@ -841,7 +850,7 @@ static int intel_dp_mst_check_bw(struct intel_atomic_state *state,
* @state must be recomputed with the updated @limits.
*
* Returns:
* - 0 if the confugration is valid
* - 0 if the configuration is valid
* - %-EAGAIN, if the configuration is invalid and @limits got updated
* with fallback values with which the configuration of all CRTCs in
* @state must be recomputed
@ -947,33 +956,32 @@ mst_connector_atomic_topology_check(struct intel_connector *connector,
}
static int
mst_connector_atomic_check(struct drm_connector *connector,
mst_connector_atomic_check(struct drm_connector *_connector,
struct drm_atomic_state *_state)
{
struct intel_atomic_state *state = to_intel_atomic_state(_state);
struct intel_connector *intel_connector =
to_intel_connector(connector);
struct intel_connector *connector = to_intel_connector(_connector);
int ret;
ret = intel_digital_connector_atomic_check(connector, &state->base);
ret = intel_digital_connector_atomic_check(&connector->base, &state->base);
if (ret)
return ret;
ret = mst_connector_atomic_topology_check(intel_connector, state);
ret = mst_connector_atomic_topology_check(connector, state);
if (ret)
return ret;
if (intel_connector_needs_modeset(state, connector)) {
if (intel_connector_needs_modeset(state, &connector->base)) {
ret = intel_dp_tunnel_atomic_check_state(state,
intel_connector->mst_port,
intel_connector);
connector->mst_port,
connector);
if (ret)
return ret;
}
return drm_dp_atomic_release_time_slots(&state->base,
&intel_connector->mst_port->mst_mgr,
intel_connector->port);
&connector->mst_port->mst_mgr,
connector->port);
}
static void mst_stream_disable(struct intel_atomic_state *state,
@ -986,6 +994,7 @@ static void mst_stream_disable(struct intel_atomic_state *state,
struct intel_dp *intel_dp = to_primary_dp(encoder);
struct intel_connector *connector =
to_intel_connector(old_conn_state->connector);
enum transcoder trans = old_crtc_state->cpu_transcoder;
drm_dbg_kms(display->drm, "active links %d\n",
intel_dp->active_mst_links);
@ -996,6 +1005,9 @@ static void mst_stream_disable(struct intel_atomic_state *state,
intel_hdcp_disable(intel_mst->connector);
intel_dp_sink_disable_decompression(state, connector, old_crtc_state);
if (DISPLAY_VER(display) >= 20)
intel_de_write(display, DP_MIN_HBLANK_CTL(trans), 0);
}
static void mst_stream_post_disable(struct intel_atomic_state *state,
@ -1224,11 +1236,10 @@ static void mst_stream_pre_enable(struct intel_atomic_state *state,
static void enable_bs_jitter_was(const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
u32 clear = 0;
u32 set = 0;
if (!IS_ALDERLAKE_P(i915))
if (!display->platform.alderlake_p)
return;
if (!IS_DISPLAY_STEP(display, STEP_D0, STEP_FOREVER))
@ -1269,7 +1280,7 @@ static void mst_stream_enable(struct intel_atomic_state *state,
enum transcoder trans = pipe_config->cpu_transcoder;
bool first_mst_stream = intel_dp->active_mst_links == 1;
struct intel_crtc *pipe_crtc;
int ret, i;
int ret, i, min_hblank;
drm_WARN_ON(display->drm, pipe_config->has_pch_encoder);
@ -1284,6 +1295,29 @@ static void mst_stream_enable(struct intel_atomic_state *state,
TRANS_DP2_VFREQ_PIXEL_CLOCK(crtc_clock_hz & 0xffffff));
}
if (DISPLAY_VER(display) >= 20) {
/*
* adjust the BlankingStart/BlankingEnd framing control from
* the calculated value
*/
min_hblank = pipe_config->min_hblank - 2;
/* Maximum value to be programmed is limited to 0x10 */
min_hblank = min(0x10, min_hblank);
/*
* Minimum hblank accepted for 128b/132b would be 5 and for
* 8b/10b would be 3 symbol count
*/
if (intel_dp_is_uhbr(pipe_config))
min_hblank = max(min_hblank, 5);
else
min_hblank = max(min_hblank, 3);
intel_de_write(display, DP_MIN_HBLANK_CTL(trans),
min_hblank);
}
enable_bs_jitter_was(pipe_config);
intel_ddi_enable_transcoder_func(encoder, pipe_config);
@ -1353,23 +1387,23 @@ static bool mst_stream_initial_fastset_check(struct intel_encoder *encoder,
return intel_dp_initial_fastset_check(primary_encoder, crtc_state);
}
static int mst_connector_get_ddc_modes(struct drm_connector *connector)
static int mst_connector_get_ddc_modes(struct drm_connector *_connector)
{
struct intel_display *display = to_intel_display(connector->dev);
struct intel_connector *intel_connector = to_intel_connector(connector);
struct intel_dp *intel_dp = intel_connector->mst_port;
struct intel_connector *connector = to_intel_connector(_connector);
struct intel_display *display = to_intel_display(connector);
struct intel_dp *intel_dp = connector->mst_port;
const struct drm_edid *drm_edid;
int ret;
if (drm_connector_is_unregistered(connector))
return intel_connector_update_modes(connector, NULL);
if (drm_connector_is_unregistered(&connector->base))
return intel_connector_update_modes(&connector->base, NULL);
if (!intel_display_driver_check_access(display))
return drm_edid_connector_add_modes(connector);
return drm_edid_connector_add_modes(&connector->base);
drm_edid = drm_dp_mst_edid_read(connector, &intel_dp->mst_mgr, intel_connector->port);
drm_edid = drm_dp_mst_edid_read(&connector->base, &intel_dp->mst_mgr, connector->port);
ret = intel_connector_update_modes(connector, drm_edid);
ret = intel_connector_update_modes(&connector->base, drm_edid);
drm_edid_free(drm_edid);
@ -1377,32 +1411,29 @@ static int mst_connector_get_ddc_modes(struct drm_connector *connector)
}
static int
mst_connector_late_register(struct drm_connector *connector)
mst_connector_late_register(struct drm_connector *_connector)
{
struct intel_connector *intel_connector = to_intel_connector(connector);
struct intel_connector *connector = to_intel_connector(_connector);
int ret;
ret = drm_dp_mst_connector_late_register(connector,
intel_connector->port);
ret = drm_dp_mst_connector_late_register(&connector->base, connector->port);
if (ret < 0)
return ret;
ret = intel_connector_register(connector);
ret = intel_connector_register(&connector->base);
if (ret < 0)
drm_dp_mst_connector_early_unregister(connector,
intel_connector->port);
drm_dp_mst_connector_early_unregister(&connector->base, connector->port);
return ret;
}
static void
mst_connector_early_unregister(struct drm_connector *connector)
mst_connector_early_unregister(struct drm_connector *_connector)
{
struct intel_connector *intel_connector = to_intel_connector(connector);
struct intel_connector *connector = to_intel_connector(_connector);
intel_connector_unregister(connector);
drm_dp_mst_connector_early_unregister(connector,
intel_connector->port);
intel_connector_unregister(&connector->base);
drm_dp_mst_connector_early_unregister(&connector->base, connector->port);
}
static const struct drm_connector_funcs mst_connector_funcs = {
@ -1416,23 +1447,24 @@ static const struct drm_connector_funcs mst_connector_funcs = {
.atomic_duplicate_state = intel_digital_connector_duplicate_state,
};
static int mst_connector_get_modes(struct drm_connector *connector)
static int mst_connector_get_modes(struct drm_connector *_connector)
{
return mst_connector_get_ddc_modes(connector);
struct intel_connector *connector = to_intel_connector(_connector);
return mst_connector_get_ddc_modes(&connector->base);
}
static int
mst_connector_mode_valid_ctx(struct drm_connector *connector,
mst_connector_mode_valid_ctx(struct drm_connector *_connector,
const struct drm_display_mode *mode,
struct drm_modeset_acquire_ctx *ctx,
enum drm_mode_status *status)
{
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);
struct intel_dp *intel_dp = intel_connector->mst_port;
struct intel_connector *connector = to_intel_connector(_connector);
struct intel_display *display = to_intel_display(connector);
struct intel_dp *intel_dp = connector->mst_port;
struct drm_dp_mst_topology_mgr *mgr = &intel_dp->mst_mgr;
struct drm_dp_mst_port *port = intel_connector->port;
struct drm_dp_mst_port *port = connector->port;
const int min_bpp = 18;
int max_dotclk = display->cdclk.max_dotclk_freq;
int max_rate, mode_rate, max_lanes, max_link_clock;
@ -1443,12 +1475,12 @@ mst_connector_mode_valid_ctx(struct drm_connector *connector,
int target_clock = mode->clock;
int num_joined_pipes;
if (drm_connector_is_unregistered(connector)) {
if (drm_connector_is_unregistered(&connector->base)) {
*status = MODE_ERROR;
return 0;
}
*status = intel_cpu_transcoder_mode_valid(dev_priv, mode);
*status = intel_cpu_transcoder_mode_valid(display, mode);
if (*status != MODE_OK)
return 0;
@ -1481,7 +1513,7 @@ mst_connector_mode_valid_ctx(struct drm_connector *connector,
* corresponding link capabilities of the sink) in case the
* stream is uncompressed for it by the last branch device.
*/
num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, intel_connector,
num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, connector,
mode->hdisplay, target_clock);
max_dotclk *= num_joined_pipes;
@ -1495,14 +1527,14 @@ mst_connector_mode_valid_ctx(struct drm_connector *connector,
return 0;
}
if (intel_dp_has_dsc(intel_connector)) {
if (intel_dp_has_dsc(connector)) {
/*
* TBD pass the connector BPC,
* for now U8_MAX so that max BPC on that platform would be picked
*/
int pipe_bpp = intel_dp_dsc_compute_max_bpp(intel_connector, U8_MAX);
int pipe_bpp = intel_dp_dsc_compute_max_bpp(connector, U8_MAX);
if (drm_dp_sink_supports_fec(intel_connector->dp.fec_capability)) {
if (drm_dp_sink_supports_fec(connector->dp.fec_capability)) {
dsc_max_compressed_bpp =
intel_dp_dsc_get_max_compressed_bpp(display,
max_link_clock,
@ -1513,7 +1545,7 @@ mst_connector_mode_valid_ctx(struct drm_connector *connector,
INTEL_OUTPUT_FORMAT_RGB,
pipe_bpp, 64);
dsc_slice_count =
intel_dp_dsc_get_slice_count(intel_connector,
intel_dp_dsc_get_slice_count(connector,
target_clock,
mode->hdisplay,
num_joined_pipes);
@ -1532,44 +1564,44 @@ mst_connector_mode_valid_ctx(struct drm_connector *connector,
return 0;
}
*status = intel_mode_valid_max_plane_size(dev_priv, mode, num_joined_pipes);
*status = intel_mode_valid_max_plane_size(display, mode, num_joined_pipes);
return 0;
}
static struct drm_encoder *
mst_connector_atomic_best_encoder(struct drm_connector *connector,
mst_connector_atomic_best_encoder(struct drm_connector *_connector,
struct drm_atomic_state *state)
{
struct drm_connector_state *connector_state = drm_atomic_get_new_connector_state(state,
connector);
struct intel_connector *intel_connector = to_intel_connector(connector);
struct intel_dp *intel_dp = intel_connector->mst_port;
struct intel_connector *connector = to_intel_connector(_connector);
struct drm_connector_state *connector_state =
drm_atomic_get_new_connector_state(state, &connector->base);
struct intel_dp *intel_dp = connector->mst_port;
struct intel_crtc *crtc = to_intel_crtc(connector_state->crtc);
return &intel_dp->mst_encoders[crtc->pipe]->base.base;
}
static int
mst_connector_detect_ctx(struct drm_connector *connector,
mst_connector_detect_ctx(struct drm_connector *_connector,
struct drm_modeset_acquire_ctx *ctx, bool force)
{
struct intel_display *display = to_intel_display(connector->dev);
struct intel_connector *intel_connector = to_intel_connector(connector);
struct intel_dp *intel_dp = intel_connector->mst_port;
struct intel_connector *connector = to_intel_connector(_connector);
struct intel_display *display = to_intel_display(connector);
struct intel_dp *intel_dp = connector->mst_port;
if (!intel_display_device_enabled(display))
return connector_status_disconnected;
if (drm_connector_is_unregistered(connector))
if (drm_connector_is_unregistered(&connector->base))
return connector_status_disconnected;
if (!intel_display_driver_check_access(display))
return connector->status;
return connector->base.status;
intel_dp_flush_connector_commits(intel_connector);
intel_dp_flush_connector_commits(connector);
return drm_dp_mst_detect_port(connector, ctx, &intel_dp->mst_mgr,
intel_connector->port);
return drm_dp_mst_detect_port(&connector->base, ctx, &intel_dp->mst_mgr,
connector->port);
}
static const struct drm_connector_helper_funcs mst_connector_helper_funcs = {
@ -1605,29 +1637,30 @@ static bool mst_connector_get_hw_state(struct intel_connector *connector)
}
static int mst_topology_add_connector_properties(struct intel_dp *intel_dp,
struct drm_connector *connector,
struct drm_connector *_connector,
const char *pathprop)
{
struct intel_display *display = to_intel_display(intel_dp);
struct intel_connector *connector = to_intel_connector(_connector);
drm_object_attach_property(&connector->base,
drm_object_attach_property(&connector->base.base,
display->drm->mode_config.path_property, 0);
drm_object_attach_property(&connector->base,
drm_object_attach_property(&connector->base.base,
display->drm->mode_config.tile_property, 0);
intel_attach_force_audio_property(connector);
intel_attach_broadcast_rgb_property(connector);
intel_attach_force_audio_property(&connector->base);
intel_attach_broadcast_rgb_property(&connector->base);
/*
* Reuse the prop from the SST connector because we're
* not allowed to create new props after device registration.
*/
connector->max_bpc_property =
connector->base.max_bpc_property =
intel_dp->attached_connector->base.max_bpc_property;
if (connector->max_bpc_property)
drm_connector_attach_max_bpc_property(connector, 6, 12);
if (connector->base.max_bpc_property)
drm_connector_attach_max_bpc_property(&connector->base, 6, 12);
return drm_connector_set_path_property(connector, pathprop);
return drm_connector_set_path_property(&connector->base, pathprop);
}
static void
@ -1700,62 +1733,58 @@ mst_topology_add_connector(struct drm_dp_mst_topology_mgr *mgr,
struct intel_dp *intel_dp = container_of(mgr, struct intel_dp, mst_mgr);
struct intel_display *display = to_intel_display(intel_dp);
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct intel_connector *intel_connector;
struct drm_connector *connector;
struct intel_connector *connector;
enum pipe pipe;
int ret;
intel_connector = intel_connector_alloc();
if (!intel_connector)
connector = intel_connector_alloc();
if (!connector)
return NULL;
connector = &intel_connector->base;
intel_connector->get_hw_state = mst_connector_get_hw_state;
intel_connector->sync_state = intel_dp_connector_sync_state;
intel_connector->mst_port = intel_dp;
intel_connector->port = port;
connector->get_hw_state = mst_connector_get_hw_state;
connector->sync_state = intel_dp_connector_sync_state;
connector->mst_port = intel_dp;
connector->port = port;
drm_dp_mst_get_port_malloc(port);
intel_dp_init_modeset_retry_work(intel_connector);
ret = drm_connector_dynamic_init(display->drm, connector, &mst_connector_funcs,
ret = drm_connector_dynamic_init(display->drm, &connector->base, &mst_connector_funcs,
DRM_MODE_CONNECTOR_DisplayPort, NULL);
if (ret) {
drm_dp_mst_put_port_malloc(port);
intel_connector_free(intel_connector);
return NULL;
}
if (ret)
goto err_put_port;
intel_connector->dp.dsc_decompression_aux = drm_dp_mst_dsc_aux_for_port(port);
intel_dp_mst_read_decompression_port_dsc_caps(intel_dp, intel_connector);
intel_connector->dp.dsc_hblank_expansion_quirk =
detect_dsc_hblank_expansion_quirk(intel_connector);
connector->dp.dsc_decompression_aux = drm_dp_mst_dsc_aux_for_port(port);
intel_dp_mst_read_decompression_port_dsc_caps(intel_dp, connector);
connector->dp.dsc_hblank_expansion_quirk =
detect_dsc_hblank_expansion_quirk(connector);
drm_connector_helper_add(connector, &mst_connector_helper_funcs);
drm_connector_helper_add(&connector->base, &mst_connector_helper_funcs);
for_each_pipe(display, pipe) {
struct drm_encoder *enc =
&intel_dp->mst_encoders[pipe]->base.base;
ret = drm_connector_attach_encoder(&intel_connector->base, enc);
ret = drm_connector_attach_encoder(&connector->base, enc);
if (ret)
goto err;
goto err_cleanup_connector;
}
ret = mst_topology_add_connector_properties(intel_dp, connector, pathprop);
ret = mst_topology_add_connector_properties(intel_dp, &connector->base, pathprop);
if (ret)
goto err;
goto err_cleanup_connector;
ret = intel_dp_hdcp_init(dig_port, intel_connector);
ret = intel_dp_hdcp_init(dig_port, connector);
if (ret)
drm_dbg_kms(display->drm, "[%s:%d] HDCP MST init failed, skipping.\n",
connector->name, connector->base.id);
connector->base.name, connector->base.base.id);
return connector;
return &connector->base;
err_cleanup_connector:
drm_connector_cleanup(&connector->base);
err_put_port:
drm_dp_mst_put_port_malloc(port);
intel_connector_free(connector);
err:
drm_connector_cleanup(connector);
return NULL;
}
@ -2060,7 +2089,7 @@ bool intel_dp_mst_crtc_needs_modeset(struct intel_atomic_state *state,
* @intel_dp: DP port object
*
* Prepare an MST link for topology probing, programming the target
* link parameters to DPCD. This step is a requirement of the enumaration
* link parameters to DPCD. This step is a requirement of the enumeration
* of path resources during probing.
*/
void intel_dp_mst_prepare_probe(struct intel_dp *intel_dp)

View File

@ -33,8 +33,7 @@ bool intel_dp_mst_verify_dpcd_state(struct intel_dp *intel_dp);
int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state,
int max_bpp, int min_bpp,
struct drm_connector_state *conn_state,
int step, bool dsc);
int min_bpp_x16, int max_bpp_x16, int bpp_step_x16, bool dsc);
#endif /* __INTEL_DP_MST_H__ */

View File

@ -257,7 +257,7 @@ static void intel_dp_phy_pattern_update(struct intel_dp *intel_dp,
/*
* FIXME: Ideally pattern should come from DPCD 0x250. As
* current firmware of DPR-100 could not set it, so hardcoding
* now for complaince test.
* now for compliance test.
*/
drm_dbg_kms(display->drm,
"Set 80Bit Custom Phy Test Pattern 0x3e0f83e0 0x0f83e0f8 0x0000f83e\n");
@ -275,7 +275,7 @@ static void intel_dp_phy_pattern_update(struct intel_dp *intel_dp,
/*
* FIXME: Ideally pattern should come from DPCD 0x24A. As
* current firmware of DPR-100 could not set it, so hardcoding
* now for complaince test.
* now for compliance test.
*/
drm_dbg_kms(display->drm,
"Set HBR2 compliance Phy Test Pattern\n");

View File

@ -647,7 +647,7 @@ void intel_dp_tunnel_atomic_clear_stream_bw(struct intel_atomic_state *state,
* @state must be recomputed with the updated @limits.
*
* Returns:
* - 0 if the confugration is valid
* - 0 if the configuration is valid
* - %-EAGAIN, if the configuration is invalid and @limits got updated
* with fallback values with which the configuration of all CRTCs in
* @state must be recomputed

View File

@ -20,7 +20,8 @@ struct intel_dp;
struct intel_encoder;
struct intel_link_bw_limits;
#if IS_ENABLED(CONFIG_DRM_I915_DP_TUNNEL) && defined(I915)
#if (IS_ENABLED(CONFIG_DRM_I915_DP_TUNNEL) && defined(I915)) || \
(IS_ENABLED(CONFIG_DRM_XE_DP_TUNNEL) && !defined(I915))
int intel_dp_tunnel_detect(struct intel_dp *intel_dp, struct drm_modeset_acquire_ctx *ctx);
void intel_dp_tunnel_disconnect(struct intel_dp *intel_dp);
@ -127,6 +128,6 @@ intel_dp_tunnel_mgr_init(struct intel_display *display)
static inline void intel_dp_tunnel_mgr_cleanup(struct intel_display *display) {}
#endif /* CONFIG_DRM_I915_DP_TUNNEL */
#endif /* CONFIG_DRM_I915_DP_TUNNEL || CONFIG_DRM_XE_DP_TUNNEL */
#endif /* __INTEL_DP_TUNNEL_H__ */

View File

@ -40,7 +40,7 @@
* VLV, CHV and BXT have slightly peculiar display PHYs for driving DP/HDMI
* ports. DPIO is the name given to such a display PHY. These PHYs
* don't follow the standard programming model using direct MMIO
* registers, and instead their registers must be accessed trough IOSF
* registers, and instead their registers must be accessed through IOSF
* sideband. VLV has one such PHY for driving ports B and C, and CHV
* adds another PHY for driving port D. Each PHY responds to specific
* IOSF-SB port.
@ -1156,3 +1156,37 @@ void vlv_phy_reset_lanes(struct intel_encoder *encoder,
vlv_dpio_write(dev_priv, phy, VLV_PCS_DW1_GRP(ch), 0x00e00060);
vlv_dpio_put(dev_priv);
}
void vlv_wait_port_ready(struct intel_encoder *encoder,
unsigned int expected_mask)
{
struct intel_display *display = to_intel_display(encoder);
u32 port_mask;
i915_reg_t dpll_reg;
switch (encoder->port) {
default:
MISSING_CASE(encoder->port);
fallthrough;
case PORT_B:
port_mask = DPLL_PORTB_READY_MASK;
dpll_reg = DPLL(display, 0);
break;
case PORT_C:
port_mask = DPLL_PORTC_READY_MASK;
dpll_reg = DPLL(display, 0);
expected_mask <<= 4;
break;
case PORT_D:
port_mask = DPLL_PORTD_READY_MASK;
dpll_reg = DPIO_PHY_STATUS;
break;
}
if (intel_de_wait(display, dpll_reg, port_mask, expected_mask, 1000))
drm_WARN(display->drm, 1,
"timed out waiting for [ENCODER:%d:%s] port ready: got 0x%x, expected 0x%x\n",
encoder->base.base.id, encoder->base.name,
intel_de_read(display, dpll_reg) & port_mask,
expected_mask);
}

View File

@ -72,6 +72,8 @@ void vlv_phy_pre_encoder_enable(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void vlv_phy_reset_lanes(struct intel_encoder *encoder,
const struct intel_crtc_state *old_crtc_state);
void vlv_wait_port_ready(struct intel_encoder *encoder,
unsigned int expected_mask);
#else
static inline void bxt_port_to_phy_channel(struct intel_display *display, enum port port,
enum dpio_phy *phy, enum dpio_channel *ch)
@ -170,6 +172,10 @@ static inline void vlv_phy_reset_lanes(struct intel_encoder *encoder,
const struct intel_crtc_state *old_crtc_state)
{
}
static inline void vlv_wait_port_ready(struct intel_encoder *encoder,
unsigned int expected_mask)
{
}
#endif
#endif /* __INTEL_DPIO_PHY_H__ */

View File

@ -1843,7 +1843,7 @@ void i9xx_enable_pll(const struct intel_crtc_state *crtc_state)
enum pipe pipe = crtc->pipe;
int i;
assert_transcoder_disabled(dev_priv, crtc_state->cpu_transcoder);
assert_transcoder_disabled(display, crtc_state->cpu_transcoder);
/* PLL is protected by panel, make sure we can write it */
if (i9xx_has_pps(dev_priv))
@ -2024,7 +2024,7 @@ void vlv_enable_pll(const struct intel_crtc_state *crtc_state)
const struct i9xx_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.i9xx;
enum pipe pipe = crtc->pipe;
assert_transcoder_disabled(dev_priv, crtc_state->cpu_transcoder);
assert_transcoder_disabled(display, crtc_state->cpu_transcoder);
/* PLL is protected by panel, make sure we can write it */
assert_pps_unlocked(display, pipe);
@ -2171,7 +2171,7 @@ void chv_enable_pll(const struct intel_crtc_state *crtc_state)
const struct i9xx_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.i9xx;
enum pipe pipe = crtc->pipe;
assert_transcoder_disabled(dev_priv, crtc_state->cpu_transcoder);
assert_transcoder_disabled(display, crtc_state->cpu_transcoder);
/* PLL is protected by panel, make sure we can write it */
assert_pps_unlocked(display, pipe);
@ -2253,36 +2253,38 @@ int vlv_force_pll_on(struct drm_i915_private *dev_priv, enum pipe pipe,
void vlv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
{
struct intel_display *display = &dev_priv->display;
u32 val;
/* Make sure the pipe isn't still relying on us */
assert_transcoder_disabled(dev_priv, (enum transcoder)pipe);
assert_transcoder_disabled(display, (enum transcoder)pipe);
val = DPLL_INTEGRATED_REF_CLK_VLV |
DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS;
if (pipe != PIPE_A)
val |= DPLL_INTEGRATED_CRI_CLK_VLV;
intel_de_write(dev_priv, DPLL(dev_priv, pipe), val);
intel_de_posting_read(dev_priv, DPLL(dev_priv, pipe));
intel_de_write(display, DPLL(display, pipe), val);
intel_de_posting_read(display, DPLL(display, pipe));
}
void chv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
{
struct intel_display *display = &dev_priv->display;
enum dpio_channel ch = vlv_pipe_to_channel(pipe);
enum dpio_phy phy = vlv_pipe_to_phy(pipe);
u32 val;
/* Make sure the pipe isn't still relying on us */
assert_transcoder_disabled(dev_priv, (enum transcoder)pipe);
assert_transcoder_disabled(display, (enum transcoder)pipe);
val = DPLL_SSC_REF_CLK_CHV |
DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS;
if (pipe != PIPE_A)
val |= DPLL_INTEGRATED_CRI_CLK_VLV;
intel_de_write(dev_priv, DPLL(dev_priv, pipe), val);
intel_de_posting_read(dev_priv, DPLL(dev_priv, pipe));
intel_de_write(display, DPLL(display, pipe), val);
intel_de_posting_read(display, DPLL(display, pipe));
vlv_dpio_get(dev_priv);
@ -2296,19 +2298,19 @@ void chv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
void i9xx_disable_pll(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);
enum pipe pipe = crtc->pipe;
/* Don't disable pipe or pipe PLLs if needed */
if (IS_I830(dev_priv))
if (display->platform.i830)
return;
/* Make sure the pipe isn't still relying on us */
assert_transcoder_disabled(dev_priv, crtc_state->cpu_transcoder);
assert_transcoder_disabled(display, crtc_state->cpu_transcoder);
intel_de_write(dev_priv, DPLL(dev_priv, pipe), DPLL_VGA_MODE_DIS);
intel_de_posting_read(dev_priv, DPLL(dev_priv, pipe));
intel_de_write(display, DPLL(display, pipe), DPLL_VGA_MODE_DIS);
intel_de_posting_read(display, DPLL(display, pipe));
}
@ -2329,10 +2331,9 @@ void vlv_force_pll_off(struct drm_i915_private *dev_priv, enum pipe pipe)
}
/* Only for pre-ILK configs */
static void assert_pll(struct drm_i915_private *dev_priv,
static void assert_pll(struct intel_display *display,
enum pipe pipe, bool state)
{
struct intel_display *display = &dev_priv->display;
bool cur_state;
cur_state = intel_de_read(display, DPLL(display, pipe)) & DPLL_VCO_ENABLE;
@ -2341,12 +2342,12 @@ static void assert_pll(struct drm_i915_private *dev_priv,
str_on_off(state), str_on_off(cur_state));
}
void assert_pll_enabled(struct drm_i915_private *i915, enum pipe pipe)
void assert_pll_enabled(struct intel_display *display, enum pipe pipe)
{
assert_pll(i915, pipe, true);
assert_pll(display, pipe, true);
}
void assert_pll_disabled(struct drm_i915_private *i915, enum pipe pipe)
void assert_pll_disabled(struct intel_display *display, enum pipe pipe)
{
assert_pll(i915, pipe, false);
assert_pll(display, pipe, false);
}

View File

@ -13,6 +13,7 @@ struct drm_i915_private;
struct intel_atomic_state;
struct intel_crtc;
struct intel_crtc_state;
struct intel_display;
struct intel_dpll_hw_state;
enum pipe;
@ -46,7 +47,7 @@ void i9xx_crtc_clock_get(struct intel_crtc_state *crtc_state);
void vlv_crtc_clock_get(struct intel_crtc_state *crtc_state);
void chv_crtc_clock_get(struct intel_crtc_state *crtc_state);
void assert_pll_enabled(struct drm_i915_private *i915, enum pipe pipe);
void assert_pll_disabled(struct drm_i915_private *i915, enum pipe pipe);
void assert_pll_enabled(struct intel_display *display, enum pipe pipe);
void assert_pll_disabled(struct intel_display *display, enum pipe pipe);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -30,12 +30,11 @@
#include "intel_display_power.h"
#include "intel_wakeref.h"
#define for_each_shared_dpll(__i915, __pll, __i) \
for ((__i) = 0; (__i) < (__i915)->display.dpll.num_shared_dpll && \
((__pll) = &(__i915)->display.dpll.shared_dplls[(__i)]) ; (__i)++)
#define for_each_shared_dpll(__display, __pll, __i) \
for ((__i) = 0; (__i) < (__display)->dpll.num_shared_dpll && \
((__pll) = &(__display)->dpll.shared_dplls[(__i)]) ; (__i)++)
enum tc_port;
struct drm_i915_private;
struct drm_printer;
struct intel_atomic_state;
struct intel_crtc;
@ -318,7 +317,7 @@ struct dpll_info {
const struct intel_shared_dpll_funcs *funcs;
/**
* @id: unique indentifier for this DPLL
* @id: unique identifier for this DPLL
*/
enum intel_dpll_id id;
@ -390,9 +389,9 @@ struct intel_shared_dpll {
/* shared dpll functions */
struct intel_shared_dpll *
intel_get_shared_dpll_by_id(struct drm_i915_private *i915,
intel_get_shared_dpll_by_id(struct intel_display *display,
enum intel_dpll_id id);
void assert_shared_dpll(struct drm_i915_private *i915,
void assert_shared_dpll(struct intel_display *display,
struct intel_shared_dpll *pll,
bool state);
#define assert_shared_dpll_enabled(d, p) assert_shared_dpll(d, p, true)
@ -413,24 +412,24 @@ void icl_set_active_port_dpll(struct intel_crtc_state *crtc_state,
void intel_update_active_dpll(struct intel_atomic_state *state,
struct intel_crtc *crtc,
struct intel_encoder *encoder);
int intel_dpll_get_freq(struct drm_i915_private *i915,
int intel_dpll_get_freq(struct intel_display *display,
const struct intel_shared_dpll *pll,
const struct intel_dpll_hw_state *dpll_hw_state);
bool intel_dpll_get_hw_state(struct drm_i915_private *i915,
bool intel_dpll_get_hw_state(struct intel_display *display,
struct intel_shared_dpll *pll,
struct intel_dpll_hw_state *dpll_hw_state);
void intel_enable_shared_dpll(const struct intel_crtc_state *crtc_state);
void intel_disable_shared_dpll(const struct intel_crtc_state *crtc_state);
void intel_shared_dpll_swap_state(struct intel_atomic_state *state);
void intel_shared_dpll_init(struct drm_i915_private *i915);
void intel_dpll_update_ref_clks(struct drm_i915_private *i915);
void intel_dpll_readout_hw_state(struct drm_i915_private *i915);
void intel_dpll_sanitize_state(struct drm_i915_private *i915);
void intel_shared_dpll_init(struct intel_display *display);
void intel_dpll_update_ref_clks(struct intel_display *display);
void intel_dpll_readout_hw_state(struct intel_display *display);
void intel_dpll_sanitize_state(struct intel_display *display);
void intel_dpll_dump_hw_state(struct drm_i915_private *i915,
void intel_dpll_dump_hw_state(struct intel_display *display,
struct drm_printer *p,
const struct intel_dpll_hw_state *dpll_hw_state);
bool intel_dpll_compare_hw_state(struct drm_i915_private *i915,
bool intel_dpll_compare_hw_state(struct intel_display *display,
const struct intel_dpll_hw_state *a,
const struct intel_dpll_hw_state *b);
enum intel_dpll_id icl_tc_port_to_pll_id(enum tc_port tc_port);

View File

@ -109,38 +109,32 @@ static bool pre_commit_is_vrr_active(struct intel_atomic_state *state,
return old_crtc_state->vrr.enable && !intel_crtc_vrr_disabling(state, crtc);
}
static const struct intel_crtc_state *
pre_commit_crtc_state(struct intel_atomic_state *state,
struct intel_crtc *crtc)
static int dsb_vblank_delay(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
const struct intel_crtc_state *old_crtc_state =
intel_atomic_get_old_crtc_state(state, crtc);
const struct intel_crtc_state *new_crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
const struct intel_crtc_state *crtc_state =
intel_pre_commit_crtc_state(state, crtc);
/*
* During fastsets/etc. the transcoder is still
* running with the old timings at this point.
*/
if (intel_crtc_needs_modeset(new_crtc_state))
return new_crtc_state;
if (pre_commit_is_vrr_active(state, crtc))
/*
* When the push is sent during vblank it will trigger
* on the next scanline, hence we have up to one extra
* scanline until the delayed vblank occurs after
* TRANS_PUSH has been written.
*/
return intel_vrr_vblank_delay(crtc_state) + 1;
else
return old_crtc_state;
}
static int dsb_vblank_delay(const struct intel_crtc_state *crtc_state)
{
return intel_mode_vblank_start(&crtc_state->hw.adjusted_mode) -
intel_mode_vdisplay(&crtc_state->hw.adjusted_mode);
return intel_mode_vblank_delay(&crtc_state->hw.adjusted_mode);
}
static int dsb_vtotal(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
const struct intel_crtc_state *crtc_state = pre_commit_crtc_state(state, crtc);
const struct intel_crtc_state *crtc_state =
intel_pre_commit_crtc_state(state, crtc);
if (pre_commit_is_vrr_active(state, crtc))
return crtc_state->vrr.vmax;
return intel_vrr_vmax_vtotal(crtc_state);
else
return intel_mode_vtotal(&crtc_state->hw.adjusted_mode);
}
@ -148,7 +142,8 @@ static int dsb_vtotal(struct intel_atomic_state *state,
static int dsb_dewake_scanline_start(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
const struct intel_crtc_state *crtc_state = pre_commit_crtc_state(state, crtc);
const struct intel_crtc_state *crtc_state =
intel_pre_commit_crtc_state(state, crtc);
struct drm_i915_private *i915 = to_i915(state->base.dev);
unsigned int latency = skl_watermark_max_latency(i915, 0);
@ -159,7 +154,8 @@ static int dsb_dewake_scanline_start(struct intel_atomic_state *state,
static int dsb_dewake_scanline_end(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
const struct intel_crtc_state *crtc_state = pre_commit_crtc_state(state, crtc);
const struct intel_crtc_state *crtc_state =
intel_pre_commit_crtc_state(state, crtc);
return intel_mode_vdisplay(&crtc_state->hw.adjusted_mode);
}
@ -167,23 +163,33 @@ static int dsb_dewake_scanline_end(struct intel_atomic_state *state,
static int dsb_scanline_to_hw(struct intel_atomic_state *state,
struct intel_crtc *crtc, int scanline)
{
const struct intel_crtc_state *crtc_state = pre_commit_crtc_state(state, crtc);
const struct intel_crtc_state *crtc_state =
intel_pre_commit_crtc_state(state, crtc);
int vtotal = dsb_vtotal(state, crtc);
return (scanline + vtotal - intel_crtc_scanline_offset(crtc_state)) % vtotal;
}
/*
* Bspec suggests that we should always set DSB_SKIP_WAITS_EN. We have approach
* different from what is explained in Bspec on how flip is considered being
* complete. We are waiting for vblank in DSB and generate interrupt when it
* happens and this interrupt is considered as indication of completion -> we
* definitely do not want to skip vblank wait. We also have concern what comes
* to skipping vblank evasion. I.e. arming registers are latched before we have
* managed writing them. Due to these reasons we are not setting
* DSB_SKIP_WAITS_EN.
*/
static u32 dsb_chicken(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
if (pre_commit_is_vrr_active(state, crtc))
return DSB_SKIP_WAITS_EN |
DSB_CTRL_WAIT_SAFE_WINDOW |
return DSB_CTRL_WAIT_SAFE_WINDOW |
DSB_CTRL_NO_WAIT_VBLANK |
DSB_INST_WAIT_SAFE_WINDOW |
DSB_INST_NO_WAIT_VBLANK;
else
return DSB_SKIP_WAITS_EN;
return 0;
}
static bool assert_dsb_has_room(struct intel_dsb *dsb)
@ -378,7 +384,8 @@ void intel_dsb_interrupt(struct intel_dsb *dsb)
void intel_dsb_wait_usec(struct intel_dsb *dsb, int count)
{
intel_dsb_emit(dsb, count,
/* +1 to make sure we never wait less time than asked for */
intel_dsb_emit(dsb, count + 1,
DSB_OPCODE_WAIT_USEC << DSB_OPCODE_SHIFT);
}
@ -461,6 +468,25 @@ void intel_dsb_wait_scanline_out(struct intel_atomic_state *state,
start, end);
}
void intel_dsb_poll(struct intel_dsb *dsb,
i915_reg_t reg, u32 mask, u32 val,
int wait_us, int count)
{
struct intel_crtc *crtc = dsb->crtc;
enum pipe pipe = crtc->pipe;
intel_dsb_reg_write(dsb, DSB_POLLMASK(pipe, dsb->id), mask);
intel_dsb_reg_write(dsb, DSB_POLLFUNC(pipe, dsb->id),
DSB_POLL_ENABLE |
DSB_POLL_WAIT(wait_us) | DSB_POLL_COUNT(count));
intel_dsb_noop(dsb, 5);
intel_dsb_emit(dsb, val,
(DSB_OPCODE_POLL << DSB_OPCODE_SHIFT) |
i915_mmio_reg_offset(reg));
}
static void intel_dsb_align_tail(struct intel_dsb *dsb)
{
u32 aligned_tail, tail;
@ -532,13 +558,27 @@ void intel_dsb_vblank_evade(struct intel_atomic_state *state,
struct intel_dsb *dsb)
{
struct intel_crtc *crtc = dsb->crtc;
const struct intel_crtc_state *crtc_state = pre_commit_crtc_state(state, crtc);
const struct intel_crtc_state *crtc_state =
intel_pre_commit_crtc_state(state, crtc);
/* FIXME calibrate sensibly */
int latency = intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode, 20);
int vblank_delay = dsb_vblank_delay(crtc_state);
int start, end;
/*
* PIPEDSL is reading as 0 when in SRDENT(PSR1) or DEEP_SLEEP(PSR2). On
* wake-up scanline counting starts from vblank_start - 1. We don't know
* if wake-up is already ongoing when evasion starts. In worst case
* PIPEDSL could start reading valid value right after checking the
* scanline. In this scenario we wouldn't have enough time to write all
* registers. To tackle this evade scanline 0 as well. As a drawback we
* have 1 frame delay in flip when waking up.
*/
if (crtc_state->has_psr)
intel_dsb_emit_wait_dsl(dsb, DSB_OPCODE_WAIT_DSL_OUT, 0, 0);
if (pre_commit_is_vrr_active(state, crtc)) {
int vblank_delay = intel_vrr_vblank_delay(crtc_state);
end = intel_vrr_vmin_vblank_start(crtc_state);
start = end - vblank_delay - latency;
intel_dsb_wait_scanline_out(state, dsb, start, end);
@ -547,6 +587,8 @@ void intel_dsb_vblank_evade(struct intel_atomic_state *state,
start = end - vblank_delay - latency;
intel_dsb_wait_scanline_out(state, dsb, start, end);
} else {
int vblank_delay = intel_mode_vblank_delay(&crtc_state->hw.adjusted_mode);
end = intel_mode_vblank_start(&crtc_state->hw.adjusted_mode);
start = end - vblank_delay - latency;
intel_dsb_wait_scanline_out(state, dsb, start, end);
@ -624,9 +666,10 @@ void intel_dsb_wait_vblank_delay(struct intel_atomic_state *state,
struct intel_dsb *dsb)
{
struct intel_crtc *crtc = dsb->crtc;
const struct intel_crtc_state *crtc_state = pre_commit_crtc_state(state, crtc);
const struct intel_crtc_state *crtc_state =
intel_pre_commit_crtc_state(state, crtc);
int usecs = intel_scanlines_to_usecs(&crtc_state->hw.adjusted_mode,
dsb_vblank_delay(crtc_state)) + 1;
dsb_vblank_delay(state, crtc));
intel_dsb_wait_usec(dsb, usecs);
}
@ -825,7 +868,7 @@ void intel_dsb_irq_handler(struct intel_display *display,
if (crtc->dsb_event) {
/*
* Update vblank counter/timestmap in case it
* Update vblank counter/timestamp in case it
* hasn't been done yet for this frame.
*/
drm_crtc_accurate_vblank_count(&crtc->base);
@ -838,7 +881,16 @@ void intel_dsb_irq_handler(struct intel_display *display,
}
errors = tmp & dsb_error_int_status(display);
if (errors)
drm_err(display->drm, "[CRTC:%d:%s] DSB %d error interrupt: 0x%x\n",
crtc->base.base.id, crtc->base.name, dsb_id, errors);
if (errors & DSB_ATS_FAULT_INT_STATUS)
drm_err(display->drm, "[CRTC:%d:%s] DSB %d ATS fault\n",
crtc->base.base.id, crtc->base.name, dsb_id);
if (errors & DSB_GTT_FAULT_INT_STATUS)
drm_err(display->drm, "[CRTC:%d:%s] DSB %d GTT fault\n",
crtc->base.base.id, crtc->base.name, dsb_id);
if (errors & DSB_RSPTIMEOUT_INT_STATUS)
drm_err(display->drm, "[CRTC:%d:%s] DSB %d response timeout\n",
crtc->base.base.id, crtc->base.name, dsb_id);
if (errors & DSB_POLL_ERR_INT_STATUS)
drm_err(display->drm, "[CRTC:%d:%s] DSB %d poll error\n",
crtc->base.base.id, crtc->base.name, dsb_id);
}

View File

@ -54,6 +54,9 @@ void intel_dsb_wait_scanline_out(struct intel_atomic_state *state,
int lower, int upper);
void intel_dsb_vblank_evade(struct intel_atomic_state *state,
struct intel_dsb *dsb);
void intel_dsb_poll(struct intel_dsb *dsb,
i915_reg_t reg, u32 mask, u32 val,
int wait_us, int count);
void intel_dsb_chain(struct intel_atomic_state *state,
struct intel_dsb *dsb,
struct intel_dsb *chained_dsb,

View File

@ -60,14 +60,14 @@ int intel_dsi_get_modes(struct drm_connector *connector)
enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector,
const struct drm_display_mode *mode)
{
struct drm_i915_private *dev_priv = to_i915(connector->dev);
struct intel_display *display = to_intel_display(connector->dev);
struct intel_connector *intel_connector = to_intel_connector(connector);
const struct drm_display_mode *fixed_mode =
intel_panel_fixed_mode(intel_connector, mode);
int max_dotclk = to_i915(connector->dev)->display.cdclk.max_dotclk_freq;
int max_dotclk = display->cdclk.max_dotclk_freq;
enum drm_mode_status status;
drm_dbg_kms(&dev_priv->drm, "\n");
drm_dbg_kms(display->drm, "\n");
status = intel_panel_mode_valid(intel_connector, mode);
if (status != MODE_OK)
@ -76,7 +76,7 @@ enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector,
if (fixed_mode->clock > max_dotclk)
return MODE_CLOCK_HIGH;
return intel_mode_valid_max_plane_size(dev_priv, mode, 1);
return intel_mode_valid_max_plane_size(display, mode, 1);
}
struct intel_dsi_host *intel_dsi_host_init(struct intel_dsi *intel_dsi,

View File

@ -582,7 +582,7 @@ static const fn_mipi_elem_exec exec_elem[] = {
/*
* MIPI Sequence from VBT #53 parsing logic
* We have already separated each seqence during bios parsing
* We have already separated each sequence during bios parsing
* Following is generic execution function for any sequence
*/

View File

@ -219,16 +219,16 @@ static enum drm_mode_status
intel_dvo_mode_valid(struct drm_connector *_connector,
const struct drm_display_mode *mode)
{
struct intel_display *display = to_intel_display(_connector->dev);
struct intel_connector *connector = to_intel_connector(_connector);
struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
const struct drm_display_mode *fixed_mode =
intel_panel_fixed_mode(connector, mode);
int max_dotclk = to_i915(connector->base.dev)->display.cdclk.max_dotclk_freq;
int max_dotclk = display->cdclk.max_dotclk_freq;
int target_clock = mode->clock;
enum drm_mode_status status;
status = intel_cpu_transcoder_mode_valid(i915, mode);
status = intel_cpu_transcoder_mode_valid(display, mode);
if (status != MODE_OK)
return status;
@ -524,7 +524,7 @@ void intel_dvo_init(struct drm_i915_private *i915)
return;
}
assert_port_valid(i915, intel_dvo->dev.port);
assert_port_valid(display, intel_dvo->dev.port);
encoder->type = INTEL_OUTPUT_DVO;
encoder->power_domain = POWER_DOMAIN_PORT_OTHER;

View File

@ -57,7 +57,7 @@ struct intel_dvo_dev_ops {
* Turn on/off output.
*
* Because none of our dvo drivers support an intermediate power levels,
* we don't expose this in the interfac.
* we don't expose this in the interface.
*/
void (*dpms)(struct intel_dvo_device *dvo, bool enable);

View File

@ -20,7 +20,7 @@
#include "intel_fb_bo.h"
#include "intel_frontbuffer.h"
#define check_array_bounds(i915, a, i) drm_WARN_ON(&(i915)->drm, (i) >= ARRAY_SIZE(a))
#define check_array_bounds(display, a, i) drm_WARN_ON((display)->drm, (i) >= ARRAY_SIZE(a))
/*
* From the Sky Lake PRM:
@ -539,11 +539,13 @@ static bool check_modifier_display_ver_range(const struct intel_modifier_desc *m
display_ver_from <= md->display_ver.until;
}
static bool plane_has_modifier(struct drm_i915_private *i915,
static bool plane_has_modifier(struct intel_display *display,
u8 plane_caps,
const struct intel_modifier_desc *md)
{
if (!IS_DISPLAY_VER(i915, md->display_ver.from, md->display_ver.until))
struct drm_i915_private *i915 = to_i915(display->drm);
if (!IS_DISPLAY_VER(display, md->display_ver.from, md->display_ver.until))
return false;
if (!plane_caps_contain_all(plane_caps, md->plane_caps))
@ -570,14 +572,14 @@ static bool plane_has_modifier(struct drm_i915_private *i915,
/**
* intel_fb_plane_get_modifiers: Get the modifiers for the given platform and plane capabilities
* @i915: i915 device instance
* @display: display instance
* @plane_caps: capabilities for the plane the modifiers are queried for
*
* Returns:
* Returns the list of modifiers allowed by the @i915 platform and @plane_caps.
* Returns the list of modifiers allowed by the @display platform and @plane_caps.
* The caller must free the returned buffer.
*/
u64 *intel_fb_plane_get_modifiers(struct drm_i915_private *i915,
u64 *intel_fb_plane_get_modifiers(struct intel_display *display,
u8 plane_caps)
{
u64 *list, *p;
@ -585,17 +587,17 @@ u64 *intel_fb_plane_get_modifiers(struct drm_i915_private *i915,
int i;
for (i = 0; i < ARRAY_SIZE(intel_modifiers); i++) {
if (plane_has_modifier(i915, plane_caps, &intel_modifiers[i]))
if (plane_has_modifier(display, plane_caps, &intel_modifiers[i]))
count++;
}
list = kmalloc_array(count, sizeof(*list), GFP_KERNEL);
if (drm_WARN_ON(&i915->drm, !list))
if (drm_WARN_ON(display->drm, !list))
return NULL;
p = list;
for (i = 0; i < ARRAY_SIZE(intel_modifiers); i++) {
if (plane_has_modifier(i915, plane_caps, &intel_modifiers[i]))
if (plane_has_modifier(display, plane_caps, &intel_modifiers[i]))
*p++ = intel_modifiers[i].modifier;
}
*p++ = DRM_FORMAT_MOD_INVALID;
@ -751,33 +753,34 @@ static unsigned int gen12_ccs_aux_stride(struct intel_framebuffer *fb, int ccs_p
int skl_main_to_aux_plane(const struct drm_framebuffer *fb, int main_plane)
{
const struct intel_modifier_desc *md = lookup_modifier(fb->modifier);
struct drm_i915_private *i915 = to_i915(fb->dev);
struct intel_display *display = to_intel_display(fb->dev);
if (md->ccs.packed_aux_planes | md->ccs.planar_aux_planes)
return main_to_ccs_plane(fb, main_plane);
else if (DISPLAY_VER(i915) < 11 &&
else if (DISPLAY_VER(display) < 11 &&
format_is_yuv_semiplanar(md, fb->format))
return 1;
else
return 0;
}
unsigned int intel_tile_size(const struct drm_i915_private *i915)
unsigned int intel_tile_size(struct intel_display *display)
{
return DISPLAY_VER(i915) == 2 ? 2048 : 4096;
return DISPLAY_VER(display) == 2 ? 2048 : 4096;
}
unsigned int
intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane)
{
struct drm_i915_private *dev_priv = to_i915(fb->dev);
struct intel_display *display = to_intel_display(fb->dev);
struct drm_i915_private *i915 = to_i915(display->drm);
unsigned int cpp = fb->format->cpp[color_plane];
switch (fb->modifier) {
case DRM_FORMAT_MOD_LINEAR:
return intel_tile_size(dev_priv);
return intel_tile_size(display);
case I915_FORMAT_MOD_X_TILED:
if (DISPLAY_VER(dev_priv) == 2)
if (DISPLAY_VER(display) == 2)
return 128;
else
return 512;
@ -807,7 +810,7 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane)
return 64;
fallthrough;
case I915_FORMAT_MOD_Y_TILED:
if (DISPLAY_VER(dev_priv) == 2 || HAS_128_BYTE_Y_TILING(dev_priv))
if (DISPLAY_VER(display) == 2 || HAS_128_BYTE_Y_TILING(i915))
return 128;
else
return 512;
@ -838,7 +841,9 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane)
unsigned int intel_tile_height(const struct drm_framebuffer *fb, int color_plane)
{
return intel_tile_size(to_i915(fb->dev)) /
struct intel_display *display = to_intel_display(fb->dev);
return intel_tile_size(display) /
intel_tile_width_bytes(fb, color_plane);
}
@ -890,15 +895,17 @@ intel_fb_align_height(const struct drm_framebuffer *fb,
return ALIGN(height, tile_height);
}
bool intel_fb_modifier_uses_dpt(struct drm_i915_private *i915, u64 modifier)
bool intel_fb_modifier_uses_dpt(struct intel_display *display, u64 modifier)
{
return HAS_DPT(i915) && modifier != DRM_FORMAT_MOD_LINEAR;
return HAS_DPT(display) && modifier != DRM_FORMAT_MOD_LINEAR;
}
bool intel_fb_uses_dpt(const struct drm_framebuffer *fb)
{
return to_i915(fb->dev)->display.params.enable_dpt &&
intel_fb_modifier_uses_dpt(to_i915(fb->dev), fb->modifier);
struct intel_display *display = to_intel_display(fb->dev);
return display->params.enable_dpt &&
intel_fb_modifier_uses_dpt(display, fb->modifier);
}
void intel_fb_plane_get_subsampling(int *hsub, int *vsub,
@ -1007,16 +1014,16 @@ static u32 intel_adjust_aligned_offset(int *x, int *y,
unsigned int pitch,
u32 old_offset, u32 new_offset)
{
struct drm_i915_private *i915 = to_i915(fb->dev);
struct intel_display *display = to_intel_display(fb->dev);
unsigned int cpp = fb->format->cpp[color_plane];
drm_WARN_ON(&i915->drm, new_offset > old_offset);
drm_WARN_ON(display->drm, new_offset > old_offset);
if (!is_surface_linear(fb, color_plane)) {
unsigned int tile_size, tile_width, tile_height;
unsigned int pitch_tiles;
tile_size = intel_tile_size(i915);
tile_size = intel_tile_size(display);
intel_tile_dims(fb, color_plane, &tile_width, &tile_height);
if (drm_rotation_90_or_270(rotation)) {
@ -1042,13 +1049,13 @@ static u32 intel_adjust_aligned_offset(int *x, int *y,
* the x/y offsets.
*/
u32 intel_plane_adjust_aligned_offset(int *x, int *y,
const struct intel_plane_state *state,
const struct intel_plane_state *plane_state,
int color_plane,
u32 old_offset, u32 new_offset)
{
return intel_adjust_aligned_offset(x, y, state->hw.fb, color_plane,
state->hw.rotation,
state->view.color_plane[color_plane].mapping_stride,
return intel_adjust_aligned_offset(x, y, plane_state->hw.fb, color_plane,
plane_state->hw.rotation,
plane_state->view.color_plane[color_plane].mapping_stride,
old_offset, new_offset);
}
@ -1066,7 +1073,7 @@ u32 intel_plane_adjust_aligned_offset(int *x, int *y,
* used. This is why the user has to pass in the pitch since it
* is specified in the rotated orientation.
*/
static u32 intel_compute_aligned_offset(struct drm_i915_private *i915,
static u32 intel_compute_aligned_offset(struct intel_display *display,
int *x, int *y,
const struct drm_framebuffer *fb,
int color_plane,
@ -1081,7 +1088,7 @@ static u32 intel_compute_aligned_offset(struct drm_i915_private *i915,
unsigned int tile_size, tile_width, tile_height;
unsigned int tile_rows, tiles, pitch_tiles;
tile_size = intel_tile_size(i915);
tile_size = intel_tile_size(display);
intel_tile_dims(fb, color_plane, &tile_width, &tile_height);
if (drm_rotation_90_or_270(rotation)) {
@ -1122,17 +1129,17 @@ static u32 intel_compute_aligned_offset(struct drm_i915_private *i915,
}
u32 intel_plane_compute_aligned_offset(int *x, int *y,
const struct intel_plane_state *state,
const struct intel_plane_state *plane_state,
int color_plane)
{
struct intel_plane *plane = to_intel_plane(state->uapi.plane);
struct drm_i915_private *i915 = to_i915(plane->base.dev);
const struct drm_framebuffer *fb = state->hw.fb;
unsigned int rotation = state->hw.rotation;
unsigned int pitch = state->view.color_plane[color_plane].mapping_stride;
struct intel_display *display = to_intel_display(plane_state);
struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
const struct drm_framebuffer *fb = plane_state->hw.fb;
unsigned int rotation = plane_state->hw.rotation;
unsigned int pitch = plane_state->view.color_plane[color_plane].mapping_stride;
unsigned int alignment = plane->min_alignment(plane, fb, color_plane);
return intel_compute_aligned_offset(i915, x, y, fb, color_plane,
return intel_compute_aligned_offset(display, x, y, fb, color_plane,
pitch, rotation, alignment);
}
@ -1141,16 +1148,16 @@ static int intel_fb_offset_to_xy(int *x, int *y,
const struct drm_framebuffer *fb,
int color_plane)
{
struct drm_i915_private *i915 = to_i915(fb->dev);
struct intel_display *display = to_intel_display(fb->dev);
unsigned int height, alignment, unused;
if (fb->modifier != DRM_FORMAT_MOD_LINEAR)
alignment = intel_tile_size(i915);
alignment = intel_tile_size(display);
else
alignment = 0;
if (alignment != 0 && fb->offsets[color_plane] % alignment) {
drm_dbg_kms(&i915->drm,
drm_dbg_kms(display->drm,
"Misaligned offset 0x%08x for color plane %d\n",
fb->offsets[color_plane], color_plane);
return -EINVAL;
@ -1162,7 +1169,7 @@ static int intel_fb_offset_to_xy(int *x, int *y,
/* Catch potential overflows early */
if (check_add_overflow(mul_u32_u32(height, fb->pitches[color_plane]),
fb->offsets[color_plane], &unused)) {
drm_dbg_kms(&i915->drm,
drm_dbg_kms(display->drm,
"Bad offset 0x%08x or pitch %d for color plane %d\n",
fb->offsets[color_plane], fb->pitches[color_plane],
color_plane);
@ -1182,7 +1189,7 @@ static int intel_fb_offset_to_xy(int *x, int *y,
static int intel_fb_check_ccs_xy(const struct drm_framebuffer *fb, int ccs_plane, int x, int y)
{
struct drm_i915_private *i915 = to_i915(fb->dev);
struct intel_display *display = to_intel_display(fb->dev);
const struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
int main_plane;
int hsub, vsub;
@ -1216,13 +1223,12 @@ static int intel_fb_check_ccs_xy(const struct drm_framebuffer *fb, int ccs_plane
* x/y offsets must match between CCS and the main surface.
*/
if (main_x != ccs_x || main_y != ccs_y) {
drm_dbg_kms(&i915->drm,
"Bad CCS x/y (main %d,%d ccs %d,%d) full (main %d,%d ccs %d,%d)\n",
main_x, main_y,
ccs_x, ccs_y,
intel_fb->normal_view.color_plane[main_plane].x,
intel_fb->normal_view.color_plane[main_plane].y,
x, y);
drm_dbg_kms(display->drm,
"Bad CCS x/y (main %d,%d ccs %d,%d) full (main %d,%d ccs %d,%d)\n",
main_x, main_y, ccs_x, ccs_y,
intel_fb->normal_view.color_plane[main_plane].x,
intel_fb->normal_view.color_plane[main_plane].y,
x, y);
return -EINVAL;
}
@ -1231,8 +1237,8 @@ static int intel_fb_check_ccs_xy(const struct drm_framebuffer *fb, int ccs_plane
static bool intel_plane_can_remap(const struct intel_plane_state *plane_state)
{
struct intel_display *display = to_intel_display(plane_state);
struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
struct drm_i915_private *i915 = to_i915(plane->base.dev);
const struct drm_framebuffer *fb = plane_state->hw.fb;
int i;
@ -1246,7 +1252,7 @@ static bool intel_plane_can_remap(const struct intel_plane_state *plane_state)
* Would also need to deal with the fence POT alignment
* and gen2 2KiB GTT tile size.
*/
if (DISPLAY_VER(i915) < 4)
if (DISPLAY_VER(display) < 4)
return false;
/*
@ -1258,7 +1264,7 @@ static bool intel_plane_can_remap(const struct intel_plane_state *plane_state)
/* Linear needs a page aligned stride for remapping */
if (fb->modifier == DRM_FORMAT_MOD_LINEAR) {
unsigned int alignment = intel_tile_size(i915) - 1;
unsigned int alignment = intel_tile_size(display) - 1;
for (i = 0; i < fb->format->num_planes; i++) {
if (fb->pitches[i] & alignment)
@ -1271,12 +1277,22 @@ static bool intel_plane_can_remap(const struct intel_plane_state *plane_state)
bool intel_fb_needs_pot_stride_remap(const struct intel_framebuffer *fb)
{
struct drm_i915_private *i915 = to_i915(fb->base.dev);
struct intel_display *display = to_intel_display(fb->base.dev);
return (IS_ALDERLAKE_P(i915) || DISPLAY_VER(i915) >= 14) &&
return (display->platform.alderlake_p || DISPLAY_VER(display) >= 14) &&
intel_fb_uses_dpt(&fb->base);
}
bool intel_plane_uses_fence(const struct intel_plane_state *plane_state)
{
struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
return DISPLAY_VER(dev_priv) < 4 ||
(plane->fbc && !plane_state->no_fbc_reason &&
plane_state->view.gtt.type == I915_GTT_VIEW_NORMAL);
}
static int intel_fb_pitch(const struct intel_framebuffer *fb, int color_plane, unsigned int rotation)
{
if (drm_rotation_90_or_270(rotation))
@ -1318,12 +1334,13 @@ static bool intel_plane_needs_remap(const struct intel_plane_state *plane_state)
static int convert_plane_offset_to_xy(const struct intel_framebuffer *fb, int color_plane,
int plane_width, int *x, int *y)
{
struct intel_display *display = to_intel_display(fb->base.dev);
struct drm_gem_object *obj = intel_fb_bo(&fb->base);
int ret;
ret = intel_fb_offset_to_xy(x, y, &fb->base, color_plane);
if (ret) {
drm_dbg_kms(fb->base.dev,
drm_dbg_kms(display->drm,
"bad fb plane %d offset: 0x%x\n",
color_plane, fb->base.offsets[color_plane]);
return ret;
@ -1344,7 +1361,7 @@ static int convert_plane_offset_to_xy(const struct intel_framebuffer *fb, int co
*/
if (color_plane == 0 && intel_bo_is_tiled(obj) &&
(*x + plane_width) * fb->base.format->cpp[color_plane] > fb->base.pitches[color_plane]) {
drm_dbg_kms(fb->base.dev,
drm_dbg_kms(display->drm,
"bad fb plane %d offset: 0x%x\n",
color_plane, fb->base.offsets[color_plane]);
return -EINVAL;
@ -1355,11 +1372,11 @@ static int convert_plane_offset_to_xy(const struct intel_framebuffer *fb, int co
static u32 calc_plane_aligned_offset(const struct intel_framebuffer *fb, int color_plane, int *x, int *y)
{
struct drm_i915_private *i915 = to_i915(fb->base.dev);
unsigned int tile_size = intel_tile_size(i915);
struct intel_display *display = to_intel_display(fb->base.dev);
unsigned int tile_size = intel_tile_size(display);
u32 offset;
offset = intel_compute_aligned_offset(i915, x, y, &fb->base, color_plane,
offset = intel_compute_aligned_offset(display, x, y, &fb->base, color_plane,
fb->base.pitches[color_plane],
DRM_MODE_ROTATE_0,
tile_size);
@ -1410,10 +1427,10 @@ plane_view_scanout_stride(const struct intel_framebuffer *fb, int color_plane,
unsigned int tile_width,
unsigned int src_stride_tiles, unsigned int dst_stride_tiles)
{
struct drm_i915_private *i915 = to_i915(fb->base.dev);
struct intel_display *display = to_intel_display(fb->base.dev);
unsigned int stride_tiles;
if ((IS_ALDERLAKE_P(i915) || DISPLAY_VER(i915) >= 14) &&
if ((display->platform.alderlake_p || DISPLAY_VER(display) >= 14) &&
src_stride_tiles < dst_stride_tiles)
stride_tiles = src_stride_tiles;
else
@ -1443,23 +1460,23 @@ plane_view_linear_tiles(const struct intel_framebuffer *fb, int color_plane,
const struct fb_plane_view_dims *dims,
int x, int y)
{
struct drm_i915_private *i915 = to_i915(fb->base.dev);
struct intel_display *display = to_intel_display(fb->base.dev);
unsigned int size;
size = (y + dims->height) * fb->base.pitches[color_plane] +
x * fb->base.format->cpp[color_plane];
return DIV_ROUND_UP(size, intel_tile_size(i915));
return DIV_ROUND_UP(size, intel_tile_size(display));
}
#define assign_chk_ovf(i915, var, val) ({ \
drm_WARN_ON(&(i915)->drm, overflows_type(val, var)); \
#define assign_chk_ovf(display, var, val) ({ \
drm_WARN_ON((display)->drm, overflows_type(val, var)); \
(var) = (val); \
})
#define assign_bfld_chk_ovf(i915, var, val) ({ \
#define assign_bfld_chk_ovf(display, var, val) ({ \
(var) = (val); \
drm_WARN_ON(&(i915)->drm, (var) != (val)); \
drm_WARN_ON((display)->drm, (var) != (val)); \
(var); \
})
@ -1468,38 +1485,38 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p
u32 obj_offset, u32 gtt_offset, int x, int y,
struct intel_fb_view *view)
{
struct drm_i915_private *i915 = to_i915(fb->base.dev);
struct intel_display *display = to_intel_display(fb->base.dev);
struct intel_remapped_plane_info *remap_info = &view->gtt.remapped.plane[color_plane];
struct i915_color_plane_view *color_plane_info = &view->color_plane[color_plane];
unsigned int tile_width = dims->tile_width;
unsigned int tile_height = dims->tile_height;
unsigned int tile_size = intel_tile_size(i915);
unsigned int tile_size = intel_tile_size(display);
struct drm_rect r;
u32 size = 0;
assign_bfld_chk_ovf(i915, remap_info->offset, obj_offset);
assign_bfld_chk_ovf(display, remap_info->offset, obj_offset);
if (intel_fb_is_gen12_ccs_aux_plane(&fb->base, color_plane)) {
remap_info->linear = 1;
assign_chk_ovf(i915, remap_info->size,
assign_chk_ovf(display, remap_info->size,
plane_view_linear_tiles(fb, color_plane, dims, x, y));
} else {
remap_info->linear = 0;
assign_chk_ovf(i915, remap_info->src_stride,
assign_chk_ovf(display, remap_info->src_stride,
plane_view_src_stride_tiles(fb, color_plane, dims));
assign_chk_ovf(i915, remap_info->width,
assign_chk_ovf(display, remap_info->width,
plane_view_width_tiles(fb, color_plane, dims, x));
assign_chk_ovf(i915, remap_info->height,
assign_chk_ovf(display, remap_info->height,
plane_view_height_tiles(fb, color_plane, dims, y));
}
if (view->gtt.type == I915_GTT_VIEW_ROTATED) {
drm_WARN_ON(&i915->drm, remap_info->linear);
check_array_bounds(i915, view->gtt.rotated.plane, color_plane);
drm_WARN_ON(display->drm, remap_info->linear);
check_array_bounds(display, view->gtt.rotated.plane, color_plane);
assign_chk_ovf(i915, remap_info->dst_stride,
assign_chk_ovf(display, remap_info->dst_stride,
plane_view_dst_stride_tiles(fb, color_plane, remap_info->height));
/* rotate the x/y offsets to match the GTT view */
@ -1520,9 +1537,9 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p
/* rotate the tile dimensions to match the GTT view */
swap(tile_width, tile_height);
} else {
drm_WARN_ON(&i915->drm, view->gtt.type != I915_GTT_VIEW_REMAPPED);
drm_WARN_ON(display->drm, view->gtt.type != I915_GTT_VIEW_REMAPPED);
check_array_bounds(i915, view->gtt.remapped.plane, color_plane);
check_array_bounds(display, view->gtt.remapped.plane, color_plane);
if (view->gtt.remapped.plane_alignment) {
u32 aligned_offset = ALIGN(gtt_offset,
@ -1556,7 +1573,7 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p
dst_stride = plane_view_dst_stride_tiles(fb, color_plane, dst_stride);
assign_chk_ovf(i915, remap_info->dst_stride, dst_stride);
assign_chk_ovf(display, remap_info->dst_stride, dst_stride);
color_plane_info->mapping_stride = dst_stride *
tile_width *
fb->base.format->cpp[color_plane];
@ -1614,20 +1631,23 @@ calc_plane_normal_size(const struct intel_framebuffer *fb, int color_plane,
return tiles;
}
static void intel_fb_view_init(struct drm_i915_private *i915, struct intel_fb_view *view,
static void intel_fb_view_init(struct intel_display *display,
struct intel_fb_view *view,
enum i915_gtt_view_type view_type)
{
memset(view, 0, sizeof(*view));
view->gtt.type = view_type;
if (view_type == I915_GTT_VIEW_REMAPPED &&
(IS_ALDERLAKE_P(i915) || DISPLAY_VER(i915) >= 14))
(display->platform.alderlake_p || DISPLAY_VER(display) >= 14))
view->gtt.remapped.plane_alignment = SZ_2M / PAGE_SIZE;
}
bool intel_fb_supports_90_270_rotation(const struct intel_framebuffer *fb)
{
if (DISPLAY_VER(to_i915(fb->base.dev)) >= 13)
struct intel_display *display = to_intel_display(fb->base.dev);
if (DISPLAY_VER(display) >= 13)
return false;
return fb->base.modifier == I915_FORMAT_MOD_Y_TILED ||
@ -1636,11 +1656,11 @@ bool intel_fb_supports_90_270_rotation(const struct intel_framebuffer *fb)
static unsigned int intel_fb_min_alignment(const struct drm_framebuffer *fb)
{
struct drm_i915_private *i915 = to_i915(fb->dev);
struct intel_display *display = to_intel_display(fb->dev);
struct intel_plane *plane;
unsigned int min_alignment = 0;
for_each_intel_plane(&i915->drm, plane) {
for_each_intel_plane(display->drm, plane) {
unsigned int plane_min_alignment;
if (!drm_plane_has_format(&plane->base, fb->format->format, fb->modifier))
@ -1648,7 +1668,7 @@ static unsigned int intel_fb_min_alignment(const struct drm_framebuffer *fb)
plane_min_alignment = plane->min_alignment(plane, fb, 0);
drm_WARN_ON(&i915->drm, plane_min_alignment &&
drm_WARN_ON(display->drm, plane_min_alignment &&
!is_power_of_2(plane_min_alignment));
if (intel_plane_needs_physical(plane))
@ -1660,25 +1680,41 @@ static unsigned int intel_fb_min_alignment(const struct drm_framebuffer *fb)
return min_alignment;
}
int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer *fb)
static unsigned int intel_fb_vtd_guard(const struct drm_framebuffer *fb)
{
struct intel_display *display = to_intel_display(fb->dev);
struct intel_plane *plane;
unsigned int vtd_guard = 0;
for_each_intel_plane(display->drm, plane) {
if (!drm_plane_has_format(&plane->base, fb->format->format, fb->modifier))
continue;
vtd_guard = max_t(unsigned int, vtd_guard, plane->vtd_guard);
}
return vtd_guard;
}
int intel_fill_fb_info(struct intel_display *display, struct intel_framebuffer *fb)
{
struct drm_gem_object *obj = intel_fb_bo(&fb->base);
u32 gtt_offset_rotated = 0;
u32 gtt_offset_remapped = 0;
unsigned int max_size = 0;
int i, num_planes = fb->base.format->num_planes;
unsigned int tile_size = intel_tile_size(i915);
unsigned int tile_size = intel_tile_size(display);
intel_fb_view_init(i915, &fb->normal_view, I915_GTT_VIEW_NORMAL);
intel_fb_view_init(display, &fb->normal_view, I915_GTT_VIEW_NORMAL);
drm_WARN_ON(&i915->drm,
drm_WARN_ON(display->drm,
intel_fb_supports_90_270_rotation(fb) &&
intel_fb_needs_pot_stride_remap(fb));
if (intel_fb_supports_90_270_rotation(fb))
intel_fb_view_init(i915, &fb->rotated_view, I915_GTT_VIEW_ROTATED);
intel_fb_view_init(display, &fb->rotated_view, I915_GTT_VIEW_ROTATED);
if (intel_fb_needs_pot_stride_remap(fb))
intel_fb_view_init(i915, &fb->remapped_view, I915_GTT_VIEW_REMAPPED);
intel_fb_view_init(display, &fb->remapped_view, I915_GTT_VIEW_REMAPPED);
for (i = 0; i < num_planes; i++) {
struct fb_plane_view_dims view_dims;
@ -1694,10 +1730,24 @@ int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer *
* arithmetic related to alignment and offset calculation.
*/
if (is_gen12_ccs_cc_plane(&fb->base, i)) {
if (IS_ALIGNED(fb->base.offsets[i], 64))
continue;
else
unsigned int end;
if (!IS_ALIGNED(fb->base.offsets[i], 64)) {
drm_dbg_kms(display->drm,
"fb misaligned clear color plane %d offset (0x%x)\n",
i, fb->base.offsets[i]);
return -EINVAL;
}
if (check_add_overflow(fb->base.offsets[i], 64, &end)) {
drm_dbg_kms(display->drm,
"fb bad clear color plane %d offset (0x%x)\n",
i, fb->base.offsets[i]);
return -EINVAL;
}
max_size = max(max_size, DIV_ROUND_UP(end, tile_size));
continue;
}
intel_fb_plane_dims(fb, i, &width, &height);
@ -1736,21 +1786,52 @@ int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer *
}
if (mul_u32_u32(max_size, tile_size) > obj->size) {
drm_dbg_kms(&i915->drm,
drm_dbg_kms(display->drm,
"fb too big for bo (need %llu bytes, have %zu bytes)\n",
mul_u32_u32(max_size, tile_size), obj->size);
return -EINVAL;
}
fb->min_alignment = intel_fb_min_alignment(&fb->base);
fb->vtd_guard = intel_fb_vtd_guard(&fb->base);
return 0;
}
unsigned int intel_fb_view_vtd_guard(const struct drm_framebuffer *fb,
const struct intel_fb_view *view,
unsigned int rotation)
{
unsigned int vtd_guard;
int color_plane;
vtd_guard = to_intel_framebuffer(fb)->vtd_guard;
if (!vtd_guard)
return 0;
for (color_plane = 0; color_plane < fb->format->num_planes; color_plane++) {
unsigned int stride, tile;
if (intel_fb_is_ccs_aux_plane(fb, color_plane) ||
is_gen12_ccs_cc_plane(fb, color_plane))
continue;
stride = view->color_plane[color_plane].mapping_stride;
if (drm_rotation_90_or_270(rotation))
tile = intel_tile_height(fb, color_plane);
else
tile = intel_tile_width_bytes(fb, color_plane);
vtd_guard = max(vtd_guard, DIV_ROUND_UP(stride, tile));
}
return vtd_guard;
}
static void intel_plane_remap_gtt(struct intel_plane_state *plane_state)
{
struct drm_i915_private *i915 =
to_i915(plane_state->uapi.plane->dev);
struct intel_display *display = to_intel_display(plane_state);
struct drm_framebuffer *fb = plane_state->hw.fb;
struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
unsigned int rotation = plane_state->hw.rotation;
@ -1759,7 +1840,7 @@ static void intel_plane_remap_gtt(struct intel_plane_state *plane_state)
unsigned int src_w, src_h;
u32 gtt_offset = 0;
intel_fb_view_init(i915, &plane_state->view,
intel_fb_view_init(display, &plane_state->view,
drm_rotation_90_or_270(rotation) ? I915_GTT_VIEW_ROTATED :
I915_GTT_VIEW_REMAPPED);
@ -1768,7 +1849,7 @@ static void intel_plane_remap_gtt(struct intel_plane_state *plane_state)
src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
drm_WARN_ON(&i915->drm, intel_fb_is_ccs_modifier(fb->modifier));
drm_WARN_ON(display->drm, intel_fb_is_ccs_modifier(fb->modifier));
/* Make src coordinates relative to the viewport */
drm_rect_translate(&plane_state->uapi.src,
@ -1810,6 +1891,42 @@ static void intel_plane_remap_gtt(struct intel_plane_state *plane_state)
}
}
unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info)
{
unsigned int size = 0;
int i;
for (i = 0 ; i < ARRAY_SIZE(rot_info->plane); i++)
size += rot_info->plane[i].dst_stride * rot_info->plane[i].width;
return size;
}
unsigned int intel_remapped_info_size(const struct intel_remapped_info *rem_info)
{
unsigned int size = 0;
int i;
for (i = 0 ; i < ARRAY_SIZE(rem_info->plane); i++) {
unsigned int plane_size;
if (rem_info->plane[i].linear)
plane_size = rem_info->plane[i].size;
else
plane_size = rem_info->plane[i].dst_stride * rem_info->plane[i].height;
if (plane_size == 0)
continue;
if (rem_info->plane_alignment)
size = ALIGN(size, rem_info->plane_alignment);
size += plane_size;
}
return size;
}
void intel_fb_fill_view(const struct intel_framebuffer *fb, unsigned int rotation,
struct intel_fb_view *view)
{
@ -1821,8 +1938,39 @@ void intel_fb_fill_view(const struct intel_framebuffer *fb, unsigned int rotatio
*view = fb->normal_view;
}
/*
* Convert the x/y offsets into a linear offset.
* Only valid with 0/180 degree rotation, which is fine since linear
* offset is only used with linear buffers on pre-hsw and tiled buffers
* with gen2/3, and 90/270 degree rotations isn't supported on any of them.
*/
u32 intel_fb_xy_to_linear(int x, int y,
const struct intel_plane_state *plane_state,
int color_plane)
{
const struct drm_framebuffer *fb = plane_state->hw.fb;
unsigned int cpp = fb->format->cpp[color_plane];
unsigned int pitch = plane_state->view.color_plane[color_plane].mapping_stride;
return y * pitch + x * cpp;
}
/*
* Add the x/y offsets derived from fb->offsets[] to the user
* specified plane src x/y offsets. The resulting x/y offsets
* specify the start of scanout from the beginning of the gtt mapping.
*/
void intel_add_fb_offsets(int *x, int *y,
const struct intel_plane_state *plane_state,
int color_plane)
{
*x += plane_state->view.color_plane[color_plane].x;
*y += plane_state->view.color_plane[color_plane].y;
}
static
u32 intel_fb_max_stride(struct drm_i915_private *dev_priv,
u32 intel_fb_max_stride(struct intel_display *display,
u32 pixel_format, u64 modifier)
{
/*
@ -1831,10 +1979,10 @@ u32 intel_fb_max_stride(struct drm_i915_private *dev_priv,
*
* The new CCS hash mode makes remapping impossible
*/
if (DISPLAY_VER(dev_priv) < 4 || intel_fb_is_ccs_modifier(modifier) ||
intel_fb_modifier_uses_dpt(dev_priv, modifier))
return intel_plane_fb_max_stride(dev_priv, pixel_format, modifier);
else if (DISPLAY_VER(dev_priv) >= 7)
if (DISPLAY_VER(display) < 4 || intel_fb_is_ccs_modifier(modifier) ||
intel_fb_modifier_uses_dpt(display, modifier))
return intel_plane_fb_max_stride(display->drm, pixel_format, modifier);
else if (DISPLAY_VER(display) >= 7)
return 256 * 1024;
else
return 128 * 1024;
@ -1843,11 +1991,11 @@ u32 intel_fb_max_stride(struct drm_i915_private *dev_priv,
static unsigned int
intel_fb_stride_alignment(const struct drm_framebuffer *fb, int color_plane)
{
struct drm_i915_private *dev_priv = to_i915(fb->dev);
struct intel_display *display = to_intel_display(fb->dev);
unsigned int tile_width;
if (is_surface_linear(fb, color_plane)) {
unsigned int max_stride = intel_plane_fb_max_stride(dev_priv,
unsigned int max_stride = intel_plane_fb_max_stride(display->drm,
fb->format->format,
fb->modifier);
@ -1857,7 +2005,7 @@ intel_fb_stride_alignment(const struct drm_framebuffer *fb, int color_plane)
*/
if (fb->pitches[color_plane] > max_stride &&
!intel_fb_is_ccs_modifier(fb->modifier))
return intel_tile_size(dev_priv);
return intel_tile_size(display);
else
return 64;
}
@ -1868,7 +2016,7 @@ intel_fb_stride_alignment(const struct drm_framebuffer *fb, int color_plane)
* On TGL the surface stride must be 4 tile aligned, mapped by
* one 64 byte cacheline on the CCS AUX surface.
*/
if (DISPLAY_VER(dev_priv) >= 12)
if (DISPLAY_VER(display) >= 12)
tile_width *= 4;
/*
* Display WA #0531: skl,bxt,kbl,glk
@ -1879,7 +2027,7 @@ intel_fb_stride_alignment(const struct drm_framebuffer *fb, int color_plane)
* require the entire fb to accommodate that to avoid
* potential runtime errors at plane configuration time.
*/
else if ((DISPLAY_VER(dev_priv) == 9 || IS_GEMINILAKE(dev_priv)) &&
else if ((DISPLAY_VER(display) == 9 || display->platform.geminilake) &&
color_plane == 0 && fb->width > 3840)
tile_width *= 4;
}
@ -1888,6 +2036,7 @@ intel_fb_stride_alignment(const struct drm_framebuffer *fb, int color_plane)
static int intel_plane_check_stride(const struct intel_plane_state *plane_state)
{
struct intel_display *display = to_intel_display(plane_state);
struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
const struct drm_framebuffer *fb = plane_state->hw.fb;
unsigned int rotation = plane_state->hw.rotation;
@ -1909,7 +2058,7 @@ static int intel_plane_check_stride(const struct intel_plane_state *plane_state)
fb->modifier, rotation);
if (stride > max_stride) {
drm_dbg_kms(plane->base.dev,
drm_dbg_kms(display->drm,
"[FB:%d] stride (%d) exceeds [PLANE:%d:%s] max stride (%d)\n",
fb->base.id, stride,
plane->base.base.id, plane->base.name, max_stride);
@ -2058,13 +2207,13 @@ int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
struct drm_gem_object *obj,
struct drm_mode_fb_cmd2 *mode_cmd)
{
struct drm_i915_private *dev_priv = to_i915(obj->dev);
struct intel_display *display = to_intel_display(obj->dev);
struct drm_framebuffer *fb = &intel_fb->base;
u32 max_stride;
int ret = -EINVAL;
int i;
ret = intel_fb_bo_framebuffer_init(intel_fb, obj, mode_cmd);
ret = intel_fb_bo_framebuffer_init(fb, obj, mode_cmd);
if (ret)
return ret;
@ -2075,19 +2224,19 @@ int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
}
ret = -EINVAL;
if (!drm_any_plane_has_format(&dev_priv->drm,
if (!drm_any_plane_has_format(display->drm,
mode_cmd->pixel_format,
mode_cmd->modifier[0])) {
drm_dbg_kms(&dev_priv->drm,
drm_dbg_kms(display->drm,
"unsupported pixel format %p4cc / modifier 0x%llx\n",
&mode_cmd->pixel_format, mode_cmd->modifier[0]);
goto err_frontbuffer_put;
}
max_stride = intel_fb_max_stride(dev_priv, mode_cmd->pixel_format,
max_stride = intel_fb_max_stride(display, mode_cmd->pixel_format,
mode_cmd->modifier[0]);
if (mode_cmd->pitches[0] > max_stride) {
drm_dbg_kms(&dev_priv->drm,
drm_dbg_kms(display->drm,
"%s pitch (%u) must be at most %d\n",
mode_cmd->modifier[0] != DRM_FORMAT_MOD_LINEAR ?
"tiled" : "linear",
@ -2097,26 +2246,25 @@ int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
/* FIXME need to adjust LINOFF/TILEOFF accordingly. */
if (mode_cmd->offsets[0] != 0) {
drm_dbg_kms(&dev_priv->drm,
drm_dbg_kms(display->drm,
"plane 0 offset (0x%08x) must be 0\n",
mode_cmd->offsets[0]);
goto err_frontbuffer_put;
}
drm_helper_mode_fill_fb_struct(&dev_priv->drm, fb, mode_cmd);
drm_helper_mode_fill_fb_struct(display->drm, fb, mode_cmd);
for (i = 0; i < fb->format->num_planes; i++) {
unsigned int stride_alignment;
if (mode_cmd->handles[i] != mode_cmd->handles[0]) {
drm_dbg_kms(&dev_priv->drm, "bad plane %d handle\n",
i);
drm_dbg_kms(display->drm, "bad plane %d handle\n", i);
goto err_frontbuffer_put;
}
stride_alignment = intel_fb_stride_alignment(fb, i);
if (fb->pitches[i] & (stride_alignment - 1)) {
drm_dbg_kms(&dev_priv->drm,
drm_dbg_kms(display->drm,
"plane %d pitch (%d) must be at least %u byte aligned\n",
i, fb->pitches[i], stride_alignment);
goto err_frontbuffer_put;
@ -2126,10 +2274,9 @@ int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
unsigned int ccs_aux_stride = gen12_ccs_aux_stride(intel_fb, i);
if (fb->pitches[i] != ccs_aux_stride) {
drm_dbg_kms(&dev_priv->drm,
drm_dbg_kms(display->drm,
"ccs aux plane %d pitch (%d) must be %d\n",
i,
fb->pitches[i], ccs_aux_stride);
i, fb->pitches[i], ccs_aux_stride);
goto err_frontbuffer_put;
}
}
@ -2137,7 +2284,7 @@ int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
fb->obj[i] = obj;
}
ret = intel_fill_fb_info(dev_priv, intel_fb);
ret = intel_fill_fb_info(display, intel_fb);
if (ret)
goto err_frontbuffer_put;
@ -2146,7 +2293,7 @@ int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
vm = intel_dpt_create(intel_fb);
if (IS_ERR(vm)) {
drm_dbg_kms(&dev_priv->drm, "failed to create DPT\n");
drm_dbg_kms(display->drm, "failed to create DPT\n");
ret = PTR_ERR(vm);
goto err_frontbuffer_put;
}
@ -2154,9 +2301,9 @@ int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
intel_fb->dpt_vm = vm;
}
ret = drm_framebuffer_init(&dev_priv->drm, fb, &intel_fb_funcs);
ret = drm_framebuffer_init(display->drm, fb, &intel_fb_funcs);
if (ret) {
drm_err(&dev_priv->drm, "framebuffer init failed %d\n", ret);
drm_err(display->drm, "framebuffer init failed %d\n", ret);
goto err_free_dpt;
}
@ -2180,9 +2327,8 @@ intel_user_framebuffer_create(struct drm_device *dev,
struct drm_framebuffer *fb;
struct drm_gem_object *obj;
struct drm_mode_fb_cmd2 mode_cmd = *user_mode_cmd;
struct drm_i915_private *i915 = to_i915(dev);
obj = intel_fb_bo_lookup_valid_bo(i915, filp, &mode_cmd);
obj = intel_fb_bo_lookup_valid_bo(dev, filp, &mode_cmd);
if (IS_ERR(obj))
return ERR_CAST(obj);

View File

@ -13,13 +13,14 @@ struct drm_device;
struct drm_file;
struct drm_framebuffer;
struct drm_gem_object;
struct drm_i915_gem_object;
struct drm_i915_private;
struct drm_mode_fb_cmd2;
struct intel_display;
struct intel_fb_view;
struct intel_framebuffer;
struct intel_plane;
struct intel_plane_state;
struct intel_remapped_info;
struct intel_rotation_info;
#define INTEL_PLANE_CAP_NONE 0
#define INTEL_PLANE_CAP_CCS_RC BIT(0)
@ -41,7 +42,7 @@ bool intel_fb_is_tile4_modifier(u64 modifier);
bool intel_fb_is_ccs_aux_plane(const struct drm_framebuffer *fb, int color_plane);
int intel_fb_rc_ccs_cc_plane(const struct drm_framebuffer *fb);
u64 *intel_fb_plane_get_modifiers(struct drm_i915_private *i915,
u64 *intel_fb_plane_get_modifiers(struct intel_display *display,
u8 plane_caps);
bool intel_fb_plane_supports_modifier(struct intel_plane *plane, u64 modifier);
@ -58,7 +59,7 @@ int main_to_ccs_plane(const struct drm_framebuffer *fb, int main_plane);
int skl_ccs_to_main_plane(const struct drm_framebuffer *fb, int ccs_plane);
int skl_main_to_aux_plane(const struct drm_framebuffer *fb, int main_plane);
unsigned int intel_tile_size(const struct drm_i915_private *i915);
unsigned int intel_tile_size(struct intel_display *display);
unsigned int intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane);
unsigned int intel_tile_height(const struct drm_framebuffer *fb, int color_plane);
unsigned int intel_tile_row_size(const struct drm_framebuffer *fb, int color_plane);
@ -70,21 +71,35 @@ void intel_fb_plane_get_subsampling(int *hsub, int *vsub,
int color_plane);
u32 intel_plane_adjust_aligned_offset(int *x, int *y,
const struct intel_plane_state *state,
const struct intel_plane_state *plane_state,
int color_plane,
u32 old_offset, u32 new_offset);
u32 intel_plane_compute_aligned_offset(int *x, int *y,
const struct intel_plane_state *state,
const struct intel_plane_state *plane_state,
int color_plane);
bool intel_fb_needs_pot_stride_remap(const struct intel_framebuffer *fb);
bool intel_plane_uses_fence(const struct intel_plane_state *plane_state);
bool intel_fb_supports_90_270_rotation(const struct intel_framebuffer *fb);
int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer *fb);
unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info);
unsigned int intel_remapped_info_size(const struct intel_remapped_info *rem_info);
int intel_fill_fb_info(struct intel_display *display, struct intel_framebuffer *fb);
void intel_fb_fill_view(const struct intel_framebuffer *fb, unsigned int rotation,
struct intel_fb_view *view);
unsigned int intel_fb_view_vtd_guard(const struct drm_framebuffer *fb,
const struct intel_fb_view *view,
unsigned int rotation);
int intel_plane_compute_gtt(struct intel_plane_state *plane_state);
unsigned int intel_fb_xy_to_linear(int x, int y,
const struct intel_plane_state *plane_state,
int color_plane);
void intel_add_fb_offsets(int *x, int *y,
const struct intel_plane_state *plane_state,
int color_plane);
int intel_framebuffer_init(struct intel_framebuffer *ifb,
struct drm_gem_object *obj,
struct drm_mode_fb_cmd2 *mode_cmd);
@ -96,7 +111,7 @@ intel_user_framebuffer_create(struct drm_device *dev,
struct drm_file *filp,
const struct drm_mode_fb_cmd2 *user_mode_cmd);
bool intel_fb_modifier_uses_dpt(struct drm_i915_private *i915, u64 modifier);
bool intel_fb_modifier_uses_dpt(struct intel_display *display, u64 modifier);
bool intel_fb_uses_dpt(const struct drm_framebuffer *fb);
unsigned int intel_fb_modifier_to_tiling(u64 fb_modifier);

View File

@ -8,6 +8,7 @@
#include "gem/i915_gem_object.h"
#include "i915_drv.h"
#include "intel_display_types.h"
#include "intel_fb.h"
#include "intel_fb_bo.h"
@ -16,12 +17,12 @@ void intel_fb_bo_framebuffer_fini(struct drm_gem_object *obj)
/* Nothing to do for i915 */
}
int intel_fb_bo_framebuffer_init(struct intel_framebuffer *intel_fb,
int intel_fb_bo_framebuffer_init(struct drm_framebuffer *fb,
struct drm_gem_object *_obj,
struct drm_mode_fb_cmd2 *mode_cmd)
{
struct drm_i915_gem_object *obj = to_intel_bo(_obj);
struct drm_i915_private *i915 = to_i915(obj->base.dev);
struct intel_display *display = to_intel_display(obj->base.dev);
unsigned int tiling, stride;
i915_gem_object_lock(obj, NULL);
@ -36,7 +37,7 @@ int intel_fb_bo_framebuffer_init(struct intel_framebuffer *intel_fb,
*/
if (tiling != I915_TILING_NONE &&
tiling != intel_fb_modifier_to_tiling(mode_cmd->modifier[0])) {
drm_dbg_kms(&i915->drm,
drm_dbg_kms(display->drm,
"tiling_mode doesn't match fb modifier\n");
return -EINVAL;
}
@ -44,7 +45,7 @@ int intel_fb_bo_framebuffer_init(struct intel_framebuffer *intel_fb,
if (tiling == I915_TILING_X) {
mode_cmd->modifier[0] = I915_FORMAT_MOD_X_TILED;
} else if (tiling == I915_TILING_Y) {
drm_dbg_kms(&i915->drm,
drm_dbg_kms(display->drm,
"No Y tiling for legacy addfb\n");
return -EINVAL;
}
@ -54,9 +55,9 @@ int intel_fb_bo_framebuffer_init(struct intel_framebuffer *intel_fb,
* gen2/3 display engine uses the fence if present,
* so the tiling mode must match the fb modifier exactly.
*/
if (DISPLAY_VER(i915) < 4 &&
if (DISPLAY_VER(display) < 4 &&
tiling != intel_fb_modifier_to_tiling(mode_cmd->modifier[0])) {
drm_dbg_kms(&i915->drm,
drm_dbg_kms(display->drm,
"tiling_mode must match fb modifier exactly on gen2/3\n");
return -EINVAL;
}
@ -66,7 +67,7 @@ int intel_fb_bo_framebuffer_init(struct intel_framebuffer *intel_fb,
* the fb pitch and fence stride match.
*/
if (tiling != I915_TILING_NONE && mode_cmd->pitches[0] != stride) {
drm_dbg_kms(&i915->drm,
drm_dbg_kms(display->drm,
"pitch (%d) must match tiling stride (%d)\n",
mode_cmd->pitches[0], stride);
return -EINVAL;
@ -76,10 +77,11 @@ int intel_fb_bo_framebuffer_init(struct intel_framebuffer *intel_fb,
}
struct drm_gem_object *
intel_fb_bo_lookup_valid_bo(struct drm_i915_private *i915,
intel_fb_bo_lookup_valid_bo(struct drm_device *drm,
struct drm_file *filp,
const struct drm_mode_fb_cmd2 *mode_cmd)
{
struct drm_i915_private *i915 = to_i915(drm);
struct drm_i915_gem_object *obj;
obj = i915_gem_object_lookup(filp, mode_cmd->handles[0]);

View File

@ -6,20 +6,20 @@
#ifndef __INTEL_FB_BO_H__
#define __INTEL_FB_BO_H__
struct drm_device;
struct drm_file;
struct drm_framebuffer;
struct drm_gem_object;
struct drm_i915_private;
struct drm_mode_fb_cmd2;
struct intel_framebuffer;
void intel_fb_bo_framebuffer_fini(struct drm_gem_object *obj);
int intel_fb_bo_framebuffer_init(struct intel_framebuffer *intel_fb,
int intel_fb_bo_framebuffer_init(struct drm_framebuffer *fb,
struct drm_gem_object *obj,
struct drm_mode_fb_cmd2 *mode_cmd);
struct drm_gem_object *
intel_fb_bo_lookup_valid_bo(struct drm_i915_private *i915,
intel_fb_bo_lookup_valid_bo(struct drm_device *drm,
struct drm_file *filp,
const struct drm_mode_fb_cmd2 *user_mode_cmd);

View File

@ -107,6 +107,7 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb,
const struct i915_gtt_view *view,
unsigned int alignment,
unsigned int phys_alignment,
unsigned int vtd_guard,
bool uses_fence,
unsigned long *out_flags)
{
@ -126,14 +127,6 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb,
if (drm_WARN_ON(dev, alignment && !is_power_of_2(alignment)))
return ERR_PTR(-EINVAL);
/* Note that the w/a also requires 64 PTE of padding following the
* bo. We currently fill all unused PTE with the shadow page and so
* we should always have valid PTE following the scanout preventing
* the VT-d warning.
*/
if (intel_scanout_needs_vtd_wa(dev_priv) && alignment < 256 * 1024)
alignment = 256 * 1024;
/*
* Global gtt pte registers are special registers which actually forward
* writes to a chunk of system memory. Which means that there is no risk
@ -170,7 +163,7 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb,
goto err;
vma = i915_gem_object_pin_to_display_plane(obj, &ww, alignment,
view, pinctl);
vtd_guard, view, pinctl);
if (IS_ERR(vma)) {
ret = PTR_ERR(vma);
goto err_unpin;
@ -252,7 +245,16 @@ intel_plane_fb_min_phys_alignment(const struct intel_plane_state *plane_state)
return plane->min_alignment(plane, fb, 0);
}
int intel_plane_pin_fb(struct intel_plane_state *plane_state)
static unsigned int
intel_plane_fb_vtd_guard(const struct intel_plane_state *plane_state)
{
return intel_fb_view_vtd_guard(plane_state->hw.fb,
&plane_state->view,
plane_state->hw.rotation);
}
int intel_plane_pin_fb(struct intel_plane_state *plane_state,
const struct intel_plane_state *old_plane_state)
{
struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
const struct intel_framebuffer *fb =
@ -263,6 +265,7 @@ int intel_plane_pin_fb(struct intel_plane_state *plane_state)
vma = intel_fb_pin_to_ggtt(&fb->base, &plane_state->view.gtt,
intel_plane_fb_min_alignment(plane_state),
intel_plane_fb_min_phys_alignment(plane_state),
intel_plane_fb_vtd_guard(plane_state),
intel_plane_uses_fence(plane_state),
&plane_state->flags);
if (IS_ERR(vma))

View File

@ -18,12 +18,14 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb,
const struct i915_gtt_view *view,
unsigned int alignment,
unsigned int phys_alignment,
unsigned int vtd_guard,
bool uses_fence,
unsigned long *out_flags);
void intel_fb_unpin_vma(struct i915_vma *vma, unsigned long flags);
int intel_plane_pin_fb(struct intel_plane_state *plane_state);
int intel_plane_pin_fb(struct intel_plane_state *new_plane_state,
const struct intel_plane_state *old_plane_state);
void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state);
#endif

View File

@ -177,9 +177,6 @@ static int intelfb_create(struct drm_fb_helper *helper,
struct intel_framebuffer *fb = ifbdev->fb;
struct drm_device *dev = helper->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
const struct i915_gtt_view view = {
.type = I915_GTT_VIEW_NORMAL,
};
intel_wakeref_t wakeref;
struct fb_info *info;
struct i915_vma *vma;
@ -226,8 +223,10 @@ static int intelfb_create(struct drm_fb_helper *helper,
* This also validates that any existing fb inherited from the
* BIOS is suitable for own access.
*/
vma = intel_fb_pin_to_ggtt(&fb->base, &view,
vma = intel_fb_pin_to_ggtt(&fb->base, &fb->normal_view.gtt,
fb->min_alignment, 0,
intel_fb_view_vtd_guard(&fb->base, &fb->normal_view,
DRM_MODE_ROTATE_0),
false, &flags);
if (IS_ERR(vma)) {
ret = PTR_ERR(vma);
@ -695,3 +694,8 @@ struct intel_framebuffer *intel_fbdev_framebuffer(struct intel_fbdev *fbdev)
return to_intel_framebuffer(fbdev->helper.fb);
}
struct i915_vma *intel_fbdev_vma_pointer(struct intel_fbdev *fbdev)
{
return fbdev ? fbdev->vma : NULL;
}

View File

@ -17,6 +17,8 @@ struct intel_framebuffer;
void intel_fbdev_setup(struct drm_i915_private *dev_priv);
void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous);
struct intel_framebuffer *intel_fbdev_framebuffer(struct intel_fbdev *fbdev);
struct i915_vma *intel_fbdev_vma_pointer(struct intel_fbdev *fbdev);
#else
static inline void intel_fbdev_setup(struct drm_i915_private *dev_priv)
{
@ -30,6 +32,12 @@ static inline struct intel_framebuffer *intel_fbdev_framebuffer(struct intel_fbd
{
return NULL;
}
static inline struct i915_vma *intel_fbdev_vma_pointer(struct intel_fbdev *fbdev)
{
return NULL;
}
#endif
#endif /* __INTEL_FBDEV_H__ */

View File

@ -80,14 +80,13 @@ void assert_fdi_rx_disabled(struct drm_i915_private *i915, enum pipe pipe)
assert_fdi_rx(i915, pipe, false);
}
void assert_fdi_tx_pll_enabled(struct drm_i915_private *i915,
void assert_fdi_tx_pll_enabled(struct intel_display *display,
enum pipe pipe)
{
struct intel_display *display = &i915->display;
bool cur_state;
/* ILK FDI PLL is always enabled */
if (IS_IRONLAKE(i915))
if (display->platform.ironlake)
return;
/* On Haswell, DDI ports are responsible for the FDI PLL setup */
@ -99,10 +98,9 @@ void assert_fdi_tx_pll_enabled(struct drm_i915_private *i915,
"FDI TX PLL assertion failure, should be active but is disabled\n");
}
static void assert_fdi_rx_pll(struct drm_i915_private *i915,
static void assert_fdi_rx_pll(struct intel_display *display,
enum pipe pipe, bool state)
{
struct intel_display *display = &i915->display;
bool cur_state;
cur_state = intel_de_read(display, FDI_RX_CTL(pipe)) & FDI_RX_PLL_ENABLE;
@ -111,14 +109,14 @@ static void assert_fdi_rx_pll(struct drm_i915_private *i915,
str_on_off(state), str_on_off(cur_state));
}
void assert_fdi_rx_pll_enabled(struct drm_i915_private *i915, enum pipe pipe)
void assert_fdi_rx_pll_enabled(struct intel_display *display, enum pipe pipe)
{
assert_fdi_rx_pll(i915, pipe, true);
assert_fdi_rx_pll(display, pipe, true);
}
void assert_fdi_rx_pll_disabled(struct drm_i915_private *i915, enum pipe pipe)
void assert_fdi_rx_pll_disabled(struct intel_display *display, enum pipe pipe)
{
assert_fdi_rx_pll(i915, pipe, false);
assert_fdi_rx_pll(display, pipe, false);
}
void intel_fdi_link_train(struct intel_crtc *crtc,
@ -390,7 +388,7 @@ static int intel_fdi_atomic_check_bw(struct intel_atomic_state *state,
* @state must be recomputed with the updated @limits.
*
* Returns:
* - 0 if the confugration is valid
* - 0 if the configuration is valid
* - %-EAGAIN, if the configuration is invalid and @limits got updated
* with fallback values with which the configuration of all CRTCs
* in @state must be recomputed
@ -513,6 +511,7 @@ void intel_fdi_normal_train(struct intel_crtc *crtc)
static void ilk_fdi_link_train(struct intel_crtc *crtc,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc);
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
enum pipe pipe = crtc->pipe;
@ -527,7 +526,7 @@ static void ilk_fdi_link_train(struct intel_crtc *crtc,
intel_de_read(dev_priv, PIPE_DATA_M1(dev_priv, pipe)) & TU_SIZE_MASK);
/* FDI needs bits from pipe first */
assert_transcoder_enabled(dev_priv, crtc_state->cpu_transcoder);
assert_transcoder_enabled(display, crtc_state->cpu_transcoder);
/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
for train result */

View File

@ -13,6 +13,7 @@ struct drm_i915_private;
struct intel_atomic_state;
struct intel_crtc;
struct intel_crtc_state;
struct intel_display;
struct intel_encoder;
struct intel_link_bw_limits;
@ -41,8 +42,8 @@ void assert_fdi_tx_enabled(struct drm_i915_private *i915, enum pipe pipe);
void assert_fdi_tx_disabled(struct drm_i915_private *i915, enum pipe pipe);
void assert_fdi_rx_enabled(struct drm_i915_private *i915, enum pipe pipe);
void assert_fdi_rx_disabled(struct drm_i915_private *i915, enum pipe pipe);
void assert_fdi_tx_pll_enabled(struct drm_i915_private *i915, enum pipe pipe);
void assert_fdi_rx_pll_enabled(struct drm_i915_private *i915, enum pipe pipe);
void assert_fdi_rx_pll_disabled(struct drm_i915_private *i915, enum pipe pipe);
void assert_fdi_tx_pll_enabled(struct intel_display *display, enum pipe pipe);
void assert_fdi_rx_pll_enabled(struct intel_display *display, enum pipe pipe);
void assert_fdi_rx_pll_disabled(struct intel_display *display, enum pipe pipe);
#endif

View File

@ -55,16 +55,15 @@
* The code also supports underrun detection on the PCH transcoder.
*/
static bool ivb_can_enable_err_int(struct drm_device *dev)
static bool ivb_can_enable_err_int(struct intel_display *display)
{
struct intel_display *display = to_intel_display(dev);
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct intel_crtc *crtc;
enum pipe pipe;
lockdep_assert_held(&dev_priv->irq_lock);
for_each_pipe(dev_priv, pipe) {
for_each_pipe(display, pipe) {
crtc = intel_crtc_for_pipe(display, pipe);
if (crtc->cpu_fifo_underrun_disabled)
@ -74,16 +73,15 @@ static bool ivb_can_enable_err_int(struct drm_device *dev)
return true;
}
static bool cpt_can_enable_serr_int(struct drm_device *dev)
static bool cpt_can_enable_serr_int(struct intel_display *display)
{
struct intel_display *display = to_intel_display(dev);
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_private *dev_priv = to_i915(display->drm);
enum pipe pipe;
struct intel_crtc *crtc;
lockdep_assert_held(&dev_priv->irq_lock);
for_each_pipe(dev_priv, pipe) {
for_each_pipe(display, pipe) {
crtc = intel_crtc_for_pipe(display, pipe);
if (crtc->pch_fifo_underrun_disabled)
@ -97,48 +95,48 @@ static void i9xx_check_fifo_underruns(struct intel_crtc *crtc)
{
struct intel_display *display = to_intel_display(crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
i915_reg_t reg = PIPESTAT(dev_priv, crtc->pipe);
i915_reg_t reg = PIPESTAT(display, crtc->pipe);
u32 enable_mask;
lockdep_assert_held(&dev_priv->irq_lock);
if ((intel_de_read(dev_priv, reg) & PIPE_FIFO_UNDERRUN_STATUS) == 0)
if ((intel_de_read(display, reg) & PIPE_FIFO_UNDERRUN_STATUS) == 0)
return;
enable_mask = i915_pipestat_enable_mask(dev_priv, crtc->pipe);
intel_de_write(dev_priv, reg, enable_mask | PIPE_FIFO_UNDERRUN_STATUS);
intel_de_posting_read(dev_priv, reg);
enable_mask = i915_pipestat_enable_mask(display, crtc->pipe);
intel_de_write(display, reg, enable_mask | PIPE_FIFO_UNDERRUN_STATUS);
intel_de_posting_read(display, reg);
trace_intel_cpu_fifo_underrun(display, crtc->pipe);
drm_err(&dev_priv->drm, "pipe %c underrun\n", pipe_name(crtc->pipe));
drm_err(display->drm, "pipe %c underrun\n", pipe_name(crtc->pipe));
}
static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev,
static void i9xx_set_fifo_underrun_reporting(struct intel_display *display,
enum pipe pipe,
bool enable, bool old)
{
struct drm_i915_private *dev_priv = to_i915(dev);
i915_reg_t reg = PIPESTAT(dev_priv, pipe);
struct drm_i915_private *dev_priv = to_i915(display->drm);
i915_reg_t reg = PIPESTAT(display, pipe);
lockdep_assert_held(&dev_priv->irq_lock);
if (enable) {
u32 enable_mask = i915_pipestat_enable_mask(dev_priv, pipe);
u32 enable_mask = i915_pipestat_enable_mask(display, pipe);
intel_de_write(dev_priv, reg,
intel_de_write(display, reg,
enable_mask | PIPE_FIFO_UNDERRUN_STATUS);
intel_de_posting_read(dev_priv, reg);
intel_de_posting_read(display, reg);
} else {
if (old && intel_de_read(dev_priv, reg) & PIPE_FIFO_UNDERRUN_STATUS)
drm_err(&dev_priv->drm, "pipe %c underrun\n",
if (old && intel_de_read(display, reg) & PIPE_FIFO_UNDERRUN_STATUS)
drm_err(display->drm, "pipe %c underrun\n",
pipe_name(pipe));
}
}
static void ilk_set_fifo_underrun_reporting(struct drm_device *dev,
static void ilk_set_fifo_underrun_reporting(struct intel_display *display,
enum pipe pipe, bool enable)
{
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_private *dev_priv = to_i915(display->drm);
u32 bit = (pipe == PIPE_A) ?
DE_PIPEA_FIFO_UNDERRUN : DE_PIPEB_FIFO_UNDERRUN;
@ -153,30 +151,30 @@ static void ivb_check_fifo_underruns(struct intel_crtc *crtc)
struct intel_display *display = to_intel_display(crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum pipe pipe = crtc->pipe;
u32 err_int = intel_de_read(dev_priv, GEN7_ERR_INT);
u32 err_int = intel_de_read(display, GEN7_ERR_INT);
lockdep_assert_held(&dev_priv->irq_lock);
if ((err_int & ERR_INT_FIFO_UNDERRUN(pipe)) == 0)
return;
intel_de_write(dev_priv, GEN7_ERR_INT, ERR_INT_FIFO_UNDERRUN(pipe));
intel_de_posting_read(dev_priv, GEN7_ERR_INT);
intel_de_write(display, GEN7_ERR_INT, ERR_INT_FIFO_UNDERRUN(pipe));
intel_de_posting_read(display, GEN7_ERR_INT);
trace_intel_cpu_fifo_underrun(display, pipe);
drm_err(&dev_priv->drm, "fifo underrun on pipe %c\n", pipe_name(pipe));
drm_err(display->drm, "fifo underrun on pipe %c\n", pipe_name(pipe));
}
static void ivb_set_fifo_underrun_reporting(struct drm_device *dev,
static void ivb_set_fifo_underrun_reporting(struct intel_display *display,
enum pipe pipe, bool enable,
bool old)
{
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_private *dev_priv = to_i915(display->drm);
if (enable) {
intel_de_write(dev_priv, GEN7_ERR_INT,
intel_de_write(display, GEN7_ERR_INT,
ERR_INT_FIFO_UNDERRUN(pipe));
if (!ivb_can_enable_err_int(dev))
if (!ivb_can_enable_err_int(display))
return;
ilk_enable_display_irq(dev_priv, DE_ERR_INT_IVB);
@ -184,18 +182,18 @@ static void ivb_set_fifo_underrun_reporting(struct drm_device *dev,
ilk_disable_display_irq(dev_priv, DE_ERR_INT_IVB);
if (old &&
intel_de_read(dev_priv, GEN7_ERR_INT) & ERR_INT_FIFO_UNDERRUN(pipe)) {
drm_err(&dev_priv->drm,
intel_de_read(display, GEN7_ERR_INT) & ERR_INT_FIFO_UNDERRUN(pipe)) {
drm_err(display->drm,
"uncleared fifo underrun on pipe %c\n",
pipe_name(pipe));
}
}
}
static void bdw_set_fifo_underrun_reporting(struct drm_device *dev,
static void bdw_set_fifo_underrun_reporting(struct intel_display *display,
enum pipe pipe, bool enable)
{
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_private *dev_priv = to_i915(display->drm);
if (enable)
bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_FIFO_UNDERRUN);
@ -203,11 +201,11 @@ static void bdw_set_fifo_underrun_reporting(struct drm_device *dev,
bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_FIFO_UNDERRUN);
}
static void ibx_set_fifo_underrun_reporting(struct drm_device *dev,
static void ibx_set_fifo_underrun_reporting(struct intel_display *display,
enum pipe pch_transcoder,
bool enable)
{
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_private *dev_priv = to_i915(display->drm);
u32 bit = (pch_transcoder == PIPE_A) ?
SDE_TRANSA_FIFO_UNDER : SDE_TRANSB_FIFO_UNDER;
@ -222,53 +220,52 @@ static void cpt_check_pch_fifo_underruns(struct intel_crtc *crtc)
struct intel_display *display = to_intel_display(crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum pipe pch_transcoder = crtc->pipe;
u32 serr_int = intel_de_read(dev_priv, SERR_INT);
u32 serr_int = intel_de_read(display, SERR_INT);
lockdep_assert_held(&dev_priv->irq_lock);
if ((serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) == 0)
return;
intel_de_write(dev_priv, SERR_INT,
intel_de_write(display, SERR_INT,
SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder));
intel_de_posting_read(dev_priv, SERR_INT);
intel_de_posting_read(display, SERR_INT);
trace_intel_pch_fifo_underrun(display, pch_transcoder);
drm_err(&dev_priv->drm, "pch fifo underrun on pch transcoder %c\n",
drm_err(display->drm, "pch fifo underrun on pch transcoder %c\n",
pipe_name(pch_transcoder));
}
static void cpt_set_fifo_underrun_reporting(struct drm_device *dev,
static void cpt_set_fifo_underrun_reporting(struct intel_display *display,
enum pipe pch_transcoder,
bool enable, bool old)
{
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_private *dev_priv = to_i915(display->drm);
if (enable) {
intel_de_write(dev_priv, SERR_INT,
intel_de_write(display, SERR_INT,
SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder));
if (!cpt_can_enable_serr_int(dev))
if (!cpt_can_enable_serr_int(display))
return;
ibx_enable_display_interrupt(dev_priv, SDE_ERROR_CPT);
} else {
ibx_disable_display_interrupt(dev_priv, SDE_ERROR_CPT);
if (old && intel_de_read(dev_priv, SERR_INT) &
if (old && intel_de_read(display, SERR_INT) &
SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) {
drm_err(&dev_priv->drm,
drm_err(display->drm,
"uncleared pch fifo underrun on pch transcoder %c\n",
pipe_name(pch_transcoder));
}
}
}
static bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
static bool __intel_set_cpu_fifo_underrun_reporting(struct intel_display *display,
enum pipe pipe, bool enable)
{
struct intel_display *display = to_intel_display(dev);
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe);
bool old;
@ -277,21 +274,21 @@ static bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
old = !crtc->cpu_fifo_underrun_disabled;
crtc->cpu_fifo_underrun_disabled = !enable;
if (HAS_GMCH(dev_priv))
i9xx_set_fifo_underrun_reporting(dev, pipe, enable, old);
else if (IS_IRONLAKE(dev_priv) || IS_SANDYBRIDGE(dev_priv))
ilk_set_fifo_underrun_reporting(dev, pipe, enable);
else if (DISPLAY_VER(dev_priv) == 7)
ivb_set_fifo_underrun_reporting(dev, pipe, enable, old);
else if (DISPLAY_VER(dev_priv) >= 8)
bdw_set_fifo_underrun_reporting(dev, pipe, enable);
if (HAS_GMCH(display))
i9xx_set_fifo_underrun_reporting(display, pipe, enable, old);
else if (display->platform.ironlake || display->platform.sandybridge)
ilk_set_fifo_underrun_reporting(display, pipe, enable);
else if (DISPLAY_VER(display) == 7)
ivb_set_fifo_underrun_reporting(display, pipe, enable, old);
else if (DISPLAY_VER(display) >= 8)
bdw_set_fifo_underrun_reporting(display, pipe, enable);
return old;
}
/**
* intel_set_cpu_fifo_underrun_reporting - set cpu fifo underrrun reporting state
* @dev_priv: i915 device instance
* intel_set_cpu_fifo_underrun_reporting - set cpu fifo underrun reporting state
* @display: display device instance
* @pipe: (CPU) pipe to set state for
* @enable: whether underruns should be reported or not
*
@ -305,15 +302,15 @@ static bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
*
* Returns the previous state of underrun reporting.
*/
bool intel_set_cpu_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
bool intel_set_cpu_fifo_underrun_reporting(struct intel_display *display,
enum pipe pipe, bool enable)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
unsigned long flags;
bool ret;
spin_lock_irqsave(&dev_priv->irq_lock, flags);
ret = __intel_set_cpu_fifo_underrun_reporting(&dev_priv->drm, pipe,
enable);
ret = __intel_set_cpu_fifo_underrun_reporting(display, pipe, enable);
spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
return ret;
@ -321,7 +318,7 @@ bool intel_set_cpu_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
/**
* intel_set_pch_fifo_underrun_reporting - set PCH fifo underrun reporting state
* @dev_priv: i915 device instance
* @display: display device instance
* @pch_transcoder: the PCH transcoder (same as pipe on IVB and older)
* @enable: whether underruns should be reported or not
*
@ -333,13 +330,12 @@ bool intel_set_cpu_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
*
* Returns the previous state of underrun reporting.
*/
bool intel_set_pch_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
bool intel_set_pch_fifo_underrun_reporting(struct intel_display *display,
enum pipe pch_transcoder,
bool enable)
{
struct intel_display *display = &dev_priv->display;
struct intel_crtc *crtc =
intel_crtc_for_pipe(display, pch_transcoder);
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct intel_crtc *crtc = intel_crtc_for_pipe(display, pch_transcoder);
unsigned long flags;
bool old;
@ -358,11 +354,11 @@ bool intel_set_pch_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
crtc->pch_fifo_underrun_disabled = !enable;
if (HAS_PCH_IBX(dev_priv))
ibx_set_fifo_underrun_reporting(&dev_priv->drm,
ibx_set_fifo_underrun_reporting(display,
pch_transcoder,
enable);
else
cpt_set_fifo_underrun_reporting(&dev_priv->drm,
cpt_set_fifo_underrun_reporting(display,
pch_transcoder,
enable, old);
@ -372,17 +368,16 @@ bool intel_set_pch_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
/**
* intel_cpu_fifo_underrun_irq_handler - handle CPU fifo underrun interrupt
* @dev_priv: i915 device instance
* @display: display device instance
* @pipe: (CPU) pipe to set state for
*
* This handles a CPU fifo underrun interrupt, generating an underrun warning
* into dmesg if underrun reporting is enabled and then disables the underrun
* interrupt to avoid an irq storm.
*/
void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
void intel_cpu_fifo_underrun_irq_handler(struct intel_display *display,
enum pipe pipe)
{
struct intel_display *display = &dev_priv->display;
struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe);
/* We may be called too early in init, thanks BIOS! */
@ -390,63 +385,62 @@ void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
return;
/* GMCH can't disable fifo underruns, filter them. */
if (HAS_GMCH(dev_priv) &&
if (HAS_GMCH(display) &&
crtc->cpu_fifo_underrun_disabled)
return;
if (intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false)) {
if (intel_set_cpu_fifo_underrun_reporting(display, pipe, false)) {
trace_intel_cpu_fifo_underrun(display, pipe);
drm_err(&dev_priv->drm, "CPU pipe %c FIFO underrun\n", pipe_name(pipe));
drm_err(display->drm, "CPU pipe %c FIFO underrun\n", pipe_name(pipe));
}
intel_fbc_handle_fifo_underrun_irq(&dev_priv->display);
intel_fbc_handle_fifo_underrun_irq(display);
}
/**
* intel_pch_fifo_underrun_irq_handler - handle PCH fifo underrun interrupt
* @dev_priv: i915 device instance
* @display: display device instance
* @pch_transcoder: the PCH transcoder (same as pipe on IVB and older)
*
* This handles a PCH fifo underrun interrupt, generating an underrun warning
* into dmesg if underrun reporting is enabled and then disables the underrun
* interrupt to avoid an irq storm.
*/
void intel_pch_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
void intel_pch_fifo_underrun_irq_handler(struct intel_display *display,
enum pipe pch_transcoder)
{
struct intel_display *display = &dev_priv->display;
if (intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder,
if (intel_set_pch_fifo_underrun_reporting(display, pch_transcoder,
false)) {
trace_intel_pch_fifo_underrun(display, pch_transcoder);
drm_err(&dev_priv->drm, "PCH transcoder %c FIFO underrun\n",
drm_err(display->drm, "PCH transcoder %c FIFO underrun\n",
pipe_name(pch_transcoder));
}
}
/**
* intel_check_cpu_fifo_underruns - check for CPU fifo underruns immediately
* @dev_priv: i915 device instance
* @display: display device instance
*
* Check for CPU fifo underruns immediately. Useful on IVB/HSW where the shared
* error interrupt may have been disabled, and so CPU fifo underruns won't
* necessarily raise an interrupt, and on GMCH platforms where underruns never
* raise an interrupt.
*/
void intel_check_cpu_fifo_underruns(struct drm_i915_private *dev_priv)
void intel_check_cpu_fifo_underruns(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct intel_crtc *crtc;
spin_lock_irq(&dev_priv->irq_lock);
for_each_intel_crtc(&dev_priv->drm, crtc) {
for_each_intel_crtc(display->drm, crtc) {
if (crtc->cpu_fifo_underrun_disabled)
continue;
if (HAS_GMCH(dev_priv))
if (HAS_GMCH(display))
i9xx_check_fifo_underruns(crtc);
else if (DISPLAY_VER(dev_priv) == 7)
else if (DISPLAY_VER(display) == 7)
ivb_check_fifo_underruns(crtc);
}
@ -455,19 +449,20 @@ void intel_check_cpu_fifo_underruns(struct drm_i915_private *dev_priv)
/**
* intel_check_pch_fifo_underruns - check for PCH fifo underruns immediately
* @dev_priv: i915 device instance
* @display: display device instance
*
* Check for PCH fifo underruns immediately. Useful on CPT/PPT where the shared
* error interrupt may have been disabled, and so PCH fifo underruns won't
* necessarily raise an interrupt.
*/
void intel_check_pch_fifo_underruns(struct drm_i915_private *dev_priv)
void intel_check_pch_fifo_underruns(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct intel_crtc *crtc;
spin_lock_irq(&dev_priv->irq_lock);
for_each_intel_crtc(&dev_priv->drm, crtc) {
for_each_intel_crtc(display->drm, crtc) {
if (crtc->pch_fifo_underrun_disabled)
continue;
@ -478,10 +473,12 @@ void intel_check_pch_fifo_underruns(struct drm_i915_private *dev_priv)
spin_unlock_irq(&dev_priv->irq_lock);
}
void intel_init_fifo_underrun_reporting(struct drm_i915_private *i915,
void intel_init_fifo_underrun_reporting(struct intel_display *display,
struct intel_crtc *crtc,
bool enable)
{
struct drm_i915_private *i915 = to_i915(display->drm);
crtc->cpu_fifo_underrun_disabled = !enable;
/*

View File

@ -8,22 +8,22 @@
#include <linux/types.h>
struct drm_i915_private;
struct intel_crtc;
enum pipe;
struct intel_crtc;
struct intel_display;
void intel_init_fifo_underrun_reporting(struct drm_i915_private *i915,
void intel_init_fifo_underrun_reporting(struct intel_display *display,
struct intel_crtc *crtc, bool enable);
bool intel_set_cpu_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
bool intel_set_cpu_fifo_underrun_reporting(struct intel_display *display,
enum pipe pipe, bool enable);
bool intel_set_pch_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
bool intel_set_pch_fifo_underrun_reporting(struct intel_display *display,
enum pipe pch_transcoder,
bool enable);
void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
void intel_cpu_fifo_underrun_irq_handler(struct intel_display *display,
enum pipe pipe);
void intel_pch_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
void intel_pch_fifo_underrun_irq_handler(struct intel_display *display,
enum pipe pch_transcoder);
void intel_check_cpu_fifo_underruns(struct drm_i915_private *dev_priv);
void intel_check_pch_fifo_underruns(struct drm_i915_private *dev_priv);
void intel_check_cpu_fifo_underruns(struct intel_display *display);
void intel_check_pch_fifo_underruns(struct intel_display *display);
#endif /* __INTEL_FIFO_UNDERRUN_H__ */

View File

@ -227,7 +227,7 @@ static void intel_frontbuffer_flush_work(struct work_struct *work)
* @front: GEM object to flush
*
* This function is targeted for our dirty callback for queueing flush when
* dma fence is signales
* dma fence is signals
*/
void intel_frontbuffer_queue_flush(struct intel_frontbuffer *front)
{

View File

@ -761,11 +761,10 @@ gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
{
struct intel_gmbus *bus = to_intel_gmbus(adapter);
struct intel_display *display = bus->display;
struct drm_i915_private *i915 = to_i915(display->drm);
intel_wakeref_t wakeref;
int ret;
wakeref = intel_display_power_get(i915, POWER_DOMAIN_GMBUS);
wakeref = intel_display_power_get(display, POWER_DOMAIN_GMBUS);
if (bus->force_bit) {
ret = i2c_bit_algo.master_xfer(adapter, msgs, num);
@ -777,7 +776,7 @@ gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
bus->force_bit |= GMBUS_FORCE_BIT_RETRY;
}
intel_display_power_put(i915, POWER_DOMAIN_GMBUS, wakeref);
intel_display_power_put(display, POWER_DOMAIN_GMBUS, wakeref);
return ret;
}
@ -786,7 +785,6 @@ int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
{
struct intel_gmbus *bus = to_intel_gmbus(adapter);
struct intel_display *display = bus->display;
struct drm_i915_private *i915 = to_i915(display->drm);
u8 cmd = DRM_HDCP_DDC_AKSV;
u8 buf[DRM_HDCP_KSV_LEN] = {};
struct i2c_msg msgs[] = {
@ -806,7 +804,7 @@ int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
intel_wakeref_t wakeref;
int ret;
wakeref = intel_display_power_get(i915, POWER_DOMAIN_GMBUS);
wakeref = intel_display_power_get(display, POWER_DOMAIN_GMBUS);
mutex_lock(&display->gmbus.mutex);
/*
@ -817,7 +815,7 @@ int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
ret = do_gmbus_xfer(adapter, msgs, ARRAY_SIZE(msgs), GMBUS_AKSV_SELECT);
mutex_unlock(&display->gmbus.mutex);
intel_display_power_put(i915, POWER_DOMAIN_GMBUS, wakeref);
intel_display_power_put(display, POWER_DOMAIN_GMBUS, wakeref);
return ret;
}

View File

@ -9,6 +9,7 @@
*/
#include <linux/component.h>
#include <linux/debugfs.h>
#include <linux/i2c.h>
#include <linux/random.h>
@ -208,7 +209,7 @@ int intel_hdcp_read_valid_bksv(struct intel_digital_port *dig_port,
}
/* Is HDCP1.4 capable on Platform and Sink */
bool intel_hdcp_get_capability(struct intel_connector *connector)
static bool intel_hdcp_get_capability(struct intel_connector *connector)
{
struct intel_digital_port *dig_port;
const struct intel_hdcp_shim *shim = connector->hdcp.shim;
@ -264,7 +265,7 @@ static bool intel_hdcp2_prerequisite(struct intel_connector *connector)
}
/* Is HDCP2.2 capable on Platform and Sink */
bool intel_hdcp2_get_capability(struct intel_connector *connector)
static bool intel_hdcp2_get_capability(struct intel_connector *connector)
{
struct intel_hdcp *hdcp = &connector->hdcp;
bool capable = false;
@ -278,9 +279,9 @@ bool intel_hdcp2_get_capability(struct intel_connector *connector)
return capable;
}
void intel_hdcp_get_remote_capability(struct intel_connector *connector,
bool *hdcp_capable,
bool *hdcp2_capable)
static void intel_hdcp_get_remote_capability(struct intel_connector *connector,
bool *hdcp_capable,
bool *hdcp2_capable)
{
struct intel_hdcp *hdcp = &connector->hdcp;
@ -342,7 +343,7 @@ static bool hdcp_key_loadable(struct intel_display *display)
* On HSW and BDW, Display HW loads the Key as soon as Display resumes.
* On all BXT+, SW can load the keys only when the PW#1 is turned on.
*/
if (IS_HASWELL(i915) || IS_BROADWELL(i915))
if (display->platform.haswell || display->platform.broadwell)
id = HSW_DISP_PW_GLOBAL;
else
id = SKL_DISP_PW_1;
@ -353,7 +354,7 @@ static bool hdcp_key_loadable(struct intel_display *display)
/*
* Another req for hdcp key loadability is enabled state of pll for
* cdclk. Without active crtc we wont land here. So we are assuming that
* cdclk. Without active crtc we won't land here. So we are assuming that
* cdclk is already on.
*/
@ -381,7 +382,7 @@ static int intel_hdcp_load_keys(struct intel_display *display)
* On HSW and BDW HW loads the HDCP1.4 Key when Display comes
* out of reset. So if Key is not already loaded, its an error state.
*/
if (IS_HASWELL(i915) || IS_BROADWELL(i915))
if (display->platform.haswell || display->platform.broadwell)
if (!(intel_de_read(display, HDCP_KEY_STATUS) & HDCP_KEY_LOAD_DONE))
return -ENXIO;
@ -393,7 +394,7 @@ static int intel_hdcp_load_keys(struct intel_display *display)
* process from other platforms. These platforms use the GT Driver
* Mailbox interface.
*/
if (DISPLAY_VER(display) == 9 && !IS_BROXTON(i915)) {
if (DISPLAY_VER(display) == 9 && !display->platform.broxton) {
ret = snb_pcode_write(&i915->uncore, SKL_PCODE_LOAD_HDCP_KEYS, 1);
if (ret) {
drm_err(display->drm,
@ -1550,9 +1551,9 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
* with a 50ms delay if not hdcp2 capable for DP/DPMST encoders
* (dock decides to stop advertising hdcp2 capability for some reason).
* The reason being that during suspend resume dock usually keeps the
* HDCP2 registers inaccesible causing AUX error. This wouldn't be a
* HDCP2 registers inaccessible causing AUX error. This wouldn't be a
* big problem if the userspace just kept retrying with some delay while
* it continues to play low value content but most userpace applications
* it continues to play low value content but most userspace applications
* end up throwing an error when it receives one from KMD. This makes
* sure we give the dock and the sink devices to complete its power cycle
* and then try HDCP authentication. The values of 10 and delay of 50ms
@ -2338,18 +2339,16 @@ static int initialize_hdcp_port_data(struct intel_connector *connector,
static bool is_hdcp2_supported(struct intel_display *display)
{
struct drm_i915_private *i915 = to_i915(display->drm);
if (intel_hdcp_gsc_cs_required(display))
return true;
if (!IS_ENABLED(CONFIG_INTEL_MEI_HDCP))
return false;
return (DISPLAY_VER(display) >= 10 ||
IS_KABYLAKE(i915) ||
IS_COFFEELAKE(i915) ||
IS_COMETLAKE(i915));
return DISPLAY_VER(display) >= 10 ||
display->platform.kabylake ||
display->platform.coffeelake ||
display->platform.cometlake;
}
void intel_hdcp_component_init(struct intel_display *display)
@ -2473,13 +2472,16 @@ static int _intel_hdcp_enable(struct intel_atomic_state *state,
* Considering that HDCP2.2 is more secure than HDCP1.4, If the setup
* is capable of HDCP2.2, it is preferred to use HDCP2.2.
*/
if (intel_hdcp2_get_capability(connector)) {
if (!hdcp->force_hdcp14 && intel_hdcp2_get_capability(connector)) {
ret = _intel_hdcp2_enable(state, connector);
if (!ret)
check_link_interval =
DRM_HDCP2_CHECK_PERIOD_MS;
}
if (hdcp->force_hdcp14)
drm_dbg_kms(display->drm, "Forcing HDCP 1.4\n");
/*
* When HDCP2.2 fails and Content Type is not Type1, HDCP1.4 will
* be attempted.
@ -2573,7 +2575,7 @@ void intel_hdcp_update_pipe(struct intel_atomic_state *state,
/*
* During the HDCP encryption session if Type change is requested,
* disable the HDCP and reenable it with new TYPE value.
* disable the HDCP and re-enable it with new TYPE value.
*/
if (conn_state->content_protection ==
DRM_MODE_CONTENT_PROTECTION_UNDESIRED ||
@ -2616,6 +2618,15 @@ void intel_hdcp_update_pipe(struct intel_atomic_state *state,
_intel_hdcp_enable(state, encoder, crtc_state, conn_state);
}
void intel_hdcp_cancel_works(struct intel_connector *connector)
{
if (!connector->hdcp.shim)
return;
cancel_delayed_work_sync(&connector->hdcp.check_work);
cancel_work_sync(&connector->hdcp.prop_work);
}
void intel_hdcp_component_fini(struct intel_display *display)
{
mutex_lock(&display->hdcp.hdcp_mutex);
@ -2731,3 +2742,153 @@ void intel_hdcp_handle_cp_irq(struct intel_connector *connector)
queue_delayed_work(i915->unordered_wq, &hdcp->check_work, 0);
}
static void __intel_hdcp_info(struct seq_file *m, struct intel_connector *connector,
bool remote_req)
{
bool hdcp_cap = false, hdcp2_cap = false;
if (!connector->hdcp.shim) {
seq_puts(m, "No Connector Support");
goto out;
}
if (remote_req) {
intel_hdcp_get_remote_capability(connector, &hdcp_cap, &hdcp2_cap);
} else {
hdcp_cap = intel_hdcp_get_capability(connector);
hdcp2_cap = intel_hdcp2_get_capability(connector);
}
if (hdcp_cap)
seq_puts(m, "HDCP1.4 ");
if (hdcp2_cap)
seq_puts(m, "HDCP2.2 ");
if (!hdcp_cap && !hdcp2_cap)
seq_puts(m, "None");
out:
seq_puts(m, "\n");
}
void intel_hdcp_info(struct seq_file *m, struct intel_connector *connector)
{
seq_puts(m, "\tHDCP version: ");
if (connector->mst_port) {
__intel_hdcp_info(m, connector, true);
seq_puts(m, "\tMST Hub HDCP version: ");
}
__intel_hdcp_info(m, connector, false);
}
static int intel_hdcp_sink_capability_show(struct seq_file *m, void *data)
{
struct intel_connector *connector = m->private;
struct intel_display *display = to_intel_display(connector);
int ret;
ret = drm_modeset_lock_single_interruptible(&display->drm->mode_config.connection_mutex);
if (ret)
return ret;
if (!connector->base.encoder ||
connector->base.status != connector_status_connected) {
ret = -ENODEV;
goto out;
}
seq_printf(m, "%s:%d HDCP version: ", connector->base.name,
connector->base.base.id);
__intel_hdcp_info(m, connector, false);
out:
drm_modeset_unlock(&display->drm->mode_config.connection_mutex);
return ret;
}
DEFINE_SHOW_ATTRIBUTE(intel_hdcp_sink_capability);
static ssize_t intel_hdcp_force_14_write(struct file *file,
const char __user *ubuf,
size_t len, loff_t *offp)
{
struct seq_file *m = file->private_data;
struct intel_connector *connector = m->private;
struct intel_hdcp *hdcp = &connector->hdcp;
bool force_hdcp14 = false;
int ret;
if (len == 0)
return 0;
ret = kstrtobool_from_user(ubuf, len, &force_hdcp14);
if (ret < 0)
return ret;
hdcp->force_hdcp14 = force_hdcp14;
*offp += len;
return len;
}
static int intel_hdcp_force_14_show(struct seq_file *m, void *data)
{
struct intel_connector *connector = m->private;
struct intel_display *display = to_intel_display(connector);
struct intel_encoder *encoder = intel_attached_encoder(connector);
struct intel_hdcp *hdcp = &connector->hdcp;
struct drm_crtc *crtc;
int ret;
if (!encoder)
return -ENODEV;
ret = drm_modeset_lock_single_interruptible(&display->drm->mode_config.connection_mutex);
if (ret)
return ret;
crtc = connector->base.state->crtc;
if (connector->base.status != connector_status_connected || !crtc) {
ret = -ENODEV;
goto out;
}
seq_printf(m, "%s\n",
str_yes_no(hdcp->force_hdcp14));
out:
drm_modeset_unlock(&display->drm->mode_config.connection_mutex);
return ret;
}
static int intel_hdcp_force_14_open(struct inode *inode,
struct file *file)
{
return single_open(file, intel_hdcp_force_14_show,
inode->i_private);
}
static const struct file_operations intel_hdcp_force_14_fops = {
.owner = THIS_MODULE,
.open = intel_hdcp_force_14_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.write = intel_hdcp_force_14_write
};
void intel_hdcp_connector_debugfs_add(struct intel_connector *connector)
{
struct dentry *root = connector->base.debugfs_entry;
int connector_type = connector->base.connector_type;
if (connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
connector_type == DRM_MODE_CONNECTOR_HDMIA ||
connector_type == DRM_MODE_CONNECTOR_HDMIB) {
debugfs_create_file("i915_hdcp_sink_capability", 0444, root,
connector, &intel_hdcp_sink_capability_fops);
debugfs_create_file("i915_force_hdcp14", 0644, root,
connector, &intel_hdcp_force_14_fops);
}
}

View File

@ -19,8 +19,8 @@ struct intel_digital_port;
struct intel_display;
struct intel_encoder;
struct intel_hdcp_shim;
struct seq_file;
enum port;
enum transcoder;
void intel_hdcp_atomic_check(struct drm_connector *connector,
struct drm_connector_state *old_state,
@ -33,19 +33,18 @@ void intel_hdcp_enable(struct intel_atomic_state *state,
const struct intel_crtc_state *pipe_config,
const struct drm_connector_state *conn_state);
int intel_hdcp_disable(struct intel_connector *connector);
void intel_hdcp_cancel_works(struct intel_connector *connector);
void intel_hdcp_update_pipe(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state);
bool is_hdcp_supported(struct intel_display *display, enum port port);
bool intel_hdcp_get_capability(struct intel_connector *connector);
bool intel_hdcp2_get_capability(struct intel_connector *connector);
void intel_hdcp_get_remote_capability(struct intel_connector *connector,
bool *hdcp_capable,
bool *hdcp2_capable);
void intel_hdcp_component_init(struct intel_display *display);
void intel_hdcp_component_fini(struct intel_display *display);
void intel_hdcp_cleanup(struct intel_connector *connector);
void intel_hdcp_handle_cp_irq(struct intel_connector *connector);
void intel_hdcp_info(struct seq_file *m, struct intel_connector *connector);
void intel_hdcp_connector_debugfs_add(struct intel_connector *connector);
#endif /* __INTEL_HDCP_H__ */

View File

@ -1909,18 +1909,6 @@ hdmi_port_clock_valid(struct intel_hdmi *hdmi,
if (intel_encoder_is_tc(encoder) && clock > 500000 && clock < 532800)
return MODE_CLOCK_RANGE;
/*
* SNPS PHYs' MPLLB table-based programming can only handle a fixed
* set of link rates.
*
* FIXME: We will hopefully get an algorithmic way of programming
* the MPLLB for HDMI in the future.
*/
if (DISPLAY_VER(display) >= 14)
return intel_cx0_phy_check_hdmi_link_rate(hdmi, clock);
else if (IS_DG2(dev_priv))
return intel_snps_phy_check_hdmi_link_rate(clock);
return MODE_OK;
}
@ -2027,7 +2015,6 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
{
struct intel_display *display = to_intel_display(connector->dev);
struct intel_hdmi *hdmi = intel_attached_hdmi(to_intel_connector(connector));
struct drm_i915_private *dev_priv = to_i915(display->drm);
enum drm_mode_status status;
int clock = mode->clock;
int max_dotclk = to_i915(connector->dev)->display.cdclk.max_dotclk_freq;
@ -2035,7 +2022,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
bool ycbcr_420_only;
enum intel_output_format sink_format;
status = intel_cpu_transcoder_mode_valid(dev_priv, mode);
status = intel_cpu_transcoder_mode_valid(display, mode);
if (status != MODE_OK)
return status;
@ -2080,7 +2067,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
return status;
}
return intel_mode_valid_max_plane_size(dev_priv, mode, 1);
return intel_mode_valid_max_plane_size(display, mode, 1);
}
bool intel_hdmi_bpc_possible(const struct intel_crtc_state *crtc_state,
@ -2503,14 +2490,13 @@ static bool
intel_hdmi_set_edid(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_hdmi *intel_hdmi = intel_attached_hdmi(to_intel_connector(connector));
struct i2c_adapter *ddc = connector->ddc;
intel_wakeref_t wakeref;
const struct drm_edid *drm_edid;
bool connected = false;
wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
wakeref = intel_display_power_get(display, POWER_DOMAIN_GMBUS);
drm_edid = drm_edid_read_ddc(connector, ddc);
@ -2533,7 +2519,7 @@ intel_hdmi_set_edid(struct drm_connector *connector)
connected = true;
}
intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref);
intel_display_power_put(display, POWER_DOMAIN_GMBUS, wakeref);
cec_notifier_set_phys_addr(intel_hdmi->cec_notifier,
connector->display_info.source_physical_address);
@ -2546,7 +2532,6 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
{
struct intel_display *display = to_intel_display(connector->dev);
enum drm_connector_status status = connector_status_disconnected;
struct drm_i915_private *dev_priv = to_i915(connector->dev);
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(to_intel_connector(connector));
struct intel_encoder *encoder = &hdmi_to_dig_port(intel_hdmi)->base;
intel_wakeref_t wakeref;
@ -2560,7 +2545,7 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
if (!intel_display_driver_check_access(display))
return connector->status;
wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
wakeref = intel_display_power_get(display, POWER_DOMAIN_GMBUS);
if (DISPLAY_VER(display) >= 11 &&
!intel_digital_port_connected(encoder))
@ -2572,7 +2557,7 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
status = connector_status_connected;
out:
intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref);
intel_display_power_put(display, POWER_DOMAIN_GMBUS, wakeref);
if (status != connector_status_connected)
cec_notifier_phys_addr_invalidate(intel_hdmi->cec_notifier);

View File

@ -62,4 +62,13 @@ int intel_hdmi_dsc_get_num_slices(const struct intel_crtc_state *crtc_state,
int hdmi_max_slices, int hdmi_throughput);
int intel_hdmi_dsc_get_slice_height(int vactive);
void hsw_write_infoframe(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
unsigned int type,
const void *frame, ssize_t len);
void hsw_read_infoframe(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
unsigned int type,
void *frame, ssize_t len);
#endif /* __INTEL_HDMI_H__ */

View File

@ -28,8 +28,10 @@
#include "i915_drv.h"
#include "i915_irq.h"
#include "intel_connector.h"
#include "intel_display_power.h"
#include "intel_display_types.h"
#include "intel_hdcp.h"
#include "intel_hotplug.h"
#include "intel_hotplug_irq.h"
@ -82,15 +84,13 @@
/**
* intel_hpd_pin_default - return default pin associated with certain port.
* @dev_priv: private driver data pointer
* @port: the hpd port to get associated pin
*
* It is only valid and used by digital port encoder.
*
* Return pin that is associatade with @port.
*/
enum hpd_pin intel_hpd_pin_default(struct drm_i915_private *dev_priv,
enum port port)
enum hpd_pin intel_hpd_pin_default(enum port port)
{
return HPD_PORT_A + port - PORT_A;
}
@ -732,6 +732,7 @@ static void i915_hpd_poll_init_work(struct work_struct *work)
struct drm_i915_private *dev_priv =
container_of(work, struct drm_i915_private,
display.hotplug.poll_init_work);
struct intel_display *display = &dev_priv->display;
struct drm_connector_list_iter conn_iter;
struct intel_connector *connector;
intel_wakeref_t wakeref;
@ -747,7 +748,7 @@ static void i915_hpd_poll_init_work(struct work_struct *work)
* and so risk an endless loop of this same sequence.
*/
if (!enabled) {
wakeref = intel_display_power_get(dev_priv,
wakeref = intel_display_power_get(display,
POWER_DOMAIN_DISPLAY_CORE);
drm_WARN_ON(&dev_priv->drm,
READ_ONCE(dev_priv->display.hotplug.poll_enabled));
@ -789,7 +790,7 @@ static void i915_hpd_poll_init_work(struct work_struct *work)
if (!enabled) {
i915_hpd_poll_detect_connectors(dev_priv);
intel_display_power_put(dev_priv,
intel_display_power_put(display,
POWER_DOMAIN_DISPLAY_CORE,
wakeref);
}
@ -806,7 +807,7 @@ static void i915_hpd_poll_init_work(struct work_struct *work)
* of the powerwells.
*
* Since this function can get called in contexts where we're already holding
* dev->mode_config.mutex, we do the actual hotplug enabling in a seperate
* dev->mode_config.mutex, we do the actual hotplug enabling in a separate
* worker.
*
* Also see: intel_hpd_init() and intel_hpd_poll_disable().
@ -823,7 +824,7 @@ void intel_hpd_poll_enable(struct drm_i915_private *dev_priv)
/*
* We might already be holding dev->mode_config.mutex, so do this in a
* seperate worker
* separate worker
* As well, there's no issue if we race here since we always reschedule
* this worker anyway
*/
@ -844,7 +845,7 @@ void intel_hpd_poll_enable(struct drm_i915_private *dev_priv)
* of the powerwells.
*
* Since this function can get called in contexts where we're already holding
* dev->mode_config.mutex, we do the actual hotplug enabling in a seperate
* dev->mode_config.mutex, we do the actual hotplug enabling in a separate
* worker.
*
* Also used during driver init to initialize connector->polled
@ -865,6 +866,20 @@ void intel_hpd_poll_disable(struct drm_i915_private *dev_priv)
spin_unlock_irq(&dev_priv->irq_lock);
}
void intel_hpd_poll_fini(struct drm_i915_private *i915)
{
struct intel_connector *connector;
struct drm_connector_list_iter conn_iter;
/* Kill all the work that may have been queued by hpd. */
drm_connector_list_iter_begin(&i915->drm, &conn_iter);
for_each_intel_connector_iter(connector, &conn_iter) {
intel_connector_cancel_modeset_retry_work(connector);
intel_hdcp_cancel_works(connector);
}
drm_connector_list_iter_end(&conn_iter);
}
void intel_hpd_init_early(struct drm_i915_private *i915)
{
INIT_DELAYED_WORK(&i915->display.hotplug.hotplug_work,

View File

@ -16,6 +16,7 @@ enum port;
void intel_hpd_poll_enable(struct drm_i915_private *dev_priv);
void intel_hpd_poll_disable(struct drm_i915_private *dev_priv);
void intel_hpd_poll_fini(struct drm_i915_private *i915);
enum intel_hotplug_state intel_encoder_hotplug(struct intel_encoder *encoder,
struct intel_connector *connector);
void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
@ -24,8 +25,7 @@ void intel_hpd_trigger_irq(struct intel_digital_port *dig_port);
void intel_hpd_init(struct drm_i915_private *dev_priv);
void intel_hpd_init_early(struct drm_i915_private *i915);
void intel_hpd_cancel_work(struct drm_i915_private *dev_priv);
enum hpd_pin intel_hpd_pin_default(struct drm_i915_private *dev_priv,
enum port port);
enum hpd_pin intel_hpd_pin_default(enum port port);
bool intel_hpd_disable(struct drm_i915_private *dev_priv, enum hpd_pin pin);
void intel_hpd_enable(struct drm_i915_private *dev_priv, enum hpd_pin pin);
void intel_hpd_debugfs_register(struct drm_i915_private *i915);

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