Bring in patch-series from drm-next to fix skl_update_other_pipe_wm issues

(rhbz 1305038)
- Cherry pick some other drm / kms fixes from upstream
This commit is contained in:
Hans de Goede 2016-06-20 21:00:31 +02:00
parent b983da8fef
commit 93f8d223fc
24 changed files with 3597 additions and 0 deletions

View File

@ -0,0 +1,198 @@
From 2a6f0971d09e2bb88d2ae40d91ceb2776090497d Mon Sep 17 00:00:00 2001
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
Date: Mon, 20 Jun 2016 11:11:50 +0200
Subject: [PATCH 01/17] drm/i915: Reorganize WM structs/unions in CRTC state
Upstream: since drm-intel-next-2016-05-22
commit e8f1f02e7125220b99af8047703b63c11a7081d6
Author: Matt Roper <matthew.d.roper@intel.com>
AuthorDate: Thu May 12 07:05:55 2016 -0700
Commit: Matt Roper <matthew.d.roper@intel.com>
CommitDate: Fri May 13 07:32:11 2016 -0700
drm/i915: Reorganize WM structs/unions in CRTC state
Reorganize the nested structures and unions we have for pipe watermark
data in intel_crtc_state so that platform-specific data can be added in
a more sensible manner (and save a bit of memory at the same time).
The change basically changes the organization from:
union {
struct intel_pipe_wm ilk;
struct intel_pipe_wm skl;
} optimal;
struct intel_pipe_wm intermediate /* ILK-only */
to
union {
struct {
struct intel_pipe_wm intermediate;
struct intel_pipe_wm optimal;
} ilk;
struct {
struct intel_pipe_wm optimal;
} skl;
}
There should be no functional change here, but it will allow us to add
more platform-specific fields going forward (and more easily extend to
other platform types like VLV).
While we're at it, let's move the entire watermark substructure out to
its own structure definition to make the code slightly more readable.
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-2-git-send-email-matthew.d.roper@intel.com
---
drivers/gpu/drm/i915/intel_drv.h | 48 +++++++++++++++++++++++++++++++---------
drivers/gpu/drm/i915/intel_pm.c | 16 +++++++-------
2 files changed, 46 insertions(+), 18 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 3a30b37..7d19baf 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -363,6 +363,40 @@ struct skl_pipe_wm {
uint32_t linetime;
};
+struct intel_crtc_wm_state {
+ union {
+ struct {
+ /*
+ * Intermediate watermarks; these can be
+ * programmed immediately since they satisfy
+ * both the current configuration we're
+ * switching away from and the new
+ * configuration we're switching to.
+ */
+ struct intel_pipe_wm intermediate;
+
+ /*
+ * Optimal watermarks, programmed post-vblank
+ * when this state is committed.
+ */
+ struct intel_pipe_wm optimal;
+ } ilk;
+
+ struct {
+ /* gen9+ only needs 1-step wm programming */
+ struct skl_pipe_wm optimal;
+ } skl;
+ };
+
+ /*
+ * Platforms with two-step watermark programming will need to
+ * update watermark programming post-vblank to switch from the
+ * safe intermediate watermarks to the optimal final
+ * watermarks.
+ */
+ bool need_postvbl_update;
+};
+
struct intel_crtc_state {
struct drm_crtc_state base;
@@ -509,16 +543,10 @@ struct intel_crtc_state {
/* IVB sprite scaling w/a (WaCxSRDisabledForSpriteScaling:ivb) */
bool disable_lp_wm;
- struct {
- /*
- * optimal watermarks, programmed post-vblank when this state
- * is committed
- */
- union {
- struct intel_pipe_wm ilk;
- struct skl_pipe_wm skl;
- } optimal;
- } wm;
+ struct intel_crtc_wm_state wm;
+
+ /* Gamma mode programmed on the pipe */
+ uint32_t gamma_mode;
};
struct vlv_wm_state {
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 54ab023..0da1d60 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2302,7 +2302,7 @@ static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc,
if (IS_ERR(cstate))
return PTR_ERR(cstate);
- pipe_wm = &cstate->wm.optimal.ilk;
+ pipe_wm = &cstate->wm.ilk.optimal;
memset(pipe_wm, 0, sizeof(*pipe_wm));
for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
@@ -2385,7 +2385,7 @@ static void ilk_merge_wm_level(struct drm_device *dev,
for_each_intel_crtc(dev, intel_crtc) {
const struct intel_crtc_state *cstate =
to_intel_crtc_state(intel_crtc->base.state);
- const struct intel_pipe_wm *active = &cstate->wm.optimal.ilk;
+ const struct intel_pipe_wm *active = &cstate->wm.ilk.optimal;
const struct intel_wm_level *wm = &active->wm[level];
if (!active->pipe_enabled)
@@ -2536,12 +2536,12 @@ static void ilk_compute_wm_results(struct drm_device *dev,
const struct intel_crtc_state *cstate =
to_intel_crtc_state(intel_crtc->base.state);
enum pipe pipe = intel_crtc->pipe;
- const struct intel_wm_level *r = &cstate->wm.optimal.ilk.wm[0];
+ const struct intel_wm_level *r = &cstate->wm.ilk.optimal.wm[0];
if (WARN_ON(!r->enable))
continue;
- results->wm_linetime[pipe] = cstate->wm.optimal.ilk.linetime;
+ results->wm_linetime[pipe] = cstate->wm.ilk.optimal.linetime;
results->wm_pipe[pipe] =
(r->pri_val << WM0_PIPE_PLANE_SHIFT) |
@@ -3617,7 +3617,7 @@ static void skl_update_wm(struct drm_crtc *crtc)
struct drm_i915_private *dev_priv = dev->dev_private;
struct skl_wm_values *results = &dev_priv->wm.skl_results;
struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
- struct skl_pipe_wm *pipe_wm = &cstate->wm.optimal.skl;
+ struct skl_pipe_wm *pipe_wm = &cstate->wm.skl.optimal;
/* Clear all dirty flags */
@@ -3711,7 +3711,7 @@ static void ilk_update_wm(struct drm_crtc *crtc)
intel_wait_for_vblank(crtc->dev, intel_crtc->pipe);
}
- intel_crtc->wm.active.ilk = cstate->wm.optimal.ilk;
+ intel_crtc->wm.active.ilk = cstate->wm.ilk.optimal;
ilk_program_watermarks(cstate);
}
@@ -3767,7 +3767,7 @@ static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc)
struct skl_wm_values *hw = &dev_priv->wm.skl_hw;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
- struct skl_pipe_wm *active = &cstate->wm.optimal.skl;
+ struct skl_pipe_wm *active = &cstate->wm.skl.optimal;
enum pipe pipe = intel_crtc->pipe;
int level, i, max_level;
uint32_t temp;
@@ -3833,7 +3833,7 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
struct ilk_wm_values *hw = &dev_priv->wm.hw;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
- struct intel_pipe_wm *active = &cstate->wm.optimal.ilk;
+ struct intel_pipe_wm *active = &cstate->wm.ilk.optimal;
enum pipe pipe = intel_crtc->pipe;
static const i915_reg_t wm0_pipe_reg[] = {
[PIPE_A] = WM0_PIPEA_ILK,
--
2.7.4

View File

@ -0,0 +1,58 @@
From 1e5895f2c6068fb9ae5356e3a751a29a22af5f01 Mon Sep 17 00:00:00 2001
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
Date: Mon, 20 Jun 2016 14:53:03 +0200
Subject: [PATCH 1/6] drm/mgag200: Black screen fix for G200e rev 4
Upstream: since drm-fixes-for-v4.7
commit d3922b69617b62bb2509936b68301f837229d9f0
Author: Mathieu Larouche <mathieu.larouche@matrox.com>
AuthorDate: Fri May 27 15:12:50 2016 -0400
Commit: Dave Airlie <airlied@redhat.com>
CommitDate: Wed Jun 1 15:25:04 2016 +1000
drm/mgag200: Black screen fix for G200e rev 4
- Fixed black screen for some resolutions of G200e rev4
- Fixed testm & testn which had predetermined value.
Reported-by: Jan Beulich <jbeulich@suse.com>
Signed-off-by: Mathieu Larouche <mathieu.larouche@matrox.com>
Cc: stable@vger.kernel.org
Signed-off-by: Dave Airlie <airlied@redhat.com>
---
drivers/gpu/drm/mgag200/mgag200_mode.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 14e64e0..d347dca 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -182,7 +182,7 @@ static int mga_g200se_set_plls(struct mga_device *mdev, long clock)
}
}
- fvv = pllreffreq * testn / testm;
+ fvv = pllreffreq * (n + 1) / (m + 1);
fvv = (fvv - 800000) / 50000;
if (fvv > 15)
@@ -202,6 +202,14 @@ static int mga_g200se_set_plls(struct mga_device *mdev, long clock)
WREG_DAC(MGA1064_PIX_PLLC_M, m);
WREG_DAC(MGA1064_PIX_PLLC_N, n);
WREG_DAC(MGA1064_PIX_PLLC_P, p);
+
+ if (mdev->unique_rev_id >= 0x04) {
+ WREG_DAC(0x1a, 0x09);
+ msleep(20);
+ WREG_DAC(0x1a, 0x01);
+
+ }
+
return 0;
}
--
2.7.4

View File

