aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/display/intel_display.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_display.c')
-rw-r--r--drivers/gpu/drm/i915/display/intel_display.c2473
1 files changed, 1095 insertions, 1378 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index bb4a85445fc6..806d50b302ab 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -32,13 +32,14 @@
#include <linux/module.h>
#include <linux/dma-resv.h>
#include <linux/slab.h>
+#include <linux/string_helpers.h>
#include <linux/vga_switcheroo.h>
+#include <drm/display/drm_dp_helper.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_atomic_uapi.h>
#include <drm/drm_damage_helper.h>
-#include <drm/drm_dp_helper.h>
#include <drm/drm_edid.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_plane_helper.h>
@@ -50,6 +51,7 @@
#include "display/intel_crt.h"
#include "display/intel_ddi.h"
#include "display/intel_display_debugfs.h"
+#include "display/intel_display_power.h"
#include "display/intel_dp.h"
#include "display/intel_dp_mst.h"
#include "display/intel_dpll.h"
@@ -74,7 +76,9 @@
#include "g4x_dp.h"
#include "g4x_hdmi.h"
+#include "hsw_ips.h"
#include "i915_drv.h"
+#include "i915_utils.h"
#include "icl_dsi.h"
#include "intel_acpi.h"
#include "intel_atomic.h"
@@ -112,15 +116,13 @@
#include "i9xx_plane.h"
#include "skl_scaler.h"
#include "skl_universal_plane.h"
+#include "vlv_dsi.h"
#include "vlv_dsi_pll.h"
+#include "vlv_dsi_regs.h"
#include "vlv_sideband.h"
-#include "vlv_dsi.h"
static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_state);
static void intel_set_pipe_src_size(const struct intel_crtc_state *crtc_state);
-static void intel_cpu_transcoder_set_m_n(const struct intel_crtc_state *crtc_state,
- const struct intel_link_m_n *m_n,
- const struct intel_link_m_n *m2_n2);
static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state);
static void ilk_set_pipeconf(const struct intel_crtc_state *crtc_state);
static void hsw_set_transconf(const struct intel_crtc_state *crtc_state);
@@ -340,10 +342,46 @@ is_trans_port_sync_mode(const struct intel_crtc_state *crtc_state)
is_trans_port_sync_slave(crtc_state);
}
-static struct intel_crtc *intel_master_crtc(const struct intel_crtc_state *crtc_state)
+static enum pipe bigjoiner_master_pipe(const struct intel_crtc_state *crtc_state)
{
- if (crtc_state->bigjoiner_slave)
- return crtc_state->bigjoiner_linked_crtc;
+ return ffs(crtc_state->bigjoiner_pipes) - 1;
+}
+
+u8 intel_crtc_bigjoiner_slave_pipes(const struct intel_crtc_state *crtc_state)
+{
+ if (crtc_state->bigjoiner_pipes)
+ return crtc_state->bigjoiner_pipes & ~BIT(bigjoiner_master_pipe(crtc_state));
+ else
+ return 0;
+}
+
+bool intel_crtc_is_bigjoiner_slave(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+ return crtc_state->bigjoiner_pipes &&
+ crtc->pipe != bigjoiner_master_pipe(crtc_state);
+}
+
+bool intel_crtc_is_bigjoiner_master(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+ return crtc_state->bigjoiner_pipes &&
+ crtc->pipe == bigjoiner_master_pipe(crtc_state);
+}
+
+static int intel_bigjoiner_num_pipes(const struct intel_crtc_state *crtc_state)
+{
+ return hweight8(crtc_state->bigjoiner_pipes);
+}
+
+struct intel_crtc *intel_master_crtc(const struct intel_crtc_state *crtc_state)
+{
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+
+ if (intel_crtc_is_bigjoiner_slave(crtc_state))
+ return intel_crtc_for_pipe(i915, bigjoiner_master_pipe(crtc_state));
else
return to_intel_crtc(crtc_state->uapi.crtc);
}
@@ -353,16 +391,10 @@ static bool pipe_scanline_is_moving(struct drm_i915_private *dev_priv,
{
i915_reg_t reg = PIPEDSL(pipe);
u32 line1, line2;
- u32 line_mask;
- if (DISPLAY_VER(dev_priv) == 2)
- line_mask = DSL_LINEMASK_GEN2;
- else
- line_mask = DSL_LINEMASK_GEN3;
-
- line1 = intel_de_read(dev_priv, reg) & line_mask;
+ line1 = intel_de_read(dev_priv, reg) & PIPEDSL_LINE_MASK;
msleep(5);
- line2 = intel_de_read(dev_priv, reg) & line_mask;
+ line2 = intel_de_read(dev_priv, reg) & PIPEDSL_LINE_MASK;
return line1 != line2;
}
@@ -376,7 +408,7 @@ static void wait_for_pipe_scanline_moving(struct intel_crtc *crtc, bool state)
if (wait_for(pipe_scanline_is_moving(dev_priv, pipe) == state, 100))
drm_err(&dev_priv->drm,
"pipe %c scanline %s wait timed out\n",
- pipe_name(pipe), onoff(state));
+ pipe_name(pipe), str_on_off(state));
}
static void intel_wait_for_pipe_scanline_stopped(struct intel_crtc *crtc)
@@ -397,13 +429,11 @@ intel_wait_for_pipe_off(const struct intel_crtc_state *old_crtc_state)
if (DISPLAY_VER(dev_priv) >= 4) {
enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder;
- i915_reg_t reg = PIPECONF(cpu_transcoder);
/* Wait for the Pipe State to go off */
- if (intel_de_wait_for_clear(dev_priv, reg,
- I965_PIPECONF_ACTIVE, 100))
- drm_WARN(&dev_priv->drm, 1,
- "pipe_off wait timed out\n");
+ if (intel_de_wait_for_clear(dev_priv, PIPECONF(cpu_transcoder),
+ PIPECONF_STATE_ENABLE, 100))
+ drm_WARN(&dev_priv->drm, 1, "pipe_off wait timed out\n");
} else {
intel_wait_for_pipe_scanline_stopped(crtc);
}
@@ -434,7 +464,7 @@ void assert_transcoder(struct drm_i915_private *dev_priv,
I915_STATE_WARN(cur_state != state,
"transcoder %s assertion failure (expected %s, current %s)\n",
transcoder_name(cpu_transcoder),
- onoff(state), onoff(cur_state));
+ str_on_off(state), str_on_off(cur_state));
}
static void assert_plane(struct intel_plane *plane, bool state)
@@ -446,7 +476,8 @@ static void assert_plane(struct intel_plane *plane, bool state)
I915_STATE_WARN(cur_state != state,
"%s assertion failure (expected %s, current %s)\n",
- plane->base.name, onoff(state), onoff(cur_state));
+ plane->base.name, str_on_off(state),
+ str_on_off(cur_state));
}
#define assert_plane_enabled(p) assert_plane(p, true)
@@ -495,16 +526,6 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
expected_mask);
}
-enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc)
-{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-
- if (HAS_PCH_LPT(dev_priv))
- return PIPE_A;
- else
- return crtc->pipe;
-}
-
void intel_enable_transcoder(const struct intel_crtc_state *new_crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
@@ -761,10 +782,16 @@ void intel_plane_disable_noatomic(struct intel_crtc *crtc,
intel_set_plane_visible(crtc_state, plane_state, false);
fixup_plane_bitmasks(crtc_state);
crtc_state->data_rate[plane->id] = 0;
+ crtc_state->data_rate_y[plane->id] = 0;
+ crtc_state->rel_data_rate[plane->id] = 0;
+ crtc_state->rel_data_rate_y[plane->id] = 0;
crtc_state->min_cdclk[plane->id] = 0;
- if (plane->id == PLANE_PRIMARY)
- hsw_disable_ips(crtc_state);
+ if ((crtc_state->active_planes & ~BIT(PLANE_CURSOR)) == 0 &&
+ hsw_ips_disable(crtc_state)) {
+ crtc_state->ips_enabled = false;
+ intel_crtc_wait_for_next_vblank(crtc);
+ }
/*
* Vblank time updates from the shadow to live plane control register
@@ -1092,79 +1119,13 @@ static void ilk_pfit_enable(const struct intel_crtc_state *crtc_state)
* e.g. x201.
*/
if (IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv))
- intel_de_write(dev_priv, PF_CTL(pipe), PF_ENABLE |
- PF_FILTER_MED_3x3 | PF_PIPE_SEL_IVB(pipe));
+ intel_de_write_fw(dev_priv, PF_CTL(pipe), PF_ENABLE |
+ PF_FILTER_MED_3x3 | PF_PIPE_SEL_IVB(pipe));
else
- intel_de_write(dev_priv, PF_CTL(pipe), PF_ENABLE |
- PF_FILTER_MED_3x3);
- intel_de_write(dev_priv, PF_WIN_POS(pipe), x << 16 | y);
- intel_de_write(dev_priv, PF_WIN_SZ(pipe), width << 16 | height);
-}
-
-void hsw_enable_ips(const struct intel_crtc_state *crtc_state)
-{
- struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- struct drm_device *dev = crtc->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
-
- if (!crtc_state->ips_enabled)
- return;
-
- /*
- * We can only enable IPS after we enable a plane and wait for a vblank
- * This function is called from post_plane_update, which is run after
- * a vblank wait.
- */
- drm_WARN_ON(dev, !(crtc_state->active_planes & ~BIT(PLANE_CURSOR)));
-
- if (IS_BROADWELL(dev_priv)) {
- drm_WARN_ON(dev, sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL,
- IPS_ENABLE | IPS_PCODE_CONTROL));
- /* Quoting Art Runyan: "its not safe to expect any particular
- * value in IPS_CTL bit 31 after enabling IPS through the
- * mailbox." Moreover, the mailbox may return a bogus state,
- * so we need to just enable it and continue on.
- */
- } else {
- intel_de_write(dev_priv, IPS_CTL, IPS_ENABLE);
- /* The bit only becomes 1 in the next vblank, so this wait here
- * is essentially intel_wait_for_vblank. If we don't have this
- * and don't wait for vblanks until the end of crtc_enable, then
- * the HW state readout code will complain that the expected
- * IPS_CTL value is not the one we read. */
- if (intel_de_wait_for_set(dev_priv, IPS_CTL, IPS_ENABLE, 50))
- drm_err(&dev_priv->drm,
- "Timed out waiting for IPS enable\n");
- }
-}
-
-void hsw_disable_ips(const struct intel_crtc_state *crtc_state)
-{
- struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- struct drm_device *dev = crtc->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
-
- if (!crtc_state->ips_enabled)
- return;
-
- if (IS_BROADWELL(dev_priv)) {
- drm_WARN_ON(dev,
- sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0));
- /*
- * Wait for PCODE to finish disabling IPS. The BSpec specified
- * 42ms timeout value leads to occasional timeouts so use 100ms
- * instead.
- */
- if (intel_de_wait_for_clear(dev_priv, IPS_CTL, IPS_ENABLE, 100))
- drm_err(&dev_priv->drm,
- "Timed out waiting for IPS disable\n");
- } else {
- intel_de_write(dev_priv, IPS_CTL, 0);
- intel_de_posting_read(dev_priv, IPS_CTL);
- }
-
- /* We need to wait for a vblank before we can disable the plane. */
- intel_crtc_wait_for_next_vblank(crtc);
+ intel_de_write_fw(dev_priv, PF_CTL(pipe), PF_ENABLE |
+ PF_FILTER_MED_3x3);
+ intel_de_write_fw(dev_priv, PF_WIN_POS(pipe), x << 16 | y);
+ intel_de_write_fw(dev_priv, PF_WIN_SZ(pipe), width << 16 | height);
}
static void intel_crtc_dpms_overlay_disable(struct intel_crtc *crtc)
@@ -1177,67 +1138,6 @@ static void intel_crtc_dpms_overlay_disable(struct intel_crtc *crtc)
*/
}
-static bool hsw_pre_update_disable_ips(const struct intel_crtc_state *old_crtc_state,
- const struct intel_crtc_state *new_crtc_state)
-{
- struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-
- if (!old_crtc_state->ips_enabled)
- return false;
-
- if (intel_crtc_needs_modeset(new_crtc_state))
- return true;
-
- /*
- * Workaround : Do not read or write the pipe palette/gamma data while
- * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
- *
- * Disable IPS before we program the LUT.
- */
- if (IS_HASWELL(dev_priv) &&
- (new_crtc_state->uapi.color_mgmt_changed ||
- new_crtc_state->update_pipe) &&
- new_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)
- return true;
-
- return !new_crtc_state->ips_enabled;
-}
-
-static bool hsw_post_update_enable_ips(const struct intel_crtc_state *old_crtc_state,
- const struct intel_crtc_state *new_crtc_state)
-{
- struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-
- if (!new_crtc_state->ips_enabled)
- return false;
-
- if (intel_crtc_needs_modeset(new_crtc_state))
- return true;
-
- /*
- * Workaround : Do not read or write the pipe palette/gamma data while
- * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
- *
- * Re-enable IPS after the LUT has been programmed.
- */
- if (IS_HASWELL(dev_priv) &&
- (new_crtc_state->uapi.color_mgmt_changed ||
- new_crtc_state->update_pipe) &&
- new_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)
- return true;
-
- /*
- * We can't read out IPS on broadwell, assume the worst and
- * forcibly enable IPS on the first fastset.
- */
- if (new_crtc_state->update_pipe && old_crtc_state->inherited)
- return true;
-
- return !old_crtc_state->ips_enabled;
-}
-
static bool needs_nv12_wa(const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
@@ -1299,7 +1199,7 @@ static bool needs_async_flip_vtd_wa(const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
- return crtc_state->uapi.async_flip && intel_vtd_active(i915) &&
+ return crtc_state->uapi.async_flip && i915_vtd_active(i915) &&
(DISPLAY_VER(i915) == 9 || IS_BROADWELL(i915) || IS_HASWELL(i915));
}
@@ -1332,11 +1232,8 @@ static void intel_post_plane_update(struct intel_atomic_state *state,
if (new_crtc_state->update_wm_post && new_crtc_state->hw.active)
intel_update_watermarks(dev_priv);
- if (hsw_post_update_enable_ips(old_crtc_state, new_crtc_state))
- hsw_enable_ips(new_crtc_state);
-
+ hsw_ips_post_update(state, crtc);
intel_fbc_post_update(state, crtc);
- intel_drrs_page_flip(state, crtc);
if (needs_async_flip_vtd_wa(old_crtc_state) &&
!needs_async_flip_vtd_wa(new_crtc_state))
@@ -1354,6 +1251,7 @@ static void intel_post_plane_update(struct intel_atomic_state *state,
!needs_cursorclk_wa(new_crtc_state))
icl_wa_cursorclkgating(dev_priv, pipe, false);
+ intel_drrs_activate(new_crtc_state);
}
static void intel_crtc_enable_flip_done(struct intel_atomic_state *state,
@@ -1367,8 +1265,7 @@ static void intel_crtc_enable_flip_done(struct intel_atomic_state *state,
int i;
for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
- if (plane->enable_flip_done &&
- plane->pipe == crtc->pipe &&
+ if (plane->pipe == crtc->pipe &&
update_planes & BIT(plane->id))
plane->enable_flip_done(plane);
}
@@ -1385,8 +1282,7 @@ static void intel_crtc_disable_flip_done(struct intel_atomic_state *state,
int i;
for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
- if (plane->disable_flip_done &&
- plane->pipe == crtc->pipe &&
+ if (plane->pipe == crtc->pipe &&
update_planes & BIT(plane->id))
plane->disable_flip_done(plane);
}
@@ -1433,10 +1329,12 @@ static void intel_pre_plane_update(struct intel_atomic_state *state,
intel_atomic_get_new_crtc_state(state, crtc);
enum pipe pipe = crtc->pipe;
+ intel_drrs_deactivate(old_crtc_state);
+
intel_psr_pre_plane_update(state, crtc);
- if (hsw_pre_update_disable_ips(old_crtc_state, new_crtc_state))
- hsw_disable_ips(old_crtc_state);
+ if (hsw_ips_pre_update(state, crtc))
+ intel_crtc_wait_for_next_vblank(crtc);
if (intel_fbc_pre_update(state, crtc))
intel_crtc_wait_for_next_vblank(crtc);
@@ -1817,6 +1715,26 @@ static void intel_disable_primary_plane(const struct intel_crtc_state *crtc_stat
plane->disable_arm(plane, crtc_state);
}
+static void ilk_configure_cpu_transcoder(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
+
+ if (crtc_state->has_pch_encoder) {
+ intel_cpu_transcoder_set_m1_n1(crtc, cpu_transcoder,
+ &crtc_state->fdi_m_n);
+ } else if (intel_crtc_has_dp_encoder(crtc_state)) {
+ intel_cpu_transcoder_set_m1_n1(crtc, cpu_transcoder,
+ &crtc_state->dp_m_n);
+ intel_cpu_transcoder_set_m2_n2(crtc, cpu_transcoder,
+ &crtc_state->dp_m2_n2);
+ }
+
+ intel_set_transcoder_timings(crtc_state);
+
+ ilk_set_pipeconf(crtc_state);
+}
+
static void ilk_crtc_enable(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
@@ -1841,27 +1759,16 @@ static void ilk_crtc_enable(struct intel_atomic_state *state,
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false);
- if (intel_crtc_has_dp_encoder(new_crtc_state))
- intel_dp_set_m_n(new_crtc_state, M1_N1);
+ ilk_configure_cpu_transcoder(new_crtc_state);
- intel_set_transcoder_timings(new_crtc_state);
intel_set_pipe_src_size(new_crtc_state);
- if (new_crtc_state->has_pch_encoder)
- intel_cpu_transcoder_set_m_n(new_crtc_state,
- &new_crtc_state->fdi_m_n, NULL);
-
- ilk_set_pipeconf(new_crtc_state);
-
crtc->active = true;
intel_encoders_pre_enable(state, crtc);
if (new_crtc_state->has_pch_encoder) {
- /* Note: FDI PLL enabling _must_ be done before we enable the
- * cpu pipes, hence this is separate from all the other fdi/pch
- * enabling. */
- ilk_fdi_pll_enable(new_crtc_state);
+ ilk_pch_pre_enable(state, crtc);
} else {
assert_fdi_tx_disabled(dev_priv, pipe);
assert_fdi_rx_disabled(dev_priv, pipe);
@@ -1874,7 +1781,8 @@ static void ilk_crtc_enable(struct intel_atomic_state *state,
* clocks enabled
*/
intel_color_load_luts(new_crtc_state);
- intel_color_commit(new_crtc_state);
+ intel_color_commit_noarm(new_crtc_state);
+ intel_color_commit_arm(new_crtc_state);
/* update DSPCNTR to configure gamma for pipe bottom color */
intel_disable_primary_plane(new_crtc_state);
@@ -1905,12 +1813,6 @@ static void ilk_crtc_enable(struct intel_atomic_state *state,
intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true);
}
-/* IPS only exists on ULT machines and is tied to pipe A. */
-static bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
-{
- return HAS_IPS(to_i915(crtc->base.dev)) && crtc->pipe == PIPE_A;
-}
-
static void glk_pipe_scaler_clock_gating_wa(struct drm_i915_private *dev_priv,
enum pipe pipe, bool apply)
{
@@ -1925,29 +1827,6 @@ static void glk_pipe_scaler_clock_gating_wa(struct drm_i915_private *dev_priv,
intel_de_write(dev_priv, CLKGATE_DIS_PSL(pipe), val);
}
-static void icl_pipe_mbus_enable(struct intel_crtc *crtc, bool joined_mbus)
-{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- enum pipe pipe = crtc->pipe;
- u32 val;
-
- /* Wa_22010947358:adl-p */
- if (IS_ALDERLAKE_P(dev_priv))
- val = joined_mbus ? MBUS_DBOX_A_CREDIT(6) : MBUS_DBOX_A_CREDIT(4);
- else
- val = MBUS_DBOX_A_CREDIT(2);
-
- if (DISPLAY_VER(dev_priv) >= 12) {
- val |= MBUS_DBOX_BW_CREDIT(2);
- val |= MBUS_DBOX_B_CREDIT(12);
- } else {
- val |= MBUS_DBOX_BW_CREDIT(1);
- val |= MBUS_DBOX_B_CREDIT(8);
- }
-
- intel_de_write(dev_priv, PIPE_MBUS_DBOX_CTL(pipe), val);
-}
-
static void hsw_set_linetime_wm(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
@@ -1967,49 +1846,53 @@ static void hsw_set_frame_start_delay(const struct intel_crtc_state *crtc_state)
val = intel_de_read(dev_priv, reg);
val &= ~HSW_FRAME_START_DELAY_MASK;
- val |= HSW_FRAME_START_DELAY(dev_priv->framestart_delay - 1);
+ val |= HSW_FRAME_START_DELAY(crtc_state->framestart_delay - 1);
intel_de_write(dev_priv, reg, val);
}
static void icl_ddi_bigjoiner_pre_enable(struct intel_atomic_state *state,
const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(state->base.dev);
- struct intel_crtc_state *master_crtc_state;
- struct intel_crtc *master_crtc;
- struct drm_connector_state *conn_state;
- struct drm_connector *conn;
- struct intel_encoder *encoder = NULL;
- int i;
-
- master_crtc = intel_master_crtc(crtc_state);
- master_crtc_state = intel_atomic_get_new_crtc_state(state, master_crtc);
-
- for_each_new_connector_in_state(&state->base, conn, conn_state, i) {
- if (conn_state->crtc != &master_crtc->base)
- continue;
-
- encoder = to_intel_encoder(conn_state->best_encoder);
- break;
- }
+ struct intel_crtc *master_crtc = intel_master_crtc(crtc_state);
/*
* Enable sequence steps 1-7 on bigjoiner master
*/
- if (crtc_state->bigjoiner_slave)
+ if (intel_crtc_is_bigjoiner_slave(crtc_state))
intel_encoders_pre_pll_enable(state, master_crtc);
if (crtc_state->shared_dpll)
intel_enable_shared_dpll(crtc_state);
- if (crtc_state->bigjoiner_slave)
+ if (intel_crtc_is_bigjoiner_slave(crtc_state))
intel_encoders_pre_enable(state, master_crtc);
+}
- /* need to enable VDSC, which we skipped in pre-enable */
- intel_dsc_enable(crtc_state);
+static void hsw_configure_cpu_transcoder(const struct intel_crtc_state *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 transcoder cpu_transcoder = crtc_state->cpu_transcoder;
- if (DISPLAY_VER(dev_priv) >= 13)
- intel_uncompressed_joiner_enable(crtc_state);
+ if (crtc_state->has_pch_encoder) {
+ intel_cpu_transcoder_set_m1_n1(crtc, cpu_transcoder,
+ &crtc_state->fdi_m_n);
+ } else if (intel_crtc_has_dp_encoder(crtc_state)) {
+ intel_cpu_transcoder_set_m1_n1(crtc, cpu_transcoder,
+ &crtc_state->dp_m_n);
+ intel_cpu_transcoder_set_m2_n2(crtc, cpu_transcoder,
+ &crtc_state->dp_m2_n2);
+ }
+
+ intel_set_transcoder_timings(crtc_state);
+
+ if (cpu_transcoder != TRANSCODER_EDP)
+ intel_de_write(dev_priv, PIPE_MULT(cpu_transcoder),
+ crtc_state->pixel_multiplier - 1);
+
+ hsw_set_frame_start_delay(crtc_state);
+
+ hsw_set_transconf(crtc_state);
}
static void hsw_crtc_enable(struct intel_atomic_state *state,
@@ -2025,7 +1908,7 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
if (drm_WARN_ON(&dev_priv->drm, crtc->active))
return;
- if (!new_crtc_state->bigjoiner) {
+ if (!new_crtc_state->bigjoiner_pipes) {
intel_encoders_pre_pll_enable(state, crtc);
if (new_crtc_state->shared_dpll)
@@ -2036,25 +1919,18 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
icl_ddi_bigjoiner_pre_enable(state, new_crtc_state);
}
+ intel_dsc_enable(new_crtc_state);
+
+ if (DISPLAY_VER(dev_priv) >= 13)
+ intel_uncompressed_joiner_enable(new_crtc_state);
+
intel_set_pipe_src_size(new_crtc_state);
if (DISPLAY_VER(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
bdw_set_pipemisc(new_crtc_state);
- if (!new_crtc_state->bigjoiner_slave && !transcoder_is_dsi(cpu_transcoder)) {
- intel_set_transcoder_timings(new_crtc_state);
-
- if (cpu_transcoder != TRANSCODER_EDP)
- intel_de_write(dev_priv, PIPE_MULT(cpu_transcoder),
- new_crtc_state->pixel_multiplier - 1);
-
- if (new_crtc_state->has_pch_encoder)
- intel_cpu_transcoder_set_m_n(new_crtc_state,
- &new_crtc_state->fdi_m_n, NULL);
-
- hsw_set_frame_start_delay(new_crtc_state);
-
- hsw_set_transconf(new_crtc_state);
- }
+ if (!intel_crtc_is_bigjoiner_slave(new_crtc_state) &&
+ !transcoder_is_dsi(cpu_transcoder))
+ hsw_configure_cpu_transcoder(new_crtc_state);
crtc->active = true;
@@ -2074,7 +1950,8 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
* clocks enabled
*/
intel_color_load_luts(new_crtc_state);
- intel_color_commit(new_crtc_state);
+ intel_color_commit_noarm(new_crtc_state);
+ intel_color_commit_arm(new_crtc_state);
/* update DSPCNTR to configure gamma/csc for pipe bottom color */
if (DISPLAY_VER(dev_priv) < 9)
intel_disable_primary_plane(new_crtc_state);
@@ -2086,14 +1963,7 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
intel_initial_watermarks(state, crtc);
- if (DISPLAY_VER(dev_priv) >= 11) {
- const struct intel_dbuf_state *dbuf_state =
- intel_atomic_get_new_dbuf_state(state);
-
- icl_pipe_mbus_enable(crtc, dbuf_state->joined_mbus);
- }
-
- if (new_crtc_state->bigjoiner_slave)
+ if (intel_crtc_is_bigjoiner_slave(new_crtc_state))
intel_crtc_vblank_on(new_crtc_state);
intel_encoders_enable(state, crtc);
@@ -2127,9 +1997,9 @@ void ilk_pfit_disable(const struct intel_crtc_state *old_crtc_state)
if (!old_crtc_state->pch_pfit.enabled)
return;
- intel_de_write(dev_priv, PF_CTL(pipe), 0);
- intel_de_write(dev_priv, PF_WIN_POS(pipe), 0);
- intel_de_write(dev_priv, PF_WIN_SZ(pipe), 0);
+ intel_de_write_fw(dev_priv, PF_CTL(pipe), 0);
+ intel_de_write_fw(dev_priv, PF_WIN_POS(pipe), 0);
+ intel_de_write_fw(dev_priv, PF_WIN_SZ(pipe), 0);
}
static void ilk_crtc_disable(struct intel_atomic_state *state,
@@ -2178,7 +2048,7 @@ static void hsw_crtc_disable(struct intel_atomic_state *state,
* FIXME collapse everything to one hook.
* Need care with mst->ddi interactions.
*/
- if (!old_crtc_state->bigjoiner_slave) {
+ if (!intel_crtc_is_bigjoiner_slave(old_crtc_state)) {
intel_encoders_disable(state, crtc);
intel_encoders_post_disable(state, crtc);
}
@@ -2288,159 +2158,105 @@ enum tc_port intel_port_to_tc(struct drm_i915_private *dev_priv, enum port port)
return TC_PORT_1 + port - PORT_C;
}
-enum intel_display_power_domain intel_port_to_power_domain(enum port port)
-{
- switch (port) {
- case PORT_A:
- return POWER_DOMAIN_PORT_DDI_A_LANES;
- case PORT_B:
- return POWER_DOMAIN_PORT_DDI_B_LANES;
- case PORT_C:
- return POWER_DOMAIN_PORT_DDI_C_LANES;
- case PORT_D:
- return POWER_DOMAIN_PORT_DDI_D_LANES;
- case PORT_E:
- return POWER_DOMAIN_PORT_DDI_E_LANES;
- case PORT_F:
- return POWER_DOMAIN_PORT_DDI_F_LANES;
- case PORT_G:
- return POWER_DOMAIN_PORT_DDI_G_LANES;
- case PORT_H:
- return POWER_DOMAIN_PORT_DDI_H_LANES;
- case PORT_I:
- return POWER_DOMAIN_PORT_DDI_I_LANES;
- default:
- MISSING_CASE(port);
- return POWER_DOMAIN_PORT_OTHER;
- }
-}
-
enum intel_display_power_domain
intel_aux_power_domain(struct intel_digital_port *dig_port)
{
- if (intel_tc_port_in_tbt_alt_mode(dig_port)) {
- switch (dig_port->aux_ch) {
- case AUX_CH_C:
- return POWER_DOMAIN_AUX_C_TBT;
- case AUX_CH_D:
- return POWER_DOMAIN_AUX_D_TBT;
- case AUX_CH_E:
- return POWER_DOMAIN_AUX_E_TBT;
- case AUX_CH_F:
- return POWER_DOMAIN_AUX_F_TBT;
- case AUX_CH_G:
- return POWER_DOMAIN_AUX_G_TBT;
- case AUX_CH_H:
- return POWER_DOMAIN_AUX_H_TBT;
- case AUX_CH_I:
- return POWER_DOMAIN_AUX_I_TBT;
- default:
- MISSING_CASE(dig_port->aux_ch);
- return POWER_DOMAIN_AUX_C_TBT;
- }
- }
+ struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
- return intel_legacy_aux_to_power_domain(dig_port->aux_ch);
-}
+ if (intel_tc_port_in_tbt_alt_mode(dig_port))
+ return intel_display_power_tbt_aux_domain(i915, dig_port->aux_ch);
-/*
- * Converts aux_ch to power_domain without caring about TBT ports for that use
- * intel_aux_power_domain()
- */
-enum intel_display_power_domain
-intel_legacy_aux_to_power_domain(enum aux_ch aux_ch)
-{
- switch (aux_ch) {
- case AUX_CH_A:
- return POWER_DOMAIN_AUX_A;
- case AUX_CH_B:
- return POWER_DOMAIN_AUX_B;
- case AUX_CH_C:
- return POWER_DOMAIN_AUX_C;
- case AUX_CH_D:
- return POWER_DOMAIN_AUX_D;
- case AUX_CH_E:
- return POWER_DOMAIN_AUX_E;
- case AUX_CH_F:
- return POWER_DOMAIN_AUX_F;
- case AUX_CH_G:
- return POWER_DOMAIN_AUX_G;
- case AUX_CH_H:
- return POWER_DOMAIN_AUX_H;
- case AUX_CH_I:
- return POWER_DOMAIN_AUX_I;
- default:
- MISSING_CASE(aux_ch);
- return POWER_DOMAIN_AUX_A;
- }
+ return intel_display_power_legacy_aux_domain(i915, dig_port->aux_ch);
}
-static u64 get_crtc_power_domains(struct intel_crtc_state *crtc_state)
+static void get_crtc_power_domains(struct intel_crtc_state *crtc_state,
+ struct intel_power_domain_mask *mask)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
struct drm_encoder *encoder;
enum pipe pipe = crtc->pipe;
- u64 mask;
+
+ bitmap_zero(mask->bits, POWER_DOMAIN_NUM);
if (!crtc_state->hw.active)
- return 0;
+ return;
- mask = BIT_ULL(POWER_DOMAIN_PIPE(pipe));
- mask |= BIT_ULL(POWER_DOMAIN_TRANSCODER(cpu_transcoder));
+ set_bit(POWER_DOMAIN_PIPE(pipe), mask->bits);
+ set_bit(POWER_DOMAIN_TRANSCODER(cpu_transcoder), mask->bits);
if (crtc_state->pch_pfit.enabled ||
crtc_state->pch_pfit.force_thru)
- mask |= BIT_ULL(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe));
+ set_bit(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe), mask->bits);
drm_for_each_encoder_mask(encoder, &dev_priv->drm,
crtc_state->uapi.encoder_mask) {
struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
- mask |= BIT_ULL(intel_encoder->power_domain);
+ set_bit(intel_encoder->power_domain, mask->bits);
}
if (HAS_DDI(dev_priv) && crtc_state->has_audio)
- mask |= BIT_ULL(POWER_DOMAIN_AUDIO_MMIO);
+ set_bit(POWER_DOMAIN_AUDIO_MMIO, mask->bits);
if (crtc_state->shared_dpll)
- mask |= BIT_ULL(POWER_DOMAIN_DISPLAY_CORE);
+ set_bit(POWER_DOMAIN_DISPLAY_CORE, mask->bits);
if (crtc_state->dsc.compression_enable)
- mask |= BIT_ULL(intel_dsc_power_domain(crtc, cpu_transcoder));
-
- return mask;
+ set_bit(intel_dsc_power_domain(crtc, cpu_transcoder), mask->bits);
}
-static u64
-modeset_get_crtc_power_domains(struct intel_crtc_state *crtc_state)
+static void
+modeset_get_crtc_power_domains(struct intel_crtc_state *crtc_state,
+ struct intel_power_domain_mask *old_domains)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum intel_display_power_domain domain;
- u64 domains, new_domains, old_domains;
+ struct intel_power_domain_mask domains, new_domains;
- domains = get_crtc_power_domains(crtc_state);
+ get_crtc_power_domains(crtc_state, &domains);
- new_domains = domains & ~crtc->enabled_power_domains.mask;
- old_domains = crtc->enabled_power_domains.mask & ~domains;
+ bitmap_andnot(new_domains.bits,
+ domains.bits,
+ crtc->enabled_power_domains.mask.bits,
+ POWER_DOMAIN_NUM);
+ bitmap_andnot(old_domains->bits,
+ crtc->enabled_power_domains.mask.bits,
+ domains.bits,
+ POWER_DOMAIN_NUM);
- for_each_power_domain(domain, new_domains)
+ for_each_power_domain(domain, &new_domains)
intel_display_power_get_in_set(dev_priv,
&crtc->enabled_power_domains,
domain);
-
- return old_domains;
}
static void modeset_put_crtc_power_domains(struct intel_crtc *crtc,
- u64 domains)
+ struct intel_power_domain_mask *domains)
{
intel_display_power_put_mask_in_set(to_i915(crtc->base.dev),
&crtc->enabled_power_domains,
domains);
}
+static void i9xx_configure_cpu_transcoder(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
+
+ if (intel_crtc_has_dp_encoder(crtc_state)) {
+ intel_cpu_transcoder_set_m1_n1(crtc, cpu_transcoder,
+ &crtc_state->dp_m_n);
+ intel_cpu_transcoder_set_m2_n2(crtc, cpu_transcoder,
+ &crtc_state->dp_m2_n2);
+ }
+
+ intel_set_transcoder_timings(crtc_state);
+
+ i9xx_set_pipeconf(crtc_state);
+}
+
static void valleyview_crtc_enable(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
@@ -2452,10 +2268,8 @@ static void valleyview_crtc_enable(struct intel_atomic_state *state,
if (drm_WARN_ON(&dev_priv->drm, crtc->active))
return;
- if (intel_crtc_has_dp_encoder(new_crtc_state))
- intel_dp_set_m_n(new_crtc_state, M1_N1);
+ i9xx_configure_cpu_transcoder(new_crtc_state);
- intel_set_transcoder_timings(new_crtc_state);
intel_set_pipe_src_size(new_crtc_state);
if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
@@ -2463,8 +2277,6 @@ static void valleyview_crtc_enable(struct intel_atomic_state *state,
intel_de_write(dev_priv, CHV_CANVAS(pipe), 0);
}
- i9xx_set_pipeconf(new_crtc_state);
-
crtc->active = true;
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
@@ -2481,7 +2293,8 @@ static void valleyview_crtc_enable(struct intel_atomic_state *state,
i9xx_pfit_enable(new_crtc_state);
intel_color_load_luts(new_crtc_state);
- intel_color_commit(new_crtc_state);
+ intel_color_commit_noarm(new_crtc_state);
+ intel_color_commit_arm(new_crtc_state);
/* update DSPCNTR to configure gamma for pipe bottom color */
intel_disable_primary_plane(new_crtc_state);
@@ -2504,14 +2317,10 @@ static void i9xx_crtc_enable(struct intel_atomic_state *state,
if (drm_WARN_ON(&dev_priv->drm, crtc->active))
return;
- if (intel_crtc_has_dp_encoder(new_crtc_state))
- intel_dp_set_m_n(new_crtc_state, M1_N1);
+ i9xx_configure_cpu_transcoder(new_crtc_state);
- intel_set_transcoder_timings(new_crtc_state);
intel_set_pipe_src_size(new_crtc_state);
- i9xx_set_pipeconf(new_crtc_state);
-
crtc->active = true;
if (DISPLAY_VER(dev_priv) != 2)
@@ -2524,7 +2333,8 @@ static void i9xx_crtc_enable(struct intel_atomic_state *state,
i9xx_pfit_enable(new_crtc_state);
intel_color_load_luts(new_crtc_state);
- intel_color_commit(new_crtc_state);
+ intel_color_commit_noarm(new_crtc_state);
+ intel_color_commit_arm(new_crtc_state);
/* update DSPCNTR to configure gamma for pipe bottom color */
intel_disable_primary_plane(new_crtc_state);
@@ -2757,77 +2567,6 @@ static void intel_connector_verify_state(struct intel_crtc_state *crtc_state,
}
}
-bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state)
-{
- struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-
- /* IPS only exists on ULT machines and is tied to pipe A. */
- if (!hsw_crtc_supports_ips(crtc))
- return false;
-
- if (!dev_priv->params.enable_ips)
- return false;
-
- if (crtc_state->pipe_bpp > 24)
- return false;
-
- /*
- * We compare against max which means we must take
- * the increased cdclk requirement into account when
- * calculating the new cdclk.
- *
- * Should measure whether using a lower cdclk w/o IPS
- */
- if (IS_BROADWELL(dev_priv) &&
- crtc_state->pixel_rate > dev_priv->max_cdclk_freq * 95 / 100)
- return false;
-
- return true;
-}
-
-static int hsw_compute_ips_config(struct intel_crtc_state *crtc_state)
-{
- struct drm_i915_private *dev_priv =
- to_i915(crtc_state->uapi.crtc->dev);
- struct intel_atomic_state *state =
- to_intel_atomic_state(crtc_state->uapi.state);
-
- crtc_state->ips_enabled = false;
-
- if (!hsw_crtc_state_ips_capable(crtc_state))
- return 0;
-
- /*
- * When IPS gets enabled, the pipe CRC changes. Since IPS gets
- * enabled and disabled dynamically based on package C states,
- * user space can't make reliable use of the CRCs, so let's just
- * completely disable it.
- */
- if (crtc_state->crc_enabled)
- return 0;
-
- /* IPS should be fine as long as at least one plane is enabled. */
- if (!(crtc_state->active_planes & ~BIT(PLANE_CURSOR)))
- return 0;
-
- if (IS_BROADWELL(dev_priv)) {
- const struct intel_cdclk_state *cdclk_state;
-
- cdclk_state = intel_atomic_get_cdclk_state(state);
- if (IS_ERR(cdclk_state))
- return PTR_ERR(cdclk_state);
-
- /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
- if (crtc_state->pixel_rate > cdclk_state->logical.cdclk * 95 / 100)
- return 0;
- }
-
- crtc_state->ips_enabled = true;
-
- return 0;
-}
-
static bool intel_crtc_supports_double_wide(const struct intel_crtc *crtc)
{
const struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
@@ -2851,8 +2590,8 @@ static u32 ilk_pipe_pixel_rate(const struct intel_crtc_state *crtc_state)
return pixel_rate;
drm_rect_init(&src, 0, 0,
- crtc_state->pipe_src_w << 16,
- crtc_state->pipe_src_h << 16);
+ drm_rect_width(&crtc_state->pipe_src) << 16,
+ drm_rect_height(&crtc_state->pipe_src) << 16);
return intel_adjusted_rate(&src, &crtc_state->pch_pfit.dst,
pixel_rate);
@@ -2892,58 +2631,81 @@ static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state)
ilk_pipe_pixel_rate(crtc_state);
}
+static void intel_bigjoiner_adjust_timings(const struct intel_crtc_state *crtc_state,
+ struct drm_display_mode *mode)
+{
+ int num_pipes = intel_bigjoiner_num_pipes(crtc_state);
+
+ if (num_pipes < 2)
+ return;
+
+ mode->crtc_clock /= num_pipes;
+ mode->crtc_hdisplay /= num_pipes;
+ mode->crtc_hblank_start /= num_pipes;
+ mode->crtc_hblank_end /= num_pipes;
+ mode->crtc_hsync_start /= num_pipes;
+ mode->crtc_hsync_end /= num_pipes;
+ mode->crtc_htotal /= num_pipes;
+}
+
+static void intel_splitter_adjust_timings(const struct intel_crtc_state *crtc_state,
+ struct drm_display_mode *mode)
+{
+ int overlap = crtc_state->splitter.pixel_overlap;
+ int n = crtc_state->splitter.link_count;
+
+ if (!crtc_state->splitter.enable)
+ return;
+
+ /*
+ * eDP MSO uses segment timings from EDID for transcoder
+ * timings, but full mode for everything else.
+ *
+ * h_full = (h_segment - pixel_overlap) * link_count
+ */
+ mode->crtc_hdisplay = (mode->crtc_hdisplay - overlap) * n;
+ mode->crtc_hblank_start = (mode->crtc_hblank_start - overlap) * n;
+ mode->crtc_hblank_end = (mode->crtc_hblank_end - overlap) * n;
+ mode->crtc_hsync_start = (mode->crtc_hsync_start - overlap) * n;
+ mode->crtc_hsync_end = (mode->crtc_hsync_end - overlap) * n;
+ mode->crtc_htotal = (mode->crtc_htotal - overlap) * n;
+ mode->crtc_clock *= n;
+}
+
static void intel_crtc_readout_derived_state(struct intel_crtc_state *crtc_state)
{
struct drm_display_mode *mode = &crtc_state->hw.mode;
struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode;
struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
+ /*
+ * Start with the adjusted_mode crtc timings, which
+ * have been filled with the transcoder timings.
+ */
drm_mode_copy(pipe_mode, adjusted_mode);
- if (crtc_state->bigjoiner) {
- /*
- * transcoder is programmed to the full mode,
- * but pipe timings are half of the transcoder mode
- */
- pipe_mode->crtc_hdisplay /= 2;
- pipe_mode->crtc_hblank_start /= 2;
- pipe_mode->crtc_hblank_end /= 2;
- pipe_mode->crtc_hsync_start /= 2;
- pipe_mode->crtc_hsync_end /= 2;
- pipe_mode->crtc_htotal /= 2;
- pipe_mode->crtc_clock /= 2;
- }
+ /* Expand MSO per-segment transcoder timings to full */
+ intel_splitter_adjust_timings(crtc_state, pipe_mode);
- if (crtc_state->splitter.enable) {
- int n = crtc_state->splitter.link_count;
- int overlap = crtc_state->splitter.pixel_overlap;
+ /*
+ * We want the full numbers in adjusted_mode normal timings,
+ * adjusted_mode crtc timings are left with the raw transcoder
+ * timings.
+ */
+ intel_mode_from_crtc_timings(adjusted_mode, pipe_mode);
- /*
- * eDP MSO uses segment timings from EDID for transcoder
- * timings, but full mode for everything else.
- *
- * h_full = (h_segment - pixel_overlap) * link_count
- */
- pipe_mode->crtc_hdisplay = (pipe_mode->crtc_hdisplay - overlap) * n;
- pipe_mode->crtc_hblank_start = (pipe_mode->crtc_hblank_start - overlap) * n;
- pipe_mode->crtc_hblank_end = (pipe_mode->crtc_hblank_end - overlap) * n;
- pipe_mode->crtc_hsync_start = (pipe_mode->crtc_hsync_start - overlap) * n;
- pipe_mode->crtc_hsync_end = (pipe_mode->crtc_hsync_end - overlap) * n;
- pipe_mode->crtc_htotal = (pipe_mode->crtc_htotal - overlap) * n;
- pipe_mode->crtc_clock *= n;
-
- intel_mode_from_crtc_timings(pipe_mode, pipe_mode);
- intel_mode_from_crtc_timings(adjusted_mode, pipe_mode);
- } else {
- intel_mode_from_crtc_timings(pipe_mode, pipe_mode);
- intel_mode_from_crtc_timings(adjusted_mode, adjusted_mode);
- }
+ /* Populate the "user" mode with full numbers */
+ drm_mode_copy(mode, pipe_mode);
+ intel_mode_from_crtc_timings(mode, mode);
+ mode->hdisplay = drm_rect_width(&crtc_state->pipe_src) *
+ (intel_bigjoiner_num_pipes(crtc_state) ?: 1);
+ mode->vdisplay = drm_rect_height(&crtc_state->pipe_src);
- intel_crtc_compute_pixel_rate(crtc_state);
+ /* Derive per-pipe timings in case bigjoiner is used */
+ intel_bigjoiner_adjust_timings(crtc_state, pipe_mode);
+ intel_mode_from_crtc_timings(pipe_mode, pipe_mode);
- drm_mode_copy(mode, adjusted_mode);
- mode->hdisplay = crtc_state->pipe_src_w << crtc_state->bigjoiner;
- mode->vdisplay = crtc_state->pipe_src_h;
+ intel_crtc_compute_pixel_rate(crtc_state);
}
static void intel_encoder_get_config(struct intel_encoder *encoder,
@@ -2954,44 +2716,77 @@ static void intel_encoder_get_config(struct intel_encoder *encoder,
intel_crtc_readout_derived_state(crtc_state);
}
-static int intel_crtc_compute_config(struct intel_crtc *crtc,
- struct intel_crtc_state *pipe_config)
+static void intel_bigjoiner_compute_pipe_src(struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- struct drm_display_mode *pipe_mode = &pipe_config->hw.pipe_mode;
- int clock_limit = dev_priv->max_dotclk_freq;
+ int num_pipes = intel_bigjoiner_num_pipes(crtc_state);
+ int width, height;
+
+ if (num_pipes < 2)
+ return;
- drm_mode_copy(pipe_mode, &pipe_config->hw.adjusted_mode);
+ width = drm_rect_width(&crtc_state->pipe_src);
+ height = drm_rect_height(&crtc_state->pipe_src);
- /* Adjust pipe_mode for bigjoiner, with half the horizontal mode */
- if (pipe_config->bigjoiner) {
- pipe_mode->crtc_clock /= 2;
- pipe_mode->crtc_hdisplay /= 2;
- pipe_mode->crtc_hblank_start /= 2;
- pipe_mode->crtc_hblank_end /= 2;
- pipe_mode->crtc_hsync_start /= 2;
- pipe_mode->crtc_hsync_end /= 2;
- pipe_mode->crtc_htotal /= 2;
- pipe_config->pipe_src_w /= 2;
- }
+ drm_rect_init(&crtc_state->pipe_src, 0, 0,
+ width / num_pipes, height);
+}
+
+static int intel_crtc_compute_pipe_src(struct intel_crtc_state *crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
- if (pipe_config->splitter.enable) {
- int n = pipe_config->splitter.link_count;
- int overlap = pipe_config->splitter.pixel_overlap;
+ intel_bigjoiner_compute_pipe_src(crtc_state);
- pipe_mode->crtc_hdisplay = (pipe_mode->crtc_hdisplay - overlap) * n;
- pipe_mode->crtc_hblank_start = (pipe_mode->crtc_hblank_start - overlap) * n;
- pipe_mode->crtc_hblank_end = (pipe_mode->crtc_hblank_end - overlap) * n;
- pipe_mode->crtc_hsync_start = (pipe_mode->crtc_hsync_start - overlap) * n;
- pipe_mode->crtc_hsync_end = (pipe_mode->crtc_hsync_end - overlap) * n;
- pipe_mode->crtc_htotal = (pipe_mode->crtc_htotal - overlap) * n;
- pipe_mode->crtc_clock *= n;
+ /*
+ * Pipe horizontal size must be even in:
+ * - DVO ganged mode
+ * - LVDS dual channel mode
+ * - Double wide pipe
+ */
+ if (drm_rect_width(&crtc_state->pipe_src) & 1) {
+ if (crtc_state->double_wide) {
+ drm_dbg_kms(&i915->drm,
+ "[CRTC:%d:%s] Odd pipe source width not supported with double wide pipe\n",
+ crtc->base.base.id, crtc->base.name);
+ return -EINVAL;
+ }
+
+ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) &&
+ intel_is_dual_link_lvds(i915)) {
+ drm_dbg_kms(&i915->drm,
+ "[CRTC:%d:%s] Odd pipe source width not supported with dual link LVDS\n",
+ crtc->base.base.id, crtc->base.name);
+ return -EINVAL;
+ }
}
+ return 0;
+}
+
+static int intel_crtc_compute_pipe_mode(struct intel_crtc_state *crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
+ struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode;
+ int clock_limit = i915->max_dotclk_freq;
+
+ /*
+ * Start with the adjusted_mode crtc timings, which
+ * have been filled with the transcoder timings.
+ */
+ drm_mode_copy(pipe_mode, adjusted_mode);
+
+ /* Expand MSO per-segment transcoder timings to full */
+ intel_splitter_adjust_timings(crtc_state, pipe_mode);
+
+ /* Derive per-pipe timings in case bigjoiner is used */
+ intel_bigjoiner_adjust_timings(crtc_state, pipe_mode);
intel_mode_from_crtc_timings(pipe_mode, pipe_mode);
- if (DISPLAY_VER(dev_priv) < 4) {
- clock_limit = dev_priv->max_cdclk_freq * 9 / 10;
+ if (DISPLAY_VER(i915) < 4) {
+ clock_limit = i915->max_cdclk_freq * 9 / 10;
/*
* Enable double wide mode when the dot clock
@@ -2999,44 +2794,40 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
*/
if (intel_crtc_supports_double_wide(crtc) &&
pipe_mode->crtc_clock > clock_limit) {
- clock_limit = dev_priv->max_dotclk_freq;
- pipe_config->double_wide = true;
+ clock_limit = i915->max_dotclk_freq;
+ crtc_state->double_wide = true;
}
}
if (pipe_mode->crtc_clock > clock_limit) {
- drm_dbg_kms(&dev_priv->drm,
- "requested pixel clock (%d kHz) too high (max: %d kHz, double wide: %s)\n",
+ drm_dbg_kms(&i915->drm,
+ "[CRTC:%d:%s] requested pixel clock (%d kHz) too high (max: %d kHz, double wide: %s)\n",
+ crtc->base.base.id, crtc->base.name,
pipe_mode->crtc_clock, clock_limit,
- yesno(pipe_config->double_wide));
+ str_yes_no(crtc_state->double_wide));
return -EINVAL;
}
- /*
- * Pipe horizontal size must be even in:
- * - DVO ganged mode
- * - LVDS dual channel mode
- * - Double wide pipe
- */
- if (pipe_config->pipe_src_w & 1) {
- if (pipe_config->double_wide) {
- drm_dbg_kms(&dev_priv->drm,
- "Odd pipe source width not supported with double wide pipe\n");
- return -EINVAL;
- }
+ return 0;
+}
- if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_LVDS) &&
- intel_is_dual_link_lvds(dev_priv)) {
- drm_dbg_kms(&dev_priv->drm,
- "Odd pipe source width not supported with dual link LVDS\n");
- return -EINVAL;
- }
- }
+static int intel_crtc_compute_config(struct intel_crtc *crtc,
+ struct intel_crtc_state *crtc_state)
+{
+ int ret;
- intel_crtc_compute_pixel_rate(pipe_config);
+ ret = intel_crtc_compute_pipe_src(crtc_state);
+ if (ret)
+ return ret;
- if (pipe_config->has_pch_encoder)
- return ilk_fdi_compute_config(crtc, pipe_config);
+ ret = intel_crtc_compute_pipe_mode(crtc_state);
+ if (ret)
+ return ret;
+
+ intel_crtc_compute_pixel_rate(crtc_state);
+
+ if (crtc_state->has_pch_encoder)
+ return ilk_fdi_compute_config(crtc, crtc_state);
return 0;
}
@@ -3085,7 +2876,7 @@ intel_link_compute_m_n(u16 bits_per_pixel, int nlanes,
m_n->tu = 64;
compute_m_n(data_clock,
link_clock * nlanes * 8,
- &m_n->gmch_m, &m_n->gmch_n,
+ &m_n->data_m, &m_n->data_n,
constant_n);
compute_m_n(pixel_clock, link_clock,
@@ -3109,106 +2900,73 @@ static void intel_panel_sanitize_ssc(struct drm_i915_private *dev_priv)
if (dev_priv->vbt.lvds_use_ssc != bios_lvds_use_ssc) {
drm_dbg_kms(&dev_priv->drm,
"SSC %s by BIOS, overriding VBT which says %s\n",
- enableddisabled(bios_lvds_use_ssc),
- enableddisabled(dev_priv->vbt.lvds_use_ssc));
+ str_enabled_disabled(bios_lvds_use_ssc),
+ str_enabled_disabled(dev_priv->vbt.lvds_use_ssc));
dev_priv->vbt.lvds_use_ssc = bios_lvds_use_ssc;
}
}
}
-static void intel_pch_transcoder_set_m_n(const struct intel_crtc_state *crtc_state,
- const struct intel_link_m_n *m_n)
+void intel_zero_m_n(struct intel_link_m_n *m_n)
{
- 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;
+ /* corresponds to 0 register value */
+ memset(m_n, 0, sizeof(*m_n));
+ m_n->tu = 1;
+}
- intel_de_write(dev_priv, PCH_TRANS_DATA_M1(pipe),
- TU_SIZE(m_n->tu) | m_n->gmch_m);
- intel_de_write(dev_priv, PCH_TRANS_DATA_N1(pipe), m_n->gmch_n);
- intel_de_write(dev_priv, PCH_TRANS_LINK_M1(pipe), m_n->link_m);
- intel_de_write(dev_priv, PCH_TRANS_LINK_N1(pipe), m_n->link_n);
+void intel_set_m_n(struct drm_i915_private *i915,
+ const struct intel_link_m_n *m_n,
+ i915_reg_t data_m_reg, i915_reg_t data_n_reg,
+ i915_reg_t link_m_reg, i915_reg_t link_n_reg)
+{
+ intel_de_write(i915, data_m_reg, TU_SIZE(m_n->tu) | m_n->data_m);
+ intel_de_write(i915, data_n_reg, m_n->data_n);
+ intel_de_write(i915, link_m_reg, m_n->link_m);
+ /*
+ * On BDW+ writing LINK_N arms the double buffered update
+ * of all the M/N registers, so it must be written last.
+ */
+ intel_de_write(i915, link_n_reg, m_n->link_n);
}
-static bool transcoder_has_m2_n2(struct drm_i915_private *dev_priv,
- enum transcoder transcoder)
+bool intel_cpu_transcoder_has_m2_n2(struct drm_i915_private *dev_priv,
+ enum transcoder transcoder)
{
if (IS_HASWELL(dev_priv))
return transcoder == TRANSCODER_EDP;
- /*
- * Strictly speaking some registers are available before
- * gen7, but we only support DRRS on gen7+
- */
- return DISPLAY_VER(dev_priv) == 7 || IS_CHERRYVIEW(dev_priv);
+ return IS_DISPLAY_VER(dev_priv, 5, 7) || IS_CHERRYVIEW(dev_priv);
}
-static void intel_cpu_transcoder_set_m_n(const struct intel_crtc_state *crtc_state,
- const struct intel_link_m_n *m_n,
- const struct intel_link_m_n *m2_n2)
+void intel_cpu_transcoder_set_m1_n1(struct intel_crtc *crtc,
+ enum transcoder transcoder,
+ const struct intel_link_m_n *m_n)
{
- 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;
- enum transcoder transcoder = crtc_state->cpu_transcoder;
- if (DISPLAY_VER(dev_priv) >= 5) {
- intel_de_write(dev_priv, PIPE_DATA_M1(transcoder),
- TU_SIZE(m_n->tu) | m_n->gmch_m);
- intel_de_write(dev_priv, PIPE_DATA_N1(transcoder),
- m_n->gmch_n);
- intel_de_write(dev_priv, PIPE_LINK_M1(transcoder),
- m_n->link_m);
- intel_de_write(dev_priv, PIPE_LINK_N1(transcoder),
- m_n->link_n);
- /*
- * M2_N2 registers are set only if DRRS is supported
- * (to make sure the registers are not unnecessarily accessed).
- */
- if (m2_n2 && crtc_state->has_drrs &&
- transcoder_has_m2_n2(dev_priv, transcoder)) {
- intel_de_write(dev_priv, PIPE_DATA_M2(transcoder),
- TU_SIZE(m2_n2->tu) | m2_n2->gmch_m);
- intel_de_write(dev_priv, PIPE_DATA_N2(transcoder),
- m2_n2->gmch_n);
- intel_de_write(dev_priv, PIPE_LINK_M2(transcoder),
- m2_n2->link_m);
- intel_de_write(dev_priv, PIPE_LINK_N2(transcoder),
- m2_n2->link_n);
- }
- } else {
- intel_de_write(dev_priv, PIPE_DATA_M_G4X(pipe),
- TU_SIZE(m_n->tu) | m_n->gmch_m);
- intel_de_write(dev_priv, PIPE_DATA_N_G4X(pipe), m_n->gmch_n);
- intel_de_write(dev_priv, PIPE_LINK_M_G4X(pipe), m_n->link_m);
- intel_de_write(dev_priv, PIPE_LINK_N_G4X(pipe), m_n->link_n);
- }
+ if (DISPLAY_VER(dev_priv) >= 5)
+ intel_set_m_n(dev_priv, m_n,
+ PIPE_DATA_M1(transcoder), PIPE_DATA_N1(transcoder),
+ PIPE_LINK_M1(transcoder), PIPE_LINK_N1(transcoder));
+ else
+ intel_set_m_n(dev_priv, m_n,
+ PIPE_DATA_M_G4X(pipe), PIPE_DATA_N_G4X(pipe),
+ PIPE_LINK_M_G4X(pipe), PIPE_LINK_N_G4X(pipe));
}
-void intel_dp_set_m_n(const struct intel_crtc_state *crtc_state, enum link_m_n_set m_n)
+void intel_cpu_transcoder_set_m2_n2(struct intel_crtc *crtc,
+ enum transcoder transcoder,
+ const struct intel_link_m_n *m_n)
{
- const struct intel_link_m_n *dp_m_n, *dp_m2_n2 = NULL;
- struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
-
- if (m_n == M1_N1) {
- dp_m_n = &crtc_state->dp_m_n;
- dp_m2_n2 = &crtc_state->dp_m2_n2;
- } else if (m_n == M2_N2) {
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- /*
- * M2_N2 registers are not supported. Hence m2_n2 divider value
- * needs to be programmed into M1_N1.
- */
- dp_m_n = &crtc_state->dp_m2_n2;
- } else {
- drm_err(&i915->drm, "Unsupported divider value\n");
+ if (!intel_cpu_transcoder_has_m2_n2(dev_priv, transcoder))
return;
- }
- if (crtc_state->has_pch_encoder)
- intel_pch_transcoder_set_m_n(crtc_state, &crtc_state->dp_m_n);
- else
- intel_cpu_transcoder_set_m_n(crtc_state, dp_m_n, dp_m2_n2);
+ intel_set_m_n(dev_priv, m_n,
+ PIPE_DATA_M2(transcoder), PIPE_DATA_N2(transcoder),
+ PIPE_LINK_M2(transcoder), PIPE_LINK_N2(transcoder));
}
static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_state)
@@ -3273,13 +3031,15 @@ static void intel_set_pipe_src_size(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ int width = drm_rect_width(&crtc_state->pipe_src);
+ int height = drm_rect_height(&crtc_state->pipe_src);
enum pipe pipe = crtc->pipe;
/* pipesrc controls the size that is scaled from, which should
* always be the user's requested size.
*/
intel_de_write(dev_priv, PIPESRC(pipe),
- ((crtc_state->pipe_src_w - 1) << 16) | (crtc_state->pipe_src_h - 1));
+ PIPESRC_WIDTH(width - 1) | PIPESRC_HEIGHT(height - 1));
}
static bool intel_pipe_is_interlaced(const struct intel_crtc_state *crtc_state)
@@ -3342,6 +3102,23 @@ static void intel_get_transcoder_timings(struct intel_crtc *crtc,
}
}
+static void intel_bigjoiner_adjust_pipe_src(struct intel_crtc_state *crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ int num_pipes = intel_bigjoiner_num_pipes(crtc_state);
+ enum pipe master_pipe, pipe = crtc->pipe;
+ int width;
+
+ if (num_pipes < 2)
+ return;
+
+ master_pipe = bigjoiner_master_pipe(crtc_state);
+ width = drm_rect_width(&crtc_state->pipe_src);
+
+ drm_rect_translate_to(&crtc_state->pipe_src,
+ (pipe - master_pipe) * width, 0);
+}
+
static void intel_get_pipe_src_size(struct intel_crtc *crtc,
struct intel_crtc_state *pipe_config)
{
@@ -3350,21 +3127,23 @@ static void intel_get_pipe_src_size(struct intel_crtc *crtc,
u32 tmp;
tmp = intel_de_read(dev_priv, PIPESRC(crtc->pipe));
- pipe_config->pipe_src_h = (tmp & 0xffff) + 1;
- pipe_config->pipe_src_w = ((tmp >> 16) & 0xffff) + 1;
+
+ drm_rect_init(&pipe_config->pipe_src, 0, 0,
+ REG_FIELD_GET(PIPESRC_WIDTH_MASK, tmp) + 1,
+ REG_FIELD_GET(PIPESRC_HEIGHT_MASK, tmp) + 1);
+
+ intel_bigjoiner_adjust_pipe_src(pipe_config);
}
static void i9xx_set_pipeconf(const struct intel_crtc_state *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 pipeconf;
-
- pipeconf = 0;
+ u32 pipeconf = 0;
/* we keep both pipes enabled on 830 */
if (IS_I830(dev_priv))
- pipeconf |= intel_de_read(dev_priv, PIPECONF(crtc->pipe)) & PIPECONF_ENABLE;
+ pipeconf |= PIPECONF_ENABLE;
if (crtc_state->double_wide)
pipeconf |= PIPECONF_DOUBLE_WIDE;
@@ -3379,13 +3158,13 @@ static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state)
switch (crtc_state->pipe_bpp) {
case 18:
- pipeconf |= PIPECONF_6BPC;
+ pipeconf |= PIPECONF_BPC_6;
break;
case 24:
- pipeconf |= PIPECONF_8BPC;
+ pipeconf |= PIPECONF_BPC_8;
break;
case 30:
- pipeconf |= PIPECONF_10BPC;
+ pipeconf |= PIPECONF_BPC_10;
break;
default:
/* Case prevented by intel_choose_pipe_bpp_dither. */
@@ -3400,7 +3179,7 @@ static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state)
else
pipeconf |= PIPECONF_INTERLACE_W_SYNC_SHIFT;
} else {
- pipeconf |= PIPECONF_PROGRESSIVE;
+ pipeconf |= PIPECONF_INTERLACE_PROGRESSIVE;
}
if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
@@ -3409,7 +3188,7 @@ static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state)
pipeconf |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode);
- pipeconf |= PIPECONF_FRAME_START_DELAY(dev_priv->framestart_delay - 1);
+ pipeconf |= PIPECONF_FRAME_START_DELAY(crtc_state->framestart_delay - 1);
intel_de_write(dev_priv, PIPECONF(crtc->pipe), pipeconf);
intel_de_posting_read(dev_priv, PIPECONF(crtc->pipe));
@@ -3543,11 +3322,11 @@ static void i9xx_get_pipe_color_config(struct intel_crtc_state *crtc_state)
tmp = intel_de_read(dev_priv, DSPCNTR(i9xx_plane));
- if (tmp & DISPPLANE_GAMMA_ENABLE)
+ if (tmp & DISP_PIPE_GAMMA_ENABLE)
crtc_state->gamma_enable = true;
if (!HAS_GMCH(dev_priv) &&
- tmp & DISPPLANE_PIPE_CSC_ENABLE)
+ tmp & DISP_PIPE_CSC_ENABLE)
crtc_state->csc_enable = true;
}
@@ -3578,16 +3357,17 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
if (IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) ||
IS_CHERRYVIEW(dev_priv)) {
switch (tmp & PIPECONF_BPC_MASK) {
- case PIPECONF_6BPC:
+ case PIPECONF_BPC_6:
pipe_config->pipe_bpp = 18;
break;
- case PIPECONF_8BPC:
+ case PIPECONF_BPC_8:
pipe_config->pipe_bpp = 24;
break;
- case PIPECONF_10BPC:
+ case PIPECONF_BPC_10:
pipe_config->pipe_bpp = 30;
break;
default:
+ MISSING_CASE(tmp);
break;
}
}
@@ -3596,8 +3376,9 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
(tmp & PIPECONF_COLOR_RANGE_SELECT))
pipe_config->limited_color_range = true;
- pipe_config->gamma_mode = (tmp & PIPECONF_GAMMA_MODE_MASK_I9XX) >>
- PIPECONF_GAMMA_MODE_SHIFT;
+ pipe_config->gamma_mode = REG_FIELD_GET(PIPECONF_GAMMA_MODE_MASK_I9XX, tmp);
+
+ pipe_config->framestart_delay = REG_FIELD_GET(PIPECONF_FRAME_START_DELAY_MASK, tmp) + 1;
if (IS_CHERRYVIEW(dev_priv))
pipe_config->cgm_mode = intel_de_read(dev_priv,
@@ -3684,16 +3465,16 @@ static void ilk_set_pipeconf(const struct intel_crtc_state *crtc_state)
switch (crtc_state->pipe_bpp) {
case 18:
- val |= PIPECONF_6BPC;
+ val |= PIPECONF_BPC_6;
break;
case 24:
- val |= PIPECONF_8BPC;
+ val |= PIPECONF_BPC_8;
break;
case 30:
- val |= PIPECONF_10BPC;
+ val |= PIPECONF_BPC_10;
break;
case 36:
- val |= PIPECONF_12BPC;
+ val |= PIPECONF_BPC_12;
break;
default:
/* Case prevented by intel_choose_pipe_bpp_dither. */
@@ -3701,12 +3482,12 @@ static void ilk_set_pipeconf(const struct intel_crtc_state *crtc_state)
}
if (crtc_state->dither)
- val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP);
+ val |= PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP;
if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
- val |= PIPECONF_INTERLACED_ILK;
+ val |= PIPECONF_INTERLACE_IF_ID_ILK;
else
- val |= PIPECONF_PROGRESSIVE;
+ val |= PIPECONF_INTERLACE_PF_PD_ILK;
/*
* This would end up with an odd purple hue over
@@ -3724,7 +3505,8 @@ static void ilk_set_pipeconf(const struct intel_crtc_state *crtc_state)
val |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode);
- val |= PIPECONF_FRAME_START_DELAY(dev_priv->framestart_delay - 1);
+ val |= PIPECONF_FRAME_START_DELAY(crtc_state->framestart_delay - 1);
+ val |= PIPECONF_MSA_TIMING_DELAY(crtc_state->msa_timing_delay);
intel_de_write(dev_priv, PIPECONF(pipe), val);
intel_de_posting_read(dev_priv, PIPECONF(pipe));
@@ -3738,12 +3520,12 @@ static void hsw_set_transconf(const struct intel_crtc_state *crtc_state)
u32 val = 0;
if (IS_HASWELL(dev_priv) && crtc_state->dither)
- val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP);
+ val |= PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP;
if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
- val |= PIPECONF_INTERLACED_ILK;
+ val |= PIPECONF_INTERLACE_IF_ID_ILK;
else
- val |= PIPECONF_PROGRESSIVE;
+ val |= PIPECONF_INTERLACE_PF_PD_ILK;
if (IS_HASWELL(dev_priv) &&
crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB)
@@ -3756,27 +3538,23 @@ static void hsw_set_transconf(const struct intel_crtc_state *crtc_state)
static void bdw_set_pipemisc(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- const struct intel_crtc_scaler_state *scaler_state =
- &crtc_state->scaler_state;
-
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
u32 val = 0;
- int i;
switch (crtc_state->pipe_bpp) {
case 18:
- val |= PIPEMISC_6_BPC;
+ val |= PIPEMISC_BPC_6;
break;
case 24:
- val |= PIPEMISC_8_BPC;
+ val |= PIPEMISC_BPC_8;
break;
case 30:
- val |= PIPEMISC_10_BPC;
+ val |= PIPEMISC_BPC_10;
break;
case 36:
/* Port output 12BPC defined for ADLP+ */
if (DISPLAY_VER(dev_priv) > 12)
- val |= PIPEMISC_12_BPC_ADLP;
+ val |= PIPEMISC_BPC_12_ADLP;
break;
default:
MISSING_CASE(crtc_state->pipe_bpp);
@@ -3800,23 +3578,6 @@ static void bdw_set_pipemisc(const struct intel_crtc_state *crtc_state)
if (DISPLAY_VER(dev_priv) >= 12)
val |= PIPEMISC_PIXEL_ROUNDING_TRUNC;
- if (IS_ALDERLAKE_P(dev_priv)) {
- bool scaler_in_use = false;
-
- for (i = 0; i < crtc->num_scalers; i++) {
- if (!scaler_state->scalers[i].in_use)
- continue;
-
- scaler_in_use = true;
- break;
- }
-
- intel_de_rmw(dev_priv, PIPE_MISC2(crtc->pipe),
- PIPE_MISC2_UNDERRUN_BUBBLE_COUNTER_MASK,
- scaler_in_use ? PIPE_MISC2_BUBBLE_COUNTER_SCALER_EN :
- PIPE_MISC2_BUBBLE_COUNTER_SCALER_DIS);
- }
-
intel_de_write(dev_priv, PIPEMISC(crtc->pipe), val);
}
@@ -3828,11 +3589,11 @@ int bdw_get_pipemisc_bpp(struct intel_crtc *crtc)
tmp = intel_de_read(dev_priv, PIPEMISC(crtc->pipe));
switch (tmp & PIPEMISC_BPC_MASK) {
- case PIPEMISC_6_BPC:
+ case PIPEMISC_BPC_6:
return 18;
- case PIPEMISC_8_BPC:
+ case PIPEMISC_BPC_8:
return 24;
- case PIPEMISC_10_BPC:
+ case PIPEMISC_BPC_10:
return 30;
/*
* PORT OUTPUT 12 BPC defined for ADLP+.
@@ -3844,7 +3605,7 @@ int bdw_get_pipemisc_bpp(struct intel_crtc *crtc)
* on older platforms, need to find a workaround for 12 BPC
* MIPI DSI HW readout.
*/
- case PIPEMISC_12_BPC_ADLP:
+ case PIPEMISC_BPC_12_ADLP:
if (DISPLAY_VER(dev_priv) > 12)
return 36;
fallthrough;
@@ -3865,83 +3626,47 @@ int ilk_get_lanes_required(int target_clock, int link_bw, int bpp)
return DIV_ROUND_UP(bps, link_bw * 8);
}
-static void intel_pch_transcoder_get_m_n(struct intel_crtc *crtc,
- struct intel_link_m_n *m_n)
+void intel_get_m_n(struct drm_i915_private *i915,
+ struct intel_link_m_n *m_n,
+ i915_reg_t data_m_reg, i915_reg_t data_n_reg,
+ i915_reg_t link_m_reg, i915_reg_t link_n_reg)
{
- struct drm_device *dev = crtc->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
- enum pipe pipe = crtc->pipe;
-
- m_n->link_m = intel_de_read(dev_priv, PCH_TRANS_LINK_M1(pipe));
- m_n->link_n = intel_de_read(dev_priv, PCH_TRANS_LINK_N1(pipe));
- m_n->gmch_m = intel_de_read(dev_priv, PCH_TRANS_DATA_M1(pipe))
- & ~TU_SIZE_MASK;
- m_n->gmch_n = intel_de_read(dev_priv, PCH_TRANS_DATA_N1(pipe));
- m_n->tu = ((intel_de_read(dev_priv, PCH_TRANS_DATA_M1(pipe))
- & TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1;
+ m_n->link_m = intel_de_read(i915, link_m_reg) & DATA_LINK_M_N_MASK;
+ m_n->link_n = intel_de_read(i915, link_n_reg) & DATA_LINK_M_N_MASK;
+ m_n->data_m = intel_de_read(i915, data_m_reg) & DATA_LINK_M_N_MASK;
+ m_n->data_n = intel_de_read(i915, data_n_reg) & DATA_LINK_M_N_MASK;
+ m_n->tu = REG_FIELD_GET(TU_SIZE_MASK, intel_de_read(i915, data_m_reg)) + 1;
}
-static void intel_cpu_transcoder_get_m_n(struct intel_crtc *crtc,
- enum transcoder transcoder,
- struct intel_link_m_n *m_n,
- struct intel_link_m_n *m2_n2)
+void intel_cpu_transcoder_get_m1_n1(struct intel_crtc *crtc,
+ enum transcoder transcoder,
+ struct intel_link_m_n *m_n)
{
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum pipe pipe = crtc->pipe;
- if (DISPLAY_VER(dev_priv) >= 5) {
- m_n->link_m = intel_de_read(dev_priv,
- PIPE_LINK_M1(transcoder));
- m_n->link_n = intel_de_read(dev_priv,
- PIPE_LINK_N1(transcoder));
- m_n->gmch_m = intel_de_read(dev_priv,
- PIPE_DATA_M1(transcoder))
- & ~TU_SIZE_MASK;
- m_n->gmch_n = intel_de_read(dev_priv,
- PIPE_DATA_N1(transcoder));
- m_n->tu = ((intel_de_read(dev_priv, PIPE_DATA_M1(transcoder))
- & TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1;
-
- if (m2_n2 && transcoder_has_m2_n2(dev_priv, transcoder)) {
- m2_n2->link_m = intel_de_read(dev_priv,
- PIPE_LINK_M2(transcoder));
- m2_n2->link_n = intel_de_read(dev_priv,
- PIPE_LINK_N2(transcoder));
- m2_n2->gmch_m = intel_de_read(dev_priv,
- PIPE_DATA_M2(transcoder))
- & ~TU_SIZE_MASK;
- m2_n2->gmch_n = intel_de_read(dev_priv,
- PIPE_DATA_N2(transcoder));
- m2_n2->tu = ((intel_de_read(dev_priv, PIPE_DATA_M2(transcoder))
- & TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1;
- }
- } else {
- m_n->link_m = intel_de_read(dev_priv, PIPE_LINK_M_G4X(pipe));
- m_n->link_n = intel_de_read(dev_priv, PIPE_LINK_N_G4X(pipe));
- m_n->gmch_m = intel_de_read(dev_priv, PIPE_DATA_M_G4X(pipe))
- & ~TU_SIZE_MASK;
- m_n->gmch_n = intel_de_read(dev_priv, PIPE_DATA_N_G4X(pipe));
- m_n->tu = ((intel_de_read(dev_priv, PIPE_DATA_M_G4X(pipe))
- & TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1;
- }
-}
-
-void intel_dp_get_m_n(struct intel_crtc *crtc,
- struct intel_crtc_state *pipe_config)
-{
- if (pipe_config->has_pch_encoder)
- intel_pch_transcoder_get_m_n(crtc, &pipe_config->dp_m_n);
+ if (DISPLAY_VER(dev_priv) >= 5)
+ intel_get_m_n(dev_priv, m_n,
+ PIPE_DATA_M1(transcoder), PIPE_DATA_N1(transcoder),
+ PIPE_LINK_M1(transcoder), PIPE_LINK_N1(transcoder));
else
- intel_cpu_transcoder_get_m_n(crtc, pipe_config->cpu_transcoder,
- &pipe_config->dp_m_n,
- &pipe_config->dp_m2_n2);
+ intel_get_m_n(dev_priv, m_n,
+ PIPE_DATA_M_G4X(pipe), PIPE_DATA_N_G4X(pipe),
+ PIPE_LINK_M_G4X(pipe), PIPE_LINK_N_G4X(pipe));
}
-void ilk_get_fdi_m_n_config(struct intel_crtc *crtc,
- struct intel_crtc_state *pipe_config)
+void intel_cpu_transcoder_get_m2_n2(struct intel_crtc *crtc,
+ enum transcoder transcoder,
+ struct intel_link_m_n *m_n)
{
- intel_cpu_transcoder_get_m_n(crtc, pipe_config->cpu_transcoder,
- &pipe_config->fdi_m_n, NULL);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+
+ if (!intel_cpu_transcoder_has_m2_n2(dev_priv, transcoder))
+ return;
+
+ intel_get_m_n(dev_priv, m_n,
+ PIPE_DATA_M2(transcoder), PIPE_DATA_N2(transcoder),
+ PIPE_LINK_M2(transcoder), PIPE_LINK_N2(transcoder));
}
static void ilk_get_pfit_pos_size(struct intel_crtc_state *crtc_state,
@@ -4037,16 +3762,16 @@ static bool ilk_get_pipe_config(struct intel_crtc *crtc,
goto out;
switch (tmp & PIPECONF_BPC_MASK) {
- case PIPECONF_6BPC:
+ case PIPECONF_BPC_6:
pipe_config->pipe_bpp = 18;
break;
- case PIPECONF_8BPC:
+ case PIPECONF_BPC_8:
pipe_config->pipe_bpp = 24;
break;
- case PIPECONF_10BPC:
+ case PIPECONF_BPC_10:
pipe_config->pipe_bpp = 30;
break;
- case PIPECONF_12BPC:
+ case PIPECONF_BPC_12:
pipe_config->pipe_bpp = 36;
break;
default:
@@ -4066,8 +3791,11 @@ static bool ilk_get_pipe_config(struct intel_crtc *crtc,
break;
}
- pipe_config->gamma_mode = (tmp & PIPECONF_GAMMA_MODE_MASK_ILK) >>
- PIPECONF_GAMMA_MODE_SHIFT;
+ pipe_config->gamma_mode = REG_FIELD_GET(PIPECONF_GAMMA_MODE_MASK_ILK, tmp);
+
+ pipe_config->framestart_delay = REG_FIELD_GET(PIPECONF_FRAME_START_DELAY_MASK, tmp) + 1;
+
+ pipe_config->msa_timing_delay = REG_FIELD_GET(PIPECONF_MSA_TIMING_DELAY_MASK, tmp);
pipe_config->csc_mode = intel_de_read(dev_priv,
PIPE_CSC_MODE(crtc->pipe));
@@ -4117,19 +3845,20 @@ static bool transcoder_ddi_func_is_enabled(struct drm_i915_private *dev_priv,
return tmp & TRANS_DDI_FUNC_ENABLE;
}
-static u8 enabled_bigjoiner_pipes(struct drm_i915_private *dev_priv)
+static void enabled_bigjoiner_pipes(struct drm_i915_private *dev_priv,
+ u8 *master_pipes, u8 *slave_pipes)
{
- u8 master_pipes = 0, slave_pipes = 0;
struct intel_crtc *crtc;
- for_each_intel_crtc(&dev_priv->drm, crtc) {
+ *master_pipes = 0;
+ *slave_pipes = 0;
+
+ for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, crtc,
+ bigjoiner_pipes(dev_priv)) {
enum intel_display_power_domain power_domain;
enum pipe pipe = crtc->pipe;
intel_wakeref_t wakeref;
- if ((bigjoiner_pipes(dev_priv) & BIT(pipe)) == 0)
- continue;
-
power_domain = intel_dsc_power_domain(crtc, (enum transcoder) pipe);
with_intel_display_power_if_enabled(dev_priv, power_domain, wakeref) {
u32 tmp = intel_de_read(dev_priv, ICL_PIPE_DSS_CTL1(pipe));
@@ -4138,9 +3867,9 @@ static u8 enabled_bigjoiner_pipes(struct drm_i915_private *dev_priv)
continue;
if (tmp & MASTER_BIG_JOINER_ENABLE)
- master_pipes |= BIT(pipe);
+ *master_pipes |= BIT(pipe);
else
- slave_pipes |= BIT(pipe);
+ *slave_pipes |= BIT(pipe);
}
if (DISPLAY_VER(dev_priv) < 13)
@@ -4151,18 +3880,47 @@ static u8 enabled_bigjoiner_pipes(struct drm_i915_private *dev_priv)
u32 tmp = intel_de_read(dev_priv, ICL_PIPE_DSS_CTL1(pipe));
if (tmp & UNCOMPRESSED_JOINER_MASTER)
- master_pipes |= BIT(pipe);
+ *master_pipes |= BIT(pipe);
if (tmp & UNCOMPRESSED_JOINER_SLAVE)
- slave_pipes |= BIT(pipe);
+ *slave_pipes |= BIT(pipe);
}
}
/* Bigjoiner pipes should always be consecutive master and slave */
- drm_WARN(&dev_priv->drm, slave_pipes != master_pipes << 1,
+ drm_WARN(&dev_priv->drm, *slave_pipes != *master_pipes << 1,
"Bigjoiner misconfigured (master pipes 0x%x, slave pipes 0x%x)\n",
- master_pipes, slave_pipes);
+ *master_pipes, *slave_pipes);
+}
- return slave_pipes;
+static enum pipe get_bigjoiner_master_pipe(enum pipe pipe, u8 master_pipes, u8 slave_pipes)
+{
+ if ((slave_pipes & BIT(pipe)) == 0)
+ return pipe;
+
+ /* ignore everything above our pipe */
+ master_pipes &= ~GENMASK(7, pipe);
+
+ /* highest remaining bit should be our master pipe */
+ return fls(master_pipes) - 1;
+}
+
+static u8 get_bigjoiner_slave_pipes(enum pipe pipe, u8 master_pipes, u8 slave_pipes)
+{
+ enum pipe master_pipe, next_master_pipe;
+
+ master_pipe = get_bigjoiner_master_pipe(pipe, master_pipes, slave_pipes);
+
+ if ((master_pipes & BIT(master_pipe)) == 0)
+ return 0;
+
+ /* ignore our master pipe and everything below it */
+ master_pipes &= ~GENMASK(master_pipe, 0);
+ /* make sure a high bit is set for the ffs() */
+ master_pipes |= BIT(7);
+ /* lowest remaining bit should be the next master pipe */
+ next_master_pipe = ffs(master_pipes) - 1;
+
+ return slave_pipes & GENMASK(next_master_pipe - 1, master_pipe);
}
static u8 hsw_panel_transcoders(struct drm_i915_private *i915)
@@ -4181,6 +3939,7 @@ static u8 hsw_enabled_transcoders(struct intel_crtc *crtc)
struct drm_i915_private *dev_priv = to_i915(dev);
u8 panel_transcoder_mask = hsw_panel_transcoders(dev_priv);
enum transcoder cpu_transcoder;
+ u8 master_pipes, slave_pipes;
u8 enabled_transcoders = 0;
/*
@@ -4232,8 +3991,10 @@ static u8 hsw_enabled_transcoders(struct intel_crtc *crtc)
enabled_transcoders |= BIT(cpu_transcoder);
/* bigjoiner slave -> consider the master pipe's transcoder as well */
- if (enabled_bigjoiner_pipes(dev_priv) & BIT(crtc->pipe)) {
- cpu_transcoder = (enum transcoder) crtc->pipe - 1;
+ enabled_bigjoiner_pipes(dev_priv, &master_pipes, &slave_pipes);
+ if (slave_pipes & BIT(crtc->pipe)) {
+ cpu_transcoder = (enum transcoder)
+ get_bigjoiner_master_pipe(crtc->pipe, master_pipes, slave_pipes);
if (transcoder_ddi_func_is_enabled(dev_priv, cpu_transcoder))
enabled_transcoders |= BIT(cpu_transcoder);
}
@@ -4358,6 +4119,23 @@ static bool bxt_get_dsi_transcoder_state(struct intel_crtc *crtc,
return transcoder_is_dsi(pipe_config->cpu_transcoder);
}
+static void intel_bigjoiner_get_config(struct intel_crtc_state *crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ u8 master_pipes, slave_pipes;
+ enum pipe pipe = crtc->pipe;
+
+ enabled_bigjoiner_pipes(i915, &master_pipes, &slave_pipes);
+
+ if (((master_pipes | slave_pipes) & BIT(pipe)) == 0)
+ return;
+
+ crtc_state->bigjoiner_pipes =
+ BIT(get_bigjoiner_master_pipe(pipe, master_pipes, slave_pipes)) |
+ get_bigjoiner_slave_pipes(pipe, master_pipes, slave_pipes);
+}
+
static bool hsw_get_pipe_config(struct intel_crtc *crtc,
struct intel_crtc_state *pipe_config)
{
@@ -4380,13 +4158,12 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc,
active = true;
}
- intel_dsc_get_config(pipe_config);
- if (DISPLAY_VER(dev_priv) >= 13 && !pipe_config->dsc.compression_enable)
- intel_uncompressed_joiner_get_config(pipe_config);
-
if (!active)
goto out;
+ intel_dsc_get_config(pipe_config);
+ intel_bigjoiner_get_config(pipe_config);
+
if (!transcoder_is_dsi(pipe_config->cpu_transcoder) ||
DISPLAY_VER(dev_priv) >= 11)
intel_get_transcoder_timings(crtc, pipe_config);
@@ -4443,19 +4220,7 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc,
ilk_get_pfit_config(pipe_config);
}
- if (hsw_crtc_supports_ips(crtc)) {
- if (IS_HASWELL(dev_priv))
- pipe_config->ips_enabled = intel_de_read(dev_priv,
- IPS_CTL) & IPS_ENABLE;
- else {
- /*
- * We cannot readout IPS state on broadwell, set to
- * true so we can set it to a defined state on first
- * commit.
- */
- pipe_config->ips_enabled = true;
- }
- }
+ hsw_ips_get_config(pipe_config);
if (pipe_config->cpu_transcoder != TRANSCODER_EDP &&
!transcoder_is_dsi(pipe_config->cpu_transcoder)) {
@@ -4466,6 +4231,15 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc,
pipe_config->pixel_multiplier = 1;
}
+ if (!transcoder_is_dsi(pipe_config->cpu_transcoder)) {
+ tmp = intel_de_read(dev_priv, CHICKEN_TRANS(pipe_config->cpu_transcoder));
+
+ pipe_config->framestart_delay = REG_FIELD_GET(HSW_FRAME_START_DELAY_MASK, tmp) + 1;
+ } else {
+ /* no idea if this is correct */
+ pipe_config->framestart_delay = 1;
+ }
+
out:
intel_display_power_put_all_in_set(dev_priv, &power_domain_set);
@@ -4867,169 +4641,6 @@ intel_encoder_current_mode(struct intel_encoder *encoder)
return mode;
}
-/**
- * intel_wm_need_update - Check whether watermarks need updating
- * @cur: current plane state
- * @new: new plane state
- *
- * Check current plane state versus the new one to determine whether
- * watermarks need to be recalculated.
- *
- * Returns true or false.
- */
-static bool intel_wm_need_update(const struct intel_plane_state *cur,
- struct intel_plane_state *new)
-{
- /* Update watermarks on tiling or size changes. */
- if (new->uapi.visible != cur->uapi.visible)
- return true;
-
- if (!cur->hw.fb || !new->hw.fb)
- return false;
-
- if (cur->hw.fb->modifier != new->hw.fb->modifier ||
- cur->hw.rotation != new->hw.rotation ||
- drm_rect_width(&new->uapi.src) != drm_rect_width(&cur->uapi.src) ||
- drm_rect_height(&new->uapi.src) != drm_rect_height(&cur->uapi.src) ||
- drm_rect_width(&new->uapi.dst) != drm_rect_width(&cur->uapi.dst) ||
- drm_rect_height(&new->uapi.dst) != drm_rect_height(&cur->uapi.dst))
- return true;
-
- return false;
-}
-
-static bool needs_scaling(const struct intel_plane_state *state)
-{
- int src_w = drm_rect_width(&state->uapi.src) >> 16;
- int src_h = drm_rect_height(&state->uapi.src) >> 16;
- int dst_w = drm_rect_width(&state->uapi.dst);
- int dst_h = drm_rect_height(&state->uapi.dst);
-
- return (src_w != dst_w || src_h != dst_h);
-}
-
-int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_crtc_state,
- struct intel_crtc_state *new_crtc_state,
- const struct intel_plane_state *old_plane_state,
- struct intel_plane_state *new_plane_state)
-{
- struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
- struct intel_plane *plane = to_intel_plane(new_plane_state->uapi.plane);
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- bool mode_changed = intel_crtc_needs_modeset(new_crtc_state);
- bool was_crtc_enabled = old_crtc_state->hw.active;
- bool is_crtc_enabled = new_crtc_state->hw.active;
- bool turn_off, turn_on, visible, was_visible;
- int ret;
-
- if (DISPLAY_VER(dev_priv) >= 9 && plane->id != PLANE_CURSOR) {
- ret = skl_update_scaler_plane(new_crtc_state, new_plane_state);
- if (ret)
- return ret;
- }
-
- was_visible = old_plane_state->uapi.visible;
- visible = new_plane_state->uapi.visible;
-
- if (!was_crtc_enabled && drm_WARN_ON(&dev_priv->drm, was_visible))
- was_visible = false;
-
- /*
- * Visibility is calculated as if the crtc was on, but
- * after scaler setup everything depends on it being off
- * when the crtc isn't active.
- *
- * FIXME this is wrong for watermarks. Watermarks should also
- * be computed as if the pipe would be active. Perhaps move
- * per-plane wm computation to the .check_plane() hook, and
- * only combine the results from all planes in the current place?
- */
- if (!is_crtc_enabled) {
- intel_plane_set_invisible(new_crtc_state, new_plane_state);
- visible = false;
- }
-
- if (!was_visible && !visible)
- return 0;
-
- turn_off = was_visible && (!visible || mode_changed);
- turn_on = visible && (!was_visible || mode_changed);
-
- drm_dbg_atomic(&dev_priv->drm,
- "[CRTC:%d:%s] with [PLANE:%d:%s] visible %i -> %i, off %i, on %i, ms %i\n",
- crtc->base.base.id, crtc->base.name,
- plane->base.base.id, plane->base.name,
- was_visible, visible,
- turn_off, turn_on, mode_changed);
-
- if (turn_on) {
- if (DISPLAY_VER(dev_priv) < 5 && !IS_G4X(dev_priv))
- new_crtc_state->update_wm_pre = true;
-
- /* must disable cxsr around plane enable/disable */
- if (plane->id != PLANE_CURSOR)
- new_crtc_state->disable_cxsr = true;
- } else if (turn_off) {
- if (DISPLAY_VER(dev_priv) < 5 && !IS_G4X(dev_priv))
- new_crtc_state->update_wm_post = true;
-
- /* must disable cxsr around plane enable/disable */
- if (plane->id != PLANE_CURSOR)
- new_crtc_state->disable_cxsr = true;
- } else if (intel_wm_need_update(old_plane_state, new_plane_state)) {
- if (DISPLAY_VER(dev_priv) < 5 && !IS_G4X(dev_priv)) {
- /* FIXME bollocks */
- new_crtc_state->update_wm_pre = true;
- new_crtc_state->update_wm_post = true;
- }
- }
-
- if (visible || was_visible)
- new_crtc_state->fb_bits |= plane->frontbuffer_bit;
-
- /*
- * ILK/SNB DVSACNTR/Sprite Enable
- * IVB SPR_CTL/Sprite Enable
- * "When in Self Refresh Big FIFO mode, a write to enable the
- * plane will be internally buffered and delayed while Big FIFO
- * mode is exiting."
- *
- * Which means that enabling the sprite can take an extra frame
- * when we start in big FIFO mode (LP1+). Thus we need to drop
- * down to LP0 and wait for vblank in order to make sure the
- * sprite gets enabled on the next vblank after the register write.
- * Doing otherwise would risk enabling the sprite one frame after
- * we've already signalled flip completion. We can resume LP1+
- * once the sprite has been enabled.
- *
- *
- * WaCxSRDisabledForSpriteScaling:ivb
- * IVB SPR_SCALE/Scaling Enable
- * "Low Power watermarks must be disabled for at least one
- * frame before enabling sprite scaling, and kept disabled
- * until sprite scaling is disabled."
- *
- * ILK/SNB DVSASCALE/Scaling Enable
- * "When in Self Refresh Big FIFO mode, scaling enable will be
- * masked off while Big FIFO mode is exiting."
- *
- * Despite the w/a only being listed for IVB we assume that
- * the ILK/SNB note has similar ramifications, hence we apply
- * the w/a on all three platforms.
- *
- * With experimental results seems this is needed also for primary
- * plane, not only sprite plane.
- */
- if (plane->id != PLANE_CURSOR &&
- (IS_IRONLAKE(dev_priv) || IS_SANDYBRIDGE(dev_priv) ||
- IS_IVYBRIDGE(dev_priv)) &&
- (turn_on || (!needs_scaling(old_plane_state) &&
- needs_scaling(new_plane_state))))
- new_crtc_state->disable_lp_wm = true;
-
- return 0;
-}
-
static bool encoders_cloneable(const struct intel_encoder *a,
const struct intel_encoder *b)
{
@@ -5110,6 +4721,8 @@ static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state)
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;
}
plane_state->planar_slave = false;
@@ -5154,6 +4767,10 @@ static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state)
crtc_state->enabled_planes |= BIT(linked->id);
crtc_state->active_planes |= BIT(linked->id);
crtc_state->update_planes |= BIT(linked->id);
+ crtc_state->data_rate[linked->id] =
+ crtc_state->data_rate_y[plane->id];
+ crtc_state->rel_data_rate[linked->id] =
+ crtc_state->rel_data_rate_y[plane->id];
drm_dbg_kms(&dev_priv->drm, "Using %s as Y plane for %s\n",
linked->base.name, plane->base.name);
@@ -5287,9 +4904,12 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state,
mode_changed && !crtc_state->hw.active)
crtc_state->update_wm_post = true;
- if (mode_changed && crtc_state->hw.enable &&
- !drm_WARN_ON(&dev_priv->drm, crtc_state->shared_dpll)) {
- ret = dev_priv->dpll_funcs->crtc_compute_clock(crtc_state);
+ if (mode_changed) {
+ ret = intel_dpll_crtc_compute_clock(state, crtc);
+ if (ret)
+ return ret;
+
+ ret = intel_dpll_crtc_get_shared_dpll(state, crtc);
if (ret)
return ret;
}
@@ -5340,7 +4960,7 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state,
}
if (HAS_IPS(dev_priv)) {
- ret = hsw_compute_ips_config(crtc_state);
+ ret = hsw_ips_compute_config(state, crtc);
if (ret)
return ret;
}
@@ -5491,9 +5111,9 @@ intel_dump_m_n_config(const struct intel_crtc_state *pipe_config,
struct drm_i915_private *i915 = to_i915(pipe_config->uapi.crtc->dev);
drm_dbg_kms(&i915->drm,
- "%s: lanes: %i; gmch_m: %u, gmch_n: %u, link_m: %u, link_n: %u, tu: %u\n",
+ "%s: lanes: %i; data_m: %u, data_n: %u, link_m: %u, link_n: %u, tu: %u\n",
id, lane_count,
- m_n->gmch_m, m_n->gmch_n,
+ m_n->data_m, m_n->data_n,
m_n->link_m, m_n->link_n, m_n->tu);
}
@@ -5586,7 +5206,7 @@ static void intel_dump_plane_state(const struct intel_plane_state *plane_state)
drm_dbg_kms(&i915->drm,
"[PLANE:%d:%s] fb: [NOFB], visible: %s\n",
plane->base.base.id, plane->base.name,
- yesno(plane_state->uapi.visible));
+ str_yes_no(plane_state->uapi.visible));
return;
}
@@ -5594,7 +5214,7 @@ static void intel_dump_plane_state(const struct intel_plane_state *plane_state)
"[PLANE:%d:%s] fb: [FB:%d] %ux%u format = %p4cc modifier = 0x%llx, visible: %s\n",
plane->base.base.id, plane->base.name,
fb->base.id, fb->width, fb->height, &fb->format->format,
- fb->modifier, yesno(plane_state->uapi.visible));
+ fb->modifier, str_yes_no(plane_state->uapi.visible));
drm_dbg_kms(&i915->drm, "\trotation: 0x%x, scaler: %d\n",
plane_state->hw.rotation, plane_state->scaler_id);
if (plane_state->uapi.visible)
@@ -5617,7 +5237,7 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config,
drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s] enable: %s %s\n",
crtc->base.base.id, crtc->base.name,
- yesno(pipe_config->hw.enable), context);
+ str_yes_no(pipe_config->hw.enable), context);
if (!pipe_config->hw.enable)
goto dump_planes;
@@ -5625,7 +5245,7 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config,
snprintf_output_types(buf, sizeof(buf), pipe_config->output_types);
drm_dbg_kms(&dev_priv->drm,
"active: %s, output_types: %s (0x%x), output format: %s\n",
- yesno(pipe_config->hw.active),
+ str_yes_no(pipe_config->hw.active),
buf, pipe_config->output_types,
output_formats(pipe_config->output_format));
@@ -5642,12 +5262,13 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config,
transcoder_name(pipe_config->master_transcoder),
pipe_config->sync_mode_slaves_mask);
- drm_dbg_kms(&dev_priv->drm, "bigjoiner: %s\n",
- pipe_config->bigjoiner_slave ? "slave" :
- pipe_config->bigjoiner ? "master" : "no");
+ drm_dbg_kms(&dev_priv->drm, "bigjoiner: %s, pipes: 0x%x\n",
+ intel_crtc_is_bigjoiner_slave(pipe_config) ? "slave" :
+ intel_crtc_is_bigjoiner_master(pipe_config) ? "master" : "no",
+ pipe_config->bigjoiner_pipes);
drm_dbg_kms(&dev_priv->drm, "splitter: %s, link count %d, overlap %d\n",
- enableddisabled(pipe_config->splitter.enable),
+ str_enabled_disabled(pipe_config->splitter.enable),
pipe_config->splitter.link_count,
pipe_config->splitter.pixel_overlap);
@@ -5658,13 +5279,16 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config,
if (intel_crtc_has_dp_encoder(pipe_config)) {
intel_dump_m_n_config(pipe_config, "dp m_n",
- pipe_config->lane_count, &pipe_config->dp_m_n);
- if (pipe_config->has_drrs)
- intel_dump_m_n_config(pipe_config, "dp m2_n2",
- pipe_config->lane_count,
- &pipe_config->dp_m2_n2);
+ pipe_config->lane_count,
+ &pipe_config->dp_m_n);
+ intel_dump_m_n_config(pipe_config, "dp m2_n2",
+ pipe_config->lane_count,
+ &pipe_config->dp_m2_n2);
}
+ drm_dbg_kms(&dev_priv->drm, "framestart delay: %d, MSA timing delay: %d\n",
+ pipe_config->framestart_delay, pipe_config->msa_timing_delay);
+
drm_dbg_kms(&dev_priv->drm,
"audio: %i, infoframes: %i, infoframes enabled: 0x%x\n",
pipe_config->has_audio, pipe_config->has_infoframe,
@@ -5694,25 +5318,24 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config,
intel_dump_dp_vsc_sdp(dev_priv, &pipe_config->infoframes.vsc);
drm_dbg_kms(&dev_priv->drm, "vrr: %s, vmin: %d, vmax: %d, pipeline full: %d, guardband: %d flipline: %d, vmin vblank: %d, vmax vblank: %d\n",
- yesno(pipe_config->vrr.enable),
+ str_yes_no(pipe_config->vrr.enable),
pipe_config->vrr.vmin, pipe_config->vrr.vmax,
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));
- drm_dbg_kms(&dev_priv->drm, "requested mode:\n");
- drm_mode_debug_printmodeline(&pipe_config->hw.mode);
- drm_dbg_kms(&dev_priv->drm, "adjusted mode:\n");
- drm_mode_debug_printmodeline(&pipe_config->hw.adjusted_mode);
+ drm_dbg_kms(&dev_priv->drm, "requested mode: " DRM_MODE_FMT "\n",
+ DRM_MODE_ARG(&pipe_config->hw.mode));
+ drm_dbg_kms(&dev_priv->drm, "adjusted mode: " DRM_MODE_FMT "\n",
+ DRM_MODE_ARG(&pipe_config->hw.adjusted_mode));
intel_dump_crtc_timings(dev_priv, &pipe_config->hw.adjusted_mode);
- drm_dbg_kms(&dev_priv->drm, "pipe mode:\n");
- drm_mode_debug_printmodeline(&pipe_config->hw.pipe_mode);
+ drm_dbg_kms(&dev_priv->drm, "pipe mode: " DRM_MODE_FMT "\n",
+ DRM_MODE_ARG(&pipe_config->hw.pipe_mode));
intel_dump_crtc_timings(dev_priv, &pipe_config->hw.pipe_mode);
drm_dbg_kms(&dev_priv->drm,
- "port clock: %d, pipe src size: %dx%d, pixel rate %d\n",
- pipe_config->port_clock,
- pipe_config->pipe_src_w, pipe_config->pipe_src_h,
+ "port clock: %d, pipe src: " DRM_RECT_FMT ", pixel rate %d\n",
+ pipe_config->port_clock, DRM_RECT_ARG(&pipe_config->pipe_src),
pipe_config->pixel_rate);
drm_dbg_kms(&dev_priv->drm, "linetime: %d, ips linetime: %d\n",
@@ -5735,11 +5358,12 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config,
drm_dbg_kms(&dev_priv->drm,
"pch pfit: " DRM_RECT_FMT ", %s, force thru: %s\n",
DRM_RECT_ARG(&pipe_config->pch_pfit.dst),
- enableddisabled(pipe_config->pch_pfit.enabled),
- yesno(pipe_config->pch_pfit.force_thru));
+ str_enabled_disabled(pipe_config->pch_pfit.enabled),
+ str_yes_no(pipe_config->pch_pfit.force_thru));
- drm_dbg_kms(&dev_priv->drm, "ips: %i, double wide: %i\n",
- pipe_config->ips_enabled, pipe_config->double_wide);
+ drm_dbg_kms(&dev_priv->drm, "ips: %i, double wide: %i, drrs: %i\n",
+ pipe_config->ips_enabled, pipe_config->double_wide,
+ pipe_config->has_drrs);
intel_dpll_dump_hw_state(dev_priv, &pipe_config->dpll_hw_state);
@@ -5841,35 +5465,44 @@ static bool check_digital_port_conflicts(struct intel_atomic_state *state)
static void
intel_crtc_copy_uapi_to_hw_state_nomodeset(struct intel_atomic_state *state,
- struct intel_crtc_state *crtc_state)
+ struct intel_crtc *crtc)
{
- const struct intel_crtc_state *master_crtc_state;
- struct intel_crtc *master_crtc;
+ struct intel_crtc_state *crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
- master_crtc = intel_master_crtc(crtc_state);
- master_crtc_state = intel_atomic_get_new_crtc_state(state, master_crtc);
+ WARN_ON(intel_crtc_is_bigjoiner_slave(crtc_state));
- /* No need to copy state if the master state is unchanged */
- if (master_crtc_state)
- intel_crtc_copy_color_blobs(crtc_state, master_crtc_state);
+ drm_property_replace_blob(&crtc_state->hw.degamma_lut,
+ crtc_state->uapi.degamma_lut);
+ drm_property_replace_blob(&crtc_state->hw.gamma_lut,
+ crtc_state->uapi.gamma_lut);
+ drm_property_replace_blob(&crtc_state->hw.ctm,
+ crtc_state->uapi.ctm);
}
static void
-intel_crtc_copy_uapi_to_hw_state(struct intel_atomic_state *state,
- struct intel_crtc_state *crtc_state)
+intel_crtc_copy_uapi_to_hw_state_modeset(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
{
+ struct intel_crtc_state *crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
+
+ WARN_ON(intel_crtc_is_bigjoiner_slave(crtc_state));
+
crtc_state->hw.enable = crtc_state->uapi.enable;
crtc_state->hw.active = crtc_state->uapi.active;
- crtc_state->hw.mode = crtc_state->uapi.mode;
- crtc_state->hw.adjusted_mode = crtc_state->uapi.adjusted_mode;
+ drm_mode_copy(&crtc_state->hw.mode,
+ &crtc_state->uapi.mode);
+ drm_mode_copy(&crtc_state->hw.adjusted_mode,
+ &crtc_state->uapi.adjusted_mode);
crtc_state->hw.scaling_filter = crtc_state->uapi.scaling_filter;
- intel_crtc_copy_uapi_to_hw_state_nomodeset(state, crtc_state);
+ intel_crtc_copy_uapi_to_hw_state_nomodeset(state, crtc);
}
static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state)
{
- if (crtc_state->bigjoiner_slave)
+ if (intel_crtc_is_bigjoiner_slave(crtc_state))
return;
crtc_state->uapi.enable = crtc_state->hw.enable;
@@ -5880,7 +5513,6 @@ static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state
crtc_state->uapi.adjusted_mode = crtc_state->hw.adjusted_mode;
crtc_state->uapi.scaling_filter = crtc_state->hw.scaling_filter;
- /* copy color blobs to uapi */
drm_property_replace_blob(&crtc_state->uapi.degamma_lut,
crtc_state->hw.degamma_lut);
drm_property_replace_blob(&crtc_state->uapi.gamma_lut,
@@ -5889,51 +5521,85 @@ static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state
crtc_state->hw.ctm);
}
+static void
+copy_bigjoiner_crtc_state_nomodeset(struct intel_atomic_state *state,
+ struct intel_crtc *slave_crtc)
+{
+ struct intel_crtc_state *slave_crtc_state =
+ intel_atomic_get_new_crtc_state(state, slave_crtc);
+ struct intel_crtc *master_crtc = intel_master_crtc(slave_crtc_state);
+ const struct intel_crtc_state *master_crtc_state =
+ intel_atomic_get_new_crtc_state(state, master_crtc);
+
+ drm_property_replace_blob(&slave_crtc_state->hw.degamma_lut,
+ master_crtc_state->hw.degamma_lut);
+ drm_property_replace_blob(&slave_crtc_state->hw.gamma_lut,
+ master_crtc_state->hw.gamma_lut);
+ drm_property_replace_blob(&slave_crtc_state->hw.ctm,
+ master_crtc_state->hw.ctm);
+
+ slave_crtc_state->uapi.color_mgmt_changed = master_crtc_state->uapi.color_mgmt_changed;
+}
+
static int
-copy_bigjoiner_crtc_state(struct intel_crtc_state *crtc_state,
- const struct intel_crtc_state *from_crtc_state)
+copy_bigjoiner_crtc_state_modeset(struct intel_atomic_state *state,
+ struct intel_crtc *slave_crtc)
{
+ struct intel_crtc_state *slave_crtc_state =
+ intel_atomic_get_new_crtc_state(state, slave_crtc);
+ struct intel_crtc *master_crtc = intel_master_crtc(slave_crtc_state);
+ const struct intel_crtc_state *master_crtc_state =
+ intel_atomic_get_new_crtc_state(state, master_crtc);
struct intel_crtc_state *saved_state;
- saved_state = kmemdup(from_crtc_state, sizeof(*saved_state), GFP_KERNEL);
+ WARN_ON(master_crtc_state->bigjoiner_pipes !=
+ slave_crtc_state->bigjoiner_pipes);
+
+ saved_state = kmemdup(master_crtc_state, sizeof(*saved_state), GFP_KERNEL);
if (!saved_state)
return -ENOMEM;
- saved_state->uapi = crtc_state->uapi;
- saved_state->scaler_state = crtc_state->scaler_state;
- saved_state->shared_dpll = crtc_state->shared_dpll;
- saved_state->dpll_hw_state = crtc_state->dpll_hw_state;
- saved_state->crc_enabled = crtc_state->crc_enabled;
+ /* preserve some things from the slave's original crtc state */
+ saved_state->uapi = slave_crtc_state->uapi;
+ saved_state->scaler_state = slave_crtc_state->scaler_state;
+ saved_state->shared_dpll = slave_crtc_state->shared_dpll;
+ saved_state->dpll_hw_state = slave_crtc_state->dpll_hw_state;
+ saved_state->crc_enabled = slave_crtc_state->crc_enabled;
- intel_crtc_free_hw_state(crtc_state);
- memcpy(crtc_state, saved_state, sizeof(*crtc_state));
+ intel_crtc_free_hw_state(slave_crtc_state);
+ memcpy(slave_crtc_state, saved_state, sizeof(*slave_crtc_state));
kfree(saved_state);
/* Re-init hw state */
- memset(&crtc_state->hw, 0, sizeof(saved_state->hw));
- crtc_state->hw.enable = from_crtc_state->hw.enable;
- crtc_state->hw.active = from_crtc_state->hw.active;
- crtc_state->hw.pipe_mode = from_crtc_state->hw.pipe_mode;
- crtc_state->hw.adjusted_mode = from_crtc_state->hw.adjusted_mode;
-
- /* Some fixups */
- crtc_state->uapi.mode_changed = from_crtc_state->uapi.mode_changed;
- crtc_state->uapi.connectors_changed = from_crtc_state->uapi.connectors_changed;
- crtc_state->uapi.active_changed = from_crtc_state->uapi.active_changed;
- crtc_state->nv12_planes = crtc_state->c8_planes = crtc_state->update_planes = 0;
- crtc_state->bigjoiner_linked_crtc = to_intel_crtc(from_crtc_state->uapi.crtc);
- crtc_state->bigjoiner_slave = true;
- crtc_state->cpu_transcoder = from_crtc_state->cpu_transcoder;
- crtc_state->has_audio = from_crtc_state->has_audio;
+ memset(&slave_crtc_state->hw, 0, sizeof(slave_crtc_state->hw));
+ slave_crtc_state->hw.enable = master_crtc_state->hw.enable;
+ slave_crtc_state->hw.active = master_crtc_state->hw.active;
+ drm_mode_copy(&slave_crtc_state->hw.mode,
+ &master_crtc_state->hw.mode);
+ drm_mode_copy(&slave_crtc_state->hw.pipe_mode,
+ &master_crtc_state->hw.pipe_mode);
+ drm_mode_copy(&slave_crtc_state->hw.adjusted_mode,
+ &master_crtc_state->hw.adjusted_mode);
+ slave_crtc_state->hw.scaling_filter = master_crtc_state->hw.scaling_filter;
+
+ copy_bigjoiner_crtc_state_nomodeset(state, slave_crtc);
+
+ slave_crtc_state->uapi.mode_changed = master_crtc_state->uapi.mode_changed;
+ slave_crtc_state->uapi.connectors_changed = master_crtc_state->uapi.connectors_changed;
+ slave_crtc_state->uapi.active_changed = master_crtc_state->uapi.active_changed;
+
+ WARN_ON(master_crtc_state->bigjoiner_pipes !=
+ slave_crtc_state->bigjoiner_pipes);
return 0;
}
static int
intel_crtc_prepare_cleared_state(struct intel_atomic_state *state,
- struct intel_crtc_state *crtc_state)
+ struct intel_crtc *crtc)
{
- struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ struct intel_crtc_state *crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
struct intel_crtc_state *saved_state;
@@ -5963,7 +5629,7 @@ intel_crtc_prepare_cleared_state(struct intel_atomic_state *state,
memcpy(crtc_state, saved_state, sizeof(*crtc_state));
kfree(saved_state);
- intel_crtc_copy_uapi_to_hw_state(state, crtc_state);
+ intel_crtc_copy_uapi_to_hw_state_modeset(state, crtc);
return 0;
}
@@ -5976,12 +5642,15 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
struct drm_i915_private *i915 = to_i915(pipe_config->uapi.crtc->dev);
struct drm_connector *connector;
struct drm_connector_state *connector_state;
+ int pipe_src_w, pipe_src_h;
int base_bpp, ret, i;
bool retry = true;
pipe_config->cpu_transcoder =
(enum transcoder) to_intel_crtc(crtc)->pipe;
+ pipe_config->framestart_delay = 1;
+
/*
* Sanitize sync polarity flags based on requested ones. If neither
* positive or negative polarity is requested, treat this as meaning
@@ -6011,8 +5680,9 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
* can be changed by the connectors in the below retry loop.
*/
drm_mode_get_hv_timing(&pipe_config->hw.mode,
- &pipe_config->pipe_src_w,
- &pipe_config->pipe_src_h);
+ &pipe_src_w, &pipe_src_h);
+ drm_rect_init(&pipe_config->pipe_src, 0, 0,
+ pipe_src_w, pipe_src_h);
for_each_new_connector_in_state(&state->base, connector, connector_state, i) {
struct intel_encoder *encoder =
@@ -6115,6 +5785,8 @@ intel_modeset_pipe_config_late(struct intel_crtc_state *crtc_state)
struct drm_connector *connector;
int i;
+ intel_bigjoiner_adjust_pipe_src(crtc_state);
+
for_each_new_connector_in_state(&state->base, connector,
conn_state, i) {
struct intel_encoder *encoder =
@@ -6189,8 +5861,8 @@ intel_compare_link_m_n(const struct intel_link_m_n *m_n,
bool exact)
{
return m_n->tu == m2_n2->tu &&
- intel_compare_m_n(m_n->gmch_m, m_n->gmch_n,
- m2_n2->gmch_m, m2_n2->gmch_n, exact) &&
+ intel_compare_m_n(m_n->data_m, m_n->data_n,
+ m2_n2->data_m, m2_n2->data_n, exact) &&
intel_compare_m_n(m_n->link_m, m_n->link_n,
m2_n2->link_m, m2_n2->link_n, exact);
}
@@ -6351,8 +6023,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
if (current_config->name != pipe_config->name) { \
pipe_config_mismatch(fastset, crtc, __stringify(name), \
"(expected %s, found %s)", \
- yesno(current_config->name), \
- yesno(pipe_config->name)); \
+ str_yes_no(current_config->name), \
+ str_yes_no(pipe_config->name)); \
ret = false; \
} \
} while (0)
@@ -6368,8 +6040,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
} else { \
pipe_config_mismatch(fastset, crtc, __stringify(name), \
"unable to verify whether state matches exactly, forcing modeset (expected %s, found %s)", \
- yesno(current_config->name), \
- yesno(pipe_config->name)); \
+ str_yes_no(current_config->name), \
+ str_yes_no(pipe_config->name)); \
ret = false; \
} \
} while (0)
@@ -6389,16 +6061,16 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
&pipe_config->name,\
!fastset)) { \
pipe_config_mismatch(fastset, crtc, __stringify(name), \
- "(expected tu %i gmch %i/%i link %i/%i, " \
- "found tu %i, gmch %i/%i link %i/%i)", \
+ "(expected tu %i data %i/%i link %i/%i, " \
+ "found tu %i, data %i/%i link %i/%i)", \
current_config->name.tu, \
- current_config->name.gmch_m, \
- current_config->name.gmch_n, \
+ current_config->name.data_m, \
+ current_config->name.data_n, \
current_config->name.link_m, \
current_config->name.link_n, \
pipe_config->name.tu, \
- pipe_config->name.gmch_m, \
- pipe_config->name.gmch_n, \
+ pipe_config->name.data_m, \
+ pipe_config->name.data_n, \
pipe_config->name.link_m, \
pipe_config->name.link_n); \
ret = false; \
@@ -6416,22 +6088,22 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
!intel_compare_link_m_n(&current_config->alt_name, \
&pipe_config->name, !fastset)) { \
pipe_config_mismatch(fastset, crtc, __stringify(name), \
- "(expected tu %i gmch %i/%i link %i/%i, " \
- "or tu %i gmch %i/%i link %i/%i, " \
- "found tu %i, gmch %i/%i link %i/%i)", \
+ "(expected tu %i data %i/%i link %i/%i, " \
+ "or tu %i data %i/%i link %i/%i, " \
+ "found tu %i, data %i/%i link %i/%i)", \
current_config->name.tu, \
- current_config->name.gmch_m, \
- current_config->name.gmch_n, \
+ current_config->name.data_m, \
+ current_config->name.data_n, \
current_config->name.link_m, \
current_config->name.link_n, \
current_config->alt_name.tu, \
- current_config->alt_name.gmch_m, \
- current_config->alt_name.gmch_n, \
+ current_config->alt_name.data_m, \
+ current_config->alt_name.data_n, \
current_config->alt_name.link_m, \
current_config->alt_name.link_n, \
pipe_config->name.tu, \
- pipe_config->name.gmch_m, \
- pipe_config->name.gmch_n, \
+ pipe_config->name.data_m, \
+ pipe_config->name.data_n, \
pipe_config->name.link_m, \
pipe_config->name.link_n); \
ret = false; \
@@ -6510,16 +6182,18 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
PIPE_CONF_CHECK_I(lane_count);
PIPE_CONF_CHECK_X(lane_lat_optim_mask);
- if (DISPLAY_VER(dev_priv) < 8) {
- PIPE_CONF_CHECK_M_N(dp_m_n);
-
- if (current_config->has_drrs)
- PIPE_CONF_CHECK_M_N(dp_m2_n2);
- } else
+ if (DISPLAY_VER(dev_priv) >= 9 || IS_BROADWELL(dev_priv)) {
PIPE_CONF_CHECK_M_N_ALT(dp_m_n, dp_m2_n2);
+ } else {
+ PIPE_CONF_CHECK_M_N(dp_m_n);
+ PIPE_CONF_CHECK_M_N(dp_m2_n2);
+ }
PIPE_CONF_CHECK_X(output_types);
+ PIPE_CONF_CHECK_I(framestart_delay);
+ PIPE_CONF_CHECK_I(msa_timing_delay);
+
PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hdisplay);
PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_htotal);
PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hblank_start);
@@ -6590,8 +6264,10 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
PIPE_CONF_CHECK_BOOL(pch_pfit.force_thru);
if (!fastset) {
- PIPE_CONF_CHECK_I(pipe_src_w);
- PIPE_CONF_CHECK_I(pipe_src_h);
+ PIPE_CONF_CHECK_I(pipe_src.x1);
+ PIPE_CONF_CHECK_I(pipe_src.y1);
+ PIPE_CONF_CHECK_I(pipe_src.x2);
+ PIPE_CONF_CHECK_I(pipe_src.y2);
PIPE_CONF_CHECK_BOOL(pch_pfit.enabled);
if (current_config->pch_pfit.enabled) {
@@ -6642,6 +6318,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr1);
PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr2);
PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr0);
+ PIPE_CONF_CHECK_X(dpll_hw_state.div0);
PIPE_CONF_CHECK_X(dpll_hw_state.ebb0);
PIPE_CONF_CHECK_X(dpll_hw_state.ebb4);
PIPE_CONF_CHECK_X(dpll_hw_state.pll0);
@@ -6692,9 +6369,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
PIPE_CONF_CHECK_X(sync_mode_slaves_mask);
PIPE_CONF_CHECK_I(master_transcoder);
- PIPE_CONF_CHECK_BOOL(bigjoiner);
- PIPE_CONF_CHECK_BOOL(bigjoiner_slave);
- PIPE_CONF_CHECK_P(bigjoiner_linked_crtc);
+ PIPE_CONF_CHECK_X(bigjoiner_pipes);
PIPE_CONF_CHECK_I(dsc.compression_enable);
PIPE_CONF_CHECK_I(dsc.dsc_split);
@@ -6750,8 +6425,8 @@ static void verify_wm_state(struct intel_crtc *crtc,
{
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
struct skl_hw_state {
+ struct skl_ddb_entry ddb[I915_MAX_PLANES];
struct skl_ddb_entry ddb_y[I915_MAX_PLANES];
- struct skl_ddb_entry ddb_uv[I915_MAX_PLANES];
struct skl_pipe_wm wm;
} *hw;
const struct skl_pipe_wm *sw_wm = &new_crtc_state->wm.skl.optimal;
@@ -6768,7 +6443,7 @@ static void verify_wm_state(struct intel_crtc *crtc,
skl_pipe_wm_get_hw_state(crtc, &hw->wm);
- skl_pipe_ddb_get_hw_state(crtc, hw->ddb_y, hw->ddb_uv);
+ skl_pipe_ddb_get_hw_state(crtc, hw->ddb, hw->ddb_y);
hw_enabled_slices = intel_enabled_dbuf_slices_mask(dev_priv);
@@ -6850,8 +6525,8 @@ static void verify_wm_state(struct intel_crtc *crtc,
}
/* DDB */
- hw_ddb_entry = &hw->ddb_y[plane->id];
- sw_ddb_entry = &new_crtc_state->wm.skl.plane_ddb_y[plane->id];
+ hw_ddb_entry = &hw->ddb[PLANE_CURSOR];
+ sw_ddb_entry = &new_crtc_state->wm.skl.plane_ddb[PLANE_CURSOR];
if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) {
drm_err(&dev_priv->drm,
@@ -7227,8 +6902,9 @@ intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- struct drm_display_mode adjusted_mode =
- crtc_state->hw.adjusted_mode;
+ struct drm_display_mode adjusted_mode;
+
+ drm_mode_init(&adjusted_mode, &crtc_state->hw.adjusted_mode);
if (crtc_state->vrr.enable) {
adjusted_mode.crtc_vtotal = crtc_state->vrr.vmax;
@@ -7286,14 +6962,10 @@ intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state)
static void intel_modeset_clear_plls(struct intel_atomic_state *state)
{
- struct drm_i915_private *dev_priv = to_i915(state->base.dev);
struct intel_crtc_state *new_crtc_state;
struct intel_crtc *crtc;
int i;
- if (!dev_priv->dpll_funcs)
- return;
-
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
if (!intel_crtc_needs_modeset(new_crtc_state))
continue;
@@ -7480,20 +7152,25 @@ static int intel_crtc_add_bigjoiner_planes(struct intel_atomic_state *state,
static int intel_bigjoiner_add_affected_planes(struct intel_atomic_state *state)
{
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
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;
+ struct intel_crtc *other;
- if (!crtc_state->bigjoiner)
- continue;
+ for_each_intel_crtc_in_pipe_mask(&i915->drm, other,
+ crtc_state->bigjoiner_pipes) {
+ int ret;
- ret = intel_crtc_add_bigjoiner_planes(state, crtc,
- crtc_state->bigjoiner_linked_crtc);
- if (ret)
- return ret;
+ if (crtc == other)
+ continue;
+
+ ret = intel_crtc_add_bigjoiner_planes(state, crtc, other);
+ if (ret)
+ return ret;
+ }
}
return 0;
@@ -7595,67 +7272,113 @@ static bool intel_cpu_transcoders_need_modeset(struct intel_atomic_state *state,
return false;
}
-static int intel_atomic_check_bigjoiner(struct intel_atomic_state *state,
- struct intel_crtc *crtc,
- struct intel_crtc_state *old_crtc_state,
- struct intel_crtc_state *new_crtc_state)
+static bool intel_pipes_need_modeset(struct intel_atomic_state *state,
+ u8 pipes)
{
- struct intel_crtc_state *slave_crtc_state, *master_crtc_state;
- struct intel_crtc *slave_crtc, *master_crtc;
+ const struct intel_crtc_state *new_crtc_state;
+ struct intel_crtc *crtc;
+ int i;
- /* slave being enabled, is master is still claiming this crtc? */
- if (old_crtc_state->bigjoiner_slave) {
- slave_crtc = crtc;
- master_crtc = old_crtc_state->bigjoiner_linked_crtc;
- master_crtc_state = intel_atomic_get_new_crtc_state(state, master_crtc);
- if (!master_crtc_state || !intel_crtc_needs_modeset(master_crtc_state))
- goto claimed;
+ for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
+ if (new_crtc_state->hw.enable &&
+ pipes & BIT(crtc->pipe) &&
+ intel_crtc_needs_modeset(new_crtc_state))
+ return true;
}
- if (!new_crtc_state->bigjoiner)
+ return false;
+}
+
+static int intel_atomic_check_bigjoiner(struct intel_atomic_state *state,
+ struct intel_crtc *master_crtc)
+{
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ struct intel_crtc_state *master_crtc_state =
+ intel_atomic_get_new_crtc_state(state, master_crtc);
+ struct intel_crtc *slave_crtc;
+
+ if (!master_crtc_state->bigjoiner_pipes)
return 0;
- slave_crtc = intel_dsc_get_bigjoiner_secondary(crtc);
- if (!slave_crtc) {
- DRM_DEBUG_KMS("[CRTC:%d:%s] Big joiner configuration requires "
- "CRTC + 1 to be used, doesn't exist\n",
- crtc->base.base.id, crtc->base.name);
+ /* sanity check */
+ if (drm_WARN_ON(&i915->drm,
+ master_crtc->pipe != bigjoiner_master_pipe(master_crtc_state)))
+ return -EINVAL;
+
+ if (master_crtc_state->bigjoiner_pipes & ~bigjoiner_pipes(i915)) {
+ drm_dbg_kms(&i915->drm,
+ "[CRTC:%d:%s] Cannot act as big joiner master "
+ "(need 0x%x as pipes, only 0x%x possible)\n",
+ master_crtc->base.base.id, master_crtc->base.name,
+ master_crtc_state->bigjoiner_pipes, bigjoiner_pipes(i915));
return -EINVAL;
}
- new_crtc_state->bigjoiner_linked_crtc = slave_crtc;
- slave_crtc_state = intel_atomic_get_crtc_state(&state->base, slave_crtc);
- master_crtc = crtc;
- if (IS_ERR(slave_crtc_state))
- return PTR_ERR(slave_crtc_state);
+ for_each_intel_crtc_in_pipe_mask(&i915->drm, slave_crtc,
+ intel_crtc_bigjoiner_slave_pipes(master_crtc_state)) {
+ struct intel_crtc_state *slave_crtc_state;
+ int ret;
+
+ slave_crtc_state = intel_atomic_get_crtc_state(&state->base, slave_crtc);
+ if (IS_ERR(slave_crtc_state))
+ return PTR_ERR(slave_crtc_state);
+
+ /* master being enabled, slave was already configured? */
+ if (slave_crtc_state->uapi.enable) {
+ drm_dbg_kms(&i915->drm,
+ "[CRTC:%d:%s] Slave is enabled as normal CRTC, but "
+ "[CRTC:%d:%s] claiming this CRTC for bigjoiner.\n",
+ slave_crtc->base.base.id, slave_crtc->base.name,
+ master_crtc->base.base.id, master_crtc->base.name);
+ return -EINVAL;
+ }
- /* master being enabled, slave was already configured? */
- if (slave_crtc_state->uapi.enable)
- goto claimed;
+ /*
+ * The state copy logic assumes the master crtc gets processed
+ * before the slave crtc during the main compute_config loop.
+ * This works because the crtcs are created in pipe order,
+ * and the hardware requires master pipe < slave pipe as well.
+ * Should that change we need to rethink the logic.
+ */
+ if (WARN_ON(drm_crtc_index(&master_crtc->base) >
+ drm_crtc_index(&slave_crtc->base)))
+ return -EINVAL;
- DRM_DEBUG_KMS("[CRTC:%d:%s] Used as slave for big joiner\n",
- slave_crtc->base.base.id, slave_crtc->base.name);
+ drm_dbg_kms(&i915->drm,
+ "[CRTC:%d:%s] Used as slave for big joiner master [CRTC:%d:%s]\n",
+ slave_crtc->base.base.id, slave_crtc->base.name,
+ master_crtc->base.base.id, master_crtc->base.name);
- return copy_bigjoiner_crtc_state(slave_crtc_state, new_crtc_state);
+ slave_crtc_state->bigjoiner_pipes =
+ master_crtc_state->bigjoiner_pipes;
-claimed:
- DRM_DEBUG_KMS("[CRTC:%d:%s] Slave is enabled as normal CRTC, but "
- "[CRTC:%d:%s] claiming this CRTC for bigjoiner.\n",
- slave_crtc->base.base.id, slave_crtc->base.name,
- master_crtc->base.base.id, master_crtc->base.name);
- return -EINVAL;
+ ret = copy_bigjoiner_crtc_state_modeset(state, slave_crtc);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
}
static void kill_bigjoiner_slave(struct intel_atomic_state *state,
- struct intel_crtc_state *master_crtc_state)
+ struct intel_crtc *master_crtc)
{
- struct intel_crtc_state *slave_crtc_state =
- intel_atomic_get_new_crtc_state(state, master_crtc_state->bigjoiner_linked_crtc);
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ struct intel_crtc_state *master_crtc_state =
+ intel_atomic_get_new_crtc_state(state, master_crtc);
+ struct intel_crtc *slave_crtc;
- slave_crtc_state->bigjoiner = master_crtc_state->bigjoiner = false;
- slave_crtc_state->bigjoiner_slave = master_crtc_state->bigjoiner_slave = false;
- slave_crtc_state->bigjoiner_linked_crtc = master_crtc_state->bigjoiner_linked_crtc = NULL;
- intel_crtc_copy_uapi_to_hw_state(state, slave_crtc_state);
+ for_each_intel_crtc_in_pipe_mask(&i915->drm, slave_crtc,
+ intel_crtc_bigjoiner_slave_pipes(master_crtc_state)) {
+ struct intel_crtc_state *slave_crtc_state =
+ intel_atomic_get_new_crtc_state(state, slave_crtc);
+
+ slave_crtc_state->bigjoiner_pipes = 0;
+
+ intel_crtc_copy_uapi_to_hw_state_modeset(state, slave_crtc);
+ }
+
+ master_crtc_state->bigjoiner_pipes = 0;
}
/**
@@ -7666,7 +7389,7 @@ static void kill_bigjoiner_slave(struct intel_atomic_state *state,
* Correspondingly, support is currently added for primary plane only.
*
* Async flip can only change the plane surface address, so anything else
- * changing is rejected from the intel_atomic_check_async() function.
+ * changing is rejected from the intel_async_flip_check_hw() function.
* Once this check is cleared, flip done interrupt is enabled using
* the intel_crtc_enable_flip_done() function.
*
@@ -7676,7 +7399,65 @@ static void kill_bigjoiner_slave(struct intel_atomic_state *state,
* correspond to the last vblank and have no relation to the actual time when
* the flip done event was sent.
*/
-static int intel_atomic_check_async(struct intel_atomic_state *state, struct intel_crtc *crtc)
+static int intel_async_flip_check_uapi(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
+{
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ const struct intel_crtc_state *new_crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
+ const struct intel_plane_state *old_plane_state;
+ struct intel_plane_state *new_plane_state;
+ struct intel_plane *plane;
+ int i;
+
+ if (!new_crtc_state->uapi.async_flip)
+ return 0;
+
+ if (!new_crtc_state->uapi.active) {
+ drm_dbg_kms(&i915->drm,
+ "[CRTC:%d:%s] not active\n",
+ crtc->base.base.id, crtc->base.name);
+ return -EINVAL;
+ }
+
+ if (intel_crtc_needs_modeset(new_crtc_state)) {
+ drm_dbg_kms(&i915->drm,
+ "[CRTC:%d:%s] modeset required\n",
+ crtc->base.base.id, crtc->base.name);
+ return -EINVAL;
+ }
+
+ for_each_oldnew_intel_plane_in_state(state, plane, old_plane_state,
+ new_plane_state, i) {
+ if (plane->pipe != crtc->pipe)
+ continue;
+
+ /*
+ * TODO: Async flip is only supported through the page flip IOCTL
+ * as of now. So support currently added for primary plane only.
+ * Support for other planes on platforms on which supports
+ * this(vlv/chv and icl+) should be added when async flip is
+ * enabled in the atomic IOCTL path.
+ */
+ if (!plane->async_flip) {
+ drm_dbg_kms(&i915->drm,
+ "[PLANE:%d:%s] async flip not supported\n",
+ plane->base.base.id, plane->base.name);
+ return -EINVAL;
+ }
+
+ if (!old_plane_state->uapi.fb || !new_plane_state->uapi.fb) {
+ drm_dbg_kms(&i915->drm,
+ "[PLANE:%d:%s] no old or new framebuffer\n",
+ plane->base.base.id, plane->base.name);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static int intel_async_flip_check_hw(struct intel_atomic_state *state, struct intel_crtc *crtc)
{
struct drm_i915_private *i915 = to_i915(state->base.dev);
const struct intel_crtc_state *old_crtc_state, *new_crtc_state;
@@ -7687,18 +7468,27 @@ static int intel_atomic_check_async(struct intel_atomic_state *state, struct int
old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc);
new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
- if (intel_crtc_needs_modeset(new_crtc_state)) {
- drm_dbg_kms(&i915->drm, "Modeset Required. Async flip not supported\n");
+ if (!new_crtc_state->uapi.async_flip)
+ return 0;
+
+ if (!new_crtc_state->hw.active) {
+ drm_dbg_kms(&i915->drm,
+ "[CRTC:%d:%s] not active\n",
+ crtc->base.base.id, crtc->base.name);
return -EINVAL;
}
- if (!new_crtc_state->hw.active) {
- drm_dbg_kms(&i915->drm, "CRTC inactive\n");
+ if (intel_crtc_needs_modeset(new_crtc_state)) {
+ drm_dbg_kms(&i915->drm,
+ "[CRTC:%d:%s] modeset required\n",
+ crtc->base.base.id, crtc->base.name);
return -EINVAL;
}
+
if (old_crtc_state->active_planes != new_crtc_state->active_planes) {
drm_dbg_kms(&i915->drm,
- "Active planes cannot be changed during async flip\n");
+ "[CRTC:%d:%s] Active planes cannot be in async flip\n",
+ crtc->base.base.id, crtc->base.name);
return -EINVAL;
}
@@ -7708,16 +7498,26 @@ static int intel_atomic_check_async(struct intel_atomic_state *state, struct int
continue;
/*
- * TODO: Async flip is only supported through the page flip IOCTL
- * as of now. So support currently added for primary plane only.
- * Support for other planes on platforms on which supports
- * this(vlv/chv and icl+) should be added when async flip is
- * enabled in the atomic IOCTL path.
+ * Only async flip capable planes should be in the state
+ * if we're really about to ask the hardware to perform
+ * an async flip. We should never get this far otherwise.
*/
- if (!plane->async_flip)
+ if (drm_WARN_ON(&i915->drm,
+ new_crtc_state->do_async_flip && !plane->async_flip))
return -EINVAL;
/*
+ * Only check async flip capable planes other planes
+ * may be involved in the initial commit due to
+ * the wm0/ddb optimization.
+ *
+ * TODO maybe should track which planes actually
+ * were requested to do the async flip...
+ */
+ if (!plane->async_flip)
+ continue;
+
+ /*
* FIXME: This check is kept generic for all platforms.
* Need to verify this for all gen9 platforms to enable
* this selectively if required.
@@ -7726,78 +7526,98 @@ static int intel_atomic_check_async(struct intel_atomic_state *state, struct int
case I915_FORMAT_MOD_X_TILED:
case I915_FORMAT_MOD_Y_TILED:
case I915_FORMAT_MOD_Yf_TILED:
+ case I915_FORMAT_MOD_4_TILED:
break;
default:
drm_dbg_kms(&i915->drm,
- "Linear memory/CCS does not support async flips\n");
+ "[PLANE:%d:%s] Modifier does not support async flips\n",
+ plane->base.base.id, plane->base.name);
return -EINVAL;
}
if (new_plane_state->hw.fb->format->num_planes > 1) {
drm_dbg_kms(&i915->drm,
- "Planar formats not supported with async flips\n");
+ "[PLANE:%d:%s] Planar formats do not support async flips\n",
+ plane->base.base.id, plane->base.name);
return -EINVAL;
}
if (old_plane_state->view.color_plane[0].mapping_stride !=
new_plane_state->view.color_plane[0].mapping_stride) {
- drm_dbg_kms(&i915->drm, "Stride cannot be changed in async flip\n");
+ drm_dbg_kms(&i915->drm,
+ "[PLANE:%d:%s] Stride cannot be changed in async flip\n",
+ plane->base.base.id, plane->base.name);
return -EINVAL;
}
if (old_plane_state->hw.fb->modifier !=
new_plane_state->hw.fb->modifier) {
drm_dbg_kms(&i915->drm,
- "Framebuffer modifiers cannot be changed in async flip\n");
+ "[PLANE:%d:%s] Modifier cannot be changed in async flip\n",
+ plane->base.base.id, plane->base.name);
return -EINVAL;
}
if (old_plane_state->hw.fb->format !=
new_plane_state->hw.fb->format) {
drm_dbg_kms(&i915->drm,
- "Framebuffer format cannot be changed in async flip\n");
+ "[PLANE:%d:%s] Pixel format cannot be changed in async flip\n",
+ plane->base.base.id, plane->base.name);
return -EINVAL;
}
if (old_plane_state->hw.rotation !=
new_plane_state->hw.rotation) {
- drm_dbg_kms(&i915->drm, "Rotation cannot be changed in async flip\n");
+ drm_dbg_kms(&i915->drm,
+ "[PLANE:%d:%s] Rotation cannot be changed in async flip\n",
+ plane->base.base.id, plane->base.name);
return -EINVAL;
}
if (!drm_rect_equals(&old_plane_state->uapi.src, &new_plane_state->uapi.src) ||
!drm_rect_equals(&old_plane_state->uapi.dst, &new_plane_state->uapi.dst)) {
drm_dbg_kms(&i915->drm,
- "Plane size/co-ordinates cannot be changed in async flip\n");
+ "[PLANE:%d:%s] Size/co-ordinates cannot be changed in async flip\n",
+ plane->base.base.id, plane->base.name);
return -EINVAL;
}
if (old_plane_state->hw.alpha != new_plane_state->hw.alpha) {
- drm_dbg_kms(&i915->drm, "Alpha value cannot be changed in async flip\n");
+ drm_dbg_kms(&i915->drm,
+ "[PLANES:%d:%s] Alpha value cannot be changed in async flip\n",
+ plane->base.base.id, plane->base.name);
return -EINVAL;
}
if (old_plane_state->hw.pixel_blend_mode !=
new_plane_state->hw.pixel_blend_mode) {
drm_dbg_kms(&i915->drm,
- "Pixel blend mode cannot be changed in async flip\n");
+ "[PLANE:%d:%s] Pixel blend mode cannot be changed in async flip\n",
+ plane->base.base.id, plane->base.name);
return -EINVAL;
}
if (old_plane_state->hw.color_encoding != new_plane_state->hw.color_encoding) {
drm_dbg_kms(&i915->drm,
- "Color encoding cannot be changed in async flip\n");
+ "[PLANE:%d:%s] Color encoding cannot be changed in async flip\n",
+ plane->base.base.id, plane->base.name);
return -EINVAL;
}
if (old_plane_state->hw.color_range != new_plane_state->hw.color_range) {
- drm_dbg_kms(&i915->drm, "Color range cannot be changed in async flip\n");
+ drm_dbg_kms(&i915->drm,
+ "[PLANE:%d:%s] Color range cannot be changed in async flip\n",
+ plane->base.base.id, plane->base.name);
return -EINVAL;
}
/* plane decryption is allow to change only in synchronous flips */
- if (old_plane_state->decrypt != new_plane_state->decrypt)
+ if (old_plane_state->decrypt != new_plane_state->decrypt) {
+ drm_dbg_kms(&i915->drm,
+ "[PLANE:%d:%s] Decryption cannot be changed in async flip\n",
+ plane->base.base.id, plane->base.name);
return -EINVAL;
+ }
}
return 0;
@@ -7805,34 +7625,37 @@ static int intel_atomic_check_async(struct intel_atomic_state *state, struct int
static int intel_bigjoiner_add_affected_crtcs(struct intel_atomic_state *state)
{
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
struct intel_crtc_state *crtc_state;
struct intel_crtc *crtc;
+ u8 affected_pipes = 0;
+ u8 modeset_pipes = 0;
int i;
for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
- struct intel_crtc_state *linked_crtc_state;
- struct intel_crtc *linked_crtc;
- int ret;
+ affected_pipes |= crtc_state->bigjoiner_pipes;
+ if (intel_crtc_needs_modeset(crtc_state))
+ modeset_pipes |= crtc_state->bigjoiner_pipes;
+ }
- if (!crtc_state->bigjoiner)
- continue;
+ for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, affected_pipes) {
+ crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
+ if (IS_ERR(crtc_state))
+ return PTR_ERR(crtc_state);
+ }
- linked_crtc = crtc_state->bigjoiner_linked_crtc;
- linked_crtc_state = intel_atomic_get_crtc_state(&state->base, linked_crtc);
- if (IS_ERR(linked_crtc_state))
- return PTR_ERR(linked_crtc_state);
+ for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, modeset_pipes) {
+ int ret;
- if (!intel_crtc_needs_modeset(crtc_state))
- continue;
+ crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
- linked_crtc_state->uapi.mode_changed = true;
+ crtc_state->uapi.mode_changed = true;
- ret = drm_atomic_add_affected_connectors(&state->base,
- &linked_crtc->base);
+ ret = drm_atomic_add_affected_connectors(&state->base, &crtc->base);
if (ret)
return ret;
- ret = intel_atomic_add_affected_planes(state, linked_crtc);
+ ret = intel_atomic_add_affected_planes(state, crtc);
if (ret)
return ret;
}
@@ -7840,8 +7663,8 @@ static int intel_bigjoiner_add_affected_crtcs(struct intel_atomic_state *state)
for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
/* Kill old bigjoiner link, we may re-establish afterwards */
if (intel_crtc_needs_modeset(crtc_state) &&
- crtc_state->bigjoiner && !crtc_state->bigjoiner_slave)
- kill_bigjoiner_slave(state, crtc_state);
+ intel_crtc_is_bigjoiner_master(crtc_state))
+ kill_bigjoiner_slave(state, crtc);
}
return 0;
@@ -7866,6 +7689,10 @@ static int intel_atomic_check(struct drm_device *dev,
new_crtc_state, i) {
if (new_crtc_state->inherited != old_crtc_state->inherited)
new_crtc_state->uapi.mode_changed = true;
+
+ if (new_crtc_state->uapi.scaling_filter !=
+ old_crtc_state->uapi.scaling_filter)
+ new_crtc_state->uapi.mode_changed = true;
}
intel_vrr_check_modeset(state);
@@ -7874,6 +7701,12 @@ static int intel_atomic_check(struct drm_device *dev,
if (ret)
goto fail;
+ for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
+ ret = intel_async_flip_check_uapi(state, crtc);
+ if (ret)
+ return ret;
+ }
+
ret = intel_bigjoiner_add_affected_crtcs(state);
if (ret)
goto fail;
@@ -7881,30 +7714,30 @@ static int intel_atomic_check(struct drm_device *dev,
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
if (!intel_crtc_needs_modeset(new_crtc_state)) {
- /* Light copy */
- intel_crtc_copy_uapi_to_hw_state_nomodeset(state, new_crtc_state);
-
+ if (intel_crtc_is_bigjoiner_slave(new_crtc_state))
+ copy_bigjoiner_crtc_state_nomodeset(state, crtc);
+ else
+ intel_crtc_copy_uapi_to_hw_state_nomodeset(state, crtc);
continue;
}
- if (!new_crtc_state->uapi.enable) {
- if (!new_crtc_state->bigjoiner_slave) {
- intel_crtc_copy_uapi_to_hw_state(state, new_crtc_state);
- any_ms = true;
- }
+ if (intel_crtc_is_bigjoiner_slave(new_crtc_state)) {
+ drm_WARN_ON(&dev_priv->drm, new_crtc_state->uapi.enable);
continue;
}
- ret = intel_crtc_prepare_cleared_state(state, new_crtc_state);
+ ret = intel_crtc_prepare_cleared_state(state, crtc);
if (ret)
goto fail;
+ if (!new_crtc_state->hw.enable)
+ continue;
+
ret = intel_modeset_pipe_config(state, new_crtc_state);
if (ret)
goto fail;
- ret = intel_atomic_check_bigjoiner(state, crtc, old_crtc_state,
- new_crtc_state);
+ ret = intel_atomic_check_bigjoiner(state, crtc);
if (ret)
goto fail;
}
@@ -7957,11 +7790,8 @@ static int intel_atomic_check(struct drm_device *dev,
}
}
- if (new_crtc_state->bigjoiner) {
- struct intel_crtc_state *linked_crtc_state =
- intel_atomic_get_new_crtc_state(state, new_crtc_state->bigjoiner_linked_crtc);
-
- if (intel_crtc_needs_modeset(linked_crtc_state)) {
+ if (new_crtc_state->bigjoiner_pipes) {
+ if (intel_pipes_need_modeset(state, new_crtc_state->bigjoiner_pipes)) {
new_crtc_state->uapi.mode_changed = true;
new_crtc_state->update_pipe = false;
}
@@ -8033,11 +7863,9 @@ static int intel_atomic_check(struct drm_device *dev,
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
- if (new_crtc_state->uapi.async_flip) {
- ret = intel_atomic_check_async(state, crtc);
- if (ret)
- goto fail;
- }
+ ret = intel_async_flip_check_hw(state, crtc);
+ if (ret)
+ goto fail;
if (!intel_crtc_needs_modeset(new_crtc_state) &&
!new_crtc_state->update_pipe)
@@ -8141,9 +7969,6 @@ static void intel_pipe_fastset(const struct intel_crtc_state *old_crtc_state,
if (DISPLAY_VER(dev_priv) >= 9 ||
IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
hsw_set_linetime_wm(new_crtc_state);
-
- if (DISPLAY_VER(dev_priv) >= 11)
- icl_set_pipe_chicken(new_crtc_state);
}
static void commit_pipe_pre_planes(struct intel_atomic_state *state,
@@ -8163,7 +7988,7 @@ static void commit_pipe_pre_planes(struct intel_atomic_state *state,
if (!modeset) {
if (new_crtc_state->uapi.color_mgmt_changed ||
new_crtc_state->update_pipe)
- intel_color_commit(new_crtc_state);
+ intel_color_commit_arm(new_crtc_state);
if (DISPLAY_VER(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
bdw_set_pipemisc(new_crtc_state);
@@ -8208,7 +8033,7 @@ static void intel_enable_crtc(struct intel_atomic_state *state,
dev_priv->display->crtc_enable(state, crtc);
- if (new_crtc_state->bigjoiner_slave)
+ if (intel_crtc_is_bigjoiner_slave(new_crtc_state))
return;
/* vblanks work again, re-enable pipe CRC. */
@@ -8218,7 +8043,7 @@ static void intel_enable_crtc(struct intel_atomic_state *state,
static void intel_update_crtc(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
- struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
const struct intel_crtc_state *old_crtc_state =
intel_atomic_get_old_crtc_state(state, crtc);
struct intel_crtc_state *new_crtc_state =
@@ -8235,21 +8060,27 @@ static void intel_update_crtc(struct intel_atomic_state *state,
if (new_crtc_state->update_pipe)
intel_encoders_update_pipe(state, crtc);
+
+ if (DISPLAY_VER(i915) >= 11 &&
+ new_crtc_state->update_pipe)
+ icl_set_pipe_chicken(new_crtc_state);
}
intel_fbc_update(state, crtc);
- intel_update_planes_on_crtc(state, crtc);
+ if (!modeset &&
+ (new_crtc_state->uapi.color_mgmt_changed ||
+ new_crtc_state->update_pipe))
+ intel_color_commit_noarm(new_crtc_state);
+
+ intel_crtc_planes_update_noarm(state, crtc);
/* Perform vblank evasion around commit operation */
intel_pipe_update_start(new_crtc_state);
commit_pipe_pre_planes(state, crtc);
- if (DISPLAY_VER(dev_priv) >= 9)
- skl_arm_planes_on_crtc(state, crtc);
- else
- i9xx_arm_planes_on_crtc(state, crtc);
+ intel_crtc_planes_update_arm(state, crtc);
commit_pipe_post_planes(state, crtc);
@@ -8325,7 +8156,7 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state)
*/
if (!is_trans_port_sync_slave(old_crtc_state) &&
!intel_dp_mst_is_slave_trans(old_crtc_state) &&
- !old_crtc_state->bigjoiner_slave)
+ !intel_crtc_is_bigjoiner_slave(old_crtc_state))
continue;
intel_old_crtc_state_disables(state, old_crtc_state,
@@ -8440,7 +8271,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
if (intel_dp_mst_is_slave_trans(new_crtc_state) ||
is_trans_port_sync_master(new_crtc_state) ||
- (new_crtc_state->bigjoiner && !new_crtc_state->bigjoiner_slave))
+ intel_crtc_is_bigjoiner_master(new_crtc_state))
continue;
modeset_pipes &= ~BIT(pipe);
@@ -8576,7 +8407,9 @@ static void intel_atomic_prepare_plane_clear_colors(struct intel_atomic_state *s
/*
* The layout of the fast clear color value expected by HW
- * (the DRM ABI requiring this value to be located in fb at offset 0 of plane#2):
+ * (the DRM ABI requiring this value to be located in fb at
+ * offset 0 of cc plane, plane #2 previous generations or
+ * plane #1 for flat ccs):
* - 4 x 4 bytes per-channel value
* (in surface type specific float/int format provided by the fb user)
* - 8 bytes native color value used by the display
@@ -8602,7 +8435,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_crtc_state *new_crtc_state, *old_crtc_state;
struct intel_crtc *crtc;
- u64 put_domains[I915_MAX_PIPES] = {};
+ struct intel_power_domain_mask put_domains[I915_MAX_PIPES] = {};
intel_wakeref_t wakeref = 0;
int i;
@@ -8619,9 +8452,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
new_crtc_state, i) {
if (intel_crtc_needs_modeset(new_crtc_state) ||
new_crtc_state->update_pipe) {
-
- put_domains[crtc->pipe] =
- modeset_get_crtc_power_domains(new_crtc_state);
+ modeset_get_crtc_power_domains(new_crtc_state, &put_domains[crtc->pipe]);
}
}
@@ -8659,9 +8490,10 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
intel_encoders_update_prepare(state);
intel_dbuf_pre_plane_update(state);
+ intel_mbus_dbox_update(state);
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
- if (new_crtc_state->uapi.async_flip)
+ if (new_crtc_state->do_async_flip)
intel_crtc_enable_flip_done(state, crtc);
}
@@ -8687,7 +8519,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
drm_atomic_helper_wait_for_flip_done(dev, &state->base);
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
- if (new_crtc_state->uapi.async_flip)
+ if (new_crtc_state->do_async_flip)
intel_crtc_disable_flip_done(state, crtc);
}
@@ -8720,7 +8552,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
intel_post_plane_update(state, crtc);
- modeset_put_crtc_power_domains(crtc, put_domains[crtc->pipe]);
+ modeset_put_crtc_power_domains(crtc, &put_domains[crtc->pipe]);
intel_modeset_verify_crtc(crtc, state, old_crtc_state, new_crtc_state);
@@ -8967,10 +8799,8 @@ static u32 intel_encoder_possible_crtcs(struct intel_encoder *encoder)
struct intel_crtc *crtc;
u32 possible_crtcs = 0;
- for_each_intel_crtc(dev, crtc) {
- if (encoder->pipe_mask & BIT(crtc->pipe))
- possible_crtcs |= drm_crtc_mask(&crtc->base);
- }
+ for_each_intel_crtc_in_pipe_mask(dev, crtc, encoder->pipe_mask)
+ possible_crtcs |= drm_crtc_mask(&crtc->base);
return possible_crtcs;
}
@@ -9026,6 +8856,7 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
intel_ddi_init(dev_priv, PORT_B);
intel_ddi_init(dev_priv, PORT_C);
intel_ddi_init(dev_priv, PORT_D_XELPD);
+ intel_ddi_init(dev_priv, PORT_TC1);
} else if (IS_ALDERLAKE_P(dev_priv)) {
intel_ddi_init(dev_priv, PORT_A);
intel_ddi_init(dev_priv, PORT_B);
@@ -9478,7 +9309,7 @@ void intel_modeset_init_hw(struct drm_i915_private *i915)
cdclk_state = to_intel_cdclk_state(i915->cdclk.obj.state);
intel_update_cdclk(i915);
- intel_dump_cdclk_config(&i915->cdclk.hw, "Current CDCLK");
+ intel_cdclk_dump_config(i915, &i915->cdclk.hw, "Current CDCLK");
cdclk_state->logical = cdclk_state->actual = i915->cdclk.hw;
}
@@ -9766,8 +9597,6 @@ int intel_modeset_init_noirq(struct drm_i915_private *i915)
i915->flip_wq = alloc_workqueue("i915_flip", WQ_HIGHPRI |
WQ_UNBOUND, WQ_UNBOUND_MAX_ACTIVE);
- i915->framestart_delay = 1; /* 1-4 */
-
i915->window2_delay = 0; /* No DSB so no window2 delay */
intel_mode_config_init(i915);
@@ -9836,7 +9665,7 @@ int intel_modeset_init_nogem(struct drm_i915_private *i915)
}
intel_plane_possible_crtcs_init(i915);
- intel_shared_dpll_init(dev);
+ intel_shared_dpll_init(i915);
intel_fdi_pll_freq_update(i915);
intel_update_czclk(i915);
@@ -9943,9 +9772,6 @@ void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
PLL_REF_INPUT_DREFCLK |
DPLL_VCO_ENABLE;
- intel_de_write(dev_priv, FP0(pipe), fp);
- intel_de_write(dev_priv, FP1(pipe), fp);
-
intel_de_write(dev_priv, HTOTAL(pipe), (640 - 1) | ((800 - 1) << 16));
intel_de_write(dev_priv, HBLANK(pipe), (640 - 1) | ((800 - 1) << 16));
intel_de_write(dev_priv, HSYNC(pipe), (656 - 1) | ((752 - 1) << 16));
@@ -9954,6 +9780,9 @@ void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
intel_de_write(dev_priv, VSYNC(pipe), (490 - 1) | ((492 - 1) << 16));
intel_de_write(dev_priv, PIPESRC(pipe), ((640 - 1) << 16) | (480 - 1));
+ intel_de_write(dev_priv, FP0(pipe), fp);
+ intel_de_write(dev_priv, FP1(pipe), fp);
+
/*
* Apparently we need to have VGA mode enabled prior to changing
* the P1/P2 dividers. Otherwise the DPLL will keep using the old
@@ -9980,8 +9809,7 @@ void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
udelay(150); /* wait for warmup */
}
- intel_de_write(dev_priv, PIPECONF(pipe),
- PIPECONF_ENABLE | PIPECONF_PROGRESSIVE);
+ intel_de_write(dev_priv, PIPECONF(pipe), PIPECONF_ENABLE);
intel_de_posting_read(dev_priv, PIPECONF(pipe));
intel_wait_for_pipe_scanline_moving(crtc);
@@ -9995,18 +9823,15 @@ void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
pipe_name(pipe));
drm_WARN_ON(&dev_priv->drm,
- intel_de_read(dev_priv, DSPCNTR(PLANE_A)) &
- DISPLAY_PLANE_ENABLE);
+ intel_de_read(dev_priv, DSPCNTR(PLANE_A)) & DISP_ENABLE);
drm_WARN_ON(&dev_priv->drm,
- intel_de_read(dev_priv, DSPCNTR(PLANE_B)) &
- DISPLAY_PLANE_ENABLE);
+ intel_de_read(dev_priv, DSPCNTR(PLANE_B)) & DISP_ENABLE);
drm_WARN_ON(&dev_priv->drm,
- intel_de_read(dev_priv, DSPCNTR(PLANE_C)) &
- DISPLAY_PLANE_ENABLE);
+ intel_de_read(dev_priv, DSPCNTR(PLANE_C)) & DISP_ENABLE);
drm_WARN_ON(&dev_priv->drm,
- intel_de_read(dev_priv, CURCNTR(PIPE_A)) & MCURSOR_MODE);
+ intel_de_read(dev_priv, CURCNTR(PIPE_A)) & MCURSOR_MODE_MASK);
drm_WARN_ON(&dev_priv->drm,
- intel_de_read(dev_priv, CURCNTR(PIPE_B)) & MCURSOR_MODE);
+ intel_de_read(dev_priv, CURCNTR(PIPE_B)) & MCURSOR_MODE_MASK);
intel_de_write(dev_priv, PIPECONF(pipe), 0);
intel_de_posting_read(dev_priv, PIPECONF(pipe));
@@ -10068,64 +9893,6 @@ static struct intel_connector *intel_encoder_find_connector(struct intel_encoder
return NULL;
}
-static bool has_pch_trancoder(struct drm_i915_private *dev_priv,
- enum pipe pch_transcoder)
-{
- return HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv) ||
- (HAS_PCH_LPT_H(dev_priv) && pch_transcoder == PIPE_A);
-}
-
-static void intel_sanitize_frame_start_delay(const struct intel_crtc_state *crtc_state)
-{
- struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
-
- if (DISPLAY_VER(dev_priv) >= 9 ||
- IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) {
- i915_reg_t reg = CHICKEN_TRANS(cpu_transcoder);
- u32 val;
-
- if (transcoder_is_dsi(cpu_transcoder))
- return;
-
- val = intel_de_read(dev_priv, reg);
- val &= ~HSW_FRAME_START_DELAY_MASK;
- val |= HSW_FRAME_START_DELAY(dev_priv->framestart_delay - 1);
- intel_de_write(dev_priv, reg, val);
- } else {
- i915_reg_t reg = PIPECONF(cpu_transcoder);
- u32 val;
-
- val = intel_de_read(dev_priv, reg);
- val &= ~PIPECONF_FRAME_START_DELAY_MASK;
- val |= PIPECONF_FRAME_START_DELAY(dev_priv->framestart_delay - 1);
- intel_de_write(dev_priv, reg, val);
- }
-
- if (!crtc_state->has_pch_encoder)
- return;
-
- if (HAS_PCH_IBX(dev_priv)) {
- i915_reg_t reg = PCH_TRANSCONF(crtc->pipe);
- u32 val;
-
- val = intel_de_read(dev_priv, reg);
- val &= ~TRANS_FRAME_START_DELAY_MASK;
- val |= TRANS_FRAME_START_DELAY(dev_priv->framestart_delay - 1);
- intel_de_write(dev_priv, reg, val);
- } else {
- enum pipe pch_transcoder = intel_crtc_pch_transcoder(crtc);
- i915_reg_t reg = TRANS_CHICKEN2(pch_transcoder);
- u32 val;
-
- val = intel_de_read(dev_priv, reg);
- val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
- val |= TRANS_CHICKEN2_FRAME_START_DELAY(dev_priv->framestart_delay - 1);
- intel_de_write(dev_priv, reg, val);
- }
-}
-
static void intel_sanitize_crtc(struct intel_crtc *crtc,
struct drm_modeset_acquire_ctx *ctx)
{
@@ -10136,9 +9903,6 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc,
if (crtc_state->hw.active) {
struct intel_plane *plane;
- /* Clear any frame start delays used for debugging left by the BIOS */
- intel_sanitize_frame_start_delay(crtc_state);
-
/* Disable everything but the primary plane */
for_each_intel_plane_on_crtc(dev, crtc, plane) {
const struct intel_plane_state *plane_state =
@@ -10150,13 +9914,14 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc,
}
/* Disable any background color/etc. set by the BIOS */
- intel_color_commit(crtc_state);
+ intel_color_commit_noarm(crtc_state);
+ intel_color_commit_arm(crtc_state);
}
/* Adjust the state of the output pipe according to whether we
* have active connectors/encoders. */
if (crtc_state->hw.active && !intel_crtc_has_encoders(crtc) &&
- !crtc_state->bigjoiner_slave)
+ !intel_crtc_is_bigjoiner_slave(crtc_state))
intel_crtc_disable_noatomic(crtc, ctx);
if (crtc_state->hw.active || HAS_GMCH(dev_priv)) {
@@ -10183,7 +9948,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc,
* PCH transcoders B and C would prevent enabling the south
* error interrupt (see cpt_can_enable_serr_int()).
*/
- if (has_pch_trancoder(dev_priv, crtc->pipe))
+ if (intel_has_pch_trancoder(dev_priv, crtc->pipe))
crtc->pch_fifo_underrun_disabled = true;
}
}
@@ -10302,7 +10067,7 @@ static void readout_plane_state(struct drm_i915_private *dev_priv)
drm_dbg_kms(&dev_priv->drm,
"[PLANE:%d:%s] hw state readout: %s, pipe %c\n",
plane->base.base.id, plane->base.name,
- enableddisabled(visible), pipe_name(pipe));
+ str_enabled_disabled(visible), pipe_name(pipe));
}
for_each_intel_crtc(&dev_priv->drm, crtc) {
@@ -10348,7 +10113,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
drm_dbg_kms(&dev_priv->drm,
"[CRTC:%d:%s] hw state readout: %s\n",
crtc->base.base.id, crtc->base.name,
- enableddisabled(crtc_state->hw.active));
+ str_enabled_disabled(crtc_state->hw.active));
}
cdclk_state->active_pipes = dbuf_state->active_pipes = active_pipes;
@@ -10368,13 +10133,19 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
intel_encoder_get_config(encoder, crtc_state);
/* read out to slave crtc as well for bigjoiner */
- if (crtc_state->bigjoiner) {
+ if (crtc_state->bigjoiner_pipes) {
+ struct intel_crtc *slave_crtc;
+
/* encoder should read be linked to bigjoiner master */
- WARN_ON(crtc_state->bigjoiner_slave);
+ WARN_ON(intel_crtc_is_bigjoiner_slave(crtc_state));
+
+ for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, slave_crtc,
+ intel_crtc_bigjoiner_slave_pipes(crtc_state)) {
+ struct intel_crtc_state *slave_crtc_state;
- crtc = crtc_state->bigjoiner_linked_crtc;
- crtc_state = to_intel_crtc_state(crtc->base.state);
- intel_encoder_get_config(encoder, crtc_state);
+ slave_crtc_state = to_intel_crtc_state(slave_crtc->base.state);
+ intel_encoder_get_config(encoder, slave_crtc_state);
+ }
}
} else {
encoder->base.crtc = NULL;
@@ -10386,7 +10157,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
drm_dbg_kms(&dev_priv->drm,
"[ENCODER:%d:%s] hw state readout: %s, pipe %c\n",
encoder->base.base.id, encoder->base.name,
- enableddisabled(encoder->base.crtc),
+ str_enabled_disabled(encoder->base.crtc),
pipe_name(pipe));
}
@@ -10424,7 +10195,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
drm_dbg_kms(&dev_priv->drm,
"[CONNECTOR:%d:%s] hw state readout: %s\n",
connector->base.base.id, connector->base.name,
- enableddisabled(connector->base.encoder));
+ str_enabled_disabled(connector->base.encoder));
}
drm_connector_list_iter_end(&conn_iter);
@@ -10550,66 +10321,6 @@ static void intel_early_display_was(struct drm_i915_private *dev_priv)
}
}
-static void ibx_sanitize_pch_hdmi_port(struct drm_i915_private *dev_priv,
- enum port port, i915_reg_t hdmi_reg)
-{
- u32 val = intel_de_read(dev_priv, hdmi_reg);
-
- if (val & SDVO_ENABLE ||
- (val & SDVO_PIPE_SEL_MASK) == SDVO_PIPE_SEL(PIPE_A))
- return;
-
- drm_dbg_kms(&dev_priv->drm,
- "Sanitizing transcoder select for HDMI %c\n",
- port_name(port));
-
- val &= ~SDVO_PIPE_SEL_MASK;
- val |= SDVO_PIPE_SEL(PIPE_A);
-
- intel_de_write(dev_priv, hdmi_reg, val);
-}
-
-static void ibx_sanitize_pch_dp_port(struct drm_i915_private *dev_priv,
- enum port port, i915_reg_t dp_reg)
-{
- u32 val = intel_de_read(dev_priv, dp_reg);
-
- if (val & DP_PORT_EN ||
- (val & DP_PIPE_SEL_MASK) == DP_PIPE_SEL(PIPE_A))
- return;
-
- drm_dbg_kms(&dev_priv->drm,
- "Sanitizing transcoder select for DP %c\n",
- port_name(port));
-
- val &= ~DP_PIPE_SEL_MASK;
- val |= DP_PIPE_SEL(PIPE_A);
-
- intel_de_write(dev_priv, dp_reg, val);
-}
-
-static void ibx_sanitize_pch_ports(struct drm_i915_private *dev_priv)
-{
- /*
- * The BIOS may select transcoder B on some of the PCH
- * ports even it doesn't enable the port. This would trip
- * assert_pch_dp_disabled() and assert_pch_hdmi_disabled().
- * Sanitize the transcoder select bits to prevent that. We
- * assume that the BIOS never actually enabled the port,
- * because if it did we'd actually have to toggle the port
- * on and back off to make the transcoder A select stick
- * (see. intel_dp_link_down(), intel_disable_hdmi(),
- * intel_disable_sdvo()).
- */
- ibx_sanitize_pch_dp_port(dev_priv, PORT_B, PCH_DP_B);
- ibx_sanitize_pch_dp_port(dev_priv, PORT_C, PCH_DP_C);
- ibx_sanitize_pch_dp_port(dev_priv, PORT_D, PCH_DP_D);
-
- /* PCH SDVOB multiplex with HDMIB */
- ibx_sanitize_pch_hdmi_port(dev_priv, PORT_B, PCH_HDMIB);
- ibx_sanitize_pch_hdmi_port(dev_priv, PORT_C, PCH_HDMIC);
- ibx_sanitize_pch_hdmi_port(dev_priv, PORT_D, PCH_HDMID);
-}
/* Scan out the current hw modeset state,
* and sanitizes it to the current state
@@ -10631,8 +10342,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
/* HW state is read out, now we need to sanitize this mess. */
get_encoder_power_domains(dev_priv);
- if (HAS_PCH_IBX(dev_priv))
- ibx_sanitize_pch_ports(dev_priv);
+ intel_pch_sanitize(dev_priv);
/*
* intel_sanitize_plane_mapping() may need to do vblank
@@ -10648,6 +10358,8 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
intel_crtc_vblank_on(crtc_state);
}
+ intel_fbc_sanitize(dev_priv);
+
intel_sanitize_plane_mapping(dev_priv);
for_each_intel_encoder(dev, encoder)
@@ -10681,14 +10393,16 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
for_each_intel_crtc(dev, crtc) {
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
- u64 put_domains;
+ struct intel_power_domain_mask put_domains;
- put_domains = modeset_get_crtc_power_domains(crtc_state);
- if (drm_WARN_ON(dev, put_domains))
- modeset_put_crtc_power_domains(crtc, put_domains);
+ modeset_get_crtc_power_domains(crtc_state, &put_domains);
+ if (drm_WARN_ON(dev, !bitmap_empty(put_domains.bits, POWER_DOMAIN_NUM)))
+ modeset_put_crtc_power_domains(crtc, &put_domains);
}
intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, wakeref);
+
+ intel_power_domains_sanitize_state(dev_priv);
}
void intel_display_resume(struct drm_device *dev)
@@ -10784,8 +10498,6 @@ void intel_modeset_driver_remove_noirq(struct drm_i915_private *i915)
intel_unregister_dsm_handler();
- intel_fbc_global_disable(i915);
-
/* flush any delayed tasks or pending work */
flush_scheduled_work();
@@ -10886,3 +10598,8 @@ void intel_display_driver_unregister(struct drm_i915_private *i915)
acpi_video_unregister();
intel_opregion_unregister(i915);
}
+
+bool intel_scanout_needs_vtd_wa(struct drm_i915_private *i915)
+{
+ return DISPLAY_VER(i915) >= 6 && i915_vtd_active(i915);
+}