summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_display.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r--drivers/gpu/drm/i915/intel_display.c445
1 files changed, 285 insertions, 160 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 622d30c..2f00828 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -44,6 +44,8 @@
#include <drm/drm_plane_helper.h>
#include <drm/drm_rect.h>
#include <linux/dma_remapping.h>
+#include <linux/reservation.h>
+#include <linux/dma-buf.h>
/* Primary plane formats for gen <= 3 */
static const uint32_t i8xx_primary_formats[] = {
@@ -186,7 +188,7 @@ int intel_hrawclk(struct drm_device *dev)
uint32_t clkcfg;
/* There is no CLKCFG reg in Valleyview. VLV hrawclk is 200 MHz */
- if (IS_VALLEYVIEW(dev))
+ if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
return 200;
clkcfg = I915_READ(CLKCFG);
@@ -214,7 +216,7 @@ int intel_hrawclk(struct drm_device *dev)
static void intel_update_czclk(struct drm_i915_private *dev_priv)
{
- if (!IS_VALLEYVIEW(dev_priv))
+ if (!(IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)))
return;
dev_priv->czclk_freq = vlv_get_cck_clock_hpll(dev_priv, "czclk",
@@ -715,11 +717,12 @@ static bool intel_PLL_is_valid(struct drm_device *dev,
if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1)
INTELPllInvalid("m1 out of range\n");
- if (!IS_PINEVIEW(dev) && !IS_VALLEYVIEW(dev) && !IS_BROXTON(dev))
+ if (!IS_PINEVIEW(dev) && !IS_VALLEYVIEW(dev) &&
+ !IS_CHERRYVIEW(dev) && !IS_BROXTON(dev))
if (clock->m1 <= clock->m2)
INTELPllInvalid("m1 <= m2\n");
- if (!IS_VALLEYVIEW(dev) && !IS_BROXTON(dev)) {
+ if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && !IS_BROXTON(dev)) {
if (clock->p < limit->p.min || limit->p.max < clock->p)
INTELPllInvalid("p out of range\n");
if (clock->m < limit->m.min || limit->m.max < clock->m)
@@ -1304,7 +1307,7 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv,
I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT)
panel_pipe = PIPE_B;
/* XXX: else fix for eDP */
- } else if (IS_VALLEYVIEW(dev)) {
+ } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
/* presumably write lock depends on pipe, not port select */
pp_reg = VLV_PIPE_PP_CONTROL(pipe);
panel_pipe = pipe;
@@ -1422,7 +1425,7 @@ static void assert_sprites_disabled(struct drm_i915_private *dev_priv,
"plane %d assertion failure, should be off on pipe %c but is still active\n",
sprite, pipe_name(pipe));
}
- } else if (IS_VALLEYVIEW(dev)) {
+ } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
for_each_sprite(dev_priv, pipe, sprite) {
u32 val = I915_READ(SPCNTR(pipe, sprite));
I915_STATE_WARN(val & SP_ENABLE,
@@ -1605,9 +1608,6 @@ static void vlv_enable_pll(struct intel_crtc *crtc,
assert_pipe_disabled(dev_priv, crtc->pipe);
- /* No really, not for ILK+ */
- BUG_ON(!IS_VALLEYVIEW(dev_priv->dev));
-
/* PLL is protected by panel, make sure we can write it */
if (IS_MOBILE(dev_priv->dev))
assert_panel_unlocked(dev_priv, crtc->pipe);
@@ -1645,8 +1645,6 @@ static void chv_enable_pll(struct intel_crtc *crtc,
assert_pipe_disabled(dev_priv, crtc->pipe);
- BUG_ON(!IS_CHERRYVIEW(dev_priv->dev));
-
mutex_lock(&dev_priv->sb_lock);
/* Enable back the 10bit clock to display controller */
@@ -2131,7 +2129,7 @@ static void intel_enable_pipe(struct intel_crtc *crtc)
* need the check.
*/
if (HAS_GMCH_DISPLAY(dev_priv->dev))
- if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI))
+ if (crtc->config->has_dsi_encoder)
assert_dsi_pll_enabled(dev_priv);
else
assert_pll_enabled(dev_priv, pipe);
@@ -2318,7 +2316,7 @@ static unsigned int intel_linear_alignment(struct drm_i915_private *dev_priv)
if (INTEL_INFO(dev_priv)->gen >= 9)
return 256 * 1024;
else if (IS_BROADWATER(dev_priv) || IS_CRESTLINE(dev_priv) ||
- IS_VALLEYVIEW(dev_priv))
+ IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
return 128 * 1024;
else if (INTEL_INFO(dev_priv)->gen >= 4)
return 4 * 1024;
@@ -3189,8 +3187,8 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- if (dev_priv->fbc.disable_fbc)
- dev_priv->fbc.disable_fbc(dev_priv);
+ if (dev_priv->fbc.deactivate)
+ dev_priv->fbc.deactivate(dev_priv);
dev_priv->display.update_primary_plane(crtc, fb, x, y);
@@ -3953,6 +3951,21 @@ static int intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
return 0;
}
+static void lpt_disable_iclkip(struct drm_i915_private *dev_priv)
+{
+ u32 temp;
+
+ I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_GATE);
+
+ mutex_lock(&dev_priv->sb_lock);
+
+ temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK);
+ temp |= SBI_SSCCTL_DISABLE;
+ intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK);
+
+ mutex_unlock(&dev_priv->sb_lock);
+}
+
/* Program iCLKIP clock to the desired frequency */
static void lpt_program_iclkip(struct drm_crtc *crtc)
{
@@ -3962,18 +3975,7 @@ static void lpt_program_iclkip(struct drm_crtc *crtc)
u32 divsel, phaseinc, auxdiv, phasedir = 0;
u32 temp;
- mutex_lock(&dev_priv->sb_lock);
-
- /* It is necessary to ungate the pixclk gate prior to programming
- * the divisors, and gate it back when it is done.
- */
- I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_GATE);
-
- /* Disable SSCCTL */
- intel_sbi_write(dev_priv, SBI_SSCCTL6,
- intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK) |
- SBI_SSCCTL_DISABLE,
- SBI_ICLK);
+ lpt_disable_iclkip(dev_priv);
/* 20MHz is a corner case which is out of range for the 7-bit divisor */
if (clock == 20000) {
@@ -3991,7 +3993,7 @@ static void lpt_program_iclkip(struct drm_crtc *crtc)
u32 iclk_pi_range = 64;
u32 desired_divisor, msb_divisor_value, pi_value;
- desired_divisor = (iclk_virtual_root_freq / clock);
+ desired_divisor = DIV_ROUND_CLOSEST(iclk_virtual_root_freq, clock);
msb_divisor_value = desired_divisor / iclk_pi_range;
pi_value = desired_divisor % iclk_pi_range;
@@ -4013,6 +4015,8 @@ static void lpt_program_iclkip(struct drm_crtc *crtc)
phasedir,
phaseinc);
+ mutex_lock(&dev_priv->sb_lock);
+
/* Program SSCDIVINTPHASE6 */
temp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE6, SBI_ICLK);
temp &= ~SBI_SSCDIVINTPHASE_DIVSEL_MASK;
@@ -4034,12 +4038,12 @@ static void lpt_program_iclkip(struct drm_crtc *crtc)
temp &= ~SBI_SSCCTL_DISABLE;
intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK);
+ mutex_unlock(&dev_priv->sb_lock);
+
/* Wait for initialization time */
udelay(24);
I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_UNGATE);
-
- mutex_unlock(&dev_priv->sb_lock);
}
static void ironlake_pch_transcoder_set_timings(struct intel_crtc *crtc,
@@ -4152,6 +4156,12 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
I915_WRITE(FDI_RX_TUSIZE1(pipe),
I915_READ(PIPE_DATA_M1(pipe)) & TU_SIZE_MASK);
+ /*
+ * Sometimes spurious CPU pipe underruns happen during FDI
+ * training, at least with VGA+HDMI cloning. Suppress them.
+ */
+ intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
+
/* For PCH output, training FDI link */
dev_priv->display.fdi_link_train(crtc);
@@ -4185,6 +4195,8 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
intel_fdi_normal_train(crtc);
+ intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
+
/* For PCH DP, enable TRANS_DP_CTL */
if (HAS_PCH_CPT(dev) && intel_crtc->config->has_dp_encoder) {
const struct drm_display_mode *adjusted_mode =
@@ -4643,7 +4655,7 @@ static void intel_crtc_load_lut(struct drm_crtc *crtc)
return;
if (HAS_GMCH_DISPLAY(dev_priv->dev)) {
- if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DSI))
+ if (intel_crtc->config->has_dsi_encoder)
assert_dsi_pll_enabled(dev_priv);
else
assert_pll_enabled(dev_priv, pipe);
@@ -4714,14 +4726,6 @@ intel_post_enable_primary(struct drm_crtc *crtc)
int pipe = intel_crtc->pipe;
/*
- * BDW signals flip done immediately if the plane
- * is disabled, even if the plane enable is already
- * armed to occur at the next vblank :(
- */
- if (IS_BROADWELL(dev))
- intel_wait_for_vblank(dev, pipe);
-
- /*
* FIXME IPS should be fine as long as one plane is
* enabled, but in practice it seems to have problems
* when going from primary only to sprite only and vice
@@ -4798,22 +4802,22 @@ intel_pre_disable_primary(struct drm_crtc *crtc)
static void intel_post_plane_update(struct intel_crtc *crtc)
{
struct intel_crtc_atomic_commit *atomic = &crtc->atomic;
+ struct intel_crtc_state *pipe_config =
+ to_intel_crtc_state(crtc->base.state);
struct drm_device *dev = crtc->base.dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
if (atomic->wait_vblank)
intel_wait_for_vblank(dev, crtc->pipe);
intel_frontbuffer_flip(dev, atomic->fb_bits);
- if (atomic->disable_cxsr)
- crtc->wm.cxsr_allowed = true;
+ crtc->wm.cxsr_allowed = true;
- if (crtc->atomic.update_wm_post)
+ if (pipe_config->wm_changed && pipe_config->base.active)
intel_update_watermarks(&crtc->base);
if (atomic->update_fbc)
- intel_fbc_update(dev_priv);
+ intel_fbc_update(crtc);
if (atomic->post_enable_primary)
intel_post_enable_primary(&crtc->base);
@@ -4826,9 +4830,11 @@ static void intel_pre_plane_update(struct intel_crtc *crtc)
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc_atomic_commit *atomic = &crtc->atomic;
+ struct intel_crtc_state *pipe_config =
+ to_intel_crtc_state(crtc->base.state);
if (atomic->disable_fbc)
- intel_fbc_disable_crtc(crtc);
+ intel_fbc_deactivate(crtc);
if (crtc->atomic.disable_ips)
hsw_disable_ips(crtc);
@@ -4836,10 +4842,13 @@ static void intel_pre_plane_update(struct intel_crtc *crtc)
if (atomic->pre_disable_primary)
intel_pre_disable_primary(&crtc->base);
- if (atomic->disable_cxsr) {
+ if (pipe_config->disable_cxsr) {
crtc->wm.cxsr_allowed = false;
intel_set_memory_cxsr(dev_priv, false);
}
+
+ if (!needs_modeset(&pipe_config->base) && pipe_config->wm_changed)
+ intel_update_watermarks(&crtc->base);
}
static void intel_crtc_disable_planes(struct drm_crtc *crtc, unsigned plane_mask)
@@ -4936,6 +4945,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
if (intel_crtc->config->has_pch_encoder)
intel_wait_for_vblank(dev, pipe);
intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true);
+
+ intel_fbc_enable(intel_crtc);
}
/* IPS only exists on ULT machines and is tied to pipe A. */
@@ -4953,7 +4964,6 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
int pipe = intel_crtc->pipe, hsw_workaround_pipe;
struct intel_crtc_state *pipe_config =
to_intel_crtc_state(crtc->state);
- bool is_dsi = intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DSI);
if (WARN_ON(intel_crtc->active))
return;
@@ -4986,10 +4996,12 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
intel_crtc->active = true;
- intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
+ if (intel_crtc->config->has_pch_encoder)
+ intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
+ else
+ intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
+
for_each_encoder_on_crtc(dev, crtc, encoder) {
- if (encoder->pre_pll_enable)
- encoder->pre_pll_enable(encoder);
if (encoder->pre_enable)
encoder->pre_enable(encoder);
}
@@ -4997,7 +5009,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
if (intel_crtc->config->has_pch_encoder)
dev_priv->display.fdi_link_train(crtc);
- if (!is_dsi)
+ if (!intel_crtc->config->has_dsi_encoder)
intel_ddi_enable_pipe_clock(intel_crtc);
if (INTEL_INFO(dev)->gen >= 9)
@@ -5012,7 +5024,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
intel_crtc_load_lut(crtc);
intel_ddi_set_pipe_settings(crtc);
- if (!is_dsi)
+ if (!intel_crtc->config->has_dsi_encoder)
intel_ddi_enable_transcoder_func(crtc);
intel_update_watermarks(crtc);
@@ -5021,7 +5033,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
if (intel_crtc->config->has_pch_encoder)
lpt_pch_enable(crtc);
- if (intel_crtc->config->dp_encoder_is_mst && !is_dsi)
+ if (intel_crtc->config->dp_encoder_is_mst)
intel_ddi_set_vc_payload_alloc(crtc, true);
assert_vblank_disabled(crtc);
@@ -5032,9 +5044,13 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
intel_opregion_notify_encoder(encoder, true);
}
- if (intel_crtc->config->has_pch_encoder)
+ if (intel_crtc->config->has_pch_encoder) {
+ intel_wait_for_vblank(dev, pipe);
+ intel_wait_for_vblank(dev, pipe);
+ intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
true);
+ }
/* If we change the relative order between pipe/planes enabling, we need
* to change the workaround. */
@@ -5043,6 +5059,8 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
intel_wait_for_vblank(dev, hsw_workaround_pipe);
intel_wait_for_vblank(dev, hsw_workaround_pipe);
}
+
+ intel_fbc_enable(intel_crtc);
}
static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force)
@@ -5077,12 +5095,22 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
drm_crtc_vblank_off(crtc);
assert_vblank_disabled(crtc);
+ /*
+ * Sometimes spurious CPU pipe underruns happen when the
+ * pipe is already disabled, but FDI RX/TX is still enabled.
+ * Happens at least with VGA+HDMI cloning. Suppress them.
+ */
+ if (intel_crtc->config->has_pch_encoder)
+ intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
+
intel_disable_pipe(intel_crtc);
ironlake_pfit_disable(intel_crtc, false);
- if (intel_crtc->config->has_pch_encoder)
+ if (intel_crtc->config->has_pch_encoder) {
ironlake_fdi_disable(crtc);
+ intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
+ }
for_each_encoder_on_crtc(dev, crtc, encoder)
if (encoder->post_disable)
@@ -5113,6 +5141,8 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
}
intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true);
+
+ intel_fbc_disable_crtc(intel_crtc);
}
static void haswell_crtc_disable(struct drm_crtc *crtc)
@@ -5122,7 +5152,6 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_encoder *encoder;
enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
- bool is_dsi = intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DSI);
if (intel_crtc->config->has_pch_encoder)
intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
@@ -5141,7 +5170,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
if (intel_crtc->config->dp_encoder_is_mst)
intel_ddi_set_vc_payload_alloc(crtc, false);
- if (!is_dsi)
+ if (!intel_crtc->config->has_dsi_encoder)
intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder);
if (INTEL_INFO(dev)->gen >= 9)
@@ -5149,21 +5178,23 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
else
ironlake_pfit_disable(intel_crtc, false);
- if (!is_dsi)
+ if (!intel_crtc->config->has_dsi_encoder)
intel_ddi_disable_pipe_clock(intel_crtc);
- if (intel_crtc->config->has_pch_encoder) {
- lpt_disable_pch_transcoder(dev_priv);
- intel_ddi_fdi_disable(crtc);
- }
-
for_each_encoder_on_crtc(dev, crtc, encoder)
if (encoder->post_disable)
encoder->post_disable(encoder);
- if (intel_crtc->config->has_pch_encoder)
+ if (intel_crtc->config->has_pch_encoder) {
+ lpt_disable_pch_transcoder(dev_priv);
+ lpt_disable_iclkip(dev_priv);
+ intel_ddi_fdi_disable(crtc);
+
intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
true);
+ }
+
+ intel_fbc_disable_crtc(intel_crtc);
}
static void i9xx_pfit_enable(struct intel_crtc *crtc)
@@ -5229,10 +5260,6 @@ static enum intel_display_power_domain port_to_aux_power_domain(enum port port)
}
}
-#define for_each_power_domain(domain, mask) \
- for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++) \
- if ((1 << (domain)) & (mask))
-
enum intel_display_power_domain
intel_display_port_power_domain(struct intel_encoder *intel_encoder)
{
@@ -5445,7 +5472,7 @@ static void intel_update_cdclk(struct drm_device *dev)
* BSpec erroneously claims we should aim for 4MHz, but
* in fact 1MHz is the correct frequency.
*/
- if (IS_VALLEYVIEW(dev)) {
+ if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
/*
* Program the gmbus_freq based on the cdclk frequency.
* BSpec erroneously claims we should aim for 4MHz, but
@@ -6155,13 +6182,10 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_encoder *encoder;
int pipe = intel_crtc->pipe;
- bool is_dsi;
if (WARN_ON(intel_crtc->active))
return;
- is_dsi = intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DSI);
-
if (intel_crtc->config->has_dp_encoder)
intel_dp_set_m_n(intel_crtc, M1_N1);
@@ -6184,7 +6208,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
if (encoder->pre_pll_enable)
encoder->pre_pll_enable(encoder);
- if (!is_dsi) {
+ if (!intel_crtc->config->has_dsi_encoder) {
if (IS_CHERRYVIEW(dev)) {
chv_prepare_pll(intel_crtc, intel_crtc->config);
chv_enable_pll(intel_crtc, intel_crtc->config);
@@ -6263,6 +6287,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
for_each_encoder_on_crtc(dev, crtc, encoder)
encoder->enable(encoder);
+
+ intel_fbc_enable(intel_crtc);
}
static void i9xx_pfit_disable(struct intel_crtc *crtc)
@@ -6310,7 +6336,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
if (encoder->post_disable)
encoder->post_disable(encoder);
- if (!intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DSI)) {
+ if (!intel_crtc->config->has_dsi_encoder) {
if (IS_CHERRYVIEW(dev))
chv_disable_pll(dev_priv, pipe);
else if (IS_VALLEYVIEW(dev))
@@ -6325,6 +6351,8 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
if (!IS_GEN2(dev))
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
+
+ intel_fbc_disable_crtc(intel_crtc);
}
static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
@@ -6464,13 +6492,11 @@ static void intel_connector_check_state(struct intel_connector *connector)
int intel_connector_init(struct intel_connector *connector)
{
- struct drm_connector_state *connector_state;
+ drm_atomic_helper_connector_reset(&connector->base);
- connector_state = kzalloc(sizeof *connector_state, GFP_KERNEL);
- if (!connector_state)
+ if (!connector->base.state)
return -ENOMEM;
- connector->base.state = connector_state;
return 0;
}
@@ -7171,7 +7197,7 @@ static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state,
WARN_ON(!crtc_state->base.state);
- if (IS_VALLEYVIEW(dev) || IS_BROXTON(dev)) {
+ if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev) || IS_BROXTON(dev)) {
refclk = 100000;
} else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) &&
intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
@@ -7870,7 +7896,7 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
pipeconf |= PIPECONF_DOUBLE_WIDE;
/* only g4x and later have fancy bpc/dither controls */
- if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) {
+ if (IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
/* Bspec claims that we can't use dithering for 30bpp pipes. */
if (intel_crtc->config->dither && intel_crtc->config->pipe_bpp != 30)
pipeconf |= PIPECONF_DITHER_EN |
@@ -7910,7 +7936,8 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
} else
pipeconf |= PIPECONF_PROGRESSIVE;
- if (IS_VALLEYVIEW(dev) && intel_crtc->config->limited_color_range)
+ if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
+ intel_crtc->config->limited_color_range)
pipeconf |= PIPECONF_COLOR_RANGE_SELECT;
I915_WRITE(PIPECONF(intel_crtc->pipe), pipeconf);
@@ -7925,8 +7952,6 @@ static int i9xx_crtc_compute_clock(struct intel_crtc *crtc,
int refclk, num_connectors = 0;
intel_clock_t clock;
bool ok;
- bool is_dsi = false;
- struct intel_encoder *encoder;
const intel_limit_t *limit;
struct drm_atomic_state *state = crtc_state->base.state;
struct drm_connector *connector;
@@ -7936,26 +7961,14 @@ static int i9xx_crtc_compute_clock(struct intel_crtc *crtc,
memset(&crtc_state->dpll_hw_state, 0,
sizeof(crtc_state->dpll_hw_state));
- for_each_connector_in_state(state, connector, connector_state, i) {
- if (connector_state->crtc != &crtc->base)
- continue;
-
- encoder = to_intel_encoder(connector_state->best_encoder);
-
- switch (encoder->type) {
- case INTEL_OUTPUT_DSI:
- is_dsi = true;
- break;
- default:
- break;
- }
+ if (crtc_state->has_dsi_encoder)
+ return 0;
- num_connectors++;
+ for_each_connector_in_state(state, connector, connector_state, i) {
+ if (connector_state->crtc == &crtc->base)
+ num_connectors++;
}
- if (is_dsi)
- return 0;
-
if (!crtc_state->clock_set) {
refclk = i9xx_get_refclk(crtc_state, num_connectors);
@@ -8171,7 +8184,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
if (!(tmp & PIPECONF_ENABLE))
return false;
- if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) {
+ if (IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
switch (tmp & PIPECONF_BPC_MASK) {
case PIPECONF_6BPC:
pipe_config->pipe_bpp = 18;
@@ -8187,7 +8200,8 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
}
}
- if (IS_VALLEYVIEW(dev) && (tmp & PIPECONF_COLOR_RANGE_SELECT))
+ if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
+ (tmp & PIPECONF_COLOR_RANGE_SELECT))
pipe_config->limited_color_range = true;
if (INTEL_INFO(dev)->gen < 4)
@@ -8215,7 +8229,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
pipe_config->pixel_multiplier = 1;
}
pipe_config->dpll_hw_state.dpll = I915_READ(DPLL(crtc->pipe));
- if (!IS_VALLEYVIEW(dev)) {
+ if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
/*
* DPLL_DVO_2X_MODE must be enabled for both DPLLs
* on 830. Filter it out here so that we don't
@@ -8567,6 +8581,67 @@ static void lpt_disable_clkout_dp(struct drm_device *dev)
mutex_unlock(&dev_priv->sb_lock);
}
+#define BEND_IDX(steps) ((50 + (steps)) / 5)
+
+static const uint16_t sscdivintphase[] = {
+ [BEND_IDX( 50)] = 0x3B23,
+ [BEND_IDX( 45)] = 0x3B23,
+ [BEND_IDX( 40)] = 0x3C23,
+ [BEND_IDX( 35)] = 0x3C23,
+ [BEND_IDX( 30)] = 0x3D23,
+ [BEND_IDX( 25)] = 0x3D23,
+ [BEND_IDX( 20)] = 0x3E23,
+ [BEND_IDX( 15)] = 0x3E23,
+ [BEND_IDX( 10)] = 0x3F23,
+ [BEND_IDX( 5)] = 0x3F23,
+ [BEND_IDX( 0)] = 0x0025,
+ [BEND_IDX( -5)] = 0x0025,
+ [BEND_IDX(-10)] = 0x0125,
+ [BEND_IDX(-15)] = 0x0125,
+ [BEND_IDX(-20)] = 0x0225,
+ [BEND_IDX(-25)] = 0x0225,
+ [BEND_IDX(-30)] = 0x0325,
+ [BEND_IDX(-35)] = 0x0325,
+ [BEND_IDX(-40)] = 0x0425,
+ [BEND_IDX(-45)] = 0x0425,
+ [BEND_IDX(-50)] = 0x0525,
+};
+
+/*
+ * Bend CLKOUT_DP
+ * steps -50 to 50 inclusive, in steps of 5
+ * < 0 slow down the clock, > 0 speed up the clock, 0 == no bend (135MHz)
+ * change in clock period = -(steps / 10) * 5.787 ps
+ */
+static void lpt_bend_clkout_dp(struct drm_i915_private *dev_priv, int steps)
+{
+ uint32_t tmp;
+ int idx = BEND_IDX(steps);
+
+ if (WARN_ON(steps % 5 != 0))
+ return;
+
+ if (WARN_ON(idx >= ARRAY_SIZE(sscdivintphase)))
+ return;
+
+ mutex_lock(&dev_priv->sb_lock);
+
+ if (steps % 10 != 0)
+ tmp = 0xAAAAAAAB;
+ else
+ tmp = 0x00000000;
+ intel_sbi_write(dev_priv, SBI_SSCDITHPHASE, tmp, SBI_ICLK);
+
+ tmp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE, SBI_ICLK);
+ tmp &= 0xffff0000;
+ tmp |= sscdivintphase[idx];
+ intel_sbi_write(dev_priv, SBI_SSCDIVINTPHASE, tmp, SBI_ICLK);
+
+ mutex_unlock(&dev_priv->sb_lock);
+}
+
+#undef BEND_IDX
+
static void lpt_init_pch_refclk(struct drm_device *dev)
{
struct intel_encoder *encoder;
@@ -8582,10 +8657,12 @@ static void lpt_init_pch_refclk(struct drm_device *dev)
}
}
- if (has_vga)
+ if (has_vga) {
+ lpt_bend_clkout_dp(to_i915(dev), 0);
lpt_enable_clkout_dp(dev, true, true);
- else
+ } else {
lpt_disable_clkout_dp(dev);
+ }
}
/*
@@ -8948,7 +9025,7 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc,
memset(&crtc_state->dpll_hw_state, 0,
sizeof(crtc_state->dpll_hw_state));
- is_lvds = intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS);
+ is_lvds = intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS);
WARN(!(HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)),
"Unexpected PCH type %d\n", INTEL_PCH_TYPE(dev));
@@ -9722,14 +9799,10 @@ static int broadwell_modeset_calc_cdclk(struct drm_atomic_state *state)
else
cdclk = 337500;
- /*
- * FIXME move the cdclk caclulation to
- * compute_config() so we can fail gracegully.
- */
if (cdclk > dev_priv->max_cdclk_freq) {
- DRM_ERROR("requested cdclk (%d kHz) exceeds max (%d kHz)\n",
- cdclk, dev_priv->max_cdclk_freq);
- cdclk = dev_priv->max_cdclk_freq;
+ DRM_DEBUG_KMS("requested cdclk (%d kHz) exceeds max (%d kHz)\n",
+ cdclk, dev_priv->max_cdclk_freq);
+ return -EINVAL;
}
to_intel_atomic_state(state)->cdclk = cdclk;
@@ -9824,6 +9897,7 @@ static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv,
break;
case PORT_CLK_SEL_SPLL:
pipe_config->shared_dpll = DPLL_ID_SPLL;
+ break;
}
}
@@ -11203,6 +11277,10 @@ static bool use_mmio_flip(struct intel_engine_cs *ring,
return true;
else if (i915.enable_execlists)
return true;
+ else if (obj->base.dma_buf &&
+ !reservation_object_test_signaled_rcu(obj->base.dma_buf->resv,
+ false))
+ return true;
else
return ring != i915_gem_request_get_ring(obj->last_write_req);
}
@@ -11317,6 +11395,9 @@ static void intel_mmio_flip_work_func(struct work_struct *work)
{
struct intel_mmio_flip *mmio_flip =
container_of(work, struct intel_mmio_flip, work);
+ struct intel_framebuffer *intel_fb =
+ to_intel_framebuffer(mmio_flip->crtc->base.primary->fb);
+ struct drm_i915_gem_object *obj = intel_fb->obj;
if (mmio_flip->req) {
WARN_ON(__i915_wait_request(mmio_flip->req,
@@ -11326,6 +11407,12 @@ static void intel_mmio_flip_work_func(struct work_struct *work)
i915_gem_request_unreference__unlocked(mmio_flip->req);
}
+ /* For framebuffer backed by dmabuf, wait for fence */
+ if (obj->base.dma_buf)
+ WARN_ON(reservation_object_wait_timeout_rcu(obj->base.dma_buf->resv,
+ false, false,
+ MAX_SCHEDULE_TIMEOUT) < 0);
+
intel_do_mmio_flip(mmio_flip);
kfree(mmio_flip);
}
@@ -11527,7 +11614,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev))
work->flip_count = I915_READ(PIPE_FLIPCOUNT_G4X(pipe)) + 1;
- if (IS_VALLEYVIEW(dev)) {
+ if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
ring = &dev_priv->ring[BCS];
if (obj->tiling_mode != intel_fb_obj(work->old_fb)->tiling_mode)
/* vlv: DISPLAY_FLIP fails to change tiling */
@@ -11596,7 +11683,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
to_intel_plane(primary)->frontbuffer_bit);
mutex_unlock(&dev->struct_mutex);
- intel_fbc_disable_crtc(intel_crtc);
+ intel_fbc_deactivate(intel_crtc);
intel_frontbuffer_flip_prepare(dev,
to_intel_plane(primary)->frontbuffer_bit);
@@ -11683,9 +11770,14 @@ static bool intel_wm_need_update(struct drm_plane *plane,
struct intel_plane_state *cur = to_intel_plane_state(plane->state);
/* Update watermarks on tiling or size changes. */
- if (!plane->state->fb || !state->fb ||
- plane->state->fb->modifier[0] != state->fb->modifier[0] ||
- plane->state->rotation != state->rotation ||
+ if (new->visible != cur->visible)
+ return true;
+
+ if (!cur->base.fb || !new->base.fb)
+ return false;
+
+ if (cur->base.fb->modifier[0] != new->base.fb->modifier[0] ||
+ cur->base.rotation != new->base.rotation ||
drm_rect_width(&new->src) != drm_rect_width(&cur->src) ||
drm_rect_height(&new->src) != drm_rect_height(&cur->src) ||
drm_rect_width(&new->dst) != drm_rect_width(&cur->dst) ||
@@ -11708,6 +11800,7 @@ static bool needs_scaling(struct intel_plane_state *state)
int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
struct drm_plane_state *plane_state)
{
+ struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc_state);
struct drm_crtc *crtc = crtc_state->crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct drm_plane *plane = plane_state->plane;
@@ -11754,25 +11847,17 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
plane->base.id, was_visible, visible,
turn_off, turn_on, mode_changed);
- if (turn_on) {
- intel_crtc->atomic.update_wm_pre = true;
- /* must disable cxsr around plane enable/disable */
- if (plane->type != DRM_PLANE_TYPE_CURSOR) {
- intel_crtc->atomic.disable_cxsr = true;
- /* to potentially re-enable cxsr */
- intel_crtc->atomic.wait_vblank = true;
- intel_crtc->atomic.update_wm_post = true;
- }
- } else if (turn_off) {
- intel_crtc->atomic.update_wm_post = true;
+ if (turn_on || turn_off) {
+ pipe_config->wm_changed = true;
+
/* must disable cxsr around plane enable/disable */
if (plane->type != DRM_PLANE_TYPE_CURSOR) {
if (is_crtc_enabled)
intel_crtc->atomic.wait_vblank = true;
- intel_crtc->atomic.disable_cxsr = true;
+ pipe_config->disable_cxsr = true;
}
} else if (intel_wm_need_update(plane, plane_state)) {
- intel_crtc->atomic.update_wm_pre = true;
+ pipe_config->wm_changed = true;
}
if (visible || was_visible)
@@ -11917,7 +12002,7 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
}
if (mode_changed && !crtc_state->active)
- intel_crtc->atomic.update_wm_post = true;
+ pipe_config->wm_changed = true;
if (mode_changed && crtc_state->enable &&
dev_priv->display.crtc_compute_clock &&
@@ -12008,7 +12093,7 @@ compute_baseline_pipe_bpp(struct intel_crtc *crtc,
struct drm_connector_state *connector_state;
int bpp, i;
- if ((IS_G4X(dev) || IS_VALLEYVIEW(dev)))
+ if ((IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)))
bpp = 10*3;
else if (INTEL_INFO(dev)->gen >= 5)
bpp = 12*3;
@@ -12603,6 +12688,8 @@ intel_pipe_config_compare(struct drm_device *dev,
} else
PIPE_CONF_CHECK_M_N_ALT(dp_m_n, dp_m2_n2);
+ PIPE_CONF_CHECK_I(has_dsi_encoder);
+
PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hdisplay);
PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_htotal);
PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hblank_start);
@@ -12620,7 +12707,7 @@ intel_pipe_config_compare(struct drm_device *dev,
PIPE_CONF_CHECK_I(pixel_multiplier);
PIPE_CONF_CHECK_I(has_hdmi_sink);
if ((INTEL_INFO(dev)->gen < 8 && !IS_HASWELL(dev)) ||
- IS_VALLEYVIEW(dev))
+ IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
PIPE_CONF_CHECK_I(limited_color_range);
PIPE_CONF_CHECK_I(has_infoframe);
@@ -13399,6 +13486,16 @@ static int intel_atomic_commit(struct drm_device *dev,
dev_priv->display.crtc_disable(crtc);
intel_crtc->active = false;
intel_disable_shared_dpll(intel_crtc);
+
+ /*
+ * Underruns don't always raise
+ * interrupts, so check manually.
+ */
+ intel_check_cpu_fifo_underruns(dev_priv);
+ intel_check_pch_fifo_underruns(dev_priv);
+
+ if (!crtc->state->active)
+ intel_update_watermarks(crtc);
}
}
@@ -13668,6 +13765,19 @@ intel_prepare_plane_fb(struct drm_plane *plane,
return ret;
}
+ /* For framebuffer backed by dmabuf, wait for fence */
+ if (obj && obj->base.dma_buf) {
+ long lret;
+
+ lret = reservation_object_wait_timeout_rcu(obj->base.dma_buf->resv,
+ false, true,
+ MAX_SCHEDULE_TIMEOUT);
+ if (lret == -ERESTARTSYS)
+ return lret;
+
+ WARN(lret < 0, "waiting returns %li\n", lret);
+ }
+
if (!obj) {
ret = 0;
} else if (plane->type == DRM_PLANE_TYPE_CURSOR &&
@@ -13823,9 +13933,6 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc,
to_intel_crtc_state(old_crtc_state);
bool modeset = needs_modeset(crtc->state);
- if (intel_crtc->atomic.update_wm_pre)
- intel_update_watermarks(crtc);
-
/* Perform vblank evasion around commit operation */
intel_pipe_update_start(intel_crtc);
@@ -13920,7 +14027,7 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
drm_universal_plane_init(dev, &primary->base, 0,
&intel_plane_funcs,
intel_primary_formats, num_formats,
- DRM_PLANE_TYPE_PRIMARY);
+ DRM_PLANE_TYPE_PRIMARY, NULL);
if (INTEL_INFO(dev)->gen >= 4)
intel_create_rotation_property(dev, primary);
@@ -14072,7 +14179,7 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
&intel_plane_funcs,
intel_cursor_formats,
ARRAY_SIZE(intel_cursor_formats),
- DRM_PLANE_TYPE_CURSOR);
+ DRM_PLANE_TYPE_CURSOR, NULL);
if (INTEL_INFO(dev)->gen >= 4) {
if (!dev->mode_config.rotation_property)
@@ -14149,7 +14256,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
goto fail;
ret = drm_crtc_init_with_planes(dev, &intel_crtc->base, primary,
- cursor, &intel_crtc_funcs);
+ cursor, &intel_crtc_funcs, NULL);
if (ret)
goto fail;
@@ -14275,7 +14382,14 @@ static bool intel_crt_present(struct drm_device *dev)
if (IS_CHERRYVIEW(dev))
return false;
- if (IS_VALLEYVIEW(dev) && !dev_priv->vbt.int_crt_support)
+ if (HAS_PCH_LPT_H(dev) && I915_READ(SFUSE_STRAP) & SFUSE_STRAP_CRT_DISABLED)
+ return false;
+
+ /* DDI E can't be used if DDI A requires 4 lanes */
+ if (HAS_DDI(dev) && I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES)
+ return false;
+
+ if (!dev_priv->vbt.int_crt_support)
return false;
return true;
@@ -14360,7 +14474,7 @@ static void intel_setup_outputs(struct drm_device *dev)
if (I915_READ(PCH_DP_D) & DP_DETECTED)
intel_dp_init(dev, PCH_DP_D, PORT_D);
- } else if (IS_VALLEYVIEW(dev)) {
+ } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
/*
* The DP_DETECTED bit is the latched state of the DDC
* SDA pin at boot. However since eDP doesn't require DDC
@@ -14509,7 +14623,7 @@ u32 intel_fb_pitch_limit(struct drm_device *dev, uint64_t fb_modifier,
* pixels and 32K bytes."
*/
return min(8192*drm_format_plane_cpp(pixel_format, 0), 32768);
- } else if (gen >= 5 && !IS_VALLEYVIEW(dev)) {
+ } else if (gen >= 5 && !IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
return 32*1024;
} else if (gen >= 4) {
if (fb_modifier == I915_FORMAT_MOD_X_TILED)
@@ -14613,7 +14727,8 @@ static int intel_framebuffer_init(struct drm_device *dev,
}
break;
case DRM_FORMAT_ABGR8888:
- if (!IS_VALLEYVIEW(dev) && INTEL_INFO(dev)->gen < 9) {
+ if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) &&
+ INTEL_INFO(dev)->gen < 9) {
DRM_DEBUG("unsupported pixel format: %s\n",
drm_get_format_name(mode_cmd->pixel_format));
return -EINVAL;
@@ -14629,7 +14744,7 @@ static int intel_framebuffer_init(struct drm_device *dev,
}
break;
case DRM_FORMAT_ABGR2101010:
- if (!IS_VALLEYVIEW(dev)) {
+ if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
DRM_DEBUG("unsupported pixel format: %s\n",
drm_get_format_name(mode_cmd->pixel_format));
return -EINVAL;
@@ -14757,7 +14872,7 @@ static void intel_init_display(struct drm_device *dev)
dev_priv->display.crtc_disable = ironlake_crtc_disable;
dev_priv->display.update_primary_plane =
ironlake_update_primary_plane;
- } else if (IS_VALLEYVIEW(dev)) {
+ } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
dev_priv->display.get_initial_plane_config =
i9xx_get_initial_plane_config;
@@ -14790,7 +14905,7 @@ static void intel_init_display(struct drm_device *dev)
else if (IS_HASWELL(dev))
dev_priv->display.get_display_clock_speed =
haswell_get_display_clock_speed;
- else if (IS_VALLEYVIEW(dev))
+ else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
dev_priv->display.get_display_clock_speed =
valleyview_get_display_clock_speed;
else if (IS_GEN5(dev))
@@ -14818,9 +14933,6 @@ static void intel_init_display(struct drm_device *dev)
else if (IS_I945GM(dev) || IS_845G(dev))
dev_priv->display.get_display_clock_speed =
i9xx_misc_get_display_clock_speed;
- else if (IS_PINEVIEW(dev))
- dev_priv->display.get_display_clock_speed =
- pnv_get_display_clock_speed;
else if (IS_I915GM(dev))
dev_priv->display.get_display_clock_speed =
i915gm_get_display_clock_speed;
@@ -14851,7 +14963,7 @@ static void intel_init_display(struct drm_device *dev)
dev_priv->display.modeset_calc_cdclk =
broadwell_modeset_calc_cdclk;
}
- } else if (IS_VALLEYVIEW(dev)) {
+ } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
dev_priv->display.modeset_commit_cdclk =
valleyview_modeset_commit_cdclk;
dev_priv->display.modeset_calc_cdclk =
@@ -15338,6 +15450,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, NULL) < 0);
crtc->base.state->active = crtc->active;
crtc->base.enabled = crtc->active;
+ crtc->base.state->connector_mask = 0;
/* Because we only establish the connector -> encoder ->
* crtc links if something is active, this means the
@@ -15540,7 +15653,21 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
for_each_intel_connector(dev, connector) {
if (connector->get_hw_state(connector)) {
connector->base.dpms = DRM_MODE_DPMS_ON;
- connector->base.encoder = &connector->encoder->base;
+
+ encoder = connector->encoder;
+ connector->base.encoder = &encoder->base;
+
+ if (encoder->base.crtc &&
+ encoder->base.crtc->state->active) {
+ /*
+ * This has to be done during hardware readout
+ * because anything calling .crtc_disable may
+ * rely on the connector_mask being accurate.
+ */
+ encoder->base.crtc->state->connector_mask |=
+ 1 << drm_connector_index(&connector->base);
+ }
+
} else {
connector->base.dpms = DRM_MODE_DPMS_OFF;
connector->base.encoder = NULL;
@@ -15625,7 +15752,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev)
pll->on = false;
}
- if (IS_VALLEYVIEW(dev))
+ if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
vlv_wm_get_hw_state(dev);
else if (IS_GEN9(dev))
skl_wm_get_hw_state(dev);
@@ -15748,7 +15875,7 @@ void intel_connector_unregister(struct intel_connector *intel_connector)
void intel_modeset_cleanup(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- struct drm_connector *connector;
+ struct intel_connector *connector;
intel_disable_gt_powersave(dev);
@@ -15775,12 +15902,8 @@ void intel_modeset_cleanup(struct drm_device *dev)
flush_scheduled_work();
/* destroy the backlight and sysfs files before encoders/connectors */
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- struct intel_connector *intel_connector;
-
- intel_connector = to_intel_connector(connector);
- intel_connector->unregister(intel_connector);
- }
+ for_each_intel_connector(dev, connector)
+ connector->unregister(connector);
drm_mode_config_cleanup(dev);
@@ -15789,6 +15912,8 @@ void intel_modeset_cleanup(struct drm_device *dev)
mutex_lock(&dev->struct_mutex);
intel_cleanup_gt_powersave(dev);
mutex_unlock(&dev->struct_mutex);
+
+ intel_teardown_gmbus(dev);
}
/*
OpenPOWER on IntegriCloud