@ -0,0 +1,60 @@
From 4d428f0fd6aaaa75382885d897900f619b2dad35 Mon Sep 17 00:00:00 2001
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
Date: Mon, 20 Jun 2016 11:12:56 +0200
Subject: [PATCH 02/17] drm/i915: Rename
s/skl_compute_pipe_wm/skl_build_pipe_wm/
Upstream: since drm-intel-next-2016-05-22
commit e7649b54777ba6491204acbe1f1a34fce78637d5
Author: Matt Roper <matthew.d.roper@intel.com>
AuthorDate: Thu May 12 07:05:56 2016 -0700
Commit: Matt Roper <matthew.d.roper@intel.com>
CommitDate: Fri May 13 07:32:27 2016 -0700
drm/i915: Rename s/skl_compute_pipe_wm/skl_build_pipe_wm/
When we added atomic watermarks, we added a new display vfunc
'compute_pipe_wm' that is used to compute any pipe-specific watermark
information that we can at atomic check time. This was a somewhat poor
naming choice since we already had a 'skl_compute_pipe_wm' function that
doesn't quite fit this model --- the existing SKL function is something
that gets used at atomic commit time, after the DDB allocation has been
determined. Let's rename the existing SKL function to avoid confusion.
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-3-git-send-email-matthew.d.roper@intel.com
---
drivers/gpu/drm/i915/intel_pm.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 0da1d60..8f081b2 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3266,9 +3266,9 @@ static void skl_compute_transition_wm(struct intel_crtc_state *cstate,
}
}
-static void skl_compute_pipe_wm(struct intel_crtc_state *cstate,
- struct skl_ddb_allocation *ddb,
- struct skl_pipe_wm *pipe_wm)
+static void skl_build_pipe_wm(struct intel_crtc_state *cstate,
+ struct skl_ddb_allocation *ddb,
+ struct skl_pipe_wm *pipe_wm)
{
struct drm_device *dev = cstate->base.crtc->dev;
const struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3535,7 +3535,7 @@ static bool skl_update_pipe_wm(struct drm_crtc *crtc,
struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
skl_allocate_pipe_ddb(cstate, ddb);
- skl_compute_pipe_wm(cstate, ddb, pipe_wm);
+ skl_build_pipe_wm(cstate, ddb, pipe_wm);
if (!memcmp(&intel_crtc->wm.active.skl, pipe_wm, sizeof(*pipe_wm)))
return false;
--
2.7.4

View File

@ -0,0 +1,138 @@
From 02510a8805db2c3f8ca2926f90c4b3793934404a Mon Sep 17 00:00:00 2001
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
Date: Mon, 20 Jun 2016 14:51:45 +0200
Subject: [PATCH 2/6] drm/nouveau/fbcon: fix out-of-bounds memory accesses
Upstream: drm-fixes for 4.7 (and cc'd 4.6-stable)
commit f045f459d925138fe7d6193a8c86406bda7e49da
Author: Ben Skeggs <bskeggs@redhat.com>
AuthorDate: Thu Jun 2 12:23:31 2016 +1000
Commit: Ben Skeggs <bskeggs@redhat.com>
CommitDate: Thu Jun 2 13:53:44 2016 +1000
drm/nouveau/fbcon: fix out-of-bounds memory accesses
Reported by KASAN.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Cc: stable@vger.kernel.org
---
drivers/gpu/drm/nouveau/nouveau_fbcon.c | 1 +
drivers/gpu/drm/nouveau/nv04_fbcon.c | 7 ++-----
drivers/gpu/drm/nouveau/nv50_fbcon.c | 6 ++----
drivers/gpu/drm/nouveau/nvc0_fbcon.c | 6 ++----
4 files changed, 7 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index 59f27e7..bd89c86 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -557,6 +557,7 @@ nouveau_fbcon_init(struct drm_device *dev)
if (ret)
goto fini;
+ fbcon->helper.fbdev->pixmap.buf_align = 4;
return 0;
fini:
diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c
index 789dc29..8f715fe 100644
--- a/drivers/gpu/drm/nouveau/nv04_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nv04_fbcon.c
@@ -82,7 +82,6 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
uint32_t fg;
uint32_t bg;
uint32_t dsize;
- uint32_t width;
uint32_t *data = (uint32_t *)image->data;
int ret;
@@ -93,9 +92,6 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
if (ret)
return ret;
- width = ALIGN(image->width, 8);
- dsize = ALIGN(width * image->height, 32) >> 5;
-
if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
fg = ((uint32_t *) info->pseudo_palette)[image->fg_color];
@@ -111,10 +107,11 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
((image->dx + image->width) & 0xffff));
OUT_RING(chan, bg);
OUT_RING(chan, fg);
- OUT_RING(chan, (image->height << 16) | width);
+ OUT_RING(chan, (image->height << 16) | image->width);
OUT_RING(chan, (image->height << 16) | image->width);
OUT_RING(chan, (image->dy << 16) | (image->dx & 0xffff));
+ dsize = ALIGN(image->width * image->height, 32) >> 5;
while (dsize) {
int iter_len = dsize > 128 ? 128 : dsize;
diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c
index e05499d..a4e259a 100644
--- a/drivers/gpu/drm/nouveau/nv50_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c
@@ -95,7 +95,7 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
struct nouveau_fbdev *nfbdev = info->par;
struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
struct nouveau_channel *chan = drm->channel;
- uint32_t width, dwords, *data = (uint32_t *)image->data;
+ uint32_t dwords, *data = (uint32_t *)image->data;
uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel));
uint32_t *palette = info->pseudo_palette;
int ret;
@@ -107,9 +107,6 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
if (ret)
return ret;
- width = ALIGN(image->width, 32);
- dwords = (width * image->height) >> 5;
-
BEGIN_NV04(chan, NvSub2D, 0x0814, 2);
if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
@@ -128,6 +125,7 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
OUT_RING(chan, 0);
OUT_RING(chan, image->dy);
+ dwords = ALIGN(image->width * image->height, 32) >> 5;
while (dwords) {
int push = dwords > 2047 ? 2047 : dwords;
diff --git a/drivers/gpu/drm/nouveau/nvc0_fbcon.c b/drivers/gpu/drm/nouveau/nvc0_fbcon.c
index c97395b..f28315e 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fbcon.c
@@ -95,7 +95,7 @@ nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
struct nouveau_fbdev *nfbdev = info->par;
struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
struct nouveau_channel *chan = drm->channel;
- uint32_t width, dwords, *data = (uint32_t *)image->data;
+ uint32_t dwords, *data = (uint32_t *)image->data;
uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel));
uint32_t *palette = info->pseudo_palette;
int ret;
@@ -107,9 +107,6 @@ nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
if (ret)
return ret;
- width = ALIGN(image->width, 32);
- dwords = (width * image->height) >> 5;
-
BEGIN_NVC0(chan, NvSub2D, 0x0814, 2);
if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
@@ -128,6 +125,7 @@ nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
OUT_RING (chan, 0);
OUT_RING (chan, image->dy);
+ dwords = ALIGN(image->width * image->height, 32) >> 5;
while (dwords) {
int push = dwords > 2047 ? 2047 : dwords;
--
2.7.4

View File

@ -0,0 +1,214 @@
From 0206aec944641c69815562407b73b6f9df22f041 Mon Sep 17 00:00:00 2001
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
Date: Mon, 20 Jun 2016 11:13:09 +0200
Subject: [PATCH 03/17] drm/i915/gen9: Cache plane data rates in CRTC state
Upstream: since drm-intel-next-2016-05-22
commit a1de91e5f3039dfc32ac2b77ffb280a68646cbc7
Author: Matt Roper <matthew.d.roper@intel.com>
AuthorDate: Thu May 12 07:05:57 2016 -0700
Commit: Matt Roper <matthew.d.roper@intel.com>
CommitDate: Fri May 13 07:32:35 2016 -0700
drm/i915/gen9: Cache plane data rates in CRTC state
This will be important when we start calculating CRTC data rates for
in-flight CRTC states since it will allow us to calculate the total data
rate without needing to grab the plane state for any planes that aren't
updated by the transaction.
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-4-git-send-email-matthew.d.roper@intel.com
---
drivers/gpu/drm/i915/intel_drv.h | 4 ++
drivers/gpu/drm/i915/intel_pm.c | 92 ++++++++++++++++++++++++++--------------
2 files changed, 63 insertions(+), 33 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 7d19baf..7c00ab6 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -385,6 +385,10 @@ struct intel_crtc_wm_state {
struct {
/* gen9+ only needs 1-step wm programming */
struct skl_pipe_wm optimal;
+
+ /* cached plane data rate */
+ unsigned plane_data_rate[I915_MAX_PLANES];
+ unsigned plane_y_data_rate[I915_MAX_PLANES];
} skl;
};
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 8f081b2..854f0a4 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2879,6 +2879,14 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate);
struct drm_framebuffer *fb = pstate->fb;
uint32_t width = 0, height = 0;
+ unsigned format = fb ? fb->pixel_format : DRM_FORMAT_XRGB8888;
+
+ if (!intel_pstate->visible)
+ return 0;
+ if (pstate->plane->type == DRM_PLANE_TYPE_CURSOR)
+ return 0;
+ if (y && format != DRM_FORMAT_NV12)
+ return 0;
width = drm_rect_width(&intel_pstate->src) >> 16;
height = drm_rect_height(&intel_pstate->src) >> 16;
@@ -2887,17 +2895,17 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
swap(width, height);
/* for planar format */
- if (fb->pixel_format == DRM_FORMAT_NV12) {
+ if (format == DRM_FORMAT_NV12) {
if (y) /* y-plane data rate */
return width * height *
- drm_format_plane_cpp(fb->pixel_format, 0);
+ drm_format_plane_cpp(format, 0);
else /* uv-plane data rate */
return (width / 2) * (height / 2) *
- drm_format_plane_cpp(fb->pixel_format, 1);
+ drm_format_plane_cpp(format, 1);
}
/* for packed formats */
- return width * height * drm_format_plane_cpp(fb->pixel_format, 0);
+ return width * height * drm_format_plane_cpp(format, 0);
}
/*
@@ -2906,32 +2914,34 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
* 3 * 4096 * 8192 * 4 < 2^32
*/
static unsigned int
-skl_get_total_relative_data_rate(const struct intel_crtc_state *cstate)
+skl_get_total_relative_data_rate(struct intel_crtc_state *cstate)
{
struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
struct drm_device *dev = intel_crtc->base.dev;
const struct intel_plane *intel_plane;
- unsigned int total_data_rate = 0;
+ unsigned int rate, total_data_rate = 0;
+ /* Calculate and cache data rate for each plane */
for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
const struct drm_plane_state *pstate = intel_plane->base.state;
+ int id = skl_wm_plane_id(intel_plane);
- if (pstate->fb == NULL)
- continue;
+ /* packed/uv */
+ rate = skl_plane_relative_data_rate(cstate, pstate, 0);
+ cstate->wm.skl.plane_data_rate[id] = rate;
- if (intel_plane->base.type == DRM_PLANE_TYPE_CURSOR)
- continue;
+ /* y-plane */
+ rate = skl_plane_relative_data_rate(cstate, pstate, 1);
+ cstate->wm.skl.plane_y_data_rate[id] = rate;
+ }
- /* packed/uv */
- total_data_rate += skl_plane_relative_data_rate(cstate,
- pstate,
- 0);
+ /* Calculate CRTC's total data rate from cached values */
+ for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
+ int id = skl_wm_plane_id(intel_plane);
- if (pstate->fb->pixel_format == DRM_FORMAT_NV12)
- /* y-plane */
- total_data_rate += skl_plane_relative_data_rate(cstate,
- pstate,
- 1);
+ /* packed/uv */
+ total_data_rate += cstate->wm.skl.plane_data_rate[id];
+ total_data_rate += cstate->wm.skl.plane_y_data_rate[id];
}
return total_data_rate;
@@ -2995,6 +3005,8 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
* FIXME: we may not allocate every single block here.
*/
total_data_rate = skl_get_total_relative_data_rate(cstate);
+ if (total_data_rate == 0)
+ return;
start = alloc->start;
for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
@@ -3009,7 +3021,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
if (plane->type == DRM_PLANE_TYPE_CURSOR)
continue;
- data_rate = skl_plane_relative_data_rate(cstate, pstate, 0);
+ data_rate = cstate->wm.skl.plane_data_rate[id];
/*
* allocation for (packed formats) or (uv-plane part of planar format):
@@ -3028,20 +3040,16 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
/*
* allocation for y_plane part of planar format:
*/
- if (pstate->fb->pixel_format == DRM_FORMAT_NV12) {
- y_data_rate = skl_plane_relative_data_rate(cstate,
- pstate,
- 1);
- y_plane_blocks = y_minimum[id];
- y_plane_blocks += div_u64((uint64_t)alloc_size * y_data_rate,
- total_data_rate);
-
- ddb->y_plane[pipe][id].start = start;
- ddb->y_plane[pipe][id].end = start + y_plane_blocks;
-
- start += y_plane_blocks;
- }
+ y_data_rate = cstate->wm.skl.plane_y_data_rate[id];
+
+ y_plane_blocks = y_minimum[id];
+ y_plane_blocks += div_u64((uint64_t)alloc_size * y_data_rate,
+ total_data_rate);
+ ddb->y_plane[pipe][id].start = start;
+ ddb->y_plane[pipe][id].end = start + y_plane_blocks;
+
+ start += y_plane_blocks;
}
}
@@ -3820,10 +3828,28 @@ void skl_wm_get_hw_state(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private;
struct skl_ddb_allocation *ddb = &dev_priv->wm.skl_hw.ddb;
struct drm_crtc *crtc;
+ struct intel_crtc *intel_crtc;
skl_ddb_get_hw_state(dev_priv, ddb);
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
skl_pipe_wm_get_hw_state(crtc);
+
+ /* Calculate plane data rates */
+ for_each_intel_crtc(dev, intel_crtc) {
+ struct intel_crtc_state *cstate = intel_crtc->config;
+ struct intel_plane *intel_plane;
+
+ for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
+ const struct drm_plane_state *pstate =
+ intel_plane->base.state;
+ int id = skl_wm_plane_id(intel_plane);
+
+ cstate->wm.skl.plane_data_rate[id] =
+ skl_plane_relative_data_rate(cstate, pstate, 0);
+ cstate->wm.skl.plane_y_data_rate[id] =
+ skl_plane_relative_data_rate(cstate, pstate, 1);
+ }
+ }
}
static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
--
2.7.4

View File

@ -0,0 +1,46 @@
From de35f524e89daf8862d49724b9045f9254bfdfea Mon Sep 17 00:00:00 2001
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
Date: Mon, 20 Jun 2016 14:52:01 +0200
Subject: [PATCH 3/6] drm/nouveau/disp/sor/gf119: both links use the same
training register
Upstream: drm-fixes for 4.7 (and cc'd 4.6-stable)
commit a8953c52b95167b5d21a66f0859751570271d834
Author: Ben Skeggs <bskeggs@redhat.com>
AuthorDate: Fri Jun 3 14:37:40 2016 +1000
Commit: Ben Skeggs <bskeggs@redhat.com>
CommitDate: Tue Jun 7 08:11:14 2016 +1000
drm/nouveau/disp/sor/gf119: both links use the same training register
It appears that, for whatever reason, both link A and B use the same
register to control the training pattern. It's a little odd, as the
GPUs before this (Tesla/Fermi1) have per-link registers, as do newer
GPUs (Maxwell).
Fixes the third DP output on NVS 510 (GK107).
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Cc: stable@vger.kernel.org
---
drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
index b4b41b1..5111560 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
@@ -40,8 +40,7 @@ static int
gf119_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern)
{
struct nvkm_device *device = outp->base.disp->engine.subdev.device;
- const u32 loff = gf119_sor_loff(outp);
- nvkm_mask(device, 0x61c110 + loff, 0x0f0f0f0f, 0x01010101 * pattern);
+ nvkm_mask(device, 0x61c110, 0x0f0f0f0f, 0x01010101 * pattern);
return 0;
}
--
2.7.4

View File

@ -0,0 +1,141 @@
From a75a3c793e2cd3e7648597f2c77d87453f520f31 Mon Sep 17 00:00:00 2001
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
Date: Mon, 20 Jun 2016 11:13:23 +0200
Subject: [PATCH 04/17] drm/i915/gen9: Allow calculation of data rate for
in-flight state (v2)
Upstream: since drm-intel-next-2016-05-22
commit 9c74d82621c553f0da1f41bd5d90f5eab5659fdb
Author: Matt Roper <matthew.d.roper@intel.com>
AuthorDate: Thu May 12 07:05:58 2016 -0700
Commit: Matt Roper <matthew.d.roper@intel.com>
CommitDate: Fri May 13 07:32:49 2016 -0700
drm/i915/gen9: Allow calculation of data rate for in-flight state (v2)
Our skl_get_total_relative_data_rate() function gets passed a crtc state
object to calculate the data rate for, but it currently always looks
up the committed plane states that correspond to that CRTC. Let's
check whether the CRTC state is an in-flight state (meaning
cstate->state is non-NULL) and if so, use the corresponding in-flight
plane states.
We'll soon be using this function exclusively for in-flight states; at
that time we'll be able to simplify the function a bit, but for now we
allow it to be used in either mode.
v2:
- Rebase on top of changes to cache plane data rates.
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-5-git-send-email-matthew.d.roper@intel.com
---
drivers/gpu/drm/i915/intel_pm.c | 74 +++++++++++++++++++++++++++++++++--------
1 file changed, 60 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 854f0a4..b863bfc 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2914,25 +2914,69 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
* 3 * 4096 * 8192 * 4 < 2^32
*/
static unsigned int
-skl_get_total_relative_data_rate(struct intel_crtc_state *cstate)
+skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate)
{
- struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
- struct drm_device *dev = intel_crtc->base.dev;
+ struct drm_crtc_state *cstate = &intel_cstate->base;
+ struct drm_atomic_state *state = cstate->state;
+ struct drm_crtc *crtc = cstate->crtc;
+ struct drm_device *dev = crtc->dev;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
const struct intel_plane *intel_plane;
unsigned int rate, total_data_rate = 0;
+ int id;
/* Calculate and cache data rate for each plane */
- for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
- const struct drm_plane_state *pstate = intel_plane->base.state;
- int id = skl_wm_plane_id(intel_plane);
+ /*
+ * FIXME: At the moment this function can be called on either an
+ * in-flight or a committed state object. If it's in-flight then we
+ * only want to re-calculate the plane data rate for planes that are
+ * part of the transaction (i.e., we don't want to grab any additional
+ * plane states if we don't have to). If we're operating on committed
+ * state, we'll just go ahead and recalculate the plane data rate for
+ * all planes.
+ *
+ * Once we finish moving our DDB allocation to the atomic check phase,
+ * we'll only be calling this function on in-flight state objects, so
+ * the 'else' branch here will go away.
+ */
+ if (state) {
+ struct drm_plane *plane;
+ struct drm_plane_state *pstate;
+ int i;
+
+ for_each_plane_in_state(state, plane, pstate, i) {
+ intel_plane = to_intel_plane(plane);
+ id = skl_wm_plane_id(intel_plane);
+
+ if (intel_plane->pipe != intel_crtc->pipe)
+ continue;
+
+ /* packed/uv */
+ rate = skl_plane_relative_data_rate(intel_cstate,
+ pstate, 0);
+ intel_cstate->wm.skl.plane_data_rate[id] = rate;
+
+ /* y-plane */
+ rate = skl_plane_relative_data_rate(intel_cstate,
+ pstate, 1);
+ intel_cstate->wm.skl.plane_y_data_rate[id] = rate;
+ }
+ } else {
+ for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
+ const struct drm_plane_state *pstate =
+ intel_plane->base.state;
+ int id = skl_wm_plane_id(intel_plane);
- /* packed/uv */
- rate = skl_plane_relative_data_rate(cstate, pstate, 0);
- cstate->wm.skl.plane_data_rate[id] = rate;
+ /* packed/uv */
+ rate = skl_plane_relative_data_rate(intel_cstate,
+ pstate, 0);
+ intel_cstate->wm.skl.plane_data_rate[id] = rate;
- /* y-plane */
- rate = skl_plane_relative_data_rate(cstate, pstate, 1);
- cstate->wm.skl.plane_y_data_rate[id] = rate;
+ /* y-plane */
+ rate = skl_plane_relative_data_rate(intel_cstate,
+ pstate, 1);
+ intel_cstate->wm.skl.plane_y_data_rate[id] = rate;
+ }
}
/* Calculate CRTC's total data rate from cached values */
@@ -2940,10 +2984,12 @@ skl_get_total_relative_data_rate(struct intel_crtc_state *cstate)
int id = skl_wm_plane_id(intel_plane);
/* packed/uv */
- total_data_rate += cstate->wm.skl.plane_data_rate[id];
- total_data_rate += cstate->wm.skl.plane_y_data_rate[id];
+ total_data_rate += intel_cstate->wm.skl.plane_data_rate[id];
+ total_data_rate += intel_cstate->wm.skl.plane_y_data_rate[id];
}
+ WARN_ON(cstate->plane_mask && total_data_rate == 0);
+
return total_data_rate;
}
--
2.7.4

View File

@ -0,0 +1,195 @@
From eb4668302adce316f53896b0fd8144ffe380a3ad Mon Sep 17 00:00:00 2001
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
Date: Mon, 20 Jun 2016 14:52:06 +0200
Subject: [PATCH 4/6] drm/nouveau/disp/sor/gm107: training pattern registers
are like gm200
Upstream: drm-fixes for 4.7 (and cc'd 4.6-stable)
commit 4691409b3e2250ed66aa8dcefa23fe765daf7add
Author: Ben Skeggs <bskeggs@redhat.com>
AuthorDate: Fri Jun 3 15:05:52 2016 +1000
Commit: Ben Skeggs <bskeggs@redhat.com>
CommitDate: Tue Jun 7 08:11:25 2016 +1000
drm/nouveau/disp/sor/gm107: training pattern registers are like gm200
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Cc: stable@vger.kernel.org
---
drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild | 1 +
drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c | 2 +-
drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h | 9 +++-
.../gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c | 2 +-
.../nvkm/engine/disp/{gm107.c => sorgm107.c} | 50 +++++++++++-----------
.../gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c | 15 +------
6 files changed, 36 insertions(+), 43 deletions(-)
copy drivers/gpu/drm/nouveau/nvkm/engine/disp/{gm107.c => sorgm107.c} (55%)
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
index a74c5dd..e2a64ed 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
@@ -18,6 +18,7 @@ nvkm-y += nvkm/engine/disp/piornv50.o
nvkm-y += nvkm/engine/disp/sornv50.o
nvkm-y += nvkm/engine/disp/sorg94.o
nvkm-y += nvkm/engine/disp/sorgf119.o
+nvkm-y += nvkm/engine/disp/sorgm107.o
nvkm-y += nvkm/engine/disp/sorgm200.o
nvkm-y += nvkm/engine/disp/dport.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c
index b694414..f4b9cf8 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c
@@ -36,7 +36,7 @@ gm107_disp = {
.outp.internal.crt = nv50_dac_output_new,
.outp.internal.tmds = nv50_sor_output_new,
.outp.internal.lvds = nv50_sor_output_new,
- .outp.internal.dp = gf119_sor_dp_new,
+ .outp.internal.dp = gm107_sor_dp_new,
.dac.nr = 3,
.dac.power = nv50_dac_power,
.dac.sense = nv50_dac_sense,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h
index e9067ba..4e983f6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h
@@ -62,7 +62,12 @@ int g94_sor_dp_lnk_pwr(struct nvkm_output_dp *, int);
int gf119_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *,
struct nvkm_output **);
int gf119_sor_dp_lnk_ctl(struct nvkm_output_dp *, int, int, bool);
+int gf119_sor_dp_drv_ctl(struct nvkm_output_dp *, int, int, int, int);
-int gm200_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *,
- struct nvkm_output **);
+int gm107_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *,
+ struct nvkm_output **);
+int gm107_sor_dp_pattern(struct nvkm_output_dp *, int);
+
+int gm200_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *,
+ struct nvkm_output **);
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
index 5111560..22706c0 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
@@ -63,7 +63,7 @@ gf119_sor_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef)
return 0;
}
-static int
+int
gf119_sor_dp_drv_ctl(struct nvkm_output_dp *outp,
int ln, int vs, int pe, int pc)
{
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c
similarity index 55%
copy from drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c
copy to drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c
index b694414..37790b2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 Red Hat Inc.
+ * Copyright 2016 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -19,35 +19,35 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
- * Authors: Ben Skeggs
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
*/
#include "nv50.h"
-#include "rootnv50.h"
+#include "outpdp.h"
-static const struct nv50_disp_func
-gm107_disp = {
- .intr = gf119_disp_intr,
- .uevent = &gf119_disp_chan_uevent,
- .super = gf119_disp_intr_supervisor,
- .root = &gm107_disp_root_oclass,
- .head.vblank_init = gf119_disp_vblank_init,
- .head.vblank_fini = gf119_disp_vblank_fini,
- .head.scanoutpos = gf119_disp_root_scanoutpos,
- .outp.internal.crt = nv50_dac_output_new,
- .outp.internal.tmds = nv50_sor_output_new,
- .outp.internal.lvds = nv50_sor_output_new,
- .outp.internal.dp = gf119_sor_dp_new,
- .dac.nr = 3,
- .dac.power = nv50_dac_power,
- .dac.sense = nv50_dac_sense,
- .sor.nr = 4,
- .sor.power = nv50_sor_power,
- .sor.hda_eld = gf119_hda_eld,
- .sor.hdmi = gk104_hdmi_ctrl,
+int
+gm107_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern)
+{
+ struct nvkm_device *device = outp->base.disp->engine.subdev.device;
+ const u32 soff = outp->base.or * 0x800;
+ const u32 data = 0x01010101 * pattern;
+ if (outp->base.info.sorconf.link & 1)
+ nvkm_mask(device, 0x61c110 + soff, 0x0f0f0f0f, data);
+ else
+ nvkm_mask(device, 0x61c12c + soff, 0x0f0f0f0f, data);
+ return 0;
+}
+
+static const struct nvkm_output_dp_func
+gm107_sor_dp_func = {
+ .pattern = gm107_sor_dp_pattern,
+ .lnk_pwr = g94_sor_dp_lnk_pwr,
+ .lnk_ctl = gf119_sor_dp_lnk_ctl,
+ .drv_ctl = gf119_sor_dp_drv_ctl,
};
int
-gm107_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
+gm107_sor_dp_new(struct nvkm_disp *disp, int index,
+ struct dcb_output *dcbE, struct nvkm_output **poutp)
{
- return gf119_disp_new_(&gm107_disp, device, index, pdisp);
+ return nvkm_output_dp_new_(&gm107_sor_dp_func, disp, index, dcbE, poutp);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c
index 2cfbef9..c44fa7e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c
@@ -57,19 +57,6 @@ gm200_sor_dp_lane_map(struct nvkm_device *device, u8 lane)
}
static int
-gm200_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern)
-{
- struct nvkm_device *device = outp->base.disp->engine.subdev.device;
- const u32 soff = gm200_sor_soff(outp);
- const u32 data = 0x01010101 * pattern;
- if (outp->base.info.sorconf.link & 1)
- nvkm_mask(device, 0x61c110 + soff, 0x0f0f0f0f, data);
- else
- nvkm_mask(device, 0x61c12c + soff, 0x0f0f0f0f, data);
- return 0;
-}
-
-static int
gm200_sor_dp_lnk_pwr(struct nvkm_output_dp *outp, int nr)
{
struct nvkm_device *device = outp->base.disp->engine.subdev.device;
@@ -129,7 +116,7 @@ gm200_sor_dp_drv_ctl(struct nvkm_output_dp *outp,
static const struct nvkm_output_dp_func
gm200_sor_dp_func = {
- .pattern = gm200_sor_dp_pattern,
+ .pattern = gm107_sor_dp_pattern,
.lnk_pwr = gm200_sor_dp_lnk_pwr,
.lnk_ctl = gf119_sor_dp_lnk_ctl,
.drv_ctl = gm200_sor_dp_drv_ctl,
--
2.7.4

View File

@ -0,0 +1,67 @@
From cd21ce996b94fd149b3487398e5250e9f0cc8811 Mon Sep 17 00:00:00 2001
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
Date: Mon, 20 Jun 2016 12:39:24 +0200
Subject: [PATCH 05/17] drm/i915/gen9: Store plane minimum blocks in CRTC wm
state (v2)
Upstream: since drm-intel-next-2016-05-22
commit 86a2100a8b96594902bb59b90614377df4f64ce0
Author: Matt Roper <matthew.d.roper@intel.com>
AuthorDate: Thu May 12 07:05:59 2016 -0700
Commit: Matt Roper <matthew.d.roper@intel.com>
CommitDate: Fri May 13 07:32:56 2016 -0700
drm/i915/gen9: Store plane minimum blocks in CRTC wm state (v2)
This will eventually allow us to re-use old values without
re-calculating them for unchanged planes (which also helps us avoid
re-grabbing extra plane states).
v2:
- Drop unnecessary memset's; they were meant for a later patch (which
got reworked anyway to not need them, but were mis-rebased into this
one. (Maarten)
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-6-git-send-email-matthew.d.roper@intel.com
---
drivers/gpu/drm/i915/intel_drv.h | 4 ++++
drivers/gpu/drm/i915/intel_pm.c | 4 ++--
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 7c00ab6..d246308 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -389,6 +389,10 @@ struct intel_crtc_wm_state {
/* cached plane data rate */
unsigned plane_data_rate[I915_MAX_PLANES];
unsigned plane_y_data_rate[I915_MAX_PLANES];
+
+ /* minimum block allocation */
+ uint16_t minimum_blocks[I915_MAX_PLANES];
+ uint16_t minimum_y_blocks[I915_MAX_PLANES];
} skl;
};
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index b863bfc..00db6e9 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3006,8 +3006,8 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
enum pipe pipe = intel_crtc->pipe;
struct skl_ddb_entry *alloc = &ddb->pipe[pipe];
uint16_t alloc_size, start, cursor_blocks;
- uint16_t minimum[I915_MAX_PLANES];
- uint16_t y_minimum[I915_MAX_PLANES];
+ uint16_t *minimum = cstate->wm.skl.minimum_blocks;
+ uint16_t *y_minimum = cstate->wm.skl.minimum_y_blocks;
unsigned int total_data_rate;
skl_ddb_get_pipe_allocation_limits(dev, cstate, config, alloc);
--
2.7.4

View File

@ -0,0 +1,55 @@
From 28d0147bded959b2c4d3eb1aa957452d5dbb0cc9 Mon Sep 17 00:00:00 2001
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
Date: Mon, 20 Jun 2016 14:52:10 +0200
Subject: [PATCH 5/6] i915/fbc: Disable on HSW by default for now
Upstream: posted on dri-devel (and r-b'd)
Author: cpaul@redhat.com <cpaul@redhat.com>
AuthorDate: Thu Jun 9 11:58:15 2016 -0400
Commit: Rob Clark <rclark@redhat.com>
CommitDate: Thu Jun 9 15:43:07 2016 -0400
i915/fbc: Disable on HSW by default for now
>From https://bugs.freedesktop.org/show_bug.cgi?id=96461 :
This was kind of a difficult bug to track down. If you're using a
Haswell system running GNOME and you have fbc completely enabled and
working, playing videos can result in video artifacts. Steps to
reproduce:
- Run GNOME
- Ensure FBC is enabled and active
- Download a movie, I used the ogg version of Big Buck Bunny for this
- Run `gst-launch-1.0 filesrc location='some_movie.ogg' ! decodebin !
glimagesink` in a terminal
- Watch for about over a minute, you'll see small horizontal lines go
down the screen.
For the time being, disable FBC for Haswell by default.
Signed-off-by: Lyude <cpaul@redhat.com>
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Cc: stable@vger.kernel.org
---
drivers/gpu/drm/i915/intel_fbc.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 0f0492f..28f4407 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -823,8 +823,7 @@ static bool intel_fbc_can_choose(struct intel_crtc *crtc)
{
struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
struct intel_fbc *fbc = &dev_priv->fbc;
- bool enable_by_default = IS_HASWELL(dev_priv) ||
- IS_BROADWELL(dev_priv);
+ bool enable_by_default = IS_BROADWELL(dev_priv);
if (intel_vgpu_active(dev_priv->dev)) {
fbc->no_fbc_reason = "VGPU is active";
--
2.7.4

View File

@ -0,0 +1,145 @@
From b87459ac92803eafc8dd9f8a8ccc36190fe427f1 Mon Sep 17 00:00:00 2001
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Date: Wed, 4 May 2016 14:38:26 +0200
Subject: [PATCH 6/6] drm/core: Do not preserve framebuffer on rmfb, v4.
Upstream since: 4.7-rc1
commit f2d580b9a8149735cbc4b59c4a8df60173658140
It turns out that preserving framebuffers after the rmfb call breaks
vmwgfx userspace. This was originally introduced because it was thought
nobody relied on the behavior, but unfortunately it seems there are
exceptions.
drm_framebuffer_remove may fail with -EINTR now, so a straight revert
is impossible. There is no way to remove the framebuffer from the lists
and active planes without introducing a race because of the different
locking requirements. Instead call drm_framebuffer_remove from a
workqueue, which is unaffected by signals.
Changes since v1:
- Add comment.
Changes since v2:
- Add fastpath for refcount = 1. (danvet)
Changes since v3:
- Rebased.
- Restore lastclose framebuffer removal too.
Cc: stable@vger.kernel.org #v4.4+
Fixes: 13803132818c ("drm/core: Preserve the framebuffer after removing it.")
Testcase: kms_rmfb_basic
References: https://lists.freedesktop.org/archives/dri-devel/2016-March/102876.html
Cc: Thomas Hellstrom <thellstrom@vmware.com>
Cc: David Herrmann <dh.herrmann@gmail.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Tested-by: Thomas Hellstrom <thellstrom@vmware.com> #v3
Tested-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/6c63ca37-0e7e-ac7f-a6d2-c7822e3d611f@linux.intel.com
---
drivers/gpu/drm/drm_crtc.c | 60 ++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 55 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index e08f962..f30de80 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -3434,6 +3434,24 @@ int drm_mode_addfb2(struct drm_device *dev,
return 0;
}
+struct drm_mode_rmfb_work {
+ struct work_struct work;
+ struct list_head fbs;
+};
+
+static void drm_mode_rmfb_work_fn(struct work_struct *w)
+{
+ struct drm_mode_rmfb_work *arg = container_of(w, typeof(*arg), work);
+
+ while (!list_empty(&arg->fbs)) {
+ struct drm_framebuffer *fb =
+ list_first_entry(&arg->fbs, typeof(*fb), filp_head);
+
+ list_del_init(&fb->filp_head);
+ drm_framebuffer_remove(fb);
+ }
+}
+
/**
* drm_mode_rmfb - remove an FB from the configuration
* @dev: drm device for the ioctl
@@ -3474,7 +3492,25 @@ int drm_mode_rmfb(struct drm_device *dev,
mutex_unlock(&dev->mode_config.fb_lock);
mutex_unlock(&file_priv->fbs_lock);
- drm_framebuffer_unreference(fb);
+ /*
+ * we now own the reference that was stored in the fbs list
+ *
+ * drm_framebuffer_remove may fail with -EINTR on pending signals,
+ * so run this in a separate stack as there's no way to correctly
+ * handle this after the fb is already removed from the lookup table.
+ */
+ if (atomic_read(&fb->refcount.refcount) > 1) {
+ struct drm_mode_rmfb_work arg;
+
+ INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn);
+ INIT_LIST_HEAD(&arg.fbs);
+ list_add_tail(&fb->filp_head, &arg.fbs);
+
+ schedule_work(&arg.work);
+ flush_work(&arg.work);
+ destroy_work_on_stack(&arg.work);
+ } else
+ drm_framebuffer_unreference(fb);
return 0;
@@ -3627,7 +3663,6 @@ out_err1:
return ret;
}
-
/**
* drm_fb_release - remove and free the FBs on this file
* @priv: drm file for the ioctl
@@ -3642,6 +3677,9 @@ out_err1:
void drm_fb_release(struct drm_file *priv)
{
struct drm_framebuffer *fb, *tfb;
+ struct drm_mode_rmfb_work arg;
+
+ INIT_LIST_HEAD(&arg.fbs);
/*
* When the file gets released that means no one else can access the fb
@@ -3654,10 +3692,22 @@ void drm_fb_release(struct drm_file *priv)
* at it any more.
*/
list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
- list_del_init(&fb->filp_head);
+ if (atomic_read(&fb->refcount.refcount) > 1) {
+ list_move_tail(&fb->filp_head, &arg.fbs);
+ } else {
+ list_del_init(&fb->filp_head);
- /* This drops the fpriv->fbs reference. */
- drm_framebuffer_unreference(fb);
+ /* This drops the fpriv->fbs reference. */
+ drm_framebuffer_unreference(fb);
+ }
+ }
+
+ if (!list_empty(&arg.fbs)) {
+ INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn);
+
+ schedule_work(&arg.work);
+ flush_work(&arg.work);
+ destroy_work_on_stack(&arg.work);
}
}
--
2.7.4

View File

@ -0,0 +1,68 @@
From 00edb23bcefa3ad6931f2a2855fe0801a55523f7 Mon Sep 17 00:00:00 2001
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
Date: Mon, 20 Jun 2016 12:39:40 +0200
Subject: [PATCH 06/17] drm/i915: Track whether an atomic transaction changes
the active CRTC's
Upstream: since drm-intel-next-2016-05-22
commit 8b4a7d0597cd9910d7127ffae6ae91d21853a8a2
Author: Matt Roper <matthew.d.roper@intel.com>
AuthorDate: Thu May 12 07:06:00 2016 -0700
Commit: Matt Roper <matthew.d.roper@intel.com>
CommitDate: Fri May 13 07:33:10 2016 -0700
drm/i915: Track whether an atomic transaction changes the active CRTC's
For the purposes of DDB re-allocation we need to know whether a
transaction changes the list of CRTC's that are active. While
state->modeset could be used for this purpose, that would be slightly
too aggressive since it would lead us to re-allocate the DDB when a
CRTC's mode changes, but not its final active state.
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-7-git-send-email-matthew.d.roper@intel.com
---
drivers/gpu/drm/i915/intel_display.c | 3 +++
drivers/gpu/drm/i915/intel_drv.h | 10 ++++++++++
2 files changed, 13 insertions(+)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 7d855ba..f53df81 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -13183,6 +13183,9 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
intel_state->active_crtcs |= 1 << i;
else
intel_state->active_crtcs &= ~(1 << i);
+
+ if (crtc_state->active != crtc->state->active)
+ intel_state->active_pipe_changes |= drm_crtc_mask(crtc);
}
/*
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index d246308..672ca56 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -256,6 +256,16 @@ struct intel_atomic_state {
bool dpll_set, modeset;
+ /*
+ * Does this transaction change the pipes that are active? This mask
+ * tracks which CRTC's have changed their active state at the end of
+ * the transaction (not counting the temporary disable during modesets).
+ * This mask should only be non-zero when intel_state->modeset is true,
+ * but the converse is not necessarily true; simply changing a mode may
+ * not flip the final active status of any CRTC's
+ */
+ unsigned int active_pipe_changes;
+
unsigned int active_crtcs;
unsigned int min_pixclk[I915_MAX_PIPES];
--
2.7.4

