Commit 4e3cdb45 authored by Manasi Navare's avatar Manasi Navare

drm/i915/dp: Master/Slave enable/disable sequence for bigjoiner

Enabling is done in a special sequence and so should plane updates
be. Ideally the end user never notices the second pipe is used.

This way ideally everything will be tear free, and updates are
really atomic as userspace expects it.

This uses generic modeset_enables() calls like trans port sync
but still has special handling for disable since for slave we
should not disable things like encoder, plls that are not enabled
for  slave.
Signed-off-by: default avatarManasi Navare <manasi.d.navare@intel.com>
[vsyrjala: Appease checkpatch]
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: default avatarAnimesh Manna <animesh.manna@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20201117194718.11462-6-manasi.d.navare@intel.com
parent 8a029c11
......@@ -28,6 +28,7 @@
#include <drm/drm_scdc_helper.h>
#include "i915_drv.h"
#include "i915_trace.h"
#include "intel_audio.h"
#include "intel_combo_phy.h"
#include "intel_connector.h"
......@@ -3665,7 +3666,8 @@ static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state,
/* 7.l Configure and enable FEC if needed */
intel_ddi_enable_fec(encoder, crtc_state);
intel_dsc_enable(encoder, crtc_state);
if (!crtc_state->bigjoiner)
intel_dsc_enable(encoder, crtc_state);
}
static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state,
......@@ -3737,7 +3739,8 @@ static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state,
if (!is_mst)
intel_ddi_enable_pipe_clock(encoder, crtc_state);
intel_dsc_enable(encoder, crtc_state);
if (!crtc_state->bigjoiner)
intel_dsc_enable(encoder, crtc_state);
}
static void intel_ddi_pre_enable_dp(struct intel_atomic_state *state,
......@@ -3988,6 +3991,21 @@ static void intel_ddi_post_disable(struct intel_atomic_state *state,
ilk_pfit_disable(old_crtc_state);
}
if (old_crtc_state->bigjoiner_linked_crtc) {
struct intel_atomic_state *state =
to_intel_atomic_state(old_crtc_state->uapi.state);
struct intel_crtc *slave =
old_crtc_state->bigjoiner_linked_crtc;
const struct intel_crtc_state *old_slave_crtc_state =
intel_atomic_get_old_crtc_state(state, slave);
intel_crtc_vblank_off(old_slave_crtc_state);
trace_intel_pipe_disable(slave);
intel_dsc_disable(old_slave_crtc_state);
skl_scaler_disable(old_slave_crtc_state);
}
/*
* When called from DP MST code:
* - old_conn_state will be NULL
......@@ -4206,7 +4224,8 @@ static void intel_enable_ddi(struct intel_atomic_state *state,
{
drm_WARN_ON(state->base.dev, crtc_state->has_pch_encoder);
intel_ddi_enable_transcoder_func(encoder, crtc_state);
if (!crtc_state->bigjoiner_slave)
intel_ddi_enable_transcoder_func(encoder, crtc_state);
intel_enable_pipe(crtc_state);
......
......@@ -7138,6 +7138,45 @@ static void hsw_set_frame_start_delay(const struct intel_crtc_state *crtc_state)
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 intel_crtc *master = to_intel_crtc(crtc_state->uapi.crtc);
struct intel_crtc_state *master_crtc_state;
struct drm_connector_state *conn_state;
struct drm_connector *conn;
struct intel_encoder *encoder = NULL;
int i;
if (crtc_state->bigjoiner_slave)
master = crtc_state->bigjoiner_linked_crtc;
master_crtc_state = intel_atomic_get_new_crtc_state(state, master);
for_each_new_connector_in_state(&state->base, conn, conn_state, i) {
if (conn_state->crtc != &master->base)
continue;
encoder = to_intel_encoder(conn_state->best_encoder);
break;
}
if (!crtc_state->bigjoiner_slave) {
/* need to enable VDSC, which we skipped in pre-enable */
intel_dsc_enable(encoder, crtc_state);
} else {
/*
* Enable sequence steps 1-7 on bigjoiner master
*/
intel_encoders_pre_pll_enable(state, master);
intel_enable_shared_dpll(master_crtc_state);
intel_encoders_pre_enable(state, master);
/* and DSC on slave */
intel_dsc_enable(NULL, crtc_state);
}
}
static void hsw_crtc_enable(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
......@@ -7151,34 +7190,39 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
if (drm_WARN_ON(&dev_priv->drm, crtc->active))
return;
intel_encoders_pre_pll_enable(state, crtc);
if (new_crtc_state->shared_dpll)
intel_enable_shared_dpll(new_crtc_state);
if (!new_crtc_state->bigjoiner) {
intel_encoders_pre_pll_enable(state, crtc);
intel_encoders_pre_enable(state, crtc);
if (new_crtc_state->shared_dpll)
intel_enable_shared_dpll(new_crtc_state);
if (!transcoder_is_dsi(cpu_transcoder))
intel_set_transcoder_timings(new_crtc_state);
intel_encoders_pre_enable(state, crtc);
} else {
icl_ddi_bigjoiner_pre_enable(state, new_crtc_state);
}
intel_set_pipe_src_size(new_crtc_state);
if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
bdw_set_pipemisc(new_crtc_state);
if (cpu_transcoder != TRANSCODER_EDP &&
!transcoder_is_dsi(cpu_transcoder))
intel_de_write(dev_priv, PIPE_MULT(cpu_transcoder),
new_crtc_state->pixel_multiplier - 1);
if (!new_crtc_state->bigjoiner_slave || !transcoder_is_dsi(cpu_transcoder)) {
if (!transcoder_is_dsi(cpu_transcoder))
intel_set_transcoder_timings(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);
if (cpu_transcoder != TRANSCODER_EDP &&
!transcoder_is_dsi(cpu_transcoder))
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);
if (!transcoder_is_dsi(cpu_transcoder)) {
hsw_set_frame_start_delay(new_crtc_state);
hsw_set_pipeconf(new_crtc_state);
}
if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
bdw_set_pipemisc(new_crtc_state);
if (!transcoder_is_dsi(cpu_transcoder))
hsw_set_pipeconf(new_crtc_state);
crtc->active = true;
......@@ -7214,6 +7258,11 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
if (INTEL_GEN(dev_priv) >= 11)
icl_pipe_mbus_enable(crtc);
if (new_crtc_state->bigjoiner_slave) {
trace_intel_pipe_enable(crtc);
intel_crtc_vblank_on(new_crtc_state);
}
intel_encoders_enable(state, crtc);
if (psl_clkgate_wa) {
......@@ -15708,6 +15757,9 @@ static void intel_enable_crtc(struct intel_atomic_state *state,
dev_priv->display.crtc_enable(state, crtc);
if (new_crtc_state->bigjoiner_slave)
return;
/* vblanks work again, re-enable pipe CRC. */
intel_crtc_enable_pipe_crc(crtc);
}
......@@ -15770,8 +15822,21 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state,
{
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
drm_WARN_ON(&dev_priv->drm, old_crtc_state->bigjoiner_slave);
intel_crtc_disable_planes(state, crtc);
/*
* We still need special handling for disabling bigjoiner master
* and slaves since for slave we do not have encoder or plls
* so we dont need to disable those.
*/
if (old_crtc_state->bigjoiner) {
intel_crtc_disable_planes(state,
old_crtc_state->bigjoiner_linked_crtc);
old_crtc_state->bigjoiner_linked_crtc->active = false;
}
/*
* We need to disable pipe CRC before disabling the pipe,
* or we race against vblank off.
......@@ -15800,7 +15865,7 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state)
/* Only disable port sync and MST slaves */
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
if (!needs_modeset(new_crtc_state))
if (!needs_modeset(new_crtc_state) || old_crtc_state->bigjoiner)
continue;
if (!old_crtc_state->hw.active)
......@@ -15825,10 +15890,18 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state)
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
if (!needs_modeset(new_crtc_state) ||
(handled & BIT(crtc->pipe)))
(handled & BIT(crtc->pipe)) ||
old_crtc_state->bigjoiner_slave)
continue;
intel_pre_plane_update(state, crtc);
if (old_crtc_state->bigjoiner) {
struct intel_crtc *slave =
old_crtc_state->bigjoiner_linked_crtc;
intel_pre_plane_update(state, slave);
}
if (old_crtc_state->hw.active)
intel_old_crtc_state_disables(state, old_crtc_state,
new_crtc_state, crtc);
......@@ -15926,7 +15999,8 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
continue;
if (intel_dp_mst_is_slave_trans(new_crtc_state) ||
is_trans_port_sync_master(new_crtc_state))
is_trans_port_sync_master(new_crtc_state) ||
(new_crtc_state->bigjoiner && !new_crtc_state->bigjoiner_slave))
continue;
modeset_pipes &= ~BIT(pipe);
......@@ -15936,7 +16010,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
/*
* Then we enable all remaining pipes that depend on other
* pipes: MST slaves and port sync masters.
* pipes: MST slaves and port sync masters, big joiner master
*/
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
enum pipe pipe = crtc->pipe;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment