aboutsummaryrefslogtreecommitdiffstats
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.c1225
1 files changed, 787 insertions, 438 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 32cf97346978..2f00828ccc6e 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)
@@ -1096,7 +1099,7 @@ enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
static bool pipe_dsl_stopped(struct drm_device *dev, enum pipe pipe)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 reg = PIPEDSL(pipe);
+ i915_reg_t reg = PIPEDSL(pipe);
u32 line1, line2;
u32 line_mask;
@@ -1136,7 +1139,7 @@ static void intel_wait_for_pipe_off(struct intel_crtc *crtc)
enum pipe pipe = crtc->pipe;
if (INTEL_INFO(dev)->gen >= 4) {
- int reg = PIPECONF(cpu_transcoder);
+ i915_reg_t reg = PIPECONF(cpu_transcoder);
/* Wait for the Pipe State to go off */
if (wait_for((I915_READ(reg) & I965_PIPECONF_ACTIVE) == 0,
@@ -1286,7 +1289,7 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
struct drm_device *dev = dev_priv->dev;
- int pp_reg;
+ i915_reg_t pp_reg;
u32 val;
enum pipe panel_pipe = PIPE_A;
bool locked = true;
@@ -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,
@@ -1481,8 +1484,7 @@ static bool dp_pipe_enabled(struct drm_i915_private *dev_priv,
return false;
if (HAS_PCH_CPT(dev_priv->dev)) {
- u32 trans_dp_ctl_reg = TRANS_DP_CTL(pipe);
- u32 trans_dp_ctl = I915_READ(trans_dp_ctl_reg);
+ u32 trans_dp_ctl = I915_READ(TRANS_DP_CTL(pipe));
if ((trans_dp_ctl & TRANS_DP_PORT_SEL_MASK) != port_sel)
return false;
} else if (IS_CHERRYVIEW(dev_priv->dev)) {
@@ -1546,12 +1548,13 @@ static bool adpa_pipe_enabled(struct drm_i915_private *dev_priv,
}
static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv,
- enum pipe pipe, int reg, u32 port_sel)
+ enum pipe pipe, i915_reg_t reg,
+ u32 port_sel)
{
u32 val = I915_READ(reg);
I915_STATE_WARN(dp_pipe_enabled(dev_priv, pipe, port_sel, val),
"PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n",
- reg, pipe_name(pipe));
+ i915_mmio_reg_offset(reg), pipe_name(pipe));
I915_STATE_WARN(HAS_PCH_IBX(dev_priv->dev) && (val & DP_PORT_EN) == 0
&& (val & DP_PIPEB_SELECT),
@@ -1559,12 +1562,12 @@ static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv,
}
static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv,
- enum pipe pipe, int reg)
+ enum pipe pipe, i915_reg_t reg)
{
u32 val = I915_READ(reg);
I915_STATE_WARN(hdmi_pipe_enabled(dev_priv, pipe, val),
"PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n",
- reg, pipe_name(pipe));
+ i915_mmio_reg_offset(reg), pipe_name(pipe));
I915_STATE_WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_ENABLE) == 0
&& (val & SDVO_PIPE_B_SELECT),
@@ -1600,14 +1603,11 @@ static void vlv_enable_pll(struct intel_crtc *crtc,
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- int reg = DPLL(crtc->pipe);
+ i915_reg_t reg = DPLL(crtc->pipe);
u32 dpll = pipe_config->dpll_hw_state.dpll;
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 */
@@ -1689,7 +1687,7 @@ static void i9xx_enable_pll(struct intel_crtc *crtc)
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- int reg = DPLL(crtc->pipe);
+ i915_reg_t reg = DPLL(crtc->pipe);
u32 dpll = crtc->config->dpll_hw_state.dpll;
assert_pipe_disabled(dev_priv, crtc->pipe);
@@ -1838,7 +1836,7 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
unsigned int expected_mask)
{
u32 port_mask;
- int dpll_reg;
+ i915_reg_t dpll_reg;
switch (dport->port) {
case PORT_B:
@@ -1963,7 +1961,8 @@ static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv,
struct drm_device *dev = dev_priv->dev;
struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- uint32_t reg, val, pipeconf_val;
+ i915_reg_t reg;
+ uint32_t val, pipeconf_val;
/* PCH only available on ILK+ */
BUG_ON(!HAS_PCH_SPLIT(dev));
@@ -2052,7 +2051,8 @@ static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
struct drm_device *dev = dev_priv->dev;
- uint32_t reg, val;
+ i915_reg_t reg;
+ uint32_t val;
/* FDI relies on the transcoder */
assert_fdi_tx_disabled(dev_priv, pipe);
@@ -2069,7 +2069,7 @@ static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv,
if (wait_for((I915_READ(reg) & TRANS_STATE_ENABLE) == 0, 50))
DRM_ERROR("failed to disable transcoder %c\n", pipe_name(pipe));
- if (!HAS_PCH_IBX(dev)) {
+ if (HAS_PCH_CPT(dev)) {
/* Workaround: Clear the timing override chicken bit again. */
reg = TRANS_CHICKEN2(pipe);
val = I915_READ(reg);
@@ -2107,10 +2107,9 @@ static void intel_enable_pipe(struct intel_crtc *crtc)
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
enum pipe pipe = crtc->pipe;
- enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
- pipe);
+ enum transcoder cpu_transcoder = crtc->config->cpu_transcoder;
enum pipe pch_transcoder;
- int reg;
+ i915_reg_t reg;
u32 val;
DRM_DEBUG_KMS("enabling pipe %c\n", pipe_name(pipe));
@@ -2130,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);
@@ -2171,7 +2170,7 @@ static void intel_disable_pipe(struct intel_crtc *crtc)
struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
enum transcoder cpu_transcoder = crtc->config->cpu_transcoder;
enum pipe pipe = crtc->pipe;
- int reg;
+ i915_reg_t reg;
u32 val;
DRM_DEBUG_KMS("disabling pipe %c\n", pipe_name(pipe));
@@ -2270,20 +2269,20 @@ intel_fb_align_height(struct drm_device *dev, unsigned int height,
fb_format_modifier, 0));
}
-static int
+static void
intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
const struct drm_plane_state *plane_state)
{
- struct intel_rotation_info *info = &view->rotation_info;
+ struct intel_rotation_info *info = &view->params.rotation_info;
unsigned int tile_height, tile_pitch;
*view = i915_ggtt_view_normal;
if (!plane_state)
- return 0;
+ return;
if (!intel_rotation_90_or_270(plane_state->rotation))
- return 0;
+ return;
*view = i915_ggtt_view_rotated;
@@ -2310,8 +2309,6 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
info->size_uv = info->width_pages_uv * info->height_pages_uv *
PAGE_SIZE;
}
-
- return 0;
}
static unsigned int intel_linear_alignment(struct drm_i915_private *dev_priv)
@@ -2319,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;
@@ -2330,9 +2327,7 @@ static unsigned int intel_linear_alignment(struct drm_i915_private *dev_priv)
int
intel_pin_and_fence_fb_obj(struct drm_plane *plane,
struct drm_framebuffer *fb,
- const struct drm_plane_state *plane_state,
- struct intel_engine_cs *pipelined,
- struct drm_i915_gem_request **pipelined_request)
+ const struct drm_plane_state *plane_state)
{
struct drm_device *dev = fb->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -2367,9 +2362,7 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane,
return -EINVAL;
}
- ret = intel_fill_fb_ggtt_view(&view, fb, plane_state);
- if (ret)
- return ret;
+ intel_fill_fb_ggtt_view(&view, fb, plane_state);
/* Note that the w/a also requires 64 PTE of padding following the
* bo. We currently fill all unused PTE with the shadow page and so
@@ -2388,11 +2381,10 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane,
*/
intel_runtime_pm_get(dev_priv);
- dev_priv->mm.interruptible = false;
- ret = i915_gem_object_pin_to_display_plane(obj, alignment, pipelined,
- pipelined_request, &view);
+ ret = i915_gem_object_pin_to_display_plane(obj, alignment,
+ &view);
if (ret)
- goto err_interruptible;
+ goto err_pm;
/* Install a fence for tiled scan-out. Pre-i965 always needs a
* fence, whereas 965+ only requires a fence if using
@@ -2418,14 +2410,12 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane,
i915_gem_object_pin_fence(obj);
}
- dev_priv->mm.interruptible = true;
intel_runtime_pm_put(dev_priv);
return 0;
err_unpin:
i915_gem_object_unpin_from_display_plane(obj, &view);
-err_interruptible:
- dev_priv->mm.interruptible = true;
+err_pm:
intel_runtime_pm_put(dev_priv);
return ret;
}
@@ -2435,12 +2425,10 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb,
{
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
struct i915_ggtt_view view;
- int ret;
WARN_ON(!mutex_is_locked(&obj->base.dev->struct_mutex));
- ret = intel_fill_fb_ggtt_view(&view, fb, plane_state);
- WARN_ONCE(ret, "Couldn't get view from plane state!");
+ intel_fill_fb_ggtt_view(&view, fb, plane_state);
if (view.type == I915_GGTT_VIEW_NORMAL)
i915_gem_object_unpin_fence(obj);
@@ -2695,7 +2683,7 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
int plane = intel_crtc->plane;
unsigned long linear_offset;
u32 dspcntr;
- u32 reg = DSPCNTR(plane);
+ i915_reg_t reg = DSPCNTR(plane);
int pixel_size;
if (!visible || !fb) {
@@ -2825,7 +2813,7 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
int plane = intel_crtc->plane;
unsigned long linear_offset;
u32 dspcntr;
- u32 reg = DSPCNTR(plane);
+ i915_reg_t reg = DSPCNTR(plane);
int pixel_size;
if (!visible || !fb) {
@@ -2950,30 +2938,32 @@ u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier,
}
}
-unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
- struct drm_i915_gem_object *obj,
- unsigned int plane)
+u32 intel_plane_obj_offset(struct intel_plane *intel_plane,
+ struct drm_i915_gem_object *obj,
+ unsigned int plane)
{
- const struct i915_ggtt_view *view = &i915_ggtt_view_normal;
+ struct i915_ggtt_view view;
struct i915_vma *vma;
- unsigned char *offset;
+ u64 offset;
- if (intel_rotation_90_or_270(intel_plane->base.state->rotation))
- view = &i915_ggtt_view_rotated;
+ intel_fill_fb_ggtt_view(&view, intel_plane->base.fb,
+ intel_plane->base.state);
- vma = i915_gem_obj_to_ggtt_view(obj, view);
+ vma = i915_gem_obj_to_ggtt_view(obj, &view);
if (WARN(!vma, "ggtt vma for display object not found! (view=%u)\n",
- view->type))
+ view.type))
return -1;
- offset = (unsigned char *)vma->node.start;
+ offset = vma->node.start;
if (plane == 1) {
- offset += vma->ggtt_view.rotation_info.uv_start_page *
+ offset += vma->ggtt_view.params.rotation_info.uv_start_page *
PAGE_SIZE;
}
- return (unsigned long)offset;
+ WARN_ON(upper_32_bits(offset));
+
+ return lower_32_bits(offset);
}
static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
@@ -3099,7 +3089,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
u32 tile_height, plane_offset, plane_size;
unsigned int rotation;
int x_offset, y_offset;
- unsigned long surf_addr;
+ u32 surf_addr;
struct intel_crtc_state *crtc_state = intel_crtc->config;
struct intel_plane_state *plane_state;
int src_x = 0, src_y = 0, src_w = 0, src_h = 0;
@@ -3197,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);
@@ -3227,10 +3217,9 @@ static void intel_update_primary_planes(struct drm_device *dev)
struct intel_plane_state *plane_state;
drm_modeset_lock_crtc(crtc, &plane->base);
-
plane_state = to_intel_plane_state(plane->base.state);
- if (plane_state->base.fb)
+ if (crtc->state->active && plane_state->base.fb)
plane->commit_plane(&plane->base, plane_state);
drm_modeset_unlock_crtc(crtc);
@@ -3306,32 +3295,6 @@ void intel_finish_reset(struct drm_device *dev)
drm_modeset_unlock_all(dev);
}
-static void
-intel_finish_fb(struct drm_framebuffer *old_fb)
-{
- struct drm_i915_gem_object *obj = intel_fb_obj(old_fb);
- struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
- bool was_interruptible = dev_priv->mm.interruptible;
- int ret;
-
- /* Big Hammer, we also need to ensure that any pending
- * MI_WAIT_FOR_EVENT inside a user batch buffer on the
- * current scanout is retired before unpinning the old
- * framebuffer. Note that we rely on userspace rendering
- * into the buffer attached to the pipe they are waiting
- * on. If not, userspace generates a GPU hang with IPEHR
- * point to the MI_WAIT_FOR_EVENT.
- *
- * This should only fail upon a hung GPU, in which case we
- * can safely continue.
- */
- dev_priv->mm.interruptible = false;
- ret = i915_gem_object_wait_rendering(obj, true);
- dev_priv->mm.interruptible = was_interruptible;
-
- WARN_ON(ret);
-}
-
static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
@@ -3401,7 +3364,8 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe;
- u32 reg, temp;
+ i915_reg_t reg;
+ u32 temp;
/* enable normal train */
reg = FDI_TX_CTL(pipe);
@@ -3443,7 +3407,8 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe;
- u32 reg, temp, tries;
+ i915_reg_t reg;
+ u32 temp, tries;
/* FDI needs bits from pipe first */
assert_pipe_enabled(dev_priv, pipe);
@@ -3543,7 +3508,8 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe;
- u32 reg, temp, i, retry;
+ i915_reg_t reg;
+ u32 temp, i, retry;
/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
for train result */
@@ -3675,7 +3641,8 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe;
- u32 reg, temp, i, j;
+ i915_reg_t reg;
+ u32 temp, i, j;
/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
for train result */
@@ -3792,8 +3759,8 @@ static void ironlake_fdi_pll_enable(struct intel_crtc *intel_crtc)
struct drm_device *dev = intel_crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
int pipe = intel_crtc->pipe;
- u32 reg, temp;
-
+ i915_reg_t reg;
+ u32 temp;
/* enable PCH FDI RX PLL, wait warmup plus DMI latency */
reg = FDI_RX_CTL(pipe);
@@ -3829,7 +3796,8 @@ static void ironlake_fdi_pll_disable(struct intel_crtc *intel_crtc)
struct drm_device *dev = intel_crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
int pipe = intel_crtc->pipe;
- u32 reg, temp;
+ i915_reg_t reg;
+ u32 temp;
/* Switch from PCDclk to Rawclk */
reg = FDI_RX_CTL(pipe);
@@ -3859,7 +3827,8 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe;
- u32 reg, temp;
+ i915_reg_t reg;
+ u32 temp;
/* disable CPU FDI tx and PCH FDI rx */
reg = FDI_TX_CTL(pipe);
@@ -3952,15 +3921,23 @@ static void page_flip_completed(struct intel_crtc *intel_crtc)
work->pending_flip_obj);
}
-void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
+static int intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
+ long ret;
WARN_ON(waitqueue_active(&dev_priv->pending_flip_queue));
- if (WARN_ON(wait_event_timeout(dev_priv->pending_flip_queue,
- !intel_crtc_has_pending_flip(crtc),
- 60*HZ) == 0)) {
+
+ ret = wait_event_interruptible_timeout(
+ dev_priv->pending_flip_queue,
+ !intel_crtc_has_pending_flip(crtc),
+ 60*HZ);
+
+ if (ret < 0)
+ return ret;
+
+ if (ret == 0) {
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
spin_lock_irq(&dev->event_lock);
@@ -3971,11 +3948,22 @@ void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
spin_unlock_irq(&dev->event_lock);
}
- if (crtc->primary->fb) {
- mutex_lock(&dev->struct_mutex);
- intel_finish_fb(crtc->primary->fb);
- mutex_unlock(&dev->struct_mutex);
- }
+ 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 */
@@ -3987,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) {
@@ -4016,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;
@@ -4038,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;
@@ -4059,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,
@@ -4135,6 +4114,22 @@ static void ivybridge_update_fdi_bc_bifurcation(struct intel_crtc *intel_crtc)
}
}
+/* Return which DP Port should be selected for Transcoder DP control */
+static enum port
+intel_trans_dp_port_sel(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct intel_encoder *encoder;
+
+ for_each_encoder_on_crtc(dev, crtc, encoder) {
+ if (encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
+ encoder->type == INTEL_OUTPUT_EDP)
+ return enc_to_dig_port(&encoder->base)->port;
+ }
+
+ return -1;
+}
+
/*
* Enable PCH resources required for PCH ports:
* - PCH PLLs
@@ -4149,7 +4144,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe;
- u32 reg, temp;
+ u32 temp;
assert_pch_transcoder_disabled(dev_priv, pipe);
@@ -4161,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);
@@ -4194,10 +4195,14 @@ 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 =
+ &intel_crtc->config->base.adjusted_mode;
u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) >> 5;
- reg = TRANS_DP_CTL(pipe);
+ i915_reg_t reg = TRANS_DP_CTL(pipe);
temp = I915_READ(reg);
temp &= ~(TRANS_DP_PORT_SEL_MASK |
TRANS_DP_SYNC_MASK |
@@ -4205,19 +4210,19 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
temp |= TRANS_DP_OUTPUT_ENABLE;
temp |= bpc << 9; /* same format but at 11:9 */
- if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC)
+ if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
temp |= TRANS_DP_HSYNC_ACTIVE_HIGH;
- if (crtc->mode.flags & DRM_MODE_FLAG_PVSYNC)
+ if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
temp |= TRANS_DP_VSYNC_ACTIVE_HIGH;
switch (intel_trans_dp_port_sel(crtc)) {
- case PCH_DP_B:
+ case PORT_B:
temp |= TRANS_DP_PORT_SEL_B;
break;
- case PCH_DP_C:
+ case PORT_C:
temp |= TRANS_DP_PORT_SEL_C;
break;
- case PCH_DP_D:
+ case PORT_D:
temp |= TRANS_DP_PORT_SEL_D;
break;
default:
@@ -4357,7 +4362,7 @@ static void intel_shared_dpll_commit(struct drm_atomic_state *state)
static void cpt_verify_modeset(struct drm_device *dev, int pipe)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- int dslreg = PIPEDSL(pipe);
+ i915_reg_t dslreg = PIPEDSL(pipe);
u32 temp;
temp = I915_READ(dslreg);
@@ -4650,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);
@@ -4667,7 +4672,7 @@ static void intel_crtc_load_lut(struct drm_crtc *crtc)
}
for (i = 0; i < 256; i++) {
- u32 palreg;
+ i915_reg_t palreg;
if (HAS_GMCH_DISPLAY(dev))
palreg = PALETTE(pipe, i);
@@ -4721,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
@@ -4746,9 +4743,9 @@ intel_post_enable_primary(struct drm_crtc *crtc)
if (IS_GEN2(dev))
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
- /* Underruns don't raise interrupts, so check manually. */
- if (HAS_GMCH_DISPLAY(dev))
- i9xx_check_fifo_underruns(dev_priv);
+ /* Underruns don't always raise interrupts, so check manually. */
+ intel_check_cpu_fifo_underruns(dev_priv);
+ intel_check_pch_fifo_underruns(dev_priv);
}
/**
@@ -4805,31 +4802,26 @@ 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;
- struct drm_plane *plane;
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);
- drm_for_each_plane_mask(plane, dev, atomic->update_sprite_watermarks)
- intel_update_sprite_watermarks(plane, &crtc->base,
- 0, 0, 0, false, false);
-
memset(atomic, 0, sizeof(*atomic));
}
@@ -4838,23 +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 drm_plane *p;
-
- /* Track fb's for any planes being disabled */
- drm_for_each_plane_mask(p, dev, atomic->disabled_planes) {
- struct intel_plane *plane = to_intel_plane(p);
-
- mutex_lock(&dev->struct_mutex);
- i915_gem_track_fb(intel_fb_obj(plane->base.fb), NULL,
- plane->frontbuffer_bit);
- mutex_unlock(&dev->struct_mutex);
- }
-
- if (atomic->wait_for_flips)
- intel_crtc_wait_for_pending_flips(&crtc->base);
+ 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);
@@ -4862,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)
@@ -4900,6 +4883,9 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
return;
if (intel_crtc->config->has_pch_encoder)
+ intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false);
+
+ if (intel_crtc->config->has_pch_encoder)
intel_prepare_shared_dpll(intel_crtc);
if (intel_crtc->config->has_dp_encoder)
@@ -4917,7 +4903,6 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
intel_crtc->active = true;
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
- intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true);
for_each_encoder_on_crtc(dev, crtc, encoder)
if (encoder->pre_enable)
@@ -4955,6 +4940,13 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
if (HAS_PCH_CPT(dev))
cpt_verify_modeset(dev, intel_crtc->pipe);
+
+ /* Must wait for vblank to avoid spurious PCH FIFO underruns */
+ 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. */
@@ -4972,11 +4964,14 @@ 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;
+ if (intel_crtc->config->has_pch_encoder)
+ intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
+ false);
+
if (intel_crtc_to_shared_dpll(intel_crtc))
intel_enable_shared_dpll(intel_crtc);
@@ -5001,21 +4996,20 @@ 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);
}
- if (intel_crtc->config->has_pch_encoder) {
- intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
- true);
+ 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)
@@ -5030,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);
@@ -5039,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);
@@ -5050,6 +5044,14 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
intel_opregion_notify_encoder(encoder, true);
}
+ 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. */
hsw_workaround_pipe = pipe_config->hsw_workaround_pipe;
@@ -5057,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)
@@ -5081,7 +5085,9 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_encoder *encoder;
int pipe = intel_crtc->pipe;
- u32 reg, temp;
+
+ if (intel_crtc->config->has_pch_encoder)
+ intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false);
for_each_encoder_on_crtc(dev, crtc, encoder)
encoder->disable(encoder);
@@ -5089,15 +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_pch_fifo_underrun_reporting(dev_priv, pipe, false);
+ 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)
@@ -5107,6 +5120,9 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
ironlake_disable_pch_transcoder(dev_priv, pipe);
if (HAS_PCH_CPT(dev)) {
+ i915_reg_t reg;
+ u32 temp;
+
/* disable TRANS_DP_CTL */
reg = TRANS_DP_CTL(pipe);
temp = I915_READ(reg);
@@ -5123,6 +5139,10 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
ironlake_fdi_pll_disable(intel_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)
@@ -5132,7 +5152,10 @@ 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,
+ false);
for_each_encoder_on_crtc(dev, crtc, encoder) {
intel_opregion_notify_encoder(encoder, false);
@@ -5142,15 +5165,12 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
drm_crtc_vblank_off(crtc);
assert_vblank_disabled(crtc);
- if (intel_crtc->config->has_pch_encoder)
- intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
- false);
intel_disable_pipe(intel_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)
@@ -5158,17 +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);
+ for_each_encoder_on_crtc(dev, crtc, encoder)
+ if (encoder->post_disable)
+ encoder->post_disable(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);
}
- for_each_encoder_on_crtc(dev, crtc, encoder)
- if (encoder->post_disable)
- encoder->post_disable(encoder);
+ intel_fbc_disable_crtc(intel_crtc);
}
static void i9xx_pfit_enable(struct intel_crtc *crtc)
@@ -5199,15 +5225,15 @@ static enum intel_display_power_domain port_to_power_domain(enum port port)
{
switch (port) {
case PORT_A:
- return POWER_DOMAIN_PORT_DDI_A_4_LANES;
+ return POWER_DOMAIN_PORT_DDI_A_LANES;
case PORT_B:
- return POWER_DOMAIN_PORT_DDI_B_4_LANES;
+ return POWER_DOMAIN_PORT_DDI_B_LANES;
case PORT_C:
- return POWER_DOMAIN_PORT_DDI_C_4_LANES;
+ return POWER_DOMAIN_PORT_DDI_C_LANES;
case PORT_D:
- return POWER_DOMAIN_PORT_DDI_D_4_LANES;
+ return POWER_DOMAIN_PORT_DDI_D_LANES;
case PORT_E:
- return POWER_DOMAIN_PORT_DDI_E_2_LANES;
+ return POWER_DOMAIN_PORT_DDI_E_LANES;
default:
MISSING_CASE(port);
return POWER_DOMAIN_PORT_OTHER;
@@ -5234,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)
{
@@ -5302,13 +5324,11 @@ static unsigned long get_crtc_power_domains(struct drm_crtc *crtc)
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
enum pipe pipe = intel_crtc->pipe;
unsigned long mask;
- enum transcoder transcoder;
+ enum transcoder transcoder = intel_crtc->config->cpu_transcoder;
if (!crtc->state->active)
return 0;
- transcoder = intel_pipe_to_cpu_transcoder(dev->dev_private, pipe);
-
mask = BIT(POWER_DOMAIN_PIPE(pipe));
mask |= BIT(POWER_DOMAIN_TRANSCODER(transcoder));
if (intel_crtc->config->pch_pfit.enabled ||
@@ -5395,7 +5415,7 @@ static void intel_update_max_cdclk(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- if (IS_SKYLAKE(dev)) {
+ if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
u32 limit = I915_READ(SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK;
if (limit == SKL_DFSM_CDCLK_LIMIT_675)
@@ -5452,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
@@ -5812,32 +5832,16 @@ void skl_uninit_cdclk(struct drm_i915_private *dev_priv)
if (I915_READ(DBUF_CTL) & DBUF_POWER_STATE)
DRM_ERROR("DBuf power disable timeout\n");
- /*
- * DMC assumes ownership of LCPLL and will get confused if we touch it.
- */
- if (dev_priv->csr.dmc_payload) {
- /* disable DPLL0 */
- I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) &
- ~LCPLL_PLL_ENABLE);
- if (wait_for(!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_LOCK), 1))
- DRM_ERROR("Couldn't disable DPLL0\n");
- }
-
- intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+ /* disable DPLL0 */
+ I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) & ~LCPLL_PLL_ENABLE);
+ if (wait_for(!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_LOCK), 1))
+ DRM_ERROR("Couldn't disable DPLL0\n");
}
void skl_init_cdclk(struct drm_i915_private *dev_priv)
{
- u32 val;
unsigned int required_vco;
- /* enable PCH reset handshake */
- val = I915_READ(HSW_NDE_RSTWRN_OPT);
- I915_WRITE(HSW_NDE_RSTWRN_OPT, val | RESET_PCH_HANDSHAKE_ENABLE);
-
- /* enable PG1 and Misc I/O */
- intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS);
-
/* DPLL0 not enabled (happens on early BIOS versions) */
if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) {
/* enable DPLL0 */
@@ -5858,6 +5862,45 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv)
DRM_ERROR("DBuf power enable timeout\n");
}
+int skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
+{
+ uint32_t lcpll1 = I915_READ(LCPLL1_CTL);
+ uint32_t cdctl = I915_READ(CDCLK_CTL);
+ int freq = dev_priv->skl_boot_cdclk;
+
+ /*
+ * check if the pre-os intialized the display
+ * There is SWF18 scratchpad register defined which is set by the
+ * pre-os which can be used by the OS drivers to check the status
+ */
+ if ((I915_READ(SWF_ILK(0x18)) & 0x00FFFFFF) == 0)
+ goto sanitize;
+
+ /* Is PLL enabled and locked ? */
+ if (!((lcpll1 & LCPLL_PLL_ENABLE) && (lcpll1 & LCPLL_PLL_LOCK)))
+ goto sanitize;
+
+ /* DPLL okay; verify the cdclock
+ *
+ * Noticed in some instances that the freq selection is correct but
+ * decimal part is programmed wrong from BIOS where pre-os does not
+ * enable display. Verify the same as well.
+ */
+ if (cdctl == ((cdctl & CDCLK_FREQ_SEL_MASK) | skl_cdclk_decimal(freq)))
+ /* All well; nothing to sanitize */
+ return false;
+sanitize:
+ /*
+ * As of now initialize with max cdclk till
+ * we get dynamic cdclk support
+ * */
+ dev_priv->skl_boot_cdclk = dev_priv->max_cdclk_freq;
+ skl_init_cdclk(dev_priv);
+
+ /* we did have to sanitize */
+ return true;
+}
+
/* Adjust CDclk dividers to allow high res or save power if possible */
static void valleyview_set_cdclk(struct drm_device *dev, int cdclk)
{
@@ -6139,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);
@@ -6168,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);
@@ -6247,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)
@@ -6294,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))
@@ -6309,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)
@@ -6322,7 +6366,8 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
return;
if (to_intel_plane_state(crtc->primary->state)->visible) {
- intel_crtc_wait_for_pending_flips(crtc);
+ WARN_ON(intel_crtc->unpin_work);
+
intel_pre_disable_primary(crtc);
intel_crtc_disable_planes(crtc, 1 << drm_plane_index(crtc->primary));
@@ -6447,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;
}
@@ -6642,6 +6685,15 @@ static void hsw_compute_ips_config(struct intel_crtc *crtc,
pipe_config_supports_ips(dev_priv, pipe_config);
}
+static bool intel_crtc_supports_double_wide(const struct intel_crtc *crtc)
+{
+ const struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+
+ /* GDG double wide on either pipe, otherwise pipe A only */
+ return INTEL_INFO(dev_priv)->gen < 4 &&
+ (crtc->pipe == PIPE_A || IS_I915G(dev_priv));
+}
+
static int intel_crtc_compute_config(struct intel_crtc *crtc,
struct intel_crtc_state *pipe_config)
{
@@ -6651,23 +6703,24 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
/* FIXME should check pixel clock limits on all platforms */
if (INTEL_INFO(dev)->gen < 4) {
- int clock_limit = dev_priv->max_cdclk_freq;
+ int clock_limit = dev_priv->max_cdclk_freq * 9 / 10;
/*
- * Enable pixel doubling when the dot clock
+ * Enable double wide mode when the dot clock
* is > 90% of the (display) core speed.
- *
- * GDG double wide on either pipe,
- * otherwise pipe A only.
*/
- if ((crtc->pipe == PIPE_A || IS_I915G(dev)) &&
- adjusted_mode->crtc_clock > clock_limit * 9 / 10) {
+ if (intel_crtc_supports_double_wide(crtc) &&
+ adjusted_mode->crtc_clock > clock_limit) {
clock_limit *= 2;
pipe_config->double_wide = true;
}
- if (adjusted_mode->crtc_clock > clock_limit * 9 / 10)
+ if (adjusted_mode->crtc_clock > clock_limit) {
+ DRM_DEBUG_KMS("requested pixel clock (%d kHz) too high (max: %d kHz, double wide: %s)\n",
+ adjusted_mode->crtc_clock, clock_limit,
+ yesno(pipe_config->double_wide));
return -EINVAL;
+ }
}
/*
@@ -7144,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) {
@@ -7432,7 +7485,7 @@ static void chv_prepare_pll(struct intel_crtc *crtc,
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
int pipe = crtc->pipe;
- int dpll_reg = DPLL(crtc->pipe);
+ i915_reg_t dpll_reg = DPLL(crtc->pipe);
enum dpio_channel port = vlv_pipe_to_channel(pipe);
u32 loopfilter, tribuf_calcntr;
u32 bestn, bestm1, bestm2, bestp1, bestp2, bestm2_frac;
@@ -7843,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 |
@@ -7883,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);
@@ -7898,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;
@@ -7909,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);
@@ -8144,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;
@@ -8160,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)
@@ -8188,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
@@ -8540,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;
@@ -8555,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);
+ }
}
/*
@@ -8921,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));
@@ -9350,8 +9454,8 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
I915_STATE_WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n");
I915_STATE_WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL enabled\n");
- I915_STATE_WARN(I915_READ(WRPLL_CTL1) & WRPLL_PLL_ENABLE, "WRPLL1 enabled\n");
- I915_STATE_WARN(I915_READ(WRPLL_CTL2) & WRPLL_PLL_ENABLE, "WRPLL2 enabled\n");
+ I915_STATE_WARN(I915_READ(WRPLL_CTL(0)) & WRPLL_PLL_ENABLE, "WRPLL1 enabled\n");
+ I915_STATE_WARN(I915_READ(WRPLL_CTL(1)) & WRPLL_PLL_ENABLE, "WRPLL2 enabled\n");
I915_STATE_WARN(I915_READ(PCH_PP_STATUS) & PP_ON, "Panel power on\n");
I915_STATE_WARN(I915_READ(BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE,
"CPU PWM1 enabled\n");
@@ -9695,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;
@@ -9797,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;
}
}
@@ -9813,7 +9914,7 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc,
port = (tmp & TRANS_DDI_PORT_MASK) >> TRANS_DDI_PORT_SHIFT;
- if (IS_SKYLAKE(dev))
+ if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
skylake_get_ddi_pll(dev_priv, port, pipe_config);
else if (IS_BROXTON(dev))
bxt_get_ddi_pll(dev_priv, port, pipe_config);
@@ -10154,20 +10255,17 @@ __intel_framebuffer_create(struct drm_device *dev,
int ret;
intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
- if (!intel_fb) {
- drm_gem_object_unreference(&obj->base);
+ if (!intel_fb)
return ERR_PTR(-ENOMEM);
- }
ret = intel_framebuffer_init(dev, intel_fb, mode_cmd, obj);
if (ret)
goto err;
return &intel_fb->base;
+
err:
- drm_gem_object_unreference(&obj->base);
kfree(intel_fb);
-
return ERR_PTR(ret);
}
@@ -10207,6 +10305,7 @@ intel_framebuffer_create_for_mode(struct drm_device *dev,
struct drm_display_mode *mode,
int depth, int bpp)
{
+ struct drm_framebuffer *fb;
struct drm_i915_gem_object *obj;
struct drm_mode_fb_cmd2 mode_cmd = { 0 };
@@ -10221,7 +10320,11 @@ intel_framebuffer_create_for_mode(struct drm_device *dev,
bpp);
mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth);
- return intel_framebuffer_create(dev, &mode_cmd, obj);
+ fb = intel_framebuffer_create(dev, &mode_cmd, obj);
+ if (IS_ERR(fb))
+ drm_gem_object_unreference_unlocked(&obj->base);
+
+ return fb;
}
static struct drm_framebuffer *
@@ -11124,7 +11227,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
*/
if (ring->id == RCS) {
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
- intel_ring_emit(ring, DERRMR);
+ intel_ring_emit_reg(ring, DERRMR);
intel_ring_emit(ring, ~(DERRMR_PIPEA_PRI_FLIP_DONE |
DERRMR_PIPEB_PRI_FLIP_DONE |
DERRMR_PIPEC_PRI_FLIP_DONE));
@@ -11134,7 +11237,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
else
intel_ring_emit(ring, MI_STORE_REGISTER_MEM |
MI_SRM_LRM_GLOBAL_GTT);
- intel_ring_emit(ring, DERRMR);
+ intel_ring_emit_reg(ring, DERRMR);
intel_ring_emit(ring, ring->scratch.gtt_offset + 256);
if (IS_GEN8(dev)) {
intel_ring_emit(ring, 0);
@@ -11174,18 +11277,23 @@ 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);
}
static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
+ unsigned int rotation,
struct intel_unpin_work *work)
{
struct drm_device *dev = intel_crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_framebuffer *fb = intel_crtc->base.primary->fb;
const enum pipe pipe = intel_crtc->pipe;
- u32 ctl, stride;
+ u32 ctl, stride, tile_height;
ctl = I915_READ(PLANE_CTL(pipe, 0));
ctl &= ~PLANE_CTL_TILED_MASK;
@@ -11209,9 +11317,16 @@ static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
* The stride is either expressed as a multiple of 64 bytes chunks for
* linear buffers or in number of tiles for tiled buffers.
*/
- stride = fb->pitches[0] /
- intel_fb_stride_alignment(dev, fb->modifier[0],
- fb->pixel_format);
+ if (intel_rotation_90_or_270(rotation)) {
+ /* stride = Surface height in tiles */
+ tile_height = intel_tile_height(dev, fb->pixel_format,
+ fb->modifier[0], 0);
+ stride = DIV_ROUND_UP(fb->height, tile_height);
+ } else {
+ stride = fb->pitches[0] /
+ intel_fb_stride_alignment(dev, fb->modifier[0],
+ fb->pixel_format);
+ }
/*
* Both PLANE_CTL and PLANE_STRIDE are not updated on vblank but on
@@ -11232,10 +11347,9 @@ static void ilk_do_mmio_flip(struct intel_crtc *intel_crtc,
struct intel_framebuffer *intel_fb =
to_intel_framebuffer(intel_crtc->base.primary->fb);
struct drm_i915_gem_object *obj = intel_fb->obj;
+ i915_reg_t reg = DSPCNTR(intel_crtc->plane);
u32 dspcntr;
- u32 reg;
- reg = DSPCNTR(intel_crtc->plane);
dspcntr = I915_READ(reg);
if (obj->tiling_mode != I915_TILING_NONE)
@@ -11269,7 +11383,7 @@ static void intel_do_mmio_flip(struct intel_mmio_flip *mmio_flip)
intel_pipe_update_start(crtc);
if (INTEL_INFO(mmio_flip->i915)->gen >= 9)
- skl_do_mmio_flip(crtc, work);
+ skl_do_mmio_flip(crtc, mmio_flip->rotation, work);
else
/* use_mmio_flip() retricts MMIO flips to ilk+ */
ilk_do_mmio_flip(crtc, work);
@@ -11281,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,
@@ -11290,16 +11407,19 @@ 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);
}
static int intel_queue_mmio_flip(struct drm_device *dev,
struct drm_crtc *crtc,
- struct drm_framebuffer *fb,
- struct drm_i915_gem_object *obj,
- struct intel_engine_cs *ring,
- uint32_t flags)
+ struct drm_i915_gem_object *obj)
{
struct intel_mmio_flip *mmio_flip;
@@ -11310,6 +11430,7 @@ static int intel_queue_mmio_flip(struct drm_device *dev,
mmio_flip->i915 = to_i915(dev);
mmio_flip->req = i915_gem_request_reference(obj->last_write_req);
mmio_flip->crtc = to_intel_crtc(crtc);
+ mmio_flip->rotation = crtc->primary->state->rotation;
INIT_WORK(&mmio_flip->work, intel_mmio_flip_work_func);
schedule_work(&mmio_flip->work);
@@ -11493,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 */
@@ -11515,9 +11636,14 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
* synchronisation, so all we want here is to pin the framebuffer
* into the display plane and skip any waits.
*/
+ if (!mmio_flip) {
+ ret = i915_gem_object_sync(obj, ring, &request);
+ if (ret)
+ goto cleanup_pending;
+ }
+
ret = intel_pin_and_fence_fb_obj(crtc->primary, fb,
- crtc->primary->state,
- mmio_flip ? i915_gem_request_get_ring(obj->last_write_req) : ring, &request);
+ crtc->primary->state);
if (ret)
goto cleanup_pending;
@@ -11526,8 +11652,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
work->gtt_offset += intel_crtc->dspaddr_offset;
if (mmio_flip) {
- ret = intel_queue_mmio_flip(dev, crtc, fb, obj, ring,
- page_flip_flags);
+ ret = intel_queue_mmio_flip(dev, crtc, obj);
if (ret)
goto cleanup_unpin;
@@ -11558,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);
@@ -11641,21 +11766,41 @@ retry:
static bool intel_wm_need_update(struct drm_plane *plane,
struct drm_plane_state *state)
{
- /* Update watermarks on tiling changes. */
- if (!plane->state->fb || !state->fb ||
- plane->state->fb->modifier[0] != state->fb->modifier[0] ||
- plane->state->rotation != state->rotation)
+ struct intel_plane_state *new = to_intel_plane_state(state);
+ struct intel_plane_state *cur = to_intel_plane_state(plane->state);
+
+ /* Update watermarks on tiling or size changes. */
+ if (new->visible != cur->visible)
return true;
- if (plane->state->crtc_w != state->crtc_w)
+ 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) ||
+ drm_rect_height(&new->dst) != drm_rect_height(&cur->dst))
return true;
return false;
}
+static bool needs_scaling(struct intel_plane_state *state)
+{
+ int src_w = drm_rect_width(&state->src) >> 16;
+ int src_h = drm_rect_height(&state->src) >> 16;
+ int dst_w = drm_rect_width(&state->dst);
+ int dst_h = drm_rect_height(&state->dst);
+
+ return (src_w != dst_w || src_h != dst_h);
+}
+
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;
@@ -11668,7 +11813,6 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
bool mode_changed = needs_modeset(crtc_state);
bool was_crtc_enabled = crtc->state->active;
bool is_crtc_enabled = crtc_state->active;
-
bool turn_off, turn_on, visible, was_visible;
struct drm_framebuffer *fb = plane_state->fb;
@@ -11681,14 +11825,6 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
return ret;
}
- /*
- * Disabling a plane is always okay; we just need to update
- * fb tracking in a special way since cleanup_fb() won't
- * get called by the plane helpers.
- */
- if (old_plane_state->base.fb && !fb)
- intel_crtc->atomic.disabled_planes |= 1 << i;
-
was_visible = old_plane_state->visible;
visible = to_intel_plane_state(plane_state)->visible;
@@ -11711,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)
@@ -11738,7 +11866,6 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
switch (plane->type) {
case DRM_PLANE_TYPE_PRIMARY:
- intel_crtc->atomic.wait_for_flips = true;
intel_crtc->atomic.pre_disable_primary = turn_off;
intel_crtc->atomic.post_enable_primary = turn_on;
@@ -11786,11 +11913,23 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
case DRM_PLANE_TYPE_CURSOR:
break;
case DRM_PLANE_TYPE_OVERLAY:
- if (turn_off && !mode_changed) {
+ /*
+ * WaCxSRDisabledForSpriteScaling:ivb
+ *
+ * cstate->update_wm was already set above, so this flag will
+ * take effect when we commit and program watermarks.
+ */
+ if (IS_IVYBRIDGE(dev) &&
+ needs_scaling(to_intel_plane_state(plane_state)) &&
+ !needs_scaling(old_plane_state)) {
+ to_intel_crtc_state(crtc_state)->disable_lp_wm = true;
+ } else if (turn_off && !mode_changed) {
intel_crtc->atomic.wait_vblank = true;
intel_crtc->atomic.update_sprite_watermarks |=
1 << i;
}
+
+ break;
}
return 0;
}
@@ -11863,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 &&
@@ -11875,6 +12014,12 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
}
ret = 0;
+ if (dev_priv->display.compute_pipe_wm) {
+ ret = dev_priv->display.compute_pipe_wm(intel_crtc, state);
+ if (ret)
+ return ret;
+ }
+
if (INTEL_INFO(dev)->gen >= 9) {
if (mode_changed)
ret = skl_update_scaler_crtc(pipe_config);
@@ -11948,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;
@@ -12064,7 +12209,7 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
pipe_config->dpll_hw_state.pll9,
pipe_config->dpll_hw_state.pll10,
pipe_config->dpll_hw_state.pcsdw12);
- } else if (IS_SKYLAKE(dev)) {
+ } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
DRM_DEBUG_KMS("ddi_pll_sel: %u; dpll_hw_state: "
"ctrl1: 0x%x, cfgcr1: 0x%x, cfgcr2: 0x%x\n",
pipe_config->ddi_pll_sel,
@@ -12322,6 +12467,18 @@ intel_modeset_update_crtc_state(struct drm_atomic_state *state)
crtc->hwmode = crtc->state->adjusted_mode;
else
crtc->hwmode.crtc_clock = 0;
+
+ /*
+ * Update legacy state to satisfy fbc code. This can
+ * be removed when fbc uses the atomic state.
+ */
+ if (drm_atomic_get_existing_plane_state(state, crtc->primary)) {
+ struct drm_plane_state *plane_state = crtc->primary->state;
+
+ crtc->primary->fb = plane_state->fb;
+ crtc->x = plane_state->src_x >> 16;
+ crtc->y = plane_state->src_y >> 16;
+ }
}
}
@@ -12347,7 +12504,7 @@ static bool intel_fuzzy_clock_check(int clock1, int clock2)
list_for_each_entry((intel_crtc), \
&(dev)->mode_config.crtc_list, \
base.head) \
- if (mask & (1 <<(intel_crtc)->pipe))
+ for_each_if (mask & (1 <<(intel_crtc)->pipe))
static bool
intel_compare_m_n(unsigned int m, unsigned int n,
@@ -12531,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);
@@ -12548,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);
@@ -13085,6 +13244,45 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
return 0;
}
+/*
+ * Handle calculation of various watermark data at the end of the atomic check
+ * phase. The code here should be run after the per-crtc and per-plane 'check'
+ * handlers to ensure that all derived state has been updated.
+ */
+static void calc_watermark_data(struct drm_atomic_state *state)
+{
+ struct drm_device *dev = state->dev;
+ struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
+ struct drm_crtc *crtc;
+ struct drm_crtc_state *cstate;
+ struct drm_plane *plane;
+ struct drm_plane_state *pstate;
+
+ /*
+ * Calculate watermark configuration details now that derived
+ * plane/crtc state is all properly updated.
+ */
+ drm_for_each_crtc(crtc, dev) {
+ cstate = drm_atomic_get_existing_crtc_state(state, crtc) ?:
+ crtc->state;
+
+ if (cstate->active)
+ intel_state->wm_config.num_pipes_active++;
+ }
+ drm_for_each_legacy_plane(plane, dev) {
+ pstate = drm_atomic_get_existing_plane_state(state, plane) ?:
+ plane->state;
+
+ if (!to_intel_plane_state(pstate)->visible)
+ continue;
+
+ intel_state->wm_config.sprites_enabled = true;
+ if (pstate->crtc_w != pstate->src_w >> 16 ||
+ pstate->crtc_h != pstate->src_h >> 16)
+ intel_state->wm_config.sprites_scaled = true;
+ }
+}
+
/**
* intel_atomic_check - validate state object
* @dev: drm device
@@ -13093,6 +13291,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
static int intel_atomic_check(struct drm_device *dev,
struct drm_atomic_state *state)
{
+ struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
struct drm_crtc *crtc;
struct drm_crtc_state *crtc_state;
int ret, i;
@@ -13160,10 +13359,81 @@ static int intel_atomic_check(struct drm_device *dev,
if (ret)
return ret;
} else
- to_intel_atomic_state(state)->cdclk =
- to_i915(state->dev)->cdclk_freq;
+ intel_state->cdclk = to_i915(state->dev)->cdclk_freq;
+
+ ret = drm_atomic_helper_check_planes(state->dev, state);
+ if (ret)
+ return ret;
- return drm_atomic_helper_check_planes(state->dev, state);
+ calc_watermark_data(state);
+
+ return 0;
+}
+
+static int intel_atomic_prepare_commit(struct drm_device *dev,
+ struct drm_atomic_state *state,
+ bool async)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_plane_state *plane_state;
+ struct drm_crtc_state *crtc_state;
+ struct drm_plane *plane;
+ struct drm_crtc *crtc;
+ int i, ret;
+
+ if (async) {
+ DRM_DEBUG_KMS("i915 does not yet support async commit\n");
+ return -EINVAL;
+ }
+
+ for_each_crtc_in_state(state, crtc, crtc_state, i) {
+ ret = intel_crtc_wait_for_pending_flips(crtc);
+ if (ret)
+ return ret;
+
+ if (atomic_read(&to_intel_crtc(crtc)->unpin_work_count) >= 2)
+ flush_workqueue(dev_priv->wq);
+ }
+
+ ret = mutex_lock_interruptible(&dev->struct_mutex);
+ if (ret)
+ return ret;
+
+ ret = drm_atomic_helper_prepare_planes(dev, state);
+ if (!ret && !async && !i915_reset_in_progress(&dev_priv->gpu_error)) {
+ u32 reset_counter;
+
+ reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
+ mutex_unlock(&dev->struct_mutex);
+
+ for_each_plane_in_state(state, plane, plane_state, i) {
+ struct intel_plane_state *intel_plane_state =
+ to_intel_plane_state(plane_state);
+
+ if (!intel_plane_state->wait_req)
+ continue;
+
+ ret = __i915_wait_request(intel_plane_state->wait_req,
+ reset_counter, true,
+ NULL, NULL);
+
+ /* Swallow -EIO errors to allow updates during hw lockup. */
+ if (ret == -EIO)
+ ret = 0;
+
+ if (ret)
+ break;
+ }
+
+ if (!ret)
+ return 0;
+
+ mutex_lock(&dev->struct_mutex);
+ drm_atomic_helper_cleanup_planes(dev, state);
+ }
+
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
}
/**
@@ -13187,22 +13457,20 @@ static int intel_atomic_commit(struct drm_device *dev,
bool async)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- struct drm_crtc *crtc;
struct drm_crtc_state *crtc_state;
+ struct drm_crtc *crtc;
int ret = 0;
int i;
bool any_ms = false;
- if (async) {
- DRM_DEBUG_KMS("i915 does not yet support async commit\n");
- return -EINVAL;
- }
-
- ret = drm_atomic_helper_prepare_planes(dev, state);
- if (ret)
+ ret = intel_atomic_prepare_commit(dev, state, async);
+ if (ret) {
+ DRM_DEBUG_ATOMIC("Preparing state failed with %i\n", ret);
return ret;
+ }
drm_atomic_helper_swap_state(dev, state);
+ dev_priv->wm.config = to_intel_atomic_state(state)->wm_config;
for_each_crtc_in_state(state, crtc, crtc_state, i) {
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -13218,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);
}
}
@@ -13240,6 +13518,9 @@ static int intel_atomic_commit(struct drm_device *dev,
to_intel_crtc_state(crtc->state)->update_pipe;
unsigned long put_domains = 0;
+ if (modeset)
+ intel_display_power_get(dev_priv, POWER_DOMAIN_MODESET);
+
if (modeset && crtc->state->active) {
update_scanline_offset(to_intel_crtc(crtc));
dev_priv->display.crtc_enable(crtc);
@@ -13255,18 +13536,26 @@ static int intel_atomic_commit(struct drm_device *dev,
if (!modeset)
intel_pre_plane_update(intel_crtc);
- drm_atomic_helper_commit_planes_on_crtc(crtc_state);
+ if (crtc->state->active &&
+ (crtc->state->planes_changed || update_pipe))
+ drm_atomic_helper_commit_planes_on_crtc(crtc_state);
if (put_domains)
modeset_put_power_domains(dev_priv, put_domains);
intel_post_plane_update(intel_crtc);
+
+ if (modeset)
+ intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET);
}
/* FIXME: add subpixel order */
drm_atomic_helper_wait_for_vblanks(dev, state);
+
+ mutex_lock(&dev->struct_mutex);
drm_atomic_helper_cleanup_planes(dev, state);
+ mutex_unlock(&dev->struct_mutex);
if (any_ms)
intel_modeset_check_state(dev, state);
@@ -13435,6 +13724,8 @@ static void intel_shared_dpll_init(struct drm_device *dev)
* bits. Some older platforms need special physical address handling for
* cursor planes.
*
+ * Must be called with struct_mutex held.
+ *
* Returns 0 on success, negative error code on failure.
*/
int
@@ -13445,28 +13736,71 @@ intel_prepare_plane_fb(struct drm_plane *plane,
struct drm_framebuffer *fb = new_state->fb;
struct intel_plane *intel_plane = to_intel_plane(plane);
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
- struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb);
+ struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->state->fb);
int ret = 0;
- if (!obj)
+ if (!obj && !old_obj)
return 0;
- mutex_lock(&dev->struct_mutex);
+ if (old_obj) {
+ struct drm_crtc_state *crtc_state =
+ drm_atomic_get_existing_crtc_state(new_state->state, plane->state->crtc);
+
+ /* Big Hammer, we also need to ensure that any pending
+ * MI_WAIT_FOR_EVENT inside a user batch buffer on the
+ * current scanout is retired before unpinning the old
+ * framebuffer. Note that we rely on userspace rendering
+ * into the buffer attached to the pipe they are waiting
+ * on. If not, userspace generates a GPU hang with IPEHR
+ * point to the MI_WAIT_FOR_EVENT.
+ *
+ * This should only fail upon a hung GPU, in which case we
+ * can safely continue.
+ */
+ if (needs_modeset(crtc_state))
+ ret = i915_gem_object_wait_rendering(old_obj, true);
+
+ /* Swallow -EIO errors to allow updates during hw lockup. */
+ if (ret && ret != -EIO)
+ 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 (plane->type == DRM_PLANE_TYPE_CURSOR &&
+ if (!obj) {
+ ret = 0;
+ } else if (plane->type == DRM_PLANE_TYPE_CURSOR &&
INTEL_INFO(dev)->cursor_needs_physical) {
int align = IS_I830(dev) ? 16 * 1024 : 256;
ret = i915_gem_object_attach_phys(obj, align);
if (ret)
DRM_DEBUG_KMS("failed to attach phys object\n");
} else {
- ret = intel_pin_and_fence_fb_obj(plane, fb, new_state, NULL, NULL);
+ ret = intel_pin_and_fence_fb_obj(plane, fb, new_state);
}
- if (ret == 0)
- i915_gem_track_fb(old_obj, obj, intel_plane->frontbuffer_bit);
+ if (ret == 0) {
+ if (obj) {
+ struct intel_plane_state *plane_state =
+ to_intel_plane_state(new_state);
- mutex_unlock(&dev->struct_mutex);
+ i915_gem_request_assign(&plane_state->wait_req,
+ obj->last_write_req);
+ }
+
+ i915_gem_track_fb(old_obj, obj, intel_plane->frontbuffer_bit);
+ }
return ret;
}
@@ -13477,23 +13811,35 @@ intel_prepare_plane_fb(struct drm_plane *plane,
* @fb: old framebuffer that was on plane
*
* Cleans up a framebuffer that has just been removed from a plane.
+ *
+ * Must be called with struct_mutex held.
*/
void
intel_cleanup_plane_fb(struct drm_plane *plane,
const struct drm_plane_state *old_state)
{
struct drm_device *dev = plane->dev;
- struct drm_i915_gem_object *obj = intel_fb_obj(old_state->fb);
+ struct intel_plane *intel_plane = to_intel_plane(plane);
+ struct intel_plane_state *old_intel_state;
+ struct drm_i915_gem_object *old_obj = intel_fb_obj(old_state->fb);
+ struct drm_i915_gem_object *obj = intel_fb_obj(plane->state->fb);
- if (!obj)
+ old_intel_state = to_intel_plane_state(old_state);
+
+ if (!obj && !old_obj)
return;
- if (plane->type != DRM_PLANE_TYPE_CURSOR ||
- !INTEL_INFO(dev)->cursor_needs_physical) {
- mutex_lock(&dev->struct_mutex);
+ if (old_obj && (plane->type != DRM_PLANE_TYPE_CURSOR ||
+ !INTEL_INFO(dev)->cursor_needs_physical))
intel_unpin_fb_obj(old_state->fb, old_state);
- mutex_unlock(&dev->struct_mutex);
- }
+
+ /* prepare_fb aborted? */
+ if ((old_obj && (old_obj->frontbuffer_bits & intel_plane->frontbuffer_bit)) ||
+ (obj && !(obj->frontbuffer_bits & intel_plane->frontbuffer_bit)))
+ i915_gem_track_fb(old_obj, obj, intel_plane->frontbuffer_bit);
+
+ i915_gem_request_assign(&old_intel_state->wait_req, NULL);
+
}
int
@@ -13512,7 +13858,7 @@ skl_max_scale(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state
crtc_clock = crtc_state->base.adjusted_mode.crtc_clock;
cdclk = to_intel_atomic_state(crtc_state->base.state)->cdclk;
- if (!crtc_clock || !cdclk)
+ if (WARN_ON_ONCE(!crtc_clock || cdclk < crtc_clock))
return DRM_PLANE_HELPER_NO_SCALING;
/*
@@ -13560,18 +13906,8 @@ intel_commit_primary_plane(struct drm_plane *plane,
struct drm_framebuffer *fb = state->base.fb;
struct drm_device *dev = plane->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_crtc *intel_crtc;
- struct drm_rect *src = &state->src;
crtc = crtc ? crtc : plane->crtc;
- intel_crtc = to_intel_crtc(crtc);
-
- plane->fb = fb;
- crtc->x = src->x1 >> 16;
- crtc->y = src->y1 >> 16;
-
- if (!crtc->state->active)
- return;
dev_priv->display.update_primary_plane(crtc, fb,
state->src.x1 >> 16,
@@ -13597,12 +13933,8 @@ 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 */
- if (crtc->state->active)
- intel_pipe_update_start(intel_crtc);
+ intel_pipe_update_start(intel_crtc);
if (modeset)
return;
@@ -13618,8 +13950,7 @@ static void intel_finish_crtc_commit(struct drm_crtc *crtc,
{
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- if (crtc->state->active)
- intel_pipe_update_end(intel_crtc);
+ intel_pipe_update_end(intel_crtc);
}
/**
@@ -13696,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);
@@ -13848,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)
@@ -13925,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;
@@ -14051,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;
@@ -14087,7 +14425,7 @@ static void intel_setup_outputs(struct drm_device *dev)
*/
found = I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_INIT_DISPLAY_DETECTED;
/* WaIgnoreDDIAStrap: skl */
- if (found || IS_SKYLAKE(dev))
+ if (found || IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
intel_ddi_init(dev, PORT_A);
/* DDI B, C and D detection is indicated by the SFUSE_STRAP
@@ -14103,7 +14441,7 @@ static void intel_setup_outputs(struct drm_device *dev)
/*
* On SKL we don't have a way to detect DDI-E so we rely on VBT.
*/
- if (IS_SKYLAKE(dev) &&
+ if ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) &&
(dev_priv->vbt.ddi_port_info[PORT_E].supports_dp ||
dev_priv->vbt.ddi_port_info[PORT_E].supports_dvi ||
dev_priv->vbt.ddi_port_info[PORT_E].supports_hdmi))
@@ -14118,7 +14456,7 @@ static void intel_setup_outputs(struct drm_device *dev)
if (I915_READ(PCH_HDMIB) & SDVO_DETECTED) {
/* PCH SDVOB multiplex with HDMIB */
- found = intel_sdvo_init(dev, PCH_SDVOB, true);
+ found = intel_sdvo_init(dev, PCH_SDVOB, PORT_B);
if (!found)
intel_hdmi_init(dev, PCH_HDMIB, PORT_B);
if (!found && (I915_READ(PCH_DP_B) & DP_DETECTED))
@@ -14136,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
@@ -14174,7 +14512,7 @@ static void intel_setup_outputs(struct drm_device *dev)
if (I915_READ(GEN3_SDVOB) & SDVO_DETECTED) {
DRM_DEBUG_KMS("probing SDVOB\n");
- found = intel_sdvo_init(dev, GEN3_SDVOB, true);
+ found = intel_sdvo_init(dev, GEN3_SDVOB, PORT_B);
if (!found && IS_G4X(dev)) {
DRM_DEBUG_KMS("probing HDMI on SDVOB\n");
intel_hdmi_init(dev, GEN4_HDMIB, PORT_B);
@@ -14188,7 +14526,7 @@ static void intel_setup_outputs(struct drm_device *dev)
if (I915_READ(GEN3_SDVOB) & SDVO_DETECTED) {
DRM_DEBUG_KMS("probing SDVOC\n");
- found = intel_sdvo_init(dev, GEN3_SDVOC, false);
+ found = intel_sdvo_init(dev, GEN3_SDVOC, PORT_C);
}
if (!found && (I915_READ(GEN3_SDVOC) & SDVO_DETECTED)) {
@@ -14285,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)
@@ -14389,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;
@@ -14405,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;
@@ -14454,8 +14793,9 @@ static int intel_framebuffer_init(struct drm_device *dev,
static struct drm_framebuffer *
intel_user_framebuffer_create(struct drm_device *dev,
struct drm_file *filp,
- struct drm_mode_fb_cmd2 *user_mode_cmd)
+ const struct drm_mode_fb_cmd2 *user_mode_cmd)
{
+ struct drm_framebuffer *fb;
struct drm_i915_gem_object *obj;
struct drm_mode_fb_cmd2 mode_cmd = *user_mode_cmd;
@@ -14464,7 +14804,11 @@ intel_user_framebuffer_create(struct drm_device *dev,
if (&obj->base == NULL)
return ERR_PTR(-ENOENT);
- return intel_framebuffer_create(dev, &mode_cmd, obj);
+ fb = intel_framebuffer_create(dev, &mode_cmd, obj);
+ if (IS_ERR(fb))
+ drm_gem_object_unreference_unlocked(&obj->base);
+
+ return fb;
}
#ifndef CONFIG_DRM_FBDEV_EMULATION
@@ -14528,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;
@@ -14549,7 +14893,7 @@ static void intel_init_display(struct drm_device *dev)
}
/* Returns the core display clock speed */
- if (IS_SKYLAKE(dev))
+ if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
dev_priv->display.get_display_clock_speed =
skylake_get_display_clock_speed;
else if (IS_BROXTON(dev))
@@ -14561,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))
@@ -14589,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;
@@ -14622,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 =
@@ -14838,7 +15179,7 @@ static void i915_disable_vga(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
u8 sr1;
- u32 vga_reg = i915_vgacntrl_reg(dev);
+ i915_reg_t vga_reg = i915_vgacntrl_reg(dev);
/* WaEnableVGAAccessThroughIOPort:ctg,elk,ilk,snb,ivb,vlv,hsw */
vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO);
@@ -14954,9 +15295,6 @@ void intel_modeset_init(struct drm_device *dev)
i915_disable_vga(dev);
intel_setup_outputs(dev);
- /* Just in case the BIOS is doing something questionable. */
- intel_fbc_disable(dev_priv);
-
drm_modeset_lock_all(dev);
intel_modeset_setup_hw_state(dev);
drm_modeset_unlock_all(dev);
@@ -15043,10 +15381,9 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 reg;
+ i915_reg_t reg = PIPECONF(crtc->config->cpu_transcoder);
/* Clear any frame start delays used for debugging left by the BIOS */
- reg = PIPECONF(crtc->config->cpu_transcoder);
I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
/* restore vblank interrupts to correct state */
@@ -15113,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
@@ -15200,7 +15538,7 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
void i915_redisable_vga_power_on(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 vga_reg = i915_vgacntrl_reg(dev);
+ i915_reg_t vga_reg = i915_vgacntrl_reg(dev);
if (!(I915_READ(vga_reg) & VGA_DISP_DISABLE)) {
DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n");
@@ -15239,7 +15577,7 @@ static void readout_plane_state(struct intel_crtc *crtc)
struct intel_plane_state *plane_state =
to_intel_plane_state(primary->state);
- plane_state->visible =
+ plane_state->visible = crtc->active &&
primary_get_hw_state(to_intel_plane(primary));
if (plane_state->visible)
@@ -15315,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;
@@ -15400,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);
@@ -15496,8 +15848,7 @@ void intel_modeset_gem_init(struct drm_device *dev)
mutex_lock(&dev->struct_mutex);
ret = intel_pin_and_fence_fb_obj(c->primary,
c->primary->fb,
- c->primary->state,
- NULL, NULL);
+ c->primary->state);
mutex_unlock(&dev->struct_mutex);
if (ret) {
DRM_ERROR("failed to pin boot fb on pipe %d\n",
@@ -15524,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);
@@ -15551,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);
@@ -15565,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);
}
/*