View File

@ -0,0 +1,352 @@
From 99dd9c3733696d4a2536b21988c9b1b8f5195c5b Mon Sep 17 00:00:00 2001
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
Date: Mon, 20 Jun 2016 12:40:00 +0200
Subject: [PATCH 07/17] drm/i915/gen9: Allow skl_allocate_pipe_ddb() to operate
on in-flight state (v3)
Upstream: since drm-intel-next-2016-05-22
commit c107acfeb03187873657ccc8af4fc5c704b3626b
Author: Matt Roper <matthew.d.roper@intel.com>
AuthorDate: Thu May 12 07:06:01 2016 -0700
Commit: Matt Roper <matthew.d.roper@intel.com>
CommitDate: Fri May 13 07:33:16 2016 -0700
drm/i915/gen9: Allow skl_allocate_pipe_ddb() to operate on in-flight state (v3)
We eventually want to calculate watermark values at atomic 'check' time
instead of atomic 'commit' time so that any requested configurations
that result in impossible watermark requirements are properly rejected.
The first step along this path is to allocate the DDB at atomic 'check'
time. As we perform this transition, allow the main allocation function
to operate successfully on either an in-flight state or an
already-commited state. Once we complete the transition in a future
patch, we'll come back and remove the unnecessary logic for the
already-committed case.
v2: Rebase/refactor; we should no longer need to grab extra plane states
while allocating the DDB since we can pull cached data rates and
minimum block counts from the CRTC state for any planes that aren't
being modified by this transaction.
v3:
- Simplify memsets to clear DDB plane entries. (Maarten)
- Drop a redundant memset of plane[pipe][PLANE_CURSOR] that was added
by an earlier Coccinelle patch. (Maarten)
- Assign *num_active at the top of skl_ddb_get_pipe_allocation_limits()
so that no code paths return without setting it. (kbuild robot)
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-8-git-send-email-matthew.d.roper@intel.com
---
drivers/gpu/drm/i915/i915_drv.h | 6 ++
drivers/gpu/drm/i915/intel_pm.c | 179 +++++++++++++++++++++++++++++-----------
2 files changed, 139 insertions(+), 46 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index daba7eb..804af6f 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -281,6 +281,12 @@ struct i915_hotplug {
&dev->mode_config.plane_list, \
base.head)
+#define for_each_intel_plane_mask(dev, intel_plane, plane_mask) \
+ list_for_each_entry(intel_plane, &dev->mode_config.plane_list, \
+ base.head) \
+ for_each_if ((plane_mask) & \
+ (1 << drm_plane_index(&intel_plane->base)))
+
#define for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) \
list_for_each_entry(intel_plane, \
&(dev)->mode_config.plane_list, \
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 00db6e9..ee82b1f 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2788,13 +2788,25 @@ skl_wm_plane_id(const struct intel_plane *plane)
static void
skl_ddb_get_pipe_allocation_limits(struct drm_device *dev,
const struct intel_crtc_state *cstate,
- const struct intel_wm_config *config,
- struct skl_ddb_entry *alloc /* out */)
+ struct intel_wm_config *config,
+ struct skl_ddb_entry *alloc, /* out */
+ int *num_active /* out */)
{
+ struct drm_atomic_state *state = cstate->base.state;
+ struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
+ struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_crtc *for_crtc = cstate->base.crtc;
struct drm_crtc *crtc;
unsigned int pipe_size, ddb_size;
int nth_active_pipe;
+ int pipe = to_intel_crtc(for_crtc)->pipe;
+
+ if (intel_state && intel_state->active_pipe_changes)
+ *num_active = hweight32(intel_state->active_crtcs);
+ else if (intel_state)
+ *num_active = hweight32(dev_priv->active_crtcs);
+ else
+ *num_active = config->num_pipes_active;
if (!cstate->base.active) {
alloc->start = 0;
@@ -2809,25 +2821,56 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev,
ddb_size -= 4; /* 4 blocks for bypass path allocation */
- nth_active_pipe = 0;
- for_each_crtc(dev, crtc) {
- if (!to_intel_crtc(crtc)->active)
- continue;
+ /*
+ * FIXME: At the moment we may be called on either in-flight or fully
+ * committed cstate's. Once we fully move DDB allocation in the check
+ * phase, we'll only be called on in-flight states and the 'else'
+ * branch here will go away.
+ *
+ * The 'else' branch is slightly racy here, but it was racy to begin
+ * with; since it's going away soon, no effort is made to address that.
+ */
+ if (state) {
+ /*
+ * If the state doesn't change the active CRTC's, then there's
+ * no need to recalculate; the existing pipe allocation limits
+ * should remain unchanged. Note that we're safe from racing
+ * commits since any racing commit that changes the active CRTC
+ * list would need to grab _all_ crtc locks, including the one
+ * we currently hold.
+ */
+ if (!intel_state->active_pipe_changes) {
+ *alloc = dev_priv->wm.skl_hw.ddb.pipe[pipe];
+ return;
+ }
- if (crtc == for_crtc)
- break;
+ nth_active_pipe = hweight32(intel_state->active_crtcs &
+ (drm_crtc_mask(for_crtc) - 1));
+ pipe_size = ddb_size / hweight32(intel_state->active_crtcs);
+ alloc->start = nth_active_pipe * ddb_size / *num_active;
+ alloc->end = alloc->start + pipe_size;
+ } else {
+ nth_active_pipe = 0;
+ for_each_crtc(dev, crtc) {
+ if (!to_intel_crtc(crtc)->active)
+ continue;
- nth_active_pipe++;
- }
+ if (crtc == for_crtc)
+ break;
+
+ nth_active_pipe++;
+ }
- pipe_size = ddb_size / config->num_pipes_active;
- alloc->start = nth_active_pipe * ddb_size / config->num_pipes_active;
- alloc->end = alloc->start + pipe_size;
+ pipe_size = ddb_size / config->num_pipes_active;
+ alloc->start = nth_active_pipe * ddb_size /
+ config->num_pipes_active;
+ alloc->end = alloc->start + pipe_size;
+ }
}
-static unsigned int skl_cursor_allocation(const struct intel_wm_config *config)
+static unsigned int skl_cursor_allocation(int num_active)
{
- if (config->num_pipes_active == 1)
+ if (num_active == 1)
return 32;
return 8;
@@ -2993,33 +3036,44 @@ skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate)
return total_data_rate;
}
-static void
+static int
skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
struct skl_ddb_allocation *ddb /* out */)
{
+ struct drm_atomic_state *state = cstate->base.state;
struct drm_crtc *crtc = cstate->base.crtc;
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_wm_config *config = &dev_priv->wm.config;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_plane *intel_plane;
+ struct drm_plane *plane;
+ struct drm_plane_state *pstate;
enum pipe pipe = intel_crtc->pipe;
struct skl_ddb_entry *alloc = &ddb->pipe[pipe];
uint16_t alloc_size, start, cursor_blocks;
uint16_t *minimum = cstate->wm.skl.minimum_blocks;
uint16_t *y_minimum = cstate->wm.skl.minimum_y_blocks;
unsigned int total_data_rate;
+ int num_active;
+ int id, i;
+
+ if (!cstate->base.active) {
+ ddb->pipe[pipe].start = ddb->pipe[pipe].end = 0;
+ memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe]));
+ memset(ddb->y_plane[pipe], 0, sizeof(ddb->y_plane[pipe]));
+ return 0;
+ }
- skl_ddb_get_pipe_allocation_limits(dev, cstate, config, alloc);
+ skl_ddb_get_pipe_allocation_limits(dev, cstate, config, alloc,
+ &num_active);
alloc_size = skl_ddb_entry_size(alloc);
if (alloc_size == 0) {
memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe]));
- memset(&ddb->plane[pipe][PLANE_CURSOR], 0,
- sizeof(ddb->plane[pipe][PLANE_CURSOR]));
- return;
+ return 0;
}
- cursor_blocks = skl_cursor_allocation(config);
+ cursor_blocks = skl_cursor_allocation(num_active);
ddb->plane[pipe][PLANE_CURSOR].start = alloc->end - cursor_blocks;
ddb->plane[pipe][PLANE_CURSOR].end = alloc->end;
@@ -3027,21 +3081,55 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
alloc->end -= cursor_blocks;
/* 1. Allocate the mininum required blocks for each active plane */
- for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
- struct drm_plane *plane = &intel_plane->base;
- struct drm_framebuffer *fb = plane->state->fb;
- int id = skl_wm_plane_id(intel_plane);
+ /*
+ * TODO: Remove support for already-committed state once we
+ * only allocate DDB on in-flight states.
+ */
+ if (state) {
+ for_each_plane_in_state(state, plane, pstate, i) {
+ intel_plane = to_intel_plane(plane);
+ id = skl_wm_plane_id(intel_plane);
- if (!to_intel_plane_state(plane->state)->visible)
- continue;
+ if (intel_plane->pipe != pipe)
+ continue;
- if (plane->type == DRM_PLANE_TYPE_CURSOR)
- continue;
+ if (!to_intel_plane_state(pstate)->visible) {
+ minimum[id] = 0;
+ y_minimum[id] = 0;
+ continue;
+ }
+ if (plane->type == DRM_PLANE_TYPE_CURSOR) {
+ minimum[id] = 0;
+ y_minimum[id] = 0;
+ continue;
+ }
- minimum[id] = 8;
- alloc_size -= minimum[id];
- y_minimum[id] = (fb->pixel_format == DRM_FORMAT_NV12) ? 8 : 0;
- alloc_size -= y_minimum[id];
+ minimum[id] = 8;
+ if (pstate->fb->pixel_format == DRM_FORMAT_NV12)
+ y_minimum[id] = 8;
+ else
+ y_minimum[id] = 0;
+ }
+ } else {
+ for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
+ struct drm_plane *plane = &intel_plane->base;
+ struct drm_framebuffer *fb = plane->state->fb;
+ int id = skl_wm_plane_id(intel_plane);
+
+ if (!to_intel_plane_state(plane->state)->visible)
+ continue;
+
+ if (plane->type == DRM_PLANE_TYPE_CURSOR)
+ continue;
+
+ minimum[id] = 8;
+ y_minimum[id] = (fb->pixel_format == DRM_FORMAT_NV12) ? 8 : 0;
+ }
+ }
+
+ for (i = 0; i < PLANE_CURSOR; i++) {
+ alloc_size -= minimum[i];
+ alloc_size -= y_minimum[i];
}
/*
@@ -3052,21 +3140,14 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
*/
total_data_rate = skl_get_total_relative_data_rate(cstate);
if (total_data_rate == 0)
- return;
+ return 0;
start = alloc->start;
for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
- struct drm_plane *plane = &intel_plane->base;
- struct drm_plane_state *pstate = intel_plane->base.state;
unsigned int data_rate, y_data_rate;
uint16_t plane_blocks, y_plane_blocks = 0;
int id = skl_wm_plane_id(intel_plane);
- if (!to_intel_plane_state(pstate)->visible)
- continue;
- if (plane->type == DRM_PLANE_TYPE_CURSOR)
- continue;
-
data_rate = cstate->wm.skl.plane_data_rate[id];
/*
@@ -3078,8 +3159,11 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
plane_blocks += div_u64((uint64_t)alloc_size * data_rate,
total_data_rate);
- ddb->plane[pipe][id].start = start;
- ddb->plane[pipe][id].end = start + plane_blocks;
+ /* Leave disabled planes at (0,0) */
+ if (data_rate) {
+ ddb->plane[pipe][id].start = start;
+ ddb->plane[pipe][id].end = start + plane_blocks;
+ }
start += plane_blocks;
@@ -3092,12 +3176,15 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
y_plane_blocks += div_u64((uint64_t)alloc_size * y_data_rate,
total_data_rate);
- ddb->y_plane[pipe][id].start = start;
- ddb->y_plane[pipe][id].end = start + y_plane_blocks;
+ if (y_data_rate) {
+ ddb->y_plane[pipe][id].start = start;
+ ddb->y_plane[pipe][id].end = start + y_plane_blocks;
+ }
start += y_plane_blocks;
}
+ return 0;
}
static uint32_t skl_pipe_pixel_rate(const struct intel_crtc_state *config)
@@ -3588,7 +3675,7 @@ static bool skl_update_pipe_wm(struct drm_crtc *crtc,
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
- skl_allocate_pipe_ddb(cstate, ddb);
+ WARN_ON(skl_allocate_pipe_ddb(cstate, ddb) != 0);
skl_build_pipe_wm(cstate, ddb, pipe_wm);
if (!memcmp(&intel_crtc->wm.active.skl, pipe_wm, sizeof(*pipe_wm)))
--
2.7.4

View File

@ -0,0 +1,94 @@
From 0126336af286ea85c1137ad13882f8c93d74c6c3 Mon Sep 17 00:00:00 2001
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
Date: Mon, 20 Jun 2016 12:40:13 +0200
Subject: [PATCH 08/17] drm/i915: Add distrust_bios_wm flag to dev_priv (v2)
Upstream: since drm-intel-next-2016-05-22
commit 279e99d76e6097ee7b531114777fa9b030496d81
Author: Matt Roper <matthew.d.roper@intel.com>
AuthorDate: Thu May 12 07:06:02 2016 -0700
Commit: Matt Roper <matthew.d.roper@intel.com>
CommitDate: Fri May 13 07:33:54 2016 -0700
drm/i915: Add distrust_bios_wm flag to dev_priv (v2)
SKL-style platforms can't fully trust the watermark/DDB settings
programmed by the BIOS and need to do extra sanitization on their first
atomic update. Add a flag to dev_priv that is set during hardware
readout and cleared at the end of the first commit.
Note that for the somewhat common case where everything is turned off
when the driver starts up, we don't need to bother with a recompute...we
know exactly what the DDB should be (all zero's) so just setup the DDB
directly in that case.
v2:
- Move clearing of distrust_bios_wm up below the swap_state call since
it's a more natural / self-explanatory location. (Maarten)
- Use dev_priv->active_crtcs to test whether any CRTC's are turned on
during HW WM readout rather than trying to count the active CRTC's
again ourselves. (Maarten)
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-9-git-send-email-matthew.d.roper@intel.com
---
drivers/gpu/drm/i915/i915_drv.h | 7 +++++++
drivers/gpu/drm/i915/intel_display.c | 1 +
drivers/gpu/drm/i915/intel_pm.c | 8 ++++++++
3 files changed, 16 insertions(+)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 804af6f..ae7932a 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1986,6 +1986,13 @@ struct drm_i915_private {
};
uint8_t max_level;
+
+ /*
+ * Set during HW readout of watermarks/DDB. Some platforms
+ * need to know when we're still using BIOS-provided values
+ * (which we don't fully trust).
+ */
+ bool distrust_bios_wm;
} wm;
struct i915_runtime_pm pm;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f53df81..786f3d9 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -13516,6 +13516,7 @@ static int intel_atomic_commit(struct drm_device *dev,
drm_atomic_helper_swap_state(dev, state);
dev_priv->wm.config = to_intel_atomic_state(state)->wm_config;
+ dev_priv->wm.distrust_bios_wm = false;
if (intel_state->modeset) {
memcpy(dev_priv->min_pixclk, intel_state->min_pixclk,
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index ee82b1f..6a09d7a 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3967,6 +3967,14 @@ void skl_wm_get_hw_state(struct drm_device *dev)
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
skl_pipe_wm_get_hw_state(crtc);
+ if (dev_priv->active_crtcs) {
+ /* Fully recompute DDB on first atomic commit */
+ dev_priv->wm.distrust_bios_wm = true;
+ } else {
+ /* Easy/common case; just sanitize DDB now if everything off */
+ memset(ddb, 0, sizeof(*ddb));
+ }
+
/* Calculate plane data rates */
for_each_intel_crtc(dev, intel_crtc) {
struct intel_crtc_state *cstate = intel_crtc->config;
--
2.7.4

View File

@ -0,0 +1,254 @@
From 0e9cf00438e4df1d97af44d3c52cc1cacc4dd2c9 Mon Sep 17 00:00:00 2001
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
Date: Mon, 20 Jun 2016 12:40:26 +0200
Subject: [PATCH 09/17] drm/i915/gen9: Compute DDB allocation at atomic check
time (v4)
Upstream: since drm-intel-next-2016-05-22
commit 98d39494d3759f84ce50e505059bc80f54c1c47b
Author: Matt Roper <matthew.d.roper@intel.com>
AuthorDate: Thu May 12 07:06:03 2016 -0700
Commit: Matt Roper <matthew.d.roper@intel.com>
CommitDate: Fri May 13 07:34:00 2016 -0700
drm/i915/gen9: Compute DDB allocation at atomic check time (v4)
Calculate the DDB blocks needed to satisfy the current atomic
transaction at atomic check time. This is a prerequisite to calculating
SKL watermarks during the 'check' phase and rejecting any configurations
that we can't find valid watermarks for.
Due to the nature of DDB allocation, it's possible for the addition of a
new CRTC to make the watermark configuration already in use on another,
unchanged CRTC become invalid. A change in which CRTC's are active
triggers a recompute of the entire DDB, which unfortunately means we
need to disallow any other atomic commits from racing with such an
update. If the active CRTC's change, we need to grab the lock on all
CRTC's and run all CRTC's through their 'check' handler to recompute and
re-check their per-CRTC DDB allocations.
Note that with this patch we only compute the DDB allocation but we
don't actually use the computed values during watermark programming yet.
For ease of review/testing/bisecting, we still recompute the DDB at
watermark programming time and just WARN() if it doesn't match the
precomputed values. A future patch will switch over to using the
precomputed values once we're sure they're being properly computed.
Another clarifying note: DDB allocation itself shouldn't ever fail with
the algorithm we use today (i.e., we have enough DDB blocks on BXT to
support the minimum needs of the worst-case scenario of every pipe/plane
enabled at full size). However the watermarks calculations based on the
DDB may fail and we'll be moving those to the atomic check as well in
future patches.
v2:
- Skip DDB calculations in the rare case where our transaction doesn't
actually touch any CRTC's at all. Assuming at least one CRTC state
is present in our transaction, then it means we can't race with any
transactions that would update dev_priv->active_crtcs (which requires
_all_ CRTC locks).
v3:
- Also calculate DDB during initial hw readout, to prevent using
incorrect bios values. (Maarten)
v4:
- Use new distrust_bios_wm flag instead of skip_initial_wm (which was
never actually set).
- Set intel_state->active_pipe_changes instead of just realloc_pipes
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Lyude Paul <cpaul@redhat.com>
Cc: Radhakrishna Sripada <radhakrishna.sripada@intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-10-git-send-email-matthew.d.roper@intel.com
---
drivers/gpu/drm/i915/i915_drv.h | 5 +++
drivers/gpu/drm/i915/intel_display.c | 18 ++++++++
drivers/gpu/drm/i915/intel_drv.h | 3 ++
drivers/gpu/drm/i915/intel_pm.c | 79 ++++++++++++++++++++++++++++++++++++
4 files changed, 105 insertions(+)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index ae7932a..237df9f 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -296,6 +296,10 @@ struct i915_hotplug {
#define for_each_intel_crtc(dev, intel_crtc) \
list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head)
+#define for_each_intel_crtc_mask(dev, intel_crtc, crtc_mask) \
+ list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) \
+ for_each_if ((crtc_mask) & (1 << drm_crtc_index(&intel_crtc->base)))
+
#define for_each_intel_encoder(dev, intel_encoder) \
list_for_each_entry(intel_encoder, \
&(dev)->mode_config.encoder_list, \
@@ -638,6 +642,7 @@ struct drm_i915_display_funcs {
int (*compute_pipe_wm)(struct intel_crtc *crtc,
struct drm_atomic_state *state);
void (*program_watermarks)(struct intel_crtc_state *cstate);
+ int (*compute_global_watermarks)(struct drm_atomic_state *state);
void (*update_wm)(struct drm_crtc *crtc);
int (*modeset_calc_cdclk)(struct drm_atomic_state *state);
void (*modeset_commit_cdclk)(struct drm_atomic_state *state);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 786f3d9..03e2635 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -13225,6 +13225,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
static void calc_watermark_data(struct drm_atomic_state *state)
{
struct drm_device *dev = state->dev;
+ struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
struct drm_crtc *crtc;
struct drm_crtc_state *cstate;
@@ -13254,6 +13255,10 @@ static void calc_watermark_data(struct drm_atomic_state *state)
pstate->crtc_h != pstate->src_h >> 16)
intel_state->wm_config.sprites_scaled = true;
}
+
+ /* Is there platform-specific watermark information to calculate? */
+ if (dev_priv->display.compute_global_watermarks)
+ dev_priv->display.compute_global_watermarks(state);
}
/**
@@ -13616,6 +13621,19 @@ static int intel_atomic_commit(struct drm_device *dev,
modeset_put_power_domains(dev_priv, put_domains[i]);
}
+ /*
+ * Temporary sanity check: make sure our pre-computed DDB matches the
+ * one we actually wind up programming.
+ *
+ * Not a great place to put this, but the easiest place we have access
+ * to both the pre-computed and final DDB's; we'll be removing this
+ * check in the next patch anyway.
+ */
+ WARN(IS_GEN9(dev) &&
+ memcmp(&intel_state->ddb, &dev_priv->wm.skl_results.ddb,
+ sizeof(intel_state->ddb)),
+ "Pre-computed DDB does not match final DDB!\n");
+
if (intel_state->modeset)
intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 672ca56..4d6336a 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -271,6 +271,9 @@ struct intel_atomic_state {
struct intel_shared_dpll_config shared_dpll[I915_NUM_PLLS];
struct intel_wm_config wm_config;
+
+ /* Gen9+ only */
+ struct skl_ddb_allocation ddb;
};
struct intel_plane_state {
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 6a09d7a..f60519d 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3751,6 +3751,84 @@ static void skl_clear_wm(struct skl_wm_values *watermarks, enum pipe pipe)
}
+static int
+skl_compute_ddb(struct drm_atomic_state *state)
+{
+ struct drm_device *dev = state->dev;
+ struct drm_i915_private *dev_priv = to_i915(dev);
+ struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
+ struct intel_crtc *intel_crtc;
+ unsigned realloc_pipes = dev_priv->active_crtcs;
+ int ret;
+
+ /*
+ * If this is our first atomic update following hardware readout,
+ * we can't trust the DDB that the BIOS programmed for us. Let's
+ * pretend that all pipes switched active status so that we'll
+ * ensure a full DDB recompute.
+ */
+ if (dev_priv->wm.distrust_bios_wm)
+ intel_state->active_pipe_changes = ~0;
+
+ /*
+ * If the modeset changes which CRTC's are active, we need to
+ * recompute the DDB allocation for *all* active pipes, even
+ * those that weren't otherwise being modified in any way by this
+ * atomic commit. Due to the shrinking of the per-pipe allocations
+ * when new active CRTC's are added, it's possible for a pipe that
+ * we were already using and aren't changing at all here to suddenly
+ * become invalid if its DDB needs exceeds its new allocation.
+ *
+ * Note that if we wind up doing a full DDB recompute, we can't let
+ * any other display updates race with this transaction, so we need
+ * to grab the lock on *all* CRTC's.
+ */
+ if (intel_state->active_pipe_changes)
+ realloc_pipes = ~0;
+
+ for_each_intel_crtc_mask(dev, intel_crtc, realloc_pipes) {
+ struct intel_crtc_state *cstate;
+
+ cstate = intel_atomic_get_crtc_state(state, intel_crtc);
+ if (IS_ERR(cstate))
+ return PTR_ERR(cstate);
+
+ ret = skl_allocate_pipe_ddb(cstate, &intel_state->ddb);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int
+skl_compute_wm(struct drm_atomic_state *state)
+{
+ struct drm_crtc *crtc;
+ struct drm_crtc_state *cstate;
+ int ret, i;
+ bool changed = false;
+
+ /*
+ * If this transaction isn't actually touching any CRTC's, don't
+ * bother with watermark calculation. Note that if we pass this
+ * test, we're guaranteed to hold at least one CRTC state mutex,
+ * which means we can safely use values like dev_priv->active_crtcs
+ * since any racing commits that want to update them would need to
+ * hold _all_ CRTC state mutexes.
+ */
+ for_each_crtc_in_state(state, crtc, cstate, i)
+ changed = true;
+ if (!changed)
+ return 0;
+
+ ret = skl_compute_ddb(state);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
static void skl_update_wm(struct drm_crtc *crtc)
{
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -7258,6 +7336,7 @@ void intel_init_pm(struct drm_device *dev)
dev_priv->display.init_clock_gating =
bxt_init_clock_gating;
dev_priv->display.update_wm = skl_update_wm;
+ dev_priv->display.compute_global_watermarks = skl_compute_wm;
} else if (HAS_PCH_SPLIT(dev)) {
ilk_setup_wm_latency(dev);
--
2.7.4

View File

@ -0,0 +1,389 @@
From 6a86f1d01bb25a687c59dd6b3e6deea362cf0ee1 Mon Sep 17 00:00:00 2001
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
Date: Mon, 20 Jun 2016 12:40:40 +0200
Subject: [PATCH 10/17] drm/i915/gen9: Drop re-allocation of DDB at atomic
commit (v2)
Upstream: since drm-intel-next-2016-05-22
commit a6d3460e62d17098a815a53f23e44d814cb347e0
Author: Matt Roper <matthew.d.roper@intel.com>
AuthorDate: Thu May 12 07:06:04 2016 -0700
Commit: Matt Roper <matthew.d.roper@intel.com>
CommitDate: Fri May 13 07:34:06 2016 -0700
drm/i915/gen9: Drop re-allocation of DDB at atomic commit (v2)
Now that we're properly pre-allocating the DDB during the atomic check
phase and we trust that the allocation is appropriate, let's actually
use the allocation computed and not duplicate that work during the
commit phase.
v2:
- Significant rebasing now that we can use cached data rates and
minimum block allocations to avoid grabbing additional plane states.
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-11-git-send-email-matthew.d.roper@intel.com
---
drivers/gpu/drm/i915/intel_display.c | 14 +--
drivers/gpu/drm/i915/intel_pm.c | 224 +++++++++++------------------------
2 files changed, 67 insertions(+), 171 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 03e2635..b484fda 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -13522,6 +13522,7 @@ static int intel_atomic_commit(struct drm_device *dev,
drm_atomic_helper_swap_state(dev, state);
dev_priv->wm.config = to_intel_atomic_state(state)->wm_config;
dev_priv->wm.distrust_bios_wm = false;
+ dev_priv->wm.skl_results.ddb = intel_state->ddb;
if (intel_state->modeset) {
memcpy(dev_priv->min_pixclk, intel_state->min_pixclk,
@@ -13621,19 +13622,6 @@ static int intel_atomic_commit(struct drm_device *dev,
modeset_put_power_domains(dev_priv, put_domains[i]);
}
- /*
- * Temporary sanity check: make sure our pre-computed DDB matches the
- * one we actually wind up programming.
- *
- * Not a great place to put this, but the easiest place we have access
- * to both the pre-computed and final DDB's; we'll be removing this
- * check in the next patch anyway.
- */
- WARN(IS_GEN9(dev) &&
- memcmp(&intel_state->ddb, &dev_priv->wm.skl_results.ddb,
- sizeof(intel_state->ddb)),
- "Pre-computed DDB does not match final DDB!\n");
-
if (intel_state->modeset)
intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index f60519d..80f9f18 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2788,7 +2788,6 @@ skl_wm_plane_id(const struct intel_plane *plane)
static void
skl_ddb_get_pipe_allocation_limits(struct drm_device *dev,
const struct intel_crtc_state *cstate,
- struct intel_wm_config *config,
struct skl_ddb_entry *alloc, /* out */
int *num_active /* out */)
{
@@ -2796,24 +2795,22 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev,
struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_crtc *for_crtc = cstate->base.crtc;
- struct drm_crtc *crtc;
unsigned int pipe_size, ddb_size;
int nth_active_pipe;
int pipe = to_intel_crtc(for_crtc)->pipe;
- if (intel_state && intel_state->active_pipe_changes)
- *num_active = hweight32(intel_state->active_crtcs);
- else if (intel_state)
- *num_active = hweight32(dev_priv->active_crtcs);
- else
- *num_active = config->num_pipes_active;
-
- if (!cstate->base.active) {
+ if (WARN_ON(!state) || !cstate->base.active) {
alloc->start = 0;
alloc->end = 0;
+ *num_active = hweight32(dev_priv->active_crtcs);
return;
}
+ if (intel_state->active_pipe_changes)
+ *num_active = hweight32(intel_state->active_crtcs);
+ else
+ *num_active = hweight32(dev_priv->active_crtcs);
+
if (IS_BROXTON(dev))
ddb_size = BXT_DDB_SIZE;
else
@@ -2822,50 +2819,23 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev,
ddb_size -= 4; /* 4 blocks for bypass path allocation */
/*
- * FIXME: At the moment we may be called on either in-flight or fully
- * committed cstate's. Once we fully move DDB allocation in the check
- * phase, we'll only be called on in-flight states and the 'else'
- * branch here will go away.
- *
- * The 'else' branch is slightly racy here, but it was racy to begin
- * with; since it's going away soon, no effort is made to address that.
+ * If the state doesn't change the active CRTC's, then there's
+ * no need to recalculate; the existing pipe allocation limits
+ * should remain unchanged. Note that we're safe from racing
+ * commits since any racing commit that changes the active CRTC
+ * list would need to grab _all_ crtc locks, including the one
+ * we currently hold.
*/
- if (state) {
- /*
- * If the state doesn't change the active CRTC's, then there's
- * no need to recalculate; the existing pipe allocation limits
- * should remain unchanged. Note that we're safe from racing
- * commits since any racing commit that changes the active CRTC
- * list would need to grab _all_ crtc locks, including the one
- * we currently hold.
- */
- if (!intel_state->active_pipe_changes) {
- *alloc = dev_priv->wm.skl_hw.ddb.pipe[pipe];
- return;
- }
-
- nth_active_pipe = hweight32(intel_state->active_crtcs &
- (drm_crtc_mask(for_crtc) - 1));
- pipe_size = ddb_size / hweight32(intel_state->active_crtcs);
- alloc->start = nth_active_pipe * ddb_size / *num_active;
- alloc->end = alloc->start + pipe_size;
- } else {
- nth_active_pipe = 0;
- for_each_crtc(dev, crtc) {
- if (!to_intel_crtc(crtc)->active)
- continue;
-
- if (crtc == for_crtc)
- break;
-
- nth_active_pipe++;
- }
-
- pipe_size = ddb_size / config->num_pipes_active;
- alloc->start = nth_active_pipe * ddb_size /
- config->num_pipes_active;
- alloc->end = alloc->start + pipe_size;
+ if (!intel_state->active_pipe_changes) {
+ *alloc = dev_priv->wm.skl_hw.ddb.pipe[pipe];
+ return;
}
+
+ nth_active_pipe = hweight32(intel_state->active_crtcs &
+ (drm_crtc_mask(for_crtc) - 1));
+ pipe_size = ddb_size / hweight32(intel_state->active_crtcs);
+ alloc->start = nth_active_pipe * ddb_size / *num_active;
+ alloc->end = alloc->start + pipe_size;
}
static unsigned int skl_cursor_allocation(int num_active)
@@ -2964,62 +2934,33 @@ skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate)
struct drm_crtc *crtc = cstate->crtc;
struct drm_device *dev = crtc->dev;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ const struct drm_plane *plane;
const struct intel_plane *intel_plane;
+ struct drm_plane_state *pstate;
unsigned int rate, total_data_rate = 0;
int id;
+ int i;
+
+ if (WARN_ON(!state))
+ return 0;
/* Calculate and cache data rate for each plane */
- /*
- * FIXME: At the moment this function can be called on either an
- * in-flight or a committed state object. If it's in-flight then we
- * only want to re-calculate the plane data rate for planes that are
- * part of the transaction (i.e., we don't want to grab any additional
- * plane states if we don't have to). If we're operating on committed
- * state, we'll just go ahead and recalculate the plane data rate for
- * all planes.
- *
- * Once we finish moving our DDB allocation to the atomic check phase,
- * we'll only be calling this function on in-flight state objects, so
- * the 'else' branch here will go away.
- */
- if (state) {
- struct drm_plane *plane;
- struct drm_plane_state *pstate;
- int i;
-
- for_each_plane_in_state(state, plane, pstate, i) {
- intel_plane = to_intel_plane(plane);
- id = skl_wm_plane_id(intel_plane);
-
- if (intel_plane->pipe != intel_crtc->pipe)
- continue;
-
- /* packed/uv */
- rate = skl_plane_relative_data_rate(intel_cstate,
- pstate, 0);
- intel_cstate->wm.skl.plane_data_rate[id] = rate;
-
- /* y-plane */
- rate = skl_plane_relative_data_rate(intel_cstate,
- pstate, 1);
- intel_cstate->wm.skl.plane_y_data_rate[id] = rate;
- }
- } else {
- for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
- const struct drm_plane_state *pstate =
- intel_plane->base.state;
- int id = skl_wm_plane_id(intel_plane);
+ for_each_plane_in_state(state, plane, pstate, i) {
+ id = skl_wm_plane_id(to_intel_plane(plane));
+ intel_plane = to_intel_plane(plane);
- /* packed/uv */
- rate = skl_plane_relative_data_rate(intel_cstate,
- pstate, 0);
- intel_cstate->wm.skl.plane_data_rate[id] = rate;
+ if (intel_plane->pipe != intel_crtc->pipe)
+ continue;
- /* y-plane */
- rate = skl_plane_relative_data_rate(intel_cstate,
- pstate, 1);
- intel_cstate->wm.skl.plane_y_data_rate[id] = rate;
- }
+ /* packed/uv */
+ rate = skl_plane_relative_data_rate(intel_cstate,
+ pstate, 0);
+ intel_cstate->wm.skl.plane_data_rate[id] = rate;
+
+ /* y-plane */
+ rate = skl_plane_relative_data_rate(intel_cstate,
+ pstate, 1);
+ intel_cstate->wm.skl.plane_y_data_rate[id] = rate;
}
/* Calculate CRTC's total data rate from cached values */
@@ -3043,8 +2984,6 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
struct drm_atomic_state *state = cstate->base.state;
struct drm_crtc *crtc = cstate->base.crtc;
struct drm_device *dev = crtc->dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
- struct intel_wm_config *config = &dev_priv->wm.config;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_plane *intel_plane;
struct drm_plane *plane;
@@ -3058,6 +2997,9 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
int num_active;
int id, i;
+ if (WARN_ON(!state))
+ return 0;
+
if (!cstate->base.active) {
ddb->pipe[pipe].start = ddb->pipe[pipe].end = 0;
memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe]));
@@ -3065,8 +3007,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
return 0;
}
- skl_ddb_get_pipe_allocation_limits(dev, cstate, config, alloc,
- &num_active);
+ skl_ddb_get_pipe_allocation_limits(dev, cstate, alloc, &num_active);
alloc_size = skl_ddb_entry_size(alloc);
if (alloc_size == 0) {
memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe]));
@@ -3078,53 +3019,31 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
ddb->plane[pipe][PLANE_CURSOR].end = alloc->end;
alloc_size -= cursor_blocks;
- alloc->end -= cursor_blocks;
/* 1. Allocate the mininum required blocks for each active plane */
- /*
- * TODO: Remove support for already-committed state once we
- * only allocate DDB on in-flight states.
- */
- if (state) {
- for_each_plane_in_state(state, plane, pstate, i) {
- intel_plane = to_intel_plane(plane);
- id = skl_wm_plane_id(intel_plane);
-
- if (intel_plane->pipe != pipe)
- continue;
-
- if (!to_intel_plane_state(pstate)->visible) {
- minimum[id] = 0;
- y_minimum[id] = 0;
- continue;
- }
- if (plane->type == DRM_PLANE_TYPE_CURSOR) {
- minimum[id] = 0;
- y_minimum[id] = 0;
- continue;
- }
-
- minimum[id] = 8;
- if (pstate->fb->pixel_format == DRM_FORMAT_NV12)
- y_minimum[id] = 8;
- else
- y_minimum[id] = 0;
- }
- } else {
- for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
- struct drm_plane *plane = &intel_plane->base;
- struct drm_framebuffer *fb = plane->state->fb;
- int id = skl_wm_plane_id(intel_plane);
-
- if (!to_intel_plane_state(plane->state)->visible)
- continue;
+ for_each_plane_in_state(state, plane, pstate, i) {
+ intel_plane = to_intel_plane(plane);
+ id = skl_wm_plane_id(intel_plane);
- if (plane->type == DRM_PLANE_TYPE_CURSOR)
- continue;
+ if (intel_plane->pipe != pipe)
+ continue;
- minimum[id] = 8;
- y_minimum[id] = (fb->pixel_format == DRM_FORMAT_NV12) ? 8 : 0;
+ if (!to_intel_plane_state(pstate)->visible) {
+ minimum[id] = 0;
+ y_minimum[id] = 0;
+ continue;
+ }
+ if (plane->type == DRM_PLANE_TYPE_CURSOR) {
+ minimum[id] = 0;
+ y_minimum[id] = 0;
+ continue;
}
+
+ minimum[id] = 8;
+ if (pstate->fb->pixel_format == DRM_FORMAT_NV12)
+ y_minimum[id] = 8;
+ else
+ y_minimum[id] = 0;
}
for (i = 0; i < PLANE_CURSOR; i++) {
@@ -3675,7 +3594,6 @@ static bool skl_update_pipe_wm(struct drm_crtc *crtc,
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
- WARN_ON(skl_allocate_pipe_ddb(cstate, ddb) != 0);
skl_build_pipe_wm(cstate, ddb, pipe_wm);
if (!memcmp(&intel_crtc->wm.active.skl, pipe_wm, sizeof(*pipe_wm)))
@@ -3739,16 +3657,6 @@ static void skl_clear_wm(struct skl_wm_values *watermarks, enum pipe pipe)
memset(watermarks->plane_trans[pipe],
0, sizeof(uint32_t) * I915_MAX_PLANES);
watermarks->plane_trans[pipe][PLANE_CURSOR] = 0;
-
- /* Clear ddb entries for pipe */
- memset(&watermarks->ddb.pipe[pipe], 0, sizeof(struct skl_ddb_entry));
- memset(&watermarks->ddb.plane[pipe], 0,
- sizeof(struct skl_ddb_entry) * I915_MAX_PLANES);
- memset(&watermarks->ddb.y_plane[pipe], 0,
- sizeof(struct skl_ddb_entry) * I915_MAX_PLANES);
- memset(&watermarks->ddb.plane[pipe][PLANE_CURSOR], 0,
- sizeof(struct skl_ddb_entry));
-
}
static int
--
2.7.4

View File

@ -0,0 +1,91 @@
From eacd0ecb98a93e3ff83a4479eadeb9cda05d3579 Mon Sep 17 00:00:00 2001
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
Date: Mon, 20 Jun 2016 12:41:01 +0200
Subject: [PATCH 11/17] drm/i915/gen9: Calculate plane WM's from state
Upstream: since drm-intel-next-2016-05-22
commit 33815fa55b31a5de4b197c09926ecab3dfb79732
Author: Matt Roper <matthew.d.roper@intel.com>
AuthorDate: Thu May 12 07:06:05 2016 -0700
Commit: Matt Roper <matthew.d.roper@intel.com>
CommitDate: Fri May 13 07:34:12 2016 -0700
drm/i915/gen9: Calculate plane WM's from state
In a future patch we'll want to calculate plane watermarks for in-flight
atomic state rather than the already-committed state.
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-12-git-send-email-matthew.d.roper@intel.com
---
drivers/gpu/drm/i915/intel_pm.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 80f9f18..3164f30 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3179,16 +3179,14 @@ static bool skl_ddb_allocation_changed(const struct skl_ddb_allocation *new_ddb,
static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
struct intel_crtc_state *cstate,
- struct intel_plane *intel_plane,
+ struct intel_plane_state *intel_pstate,
uint16_t ddb_allocation,
int level,
uint16_t *out_blocks, /* out */
uint8_t *out_lines /* out */)
{
- struct drm_plane *plane = &intel_plane->base;
- struct drm_framebuffer *fb = plane->state->fb;
- struct intel_plane_state *intel_pstate =
- to_intel_plane_state(plane->state);
+ struct drm_plane_state *pstate = &intel_pstate->base;
+ struct drm_framebuffer *fb = pstate->fb;
uint32_t latency = dev_priv->wm.skl_latency[level];
uint32_t method1, method2;
uint32_t plane_bytes_per_line, plane_blocks_per_line;
@@ -3203,7 +3201,7 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
width = drm_rect_width(&intel_pstate->src) >> 16;
height = drm_rect_height(&intel_pstate->src) >> 16;
- if (intel_rotation_90_or_270(plane->state->rotation))
+ if (intel_rotation_90_or_270(pstate->rotation))
swap(width, height);
cpp = drm_format_plane_cpp(fb->pixel_format, 0);
@@ -3223,7 +3221,7 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) {
uint32_t min_scanlines = 4;
uint32_t y_tile_minimum;
- if (intel_rotation_90_or_270(plane->state->rotation)) {
+ if (intel_rotation_90_or_270(pstate->rotation)) {
int cpp = (fb->pixel_format == DRM_FORMAT_NV12) ?
drm_format_plane_cpp(fb->pixel_format, 1) :
drm_format_plane_cpp(fb->pixel_format, 0);
@@ -3277,17 +3275,19 @@ static void skl_compute_wm_level(const struct drm_i915_private *dev_priv,
struct drm_device *dev = dev_priv->dev;
struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
struct intel_plane *intel_plane;
+ struct intel_plane_state *intel_pstate;
uint16_t ddb_blocks;
enum pipe pipe = intel_crtc->pipe;
for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
int i = skl_wm_plane_id(intel_plane);
+ intel_pstate = to_intel_plane_state(intel_plane->base.state);
ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][i]);
result->plane_en[i] = skl_compute_plane_wm(dev_priv,
cstate,
- intel_plane,
+ intel_pstate,
ddb_blocks,
level,
&result->plane_res_b[i],
--
2.7.4

View File

@ -0,0 +1,156 @@
From c3d2591095045a8230361d55fadf15ce5dc9127d Mon Sep 17 00:00:00 2001
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
Date: Mon, 20 Jun 2016 12:41:12 +0200
Subject: [PATCH 12/17] drm/i915/gen9: Allow watermark calculation on in-flight
atomic state (v3)
Upstream: since drm-intel-next-2016-05-22
commit f4a967523ec7215a3ec867b7ed2e916bd34840e1
Author: Matt Roper <matthew.d.roper@intel.com>
AuthorDate: Thu May 12 07:06:06 2016 -0700
Commit: Matt Roper <matthew.d.roper@intel.com>
CommitDate: Fri May 13 07:34:23 2016 -0700
drm/i915/gen9: Allow watermark calculation on in-flight atomic state (v3)
In an upcoming patch we'll move this calculation to the atomic 'check'
phase so that the display update can be rejected early if no valid
watermark programming is possible.
v2:
- Drop intel_pstate_for_cstate_plane() helper and add note about how
the code needs to evolve in the future if we start allowing more than
one pending commit against a CRTC. (Maarten)
v3:
- Only have skl_compute_wm_level calculate watermarks for enabled
planes; we can just set the other planes on a CRTC to disabled
without having to look at the plane state. This is important because
despite our CRTC lock we can still have racing commits that modify
a disabled plane's property without turning it on. (Maarten)
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-13-git-send-email-matthew.d.roper@intel.com
---
drivers/gpu/drm/i915/intel_pm.c | 61 ++++++++++++++++++++++++++++++++---------
1 file changed, 48 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 3164f30..cd29ab6 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3266,23 +3266,56 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
return true;
}
-static void skl_compute_wm_level(const struct drm_i915_private *dev_priv,
- struct skl_ddb_allocation *ddb,
- struct intel_crtc_state *cstate,
- int level,
- struct skl_wm_level *result)
+static int
+skl_compute_wm_level(const struct drm_i915_private *dev_priv,
+ struct skl_ddb_allocation *ddb,
+ struct intel_crtc_state *cstate,
+ int level,
+ struct skl_wm_level *result)
{
struct drm_device *dev = dev_priv->dev;
+ struct drm_atomic_state *state = cstate->base.state;
struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
+ struct drm_plane *plane;
struct intel_plane *intel_plane;
struct intel_plane_state *intel_pstate;
uint16_t ddb_blocks;
enum pipe pipe = intel_crtc->pipe;
- for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
+ /*
+ * We'll only calculate watermarks for planes that are actually
+ * enabled, so make sure all other planes are set as disabled.
+ */
+ memset(result, 0, sizeof(*result));
+
+ for_each_intel_plane_mask(dev, intel_plane, cstate->base.plane_mask) {
int i = skl_wm_plane_id(intel_plane);
- intel_pstate = to_intel_plane_state(intel_plane->base.state);
+ plane = &intel_plane->base;
+ intel_pstate = NULL;
+ if (state)
+ intel_pstate =
+ intel_atomic_get_existing_plane_state(state,
+ intel_plane);
+
+ /*
+ * Note: If we start supporting multiple pending atomic commits
+ * against the same planes/CRTC's in the future, plane->state
+ * will no longer be the correct pre-state to use for the
+ * calculations here and we'll need to change where we get the
+ * 'unchanged' plane data from.
+ *
+ * For now this is fine because we only allow one queued commit
+ * against a CRTC. Even if the plane isn't modified by this
+ * transaction and we don't have a plane lock, we still have
+ * the CRTC's lock, so we know that no other transactions are
+ * racing with us to update it.
+ */
+ if (!intel_pstate)
+ intel_pstate = to_intel_plane_state(plane->state);
+
+ WARN_ON(!intel_pstate->base.fb);
+
ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][i]);
result->plane_en[i] = skl_compute_plane_wm(dev_priv,
@@ -3293,6 +3326,8 @@ static void skl_compute_wm_level(const struct drm_i915_private *dev_priv,
&result->plane_res_b[i],
&result->plane_res_l[i]);
}
+
+ return 0;
}
static uint32_t
@@ -3587,14 +3622,14 @@ static void skl_flush_wm_values(struct drm_i915_private *dev_priv,
}
}
-static bool skl_update_pipe_wm(struct drm_crtc *crtc,
+static bool skl_update_pipe_wm(struct drm_crtc_state *cstate,
struct skl_ddb_allocation *ddb, /* out */
struct skl_pipe_wm *pipe_wm /* out */)
{
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
+ struct intel_crtc *intel_crtc = to_intel_crtc(cstate->crtc);
+ struct intel_crtc_state *intel_cstate = to_intel_crtc_state(cstate);
- skl_build_pipe_wm(cstate, ddb, pipe_wm);
+ skl_build_pipe_wm(intel_cstate, ddb, pipe_wm);
if (!memcmp(&intel_crtc->wm.active.skl, pipe_wm, sizeof(*pipe_wm)))
return false;
@@ -3634,7 +3669,7 @@ static void skl_update_other_pipe_wm(struct drm_device *dev,
if (!intel_crtc->active)
continue;
- wm_changed = skl_update_pipe_wm(&intel_crtc->base,
+ wm_changed = skl_update_pipe_wm(intel_crtc->base.state,
&r->ddb, &pipe_wm);
/*
@@ -3752,7 +3787,7 @@ static void skl_update_wm(struct drm_crtc *crtc)
skl_clear_wm(results, intel_crtc->pipe);
- if (!skl_update_pipe_wm(crtc, &results->ddb, pipe_wm))
+ if (!skl_update_pipe_wm(crtc->state, &results->ddb, pipe_wm))
return;
skl_compute_wm_results(dev, pipe_wm, results, intel_crtc);
--
2.7.4

View File

@ -0,0 +1,91 @@
From b43247a865f73fa3b73a878236b5055bfb864169 Mon Sep 17 00:00:00 2001
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
Date: Mon, 20 Jun 2016 12:41:23 +0200
Subject: [PATCH 13/17] drm/i915/gen9: Use a bitmask to track dirty pipe
watermarks
Upstream: since drm-intel-next-2016-05-22
commit 2b4b9f35d94b1b533bc23110b040b04316480b28
Author: Matt Roper <matthew.d.roper@intel.com>
AuthorDate: Thu May 12 07:06:07 2016 -0700
Commit: Matt Roper <matthew.d.roper@intel.com>
CommitDate: Fri May 13 07:34:40 2016 -0700
drm/i915/gen9: Use a bitmask to track dirty pipe watermarks
Slightly easier to work with than an array of bools.
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-14-git-send-email-matthew.d.roper@intel.com
---
drivers/gpu/drm/i915/i915_drv.h | 2 +-
drivers/gpu/drm/i915/intel_pm.c | 10 +++++-----
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 237df9f..67c76b6 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1615,7 +1615,7 @@ struct skl_ddb_allocation {
};
struct skl_wm_values {
- bool dirty[I915_MAX_PIPES];
+ unsigned dirty_pipes;
struct skl_ddb_allocation ddb;
uint32_t wm_linetime[I915_MAX_PIPES];
uint32_t plane[I915_MAX_PIPES][I915_MAX_PLANES][8];
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index cd29ab6..611c5a1 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3455,7 +3455,7 @@ static void skl_write_wm_values(struct drm_i915_private *dev_priv,
int i, level, max_level = ilk_wm_max_level(dev);
enum pipe pipe = crtc->pipe;
- if (!new->dirty[pipe])
+ if ((new->dirty_pipes & drm_crtc_mask(&crtc->base)) == 0)
continue;
I915_WRITE(PIPE_WM_LINETIME(pipe), new->wm_linetime[pipe]);
@@ -3680,7 +3680,7 @@ static void skl_update_other_pipe_wm(struct drm_device *dev,
WARN_ON(!wm_changed);
skl_compute_wm_results(dev, &pipe_wm, r, intel_crtc);
- r->dirty[intel_crtc->pipe] = true;
+ r->dirty_pipes |= drm_crtc_mask(&intel_crtc->base);
}
}
@@ -3783,7 +3783,7 @@ static void skl_update_wm(struct drm_crtc *crtc)
/* Clear all dirty flags */
- memset(results->dirty, 0, sizeof(bool) * I915_MAX_PIPES);
+ results->dirty_pipes = 0;
skl_clear_wm(results, intel_crtc->pipe);
@@ -3791,7 +3791,7 @@ static void skl_update_wm(struct drm_crtc *crtc)
return;
skl_compute_wm_results(dev, pipe_wm, results, intel_crtc);
- results->dirty[intel_crtc->pipe] = true;
+ results->dirty_pipes |= drm_crtc_mask(&intel_crtc->base);
skl_update_other_pipe_wm(dev, crtc, results);
skl_write_wm_values(dev_priv, results);
@@ -3952,7 +3952,7 @@ static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc)
if (!intel_crtc->active)
return;
- hw->dirty[pipe] = true;
+ hw->dirty_pipes |= drm_crtc_mask(crtc);
active->linetime = hw->wm_linetime[pipe];
--
2.7.4

View File

@ -0,0 +1,254 @@
From 2dda82bdd570042820241e71c02ea36081835f67 Mon Sep 17 00:00:00 2001
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
Date: Mon, 20 Jun 2016 12:41:35 +0200
Subject: [PATCH 14/17] drm/i915/gen9: Propagate watermark calculation failures
up the call chain
Upstream: since drm-intel-next-2016-05-22
commit 55994c2c38a1101f84cdf277b228f830af8a9c1b
Author: Matt Roper <matthew.d.roper@intel.com>
AuthorDate: Thu May 12 07:06:08 2016 -0700
Commit: Matt Roper <matthew.d.roper@intel.com>
CommitDate: Fri May 13 07:34:48 2016 -0700
drm/i915/gen9: Propagate watermark calculation failures up the call chain
Once we move watermark calculation to the atomic check phase, we'll want
to start rejecting display configurations that exceed out watermark
limits. At the moment we just assume that there's always a valid set of
watermarks, even though this may not actually be true. Let's prepare by
passing return codes up through the call stack in preparation.
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-15-git-send-email-matthew.d.roper@intel.com
---
drivers/gpu/drm/i915/intel_display.c | 10 ++--
drivers/gpu/drm/i915/intel_pm.c | 90 ++++++++++++++++++++++--------------
2 files changed, 61 insertions(+), 39 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index b484fda..9ac2346 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -13222,7 +13222,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
* 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)
+static int calc_watermark_data(struct drm_atomic_state *state)
{
struct drm_device *dev = state->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
@@ -13258,7 +13258,9 @@ static void calc_watermark_data(struct drm_atomic_state *state)
/* Is there platform-specific watermark information to calculate? */
if (dev_priv->display.compute_global_watermarks)
- dev_priv->display.compute_global_watermarks(state);
+ return dev_priv->display.compute_global_watermarks(state);
+
+ return 0;
}
/**
@@ -13345,9 +13347,7 @@ static int intel_atomic_check(struct drm_device *dev,
return ret;
intel_fbc_choose_crtc(dev_priv, state);
- calc_watermark_data(state);
-
- return 0;
+ return calc_watermark_data(state);
}
static int intel_atomic_prepare_commit(struct drm_device *dev,
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 611c5a1..ec22d93 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3177,13 +3177,14 @@ static bool skl_ddb_allocation_changed(const struct skl_ddb_allocation *new_ddb,
return false;
}
-static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
- struct intel_crtc_state *cstate,
- struct intel_plane_state *intel_pstate,
- uint16_t ddb_allocation,
- int level,
- uint16_t *out_blocks, /* out */
- uint8_t *out_lines /* out */)
+static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
+ struct intel_crtc_state *cstate,
+ struct intel_plane_state *intel_pstate,
+ uint16_t ddb_allocation,
+ int level,
+ uint16_t *out_blocks, /* out */
+ uint8_t *out_lines, /* out */
+ bool *enabled /* out */)
{
struct drm_plane_state *pstate = &intel_pstate->base;
struct drm_framebuffer *fb = pstate->fb;
@@ -3195,8 +3196,10 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
uint8_t cpp;
uint32_t width = 0, height = 0;
- if (latency == 0 || !cstate->base.active || !intel_pstate->visible)
- return false;
+ if (latency == 0 || !cstate->base.active || !intel_pstate->visible) {
+ *enabled = false;
+ return 0;
+ }
width = drm_rect_width(&intel_pstate->src) >> 16;
height = drm_rect_height(&intel_pstate->src) >> 16;
@@ -3257,13 +3260,16 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
res_blocks++;
}
- if (res_blocks >= ddb_allocation || res_lines > 31)
- return false;
+ if (res_blocks >= ddb_allocation || res_lines > 31) {
+ *enabled = false;
+ return 0;
+ }
*out_blocks = res_blocks;
*out_lines = res_lines;
+ *enabled = true;
- return true;
+ return 0;
}
static int
@@ -3281,6 +3287,7 @@ skl_compute_wm_level(const struct drm_i915_private *dev_priv,
struct intel_plane_state *intel_pstate;
uint16_t ddb_blocks;
enum pipe pipe = intel_crtc->pipe;
+ int ret;
/*
* We'll only calculate watermarks for planes that are actually
@@ -3318,13 +3325,16 @@ skl_compute_wm_level(const struct drm_i915_private *dev_priv,
ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][i]);
- result->plane_en[i] = skl_compute_plane_wm(dev_priv,
- cstate,
- intel_pstate,
- ddb_blocks,
- level,
- &result->plane_res_b[i],
- &result->plane_res_l[i]);
+ ret = skl_compute_plane_wm(dev_priv,
+ cstate,
+ intel_pstate,
+ ddb_blocks,
+ level,
+ &result->plane_res_b[i],
+ &result->plane_res_l[i],
+ &result->plane_en[i]);
+ if (ret)
+ return ret;
}
return 0;
@@ -3361,21 +3371,26 @@ static void skl_compute_transition_wm(struct intel_crtc_state *cstate,
}
}
-static void skl_build_pipe_wm(struct intel_crtc_state *cstate,
- struct skl_ddb_allocation *ddb,
- struct skl_pipe_wm *pipe_wm)
+static int skl_build_pipe_wm(struct intel_crtc_state *cstate,
+ struct skl_ddb_allocation *ddb,
+ struct skl_pipe_wm *pipe_wm)
{
struct drm_device *dev = cstate->base.crtc->dev;
const struct drm_i915_private *dev_priv = dev->dev_private;
int level, max_level = ilk_wm_max_level(dev);
+ int ret;
for (level = 0; level <= max_level; level++) {
- skl_compute_wm_level(dev_priv, ddb, cstate,
- level, &pipe_wm->wm[level]);
+ ret = skl_compute_wm_level(dev_priv, ddb, cstate,
+ level, &pipe_wm->wm[level]);
+ if (ret)
+ return ret;
}
pipe_wm->linetime = skl_compute_linetime_wm(cstate);
skl_compute_transition_wm(cstate, &pipe_wm->trans_wm);
+
+ return 0;
}
static void skl_compute_wm_results(struct drm_device *dev,
@@ -3622,21 +3637,27 @@ static void skl_flush_wm_values(struct drm_i915_private *dev_priv,
}
}
-static bool skl_update_pipe_wm(struct drm_crtc_state *cstate,
- struct skl_ddb_allocation *ddb, /* out */
- struct skl_pipe_wm *pipe_wm /* out */)
+static int skl_update_pipe_wm(struct drm_crtc_state *cstate,
+ struct skl_ddb_allocation *ddb, /* out */
+ struct skl_pipe_wm *pipe_wm, /* out */
+ bool *changed /* out */)
{
struct intel_crtc *intel_crtc = to_intel_crtc(cstate->crtc);
struct intel_crtc_state *intel_cstate = to_intel_crtc_state(cstate);
+ int ret;
- skl_build_pipe_wm(intel_cstate, ddb, pipe_wm);
+ ret = skl_build_pipe_wm(intel_cstate, ddb, pipe_wm);
+ if (ret)
+ return ret;
if (!memcmp(&intel_crtc->wm.active.skl, pipe_wm, sizeof(*pipe_wm)))
- return false;
+ *changed = false;
+ else
+ *changed = true;
intel_crtc->wm.active.skl = *pipe_wm;
- return true;
+ return 0;
}
static void skl_update_other_pipe_wm(struct drm_device *dev,
@@ -3669,8 +3690,8 @@ static void skl_update_other_pipe_wm(struct drm_device *dev,
if (!intel_crtc->active)
continue;
- wm_changed = skl_update_pipe_wm(intel_crtc->base.state,
- &r->ddb, &pipe_wm);
+ skl_update_pipe_wm(intel_crtc->base.state,
+ &r->ddb, &pipe_wm, &wm_changed);
/*
* If we end up re-computing the other pipe WM values, it's
@@ -3780,14 +3801,15 @@ static void skl_update_wm(struct drm_crtc *crtc)
struct skl_wm_values *results = &dev_priv->wm.skl_results;
struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
struct skl_pipe_wm *pipe_wm = &cstate->wm.skl.optimal;
-
+ bool wm_changed;
/* Clear all dirty flags */
results->dirty_pipes = 0;
skl_clear_wm(results, intel_crtc->pipe);
- if (!skl_update_pipe_wm(crtc->state, &results->ddb, pipe_wm))
+ skl_update_pipe_wm(crtc->state, &results->ddb, pipe_wm, &wm_changed);
+ if (!wm_changed)
return;
skl_compute_wm_results(dev, pipe_wm, results, intel_crtc);
--
2.7.4

View File

@ -0,0 +1,321 @@
From 71136125cc79dab464a0139dbf0c02891aa9ce6e Mon Sep 17 00:00:00 2001
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
Date: Mon, 20 Jun 2016 12:41:46 +0200
Subject: [PATCH 15/17] drm/i915/gen9: Calculate watermarks during atomic
'check' (v2)
Upstream: since drm-intel-next-2016-05-22
commit 734fa01f3a17ac80d2d53cee0b05b246c03df0e4
Author: Matt Roper <matthew.d.roper@intel.com>
AuthorDate: Thu May 12 15:11:40 2016 -0700
Commit: Matt Roper <matthew.d.roper@intel.com>
CommitDate: Fri May 13 07:35:48 2016 -0700
drm/i915/gen9: Calculate watermarks during atomic 'check' (v2)
Moving watermark calculation into the check phase will allow us to to
reject display configurations for which there are no valid watermark
values before we start trying to program the hardware (although those
tests will come in a subsequent patch).
Another advantage of moving this calculation to the check phase is that
we can calculate the watermarks in a single shot as part of the atomic
transaction. The watermark interfaces we inherited from our legacy
modesetting days are a bit broken in the atomic design because they use
per-crtc entry points but actually re-calculate and re-program something
that is really more of a global state. That worked okay in the legacy
modesetting world because operations only ever updated a single CRTC at
a time. However in the atomic world, a transaction can involve multiple
CRTC's, which means we wind up computing and programming the watermarks
NxN times (where N is the number of CRTC's involved). With this patch
we eliminate the redundant re-calculation of watermark data for atomic
states (which was the cause of the WARN_ON(!wm_changed) problems that
have plagued us for a while).
We still need to work on the 'commit' side of watermark handling so that
we aren't doing redundant NxN programming of watermarks, but that's
content for future patches.
v2:
- Bail out of skl_write_wm_values() if the CRTC isn't active. Now that
we set dirty_pipes to ~0 if the active pipes change (because
we need to deal with DDB changes), we can now wind up here for
disabled pipes, whereas we couldn't before.
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=89055
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=92181
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Tested-by: Daniel Stone <daniels@collabora.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1463091100-13747-1-git-send-email-matthew.d.roper@intel.com
---
drivers/gpu/drm/i915/intel_display.c | 2 +-
drivers/gpu/drm/i915/intel_drv.h | 14 +++-
drivers/gpu/drm/i915/intel_pm.c | 135 ++++++++++++-----------------------
3 files changed, 61 insertions(+), 90 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 9ac2346..1726ea4 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -13522,7 +13522,7 @@ static int intel_atomic_commit(struct drm_device *dev,
drm_atomic_helper_swap_state(dev, state);
dev_priv->wm.config = to_intel_atomic_state(state)->wm_config;
dev_priv->wm.distrust_bios_wm = false;
- dev_priv->wm.skl_results.ddb = intel_state->ddb;
+ dev_priv->wm.skl_results = intel_state->wm_results;
if (intel_state->modeset) {
memcpy(dev_priv->min_pixclk, intel_state->min_pixclk,
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 4d6336a..e5543b8 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -273,7 +273,7 @@ struct intel_atomic_state {
struct intel_wm_config wm_config;
/* Gen9+ only */
- struct skl_ddb_allocation ddb;
+ struct skl_wm_values wm_results;
};
struct intel_plane_state {
@@ -1661,6 +1661,18 @@ intel_atomic_get_crtc_state(struct drm_atomic_state *state,
return to_intel_crtc_state(crtc_state);
}
+
+static inline struct intel_plane_state *
+intel_atomic_get_existing_plane_state(struct drm_atomic_state *state,
+ struct intel_plane *plane)
+{
+ struct drm_plane_state *plane_state;
+
+ plane_state = drm_atomic_get_existing_plane_state(state, &plane->base);
+
+ return to_intel_plane_state(plane_state);
+}
+
int intel_atomic_setup_scalers(struct drm_device *dev,
struct intel_crtc *intel_crtc,
struct intel_crtc_state *crtc_state);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index ec22d93..73e5242 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3160,23 +3160,6 @@ static uint32_t skl_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal,
return ret;
}
-static bool skl_ddb_allocation_changed(const struct skl_ddb_allocation *new_ddb,
- const struct intel_crtc *intel_crtc)
-{
- struct drm_device *dev = intel_crtc->base.dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
- const struct skl_ddb_allocation *cur_ddb = &dev_priv->wm.skl_hw.ddb;
-
- /*
- * If ddb allocation of pipes changed, it may require recalculation of
- * watermarks
- */
- if (memcmp(new_ddb->pipe, cur_ddb->pipe, sizeof(new_ddb->pipe)))
- return true;
-
- return false;
-}
-
static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
struct intel_crtc_state *cstate,
struct intel_plane_state *intel_pstate,
@@ -3472,6 +3455,8 @@ static void skl_write_wm_values(struct drm_i915_private *dev_priv,
if ((new->dirty_pipes & drm_crtc_mask(&crtc->base)) == 0)
continue;
+ if (!crtc->active)
+ continue;
I915_WRITE(PIPE_WM_LINETIME(pipe), new->wm_linetime[pipe]);
@@ -3655,66 +3640,9 @@ static int skl_update_pipe_wm(struct drm_crtc_state *cstate,
else
*changed = true;
- intel_crtc->wm.active.skl = *pipe_wm;
-
return 0;
}
-static void skl_update_other_pipe_wm(struct drm_device *dev,
- struct drm_crtc *crtc,
- struct skl_wm_values *r)
-{
- struct intel_crtc *intel_crtc;
- struct intel_crtc *this_crtc = to_intel_crtc(crtc);
-
- /*
- * If the WM update hasn't changed the allocation for this_crtc (the
- * crtc we are currently computing the new WM values for), other
- * enabled crtcs will keep the same allocation and we don't need to
- * recompute anything for them.
- */
- if (!skl_ddb_allocation_changed(&r->ddb, this_crtc))
- return;
-
- /*
- * Otherwise, because of this_crtc being freshly enabled/disabled, the
- * other active pipes need new DDB allocation and WM values.
- */
- for_each_intel_crtc(dev, intel_crtc) {
- struct skl_pipe_wm pipe_wm = {};
- bool wm_changed;
-
- if (this_crtc->pipe == intel_crtc->pipe)
- continue;
-
- if (!intel_crtc->active)
- continue;
-
- skl_update_pipe_wm(intel_crtc->base.state,
- &r->ddb, &pipe_wm, &wm_changed);
-
- /*
- * If we end up re-computing the other pipe WM values, it's
- * because it was really needed, so we expect the WM values to
- * be different.
- */
- WARN_ON(!wm_changed);
-
- skl_compute_wm_results(dev, &pipe_wm, r, intel_crtc);
- r->dirty_pipes |= drm_crtc_mask(&intel_crtc->base);
- }
-}
-
-static void skl_clear_wm(struct skl_wm_values *watermarks, enum pipe pipe)
-{
- watermarks->wm_linetime[pipe] = 0;
- memset(watermarks->plane[pipe], 0,
- sizeof(uint32_t) * 8 * I915_MAX_PLANES);
- memset(watermarks->plane_trans[pipe],
- 0, sizeof(uint32_t) * I915_MAX_PLANES);
- watermarks->plane_trans[pipe][PLANE_CURSOR] = 0;
-}
-
static int
skl_compute_ddb(struct drm_atomic_state *state)
{
@@ -3722,6 +3650,7 @@ skl_compute_ddb(struct drm_atomic_state *state)
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
struct intel_crtc *intel_crtc;
+ struct skl_ddb_allocation *ddb = &intel_state->wm_results.ddb;
unsigned realloc_pipes = dev_priv->active_crtcs;
int ret;
@@ -3747,8 +3676,10 @@ skl_compute_ddb(struct drm_atomic_state *state)
* any other display updates race with this transaction, so we need
* to grab the lock on *all* CRTC's.
*/
- if (intel_state->active_pipe_changes)
+ if (intel_state->active_pipe_changes) {
realloc_pipes = ~0;
+ intel_state->wm_results.dirty_pipes = ~0;
+ }
for_each_intel_crtc_mask(dev, intel_crtc, realloc_pipes) {
struct intel_crtc_state *cstate;
@@ -3757,7 +3688,7 @@ skl_compute_ddb(struct drm_atomic_state *state)
if (IS_ERR(cstate))
return PTR_ERR(cstate);
- ret = skl_allocate_pipe_ddb(cstate, &intel_state->ddb);
+ ret = skl_allocate_pipe_ddb(cstate, ddb);
if (ret)
return ret;
}
@@ -3770,8 +3701,11 @@ skl_compute_wm(struct drm_atomic_state *state)
{
struct drm_crtc *crtc;
struct drm_crtc_state *cstate;
- int ret, i;
+ struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
+ struct skl_wm_values *results = &intel_state->wm_results;
+ struct skl_pipe_wm *pipe_wm;
bool changed = false;
+ int ret, i;
/*
* If this transaction isn't actually touching any CRTC's, don't
@@ -3786,10 +3720,44 @@ skl_compute_wm(struct drm_atomic_state *state)
if (!changed)
return 0;
+ /* Clear all dirty flags */
+ results->dirty_pipes = 0;
+
ret = skl_compute_ddb(state);
if (ret)
return ret;
+ /*
+ * Calculate WM's for all pipes that are part of this transaction.
+ * Note that the DDB allocation above may have added more CRTC's that
+ * weren't otherwise being modified (and set bits in dirty_pipes) if
+ * pipe allocations had to change.
+ *
+ * FIXME: Now that we're doing this in the atomic check phase, we
+ * should allow skl_update_pipe_wm() to return failure in cases where
+ * no suitable watermark values can be found.
+ */
+ for_each_crtc_in_state(state, crtc, cstate, i) {
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct intel_crtc_state *intel_cstate =
+ to_intel_crtc_state(cstate);
+
+ pipe_wm = &intel_cstate->wm.skl.optimal;
+ ret = skl_update_pipe_wm(cstate, &results->ddb, pipe_wm,
+ &changed);
+ if (ret)
+ return ret;
+
+ if (changed)
+ results->dirty_pipes |= drm_crtc_mask(crtc);
+
+ if ((results->dirty_pipes & drm_crtc_mask(crtc)) == 0)
+ /* This pipe's WM's did not change */
+ continue;
+
+ skl_compute_wm_results(crtc->dev, pipe_wm, results, intel_crtc);
+ }
+
return 0;
}
@@ -3801,21 +3769,12 @@ static void skl_update_wm(struct drm_crtc *crtc)
struct skl_wm_values *results = &dev_priv->wm.skl_results;
struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
struct skl_pipe_wm *pipe_wm = &cstate->wm.skl.optimal;
- bool wm_changed;
- /* Clear all dirty flags */
- results->dirty_pipes = 0;
-
- skl_clear_wm(results, intel_crtc->pipe);
-
- skl_update_pipe_wm(crtc->state, &results->ddb, pipe_wm, &wm_changed);
- if (!wm_changed)
+ if ((results->dirty_pipes & drm_crtc_mask(crtc)) == 0)
return;
- skl_compute_wm_results(dev, pipe_wm, results, intel_crtc);
- results->dirty_pipes |= drm_crtc_mask(&intel_crtc->base);
+ intel_crtc->wm.active.skl = *pipe_wm;
- skl_update_other_pipe_wm(dev, crtc, results);
skl_write_wm_values(dev_priv, results);
skl_flush_wm_values(dev_priv, results);
--
2.7.4

View File

@ -0,0 +1,63 @@
From 7731c187f1f77501b7dddf419a06c1b42b0f1388 Mon Sep 17 00:00:00 2001
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
Date: Mon, 20 Jun 2016 12:42:00 +0200
Subject: [PATCH 16/17] drm/i915/gen9: Reject display updates that exceed wm
limitations (v2)
Upstream: since drm-intel-next-2016-05-22
commit 6b6bada7d476b586d85b1f9df43125804877e09f
Author: Matt Roper <matthew.d.roper@intel.com>
AuthorDate: Thu May 12 07:06:10 2016 -0700
Commit: Matt Roper <matthew.d.roper@intel.com>
CommitDate: Fri May 13 07:36:04 2016 -0700
drm/i915/gen9: Reject display updates that exceed wm limitations (v2)
If we can't find any valid level 0 watermark values for the requested
atomic transaction, reject the configuration before we try to start
programming the hardware.
v2:
- Add extra debugging output when we reject level 0 watermarks so that
we can more easily debug how/why they were rejected.
Cc: Lyude Paul <cpaul@redhat.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-17-git-send-email-matthew.d.roper@intel.com
---
drivers/gpu/drm/i915/intel_pm.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 73e5242..70dcd2e 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3245,7 +3245,22 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
if (res_blocks >= ddb_allocation || res_lines > 31) {
*enabled = false;
- return 0;
+
+ /*
+ * If there are no valid level 0 watermarks, then we can't
+ * support this display configuration.
+ */
+ if (level) {
+ return 0;
+ } else {
+ DRM_DEBUG_KMS("Requested display configuration exceeds system watermark limitations\n");
+ DRM_DEBUG_KMS("Plane %d.%d: blocks required = %u/%u, lines required = %u/31\n",
+ to_intel_crtc(cstate->base.crtc)->pipe,
+ skl_wm_plane_id(to_intel_plane(pstate->plane)),
+ res_blocks, ddb_allocation, res_lines);
+
+ return -EINVAL;
+ }
}
*out_blocks = res_blocks;
--
2.7.4

View File

@ -0,0 +1,115 @@
From ebe515b1696401259781bc183e211a81287242f6 Mon Sep 17 00:00:00 2001
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
Date: Mon, 20 Jun 2016 12:42:13 +0200
Subject: [PATCH 17/17] drm/i915: Remove wm_config from
dev_priv/intel_atomic_state
Upstream: since drm-intel-next-2016-05-22
commit 5b483747a92570176259bb896dcf2468291f3e42
Author: Matt Roper <matthew.d.roper@intel.com>
AuthorDate: Thu May 12 07:06:11 2016 -0700
Commit: Matt Roper <matthew.d.roper@intel.com>
CommitDate: Fri May 13 07:36:05 2016 -0700
drm/i915: Remove wm_config from dev_priv/intel_atomic_state
We calculate the watermark config into intel_atomic_state and then save
it into dev_priv, but never actually use it from there. This is
left-over from some early ILK-style watermark programming designs that
got changed over time.
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1463061971-19638-18-git-send-email-matthew.d.roper@intel.com
---
drivers/gpu/drm/i915/i915_drv.h | 3 ---
drivers/gpu/drm/i915/intel_display.c | 31 -------------------------------
drivers/gpu/drm/i915/intel_drv.h | 1 -
3 files changed, 35 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 67c76b6..59092cb 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1973,9 +1973,6 @@ struct drm_i915_private {
*/
uint16_t skl_latency[8];
- /* Committed wm config */
- struct intel_wm_config config;
-
/*
* The skl_wm_values structure is a bit too big for stack
* allocation, so we keep the staging struct where we store
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 1726ea4..f5eefb1 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -13226,35 +13226,6 @@ static int calc_watermark_data(struct drm_atomic_state *state)
{
struct drm_device *dev = state->dev;
struct drm_i915_private *dev_priv = to_i915(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;
- }
/* Is there platform-specific watermark information to calculate? */
if (dev_priv->display.compute_global_watermarks)
@@ -13520,7 +13491,6 @@ static int intel_atomic_commit(struct drm_device *dev,
}
drm_atomic_helper_swap_state(dev, state);
- dev_priv->wm.config = to_intel_atomic_state(state)->wm_config;
dev_priv->wm.distrust_bios_wm = false;
dev_priv->wm.skl_results = intel_state->wm_results;
@@ -15334,7 +15304,6 @@ retry:
}
/* Write calculated watermark values back */
- to_i915(dev)->wm.config = to_intel_atomic_state(state)->wm_config;
for_each_crtc_in_state(state, crtc, cstate, i) {
struct intel_crtc_state *cs = to_intel_crtc_state(cstate);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index e5543b8..148f79d 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -270,7 +270,6 @@ struct intel_atomic_state {
unsigned int min_pixclk[I915_MAX_PIPES];
struct intel_shared_dpll_config shared_dpll[I915_NUM_PLLS];
- struct intel_wm_config wm_config;
/* Gen9+ only */
struct skl_wm_values wm_results;
--
2.7.4

View File

@ -639,6 +639,33 @@ Patch727: KEYS-potential-uninitialized-variable.patch
#rhbz 1338025
Patch728: hp-wmi-fix-wifi-cannot-be-hard-unblock.patch
#skl_update_other_pipe_wm issue patch-series from drm-next, rhbz 1305038
Patch801: 0001-drm-i915-Reorganize-WM-structs-unions-in-CRTC-state.patch
Patch802: 0002-drm-i915-Rename-s-skl_compute_pipe_wm-skl_build_pipe.patch
Patch803: 0003-drm-i915-gen9-Cache-plane-data-rates-in-CRTC-state.patch
Patch804: 0004-drm-i915-gen9-Allow-calculation-of-data-rate-for-in-.patch
Patch805: 0005-drm-i915-gen9-Store-plane-minimum-blocks-in-CRTC-wm-.patch
Patch806: 0006-drm-i915-Track-whether-an-atomic-transaction-changes.patch
Patch807: 0007-drm-i915-gen9-Allow-skl_allocate_pipe_ddb-to-operate.patch
Patch808: 0008-drm-i915-Add-distrust_bios_wm-flag-to-dev_priv-v2.patch
Patch809: 0009-drm-i915-gen9-Compute-DDB-allocation-at-atomic-check.patch
Patch810: 0010-drm-i915-gen9-Drop-re-allocation-of-DDB-at-atomic-co.patch
Patch811: 0011-drm-i915-gen9-Calculate-plane-WM-s-from-state.patch
Patch812: 0012-drm-i915-gen9-Allow-watermark-calculation-on-in-flig.patch
Patch813: 0013-drm-i915-gen9-Use-a-bitmask-to-track-dirty-pipe-wate.patch
Patch814: 0014-drm-i915-gen9-Propagate-watermark-calculation-failur.patch
Patch815: 0015-drm-i915-gen9-Calculate-watermarks-during-atomic-che.patch
Patch816: 0016-drm-i915-gen9-Reject-display-updates-that-exceed-wm-.patch
Patch817: 0017-drm-i915-Remove-wm_config-from-dev_priv-intel_atomic.patch
#other drm/kms fixes (most Cc-ed stable)
Patch821: 0001-drm-mgag200-Black-screen-fix-for-G200e-rev-4.patch
Patch822: 0002-drm-nouveau-fbcon-fix-out-of-bounds-memory-accesses.patch
Patch823: 0003-drm-nouveau-disp-sor-gf119-both-links-use-the-same-t.patch
Patch824: 0004-drm-nouveau-disp-sor-gm107-training-pattern-register.patch
Patch825: 0005-i915-fbc-Disable-on-HSW-by-default-for-now.patch
Patch826: 0006-drm-core-Do-not-preserve-framebuffer-on-rmfb-v4.patch
# END OF PATCH DEFINITIONS
%endif
@ -2164,6 +2191,11 @@ fi
#
#
%changelog
* Mon Jun 20 2016 Hans de Goede <jwrdegoede@fedoraproject.org>
- Bring in patch-series from drm-next to fix skl_update_other_pipe_wm issues
(rhbz 1305038)
- Cherry pick some other drm / kms fixes from upstream
* Wed Jun 15 2016 Laura Abbott <labbott@fedoraproject.org>
- hp-wmi: fix wifi cannot be hard-unblock (rhbz 1338025)