All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again
@ 2012-12-12 16:15 ville.syrjala
  2012-12-12 16:15 ` [PATCH 01/81] drm: Add struct drm_region and assorted utility functions ville.syrjala
                   ` (82 more replies)
  0 siblings, 83 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

Another month, another massive atomic patchset.

I managed to clean up warts left over from the modeset-rework rebase,
but other than that I haven't really found the time to touch this too
much since the last time I posted patches from this set.

Seeing as my schedule isn't getting any less busy in the forseeable
future, it would be nice to get this monster merged sooner rather
than never.

Ever since the code started to resemble something sane, I've tried
to avoid squashing patches, just in case someone was actually trying
to follow what's changed. But clearly some of the patches can
be squashed, and that would probably allow some of the earlier ones
to be dropped entirely.

What's clearly needed is a test tool that will stresss the mode
setting side of the code more. My glplane test just changes the
modes in the beginning, and then just does flips and other plane
stuff. I'll try to get something done on that front before Christmas.

Repo is here:
https://gitorious.org/vsyrjala/linux/commits/drm_atomic_23

The repo also contains 64bit get_user() implementation for x86-32,
which I sent to lkml and x86 people for review. So this should now
be testable even on a 32bit system.

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [PATCH 01/81] drm: Add struct drm_region and assorted utility functions
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 02/81] drm: Add drm_calc_{hscale, vscale}() " ville.syrjala
                   ` (81 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

struct drm_region represents a two dimensional region. The utility
functions are there to help driver writers.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_crtc.c |  155 ++++++++++++++++++++++++++++++++++++++++++++
 include/drm/drm_crtc.h     |   24 +++++++
 2 files changed, 179 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index d6d0072..f64e572 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -3923,3 +3923,158 @@ int drm_format_vert_chroma_subsampling(uint32_t format)
 	}
 }
 EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);
+
+/**
+ * drm_region_adjust_size - adjust the size of the region
+ * @r: region to be adjusted
+ * @x: horizontal adjustment
+ * @y: vertical adjustment
+ *
+ * Change the size of region @r by @x in the horizontal direction,
+ * and by @y in the vertical direction, while keeping the center
+ * of @r stationary.
+ *
+ * Positive @x and @y increase the size, negative values decrease it.
+ */
+void drm_region_adjust_size(struct drm_region *r, int x, int y)
+{
+	r->x1 -= x >> 1;
+	r->y1 -= y >> 1;
+	r->x2 += (x + 1) >> 1;
+	r->y2 += (y + 1) >> 1;
+}
+EXPORT_SYMBOL(drm_region_adjust_size);
+
+/**
+ * drm_region_translate - translate the region
+ * @r: region to be tranlated
+ * @x: horizontal translation
+ * @y: vertical translation
+ *
+ * Move region @r by @x in the horizontal direction,
+ * and by @y in the vertical direction.
+ */
+void drm_region_translate(struct drm_region *r, int x, int y)
+{
+	r->x1 += x;
+	r->y1 += y;
+	r->x2 += x;
+	r->y2 += y;
+}
+EXPORT_SYMBOL(drm_region_translate);
+
+/**
+ * drm_region_subsample - subsample a region
+ * @r: region to be subsampled
+ * @hsub: horizontal subsampling factor
+ * @vsub: vertical subsampling factor
+ *
+ * Divide the coordinates of region @r by @hsub and @vsub.
+ */
+void drm_region_subsample(struct drm_region *r, int hsub, int vsub)
+{
+	r->x1 /= hsub;
+	r->y1 /= vsub;
+	r->x2 /= hsub;
+	r->y2 /= vsub;
+}
+EXPORT_SYMBOL(drm_region_subsample);
+
+/**
+ * drm_region_width - determine the region width
+ * @r: region whose width is returned
+ *
+ * RETURNS:
+ * The width of the region.
+ */
+int drm_region_width(const struct drm_region *r)
+{
+	return r->x2 - r->x1;
+}
+EXPORT_SYMBOL(drm_region_width);
+
+/**
+ * drm_region_height - determine the region height
+ * @r: region whose height is returned
+ *
+ * RETURNS:
+ * The height of the region.
+ */
+int drm_region_height(const struct drm_region *r)
+{
+	return r->y2 - r->y1;
+}
+EXPORT_SYMBOL(drm_region_height);
+
+/**
+ * drm_region_visible - determine if the the region is visible
+ * @r: region whose visibility is returned
+ *
+ * RETURNS:
+ * @true if the region is visible, @false otherwise.
+ */
+bool drm_region_visible(const struct drm_region *r)
+{
+	return drm_region_width(r) > 0 && drm_region_height(r) > 0;
+}
+EXPORT_SYMBOL(drm_region_visible);
+
+/**
+ * drm_region_clip - clip one region by another region
+ * @r: region to be clipped
+ * @clip: clip region
+ *
+ * Clip region @r by region @clip.
+ *
+ * RETURNS:
+ * @true if the region is still visible after being clipped,
+ * @false otherwise.
+ */
+bool drm_region_clip(struct drm_region *r, const struct drm_region *clip)
+{
+	r->x1 = max(r->x1, clip->x1);
+	r->y1 = max(r->y1, clip->y1);
+	r->x2 = min(r->x2, clip->x2);
+	r->y2 = min(r->y2, clip->y2);
+
+	return drm_region_visible(r);
+}
+EXPORT_SYMBOL(drm_region_clip);
+
+/**
+ * drm_region_clip_scaled - perform a scaled clip operation
+ * @src: source window region
+ * @dst: destination window region
+ * @clip: clip region
+ * @hscale: horizontal scaling factor
+ * @vscale: vertical scaling factor
+ *
+ * Clip region @dst by region @clip. Clip region @src by the same
+ * amounts multiplied by @hscale and @vscale.
+ *
+ * RETUTRNS:
+ * @true if region @dst is still visible after being clipped,
+ * @false otherwise
+ */
+bool drm_region_clip_scaled(struct drm_region *src, struct drm_region *dst,
+			    const struct drm_region *clip,
+			    int hscale, int vscale)
+{
+	int diff;
+
+	diff = clip->x1 - dst->x1;
+	if (diff > 0)
+		src->x1 += diff * hscale;
+	diff = clip->y1 - dst->y1;
+	if (diff > 0)
+		src->y1 += diff * vscale;
+	diff = dst->x2 - clip->x2;
+	if (diff > 0)
+		src->x2 -= diff * hscale;
+	diff = dst->y2 - clip->y2;
+	if (diff > 0)
+		src->y2 -= diff * vscale;
+
+	return drm_region_clip(dst, clip);
+}
+EXPORT_SYMBOL(drm_region_clip_scaled);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 3538eda..0ac6d83 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -1082,4 +1082,28 @@ extern int drm_format_plane_cpp(uint32_t format, int plane);
 extern int drm_format_horz_chroma_subsampling(uint32_t format);
 extern int drm_format_vert_chroma_subsampling(uint32_t format);
 
+/**
+ * drm_region - two dimensional region
+ * @x1: horizontal starting coordinate (inclusive)
+ * @x2: horizontal ending coordinate (exclusive)
+ * @y1: vertical starting coordinate (inclusive)
+ * @y2: vertical ending coordinate (exclusive)
+ */
+struct drm_region {
+	int x1, y1, x2, y2;
+};
+
+extern void drm_region_adjust_size(struct drm_region *r, int x, int y);
+extern void drm_region_translate(struct drm_region *r, int x, int y);
+extern void drm_region_subsample(struct drm_region *r, int hsub, int vsub);
+extern int drm_region_width(const struct drm_region *r);
+extern int drm_region_height(const struct drm_region *r);
+extern bool drm_region_visible(const struct drm_region *r);
+extern bool drm_region_clip(struct drm_region *r,
+			    const struct drm_region *clip);
+extern bool drm_region_clip_scaled(struct drm_region *src,
+				   struct drm_region *dst,
+				   const struct drm_region *clip,
+				   int hscale, int vscale);
+
 #endif /* __DRM_CRTC_H__ */
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 02/81] drm: Add drm_calc_{hscale, vscale}() utility functions
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
  2012-12-12 16:15 ` [PATCH 01/81] drm: Add struct drm_region and assorted utility functions ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 03/81] drm: Keep a copy of last plane coordinates ville.syrjala
                   ` (80 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_crtc.c |  102 ++++++++++++++++++++++++++++++++++++++++++++
 include/drm/drm_crtc.h     |    4 ++
 2 files changed, 106 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index f64e572..8918179 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -4078,3 +4078,105 @@ bool drm_region_clip_scaled(struct drm_region *src, struct drm_region *dst,
 	return drm_region_clip(dst, clip);
 }
 EXPORT_SYMBOL(drm_region_clip_scaled);
+
+/**
+ * drm_calc_hscale - calculate the horizontal scaling factor
+ * @src: source window region
+ * @dst: destination window region
+ * @min_hscale: minimum allowed horizontal scaling factor
+ * @max_hscale: maximum allowed horizontal scaling factor
+ *
+ * Calculate the horizontal scaling factor as
+ * (@src width) / (@dst width).
+ *
+ * If the calculated scaling factor is below @min_hscale,
+ * decrease the width of region @dst to compensate.
+ *
+ * If the calculcated scaling factor is above @max_hscale,
+ * decrease the width of region @src to compensate.
+ *
+ * RETURNS:
+ * The horizontal scaling factor.
+ */
+int drm_calc_hscale(struct drm_region *src, struct drm_region *dst,
+		    int min_hscale, int max_hscale)
+{
+	int src_w = drm_region_width(src);
+	int dst_w = drm_region_width(dst);
+	int hscale;
+
+	if (dst_w <= 0)
+		return 0;
+
+	hscale = src_w / dst_w;
+
+	if (hscale < min_hscale) {
+		int max_dst_w = src_w / min_hscale;
+
+		drm_region_adjust_size(dst, max_dst_w - dst_w, 0);
+
+		return min_hscale;
+	}
+
+	if (hscale > max_hscale) {
+		int max_src_w = dst_w * max_hscale;
+
+		drm_region_adjust_size(src, max_src_w - src_w, 0);
+
+		return max_hscale;
+	}
+
+	return hscale;
+}
+EXPORT_SYMBOL(drm_calc_hscale);
+
+/**
+ * drm_calc_vscale - calculate the vertical scaling factor
+ * @src: source window region
+ * @dst: destination window region
+ * @min_vscale: minimum allowed vertical scaling factor
+ * @max_vscale: maximum allowed vertical scaling factor
+ *
+ * Calculate the vertical scaling factor as
+ * (@src height) / (@dst height).
+ *
+ * If the calculated scaling factor is below @min_vscale,
+ * decrease the height of region @dst to compensate.
+ *
+ * If the calculcated scaling factor is above @max_vscale,
+ * decrease the height of region @src to compensate.
+ *
+ * RETURNS:
+ * The vertical scaling factor.
+ */
+int drm_calc_vscale(struct drm_region *src, struct drm_region *dst,
+		    int min_vscale, int max_vscale)
+{
+	int src_h = drm_region_height(src);
+	int dst_h = drm_region_height(dst);
+	int vscale;
+
+	if (dst_h <= 0)
+		return 0;
+
+	vscale = src_h / dst_h;
+
+	if (vscale < min_vscale) {
+		int max_dst_h = src_h / min_vscale;
+
+		drm_region_adjust_size(dst, 0, max_dst_h - dst_h);
+
+		return min_vscale;
+	}
+
+	if (vscale > max_vscale) {
+		int max_src_h = dst_h * max_vscale;
+
+		drm_region_adjust_size(src, 0, max_src_h - src_h);
+
+		return max_vscale;
+	}
+
+	return vscale;
+}
+EXPORT_SYMBOL(drm_calc_vscale);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 0ac6d83..a80a346 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -1105,5 +1105,9 @@ extern bool drm_region_clip_scaled(struct drm_region *src,
 				   struct drm_region *dst,
 				   const struct drm_region *clip,
 				   int hscale, int vscale);
+extern int drm_calc_hscale(struct drm_region *src, struct drm_region *dst,
+			   int min_hscale, int max_hscale);
+extern int drm_calc_vscale(struct drm_region *src, struct drm_region *dst,
+			   int min_vscale, int max_vscale);
 
 #endif /* __DRM_CRTC_H__ */
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 03/81] drm: Keep a copy of last plane coordinates
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
  2012-12-12 16:15 ` [PATCH 01/81] drm: Add struct drm_region and assorted utility functions ville.syrjala
  2012-12-12 16:15 ` [PATCH 02/81] drm: Add drm_calc_{hscale, vscale}() " ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 04/81] drm: Add restore_fbdev_mode() hook to drm_fb_helper ville.syrjala
                   ` (79 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

If the update_plane() operation succeeds, make a copy of the requested
src and crtc coordinates, so that the the plane may be reclipped if the
display mode changed later.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_crtc.c |    8 ++++++++
 include/drm/drm_crtc.h     |    4 ++++
 2 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 8918179..3164131 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1852,6 +1852,14 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
 	if (!ret) {
 		plane->crtc = crtc;
 		plane->fb = fb;
+		plane->crtc_x = plane_req->crtc_x;
+		plane->crtc_y = plane_req->crtc_y;
+		plane->crtc_w = plane_req->crtc_w;
+		plane->crtc_h = plane_req->crtc_h;
+		plane->src_x = plane_req->src_x;
+		plane->src_y = plane_req->src_y;
+		plane->src_w = plane_req->src_w;
+		plane->src_h = plane_req->src_h;
 	}
 
 out:
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index a80a346..6b7d809 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -672,6 +672,10 @@ struct drm_plane {
 	void *helper_private;
 
 	struct drm_object_properties properties;
+
+	uint32_t src_x, src_y, src_w, src_h;
+	int32_t crtc_x, crtc_y;
+	uint32_t crtc_w, crtc_h;
 };
 
 /**
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 04/81] drm: Add restore_fbdev_mode() hook to drm_fb_helper
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (2 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 03/81] drm: Keep a copy of last plane coordinates ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 05/81] drm: Export drm_property_create_blob() and drm_property_destroy_blob() ville.syrjala
                   ` (78 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Add an optional driver specific restore_fbdev_mode() hook to
drm_fb_helper. If the driver doesn't provide the hook,
drm_fb_helper_restore_fbdev_mode() is called directly as before.

In this hook the driver can disable additional planes, cursors etc.
that shouldn't be visible while fbdev is in control.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_fb_helper.c |    5 ++++-
 include/drm/drm_fb_helper.h     |    1 +
 2 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 05e623a..6902097 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -265,7 +265,10 @@ static bool drm_fb_helper_force_kernel_mode(void)
 		if (helper->dev->switch_power_state == DRM_SWITCH_POWER_OFF)
 			continue;
 
-		ret = drm_fb_helper_restore_fbdev_mode(helper);
+		if (helper->funcs->restore_fbdev_mode)
+			ret = helper->funcs->restore_fbdev_mode(helper);
+		else
+			ret = drm_fb_helper_restore_fbdev_mode(helper);
 		if (ret)
 			error = true;
 	}
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index 5120b01..7f76e9c 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -56,6 +56,7 @@ struct drm_fb_helper_funcs {
 
 	int (*fb_probe)(struct drm_fb_helper *helper,
 			struct drm_fb_helper_surface_size *sizes);
+	int (*restore_fbdev_mode)(struct drm_fb_helper *helper);
 };
 
 struct drm_fb_helper_connector {
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 05/81] drm: Export drm_property_create_blob() and drm_property_destroy_blob()
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (3 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 04/81] drm: Add restore_fbdev_mode() hook to drm_fb_helper ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 06/81] drm: Allow signed values for range properties ville.syrjala
                   ` (77 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_crtc.c |    8 +++++---
 include/drm/drm_crtc.h     |    4 ++++
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 3164131..38b8ce3 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -3112,8 +3112,8 @@ done:
 	return ret;
 }
 
-static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int length,
-							  void *data)
+struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int length,
+						   void *data)
 {
 	struct drm_property_blob *blob;
 	int ret;
@@ -3138,14 +3138,16 @@ static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev
 	list_add_tail(&blob->head, &dev->mode_config.property_blob_list);
 	return blob;
 }
+EXPORT_SYMBOL(drm_property_create_blob);
 
-static void drm_property_destroy_blob(struct drm_device *dev,
+void drm_property_destroy_blob(struct drm_device *dev,
 			       struct drm_property_blob *blob)
 {
 	drm_mode_object_put(dev, &blob->base);
 	list_del(&blob->head);
 	kfree(blob);
 }
+EXPORT_SYMBOL(drm_property_destroy_blob);
 
 int drm_mode_getblob_ioctl(struct drm_device *dev,
 			   void *data, struct drm_file *file_priv)
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 6b7d809..27812e0 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -970,6 +970,10 @@ struct drm_property *drm_property_create_range(struct drm_device *dev, int flags
 					 const char *name,
 					 uint64_t min, uint64_t max);
 extern void drm_property_destroy(struct drm_device *dev, struct drm_property *property);
+extern struct drm_property_blob *drm_property_create_blob(struct drm_device *dev,
+							  int length, void *data);
+extern void drm_property_destroy_blob(struct drm_device *dev,
+				      struct drm_property_blob *blob);
 extern int drm_property_add_enum(struct drm_property *property, int index,
 				 uint64_t value, const char *name);
 extern int drm_mode_create_dvi_i_properties(struct drm_device *dev);
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 06/81] drm: Allow signed values for range properties
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (4 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 05/81] drm: Export drm_property_create_blob() and drm_property_destroy_blob() ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 07/81] drm: Allow drm_mode_object_find() to look up an object of any type ville.syrjala
                   ` (76 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Treat a range property as signed when the unsigned minimum value is
larger than the unsigned maximum value.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_crtc.c |   17 ++++++++++++++---
 1 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 38b8ce3..7badd2a 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -3213,14 +3213,25 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector,
 }
 EXPORT_SYMBOL(drm_mode_connector_update_edid_property);
 
-static bool drm_property_change_is_valid(struct drm_property *property,
+static bool range_property_is_signed(const struct drm_property *property)
+{
+	return property->values[0] > property->values[1];
+}
+
+static bool drm_property_change_is_valid(const struct drm_property *property,
 					 uint64_t value)
 {
 	if (property->flags & DRM_MODE_PROP_IMMUTABLE)
 		return false;
 	if (property->flags & DRM_MODE_PROP_RANGE) {
-		if (value < property->values[0] || value > property->values[1])
-			return false;
+		if (range_property_is_signed(property)) {
+			if ((int64_t)value < (int64_t)property->values[0] ||
+			    (int64_t)value > (int64_t)property->values[1])
+				return false;
+		} else {
+			if (value < property->values[0] || value > property->values[1])
+				return false;
+		}
 		return true;
 	} else if (property->flags & DRM_MODE_PROP_BITMASK) {
 		int i;
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 07/81] drm: Allow drm_mode_object_find() to look up an object of any type
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (5 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 06/81] drm: Allow signed values for range properties ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 08/81] drm: Export drm_encoder_crtc_ok ville.syrjala
                   ` (75 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

To avoid having to pass object types from userspace for atomic mode
setting ioctl, allow drm_mode_object_find() to look up an object of any
type. This will only work as long as the all object types share the ID
space.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_crtc.c |    3 ++-
 include/drm/drm_crtc.h     |    1 +
 2 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 7badd2a..2dd3649 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -267,7 +267,8 @@ struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
 
 	mutex_lock(&dev->mode_config.idr_mutex);
 	obj = idr_find(&dev->mode_config.crtc_idr, id);
-	if (!obj || (obj->type != type) || (obj->id != id))
+	if (!obj || (type != DRM_MODE_OBJECT_ANY && obj->type != type) ||
+	    (obj->id != id))
 		obj = NULL;
 	mutex_unlock(&dev->mode_config.idr_mutex);
 
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 27812e0..28a972a 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -48,6 +48,7 @@ struct drm_object_properties;
 #define DRM_MODE_OBJECT_FB 0xfbfbfbfb
 #define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb
 #define DRM_MODE_OBJECT_PLANE 0xeeeeeeee
+#define DRM_MODE_OBJECT_ANY 0
 
 struct drm_mode_object {
 	uint32_t id;
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 08/81] drm: Export drm_encoder_crtc_ok
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (6 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 07/81] drm: Allow drm_mode_object_find() to look up an object of any type ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 09/81] drm: Export drm_crtc_prepare_encoders() ville.syrjala
                   ` (74 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

---
 drivers/gpu/drm/drm_crtc_helper.c |    5 +++--
 include/drm/drm_crtc_helper.h     |    3 +++
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 7b2d378..0d62c94 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -312,8 +312,8 @@ EXPORT_SYMBOL(drm_helper_disable_unused_functions);
  *
  * Return false if @encoder can't be driven by @crtc, true otherwise.
  */
-static bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
-				struct drm_crtc *crtc)
+bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
+			 struct drm_crtc *crtc)
 {
 	struct drm_device *dev;
 	struct drm_crtc *tmp;
@@ -333,6 +333,7 @@ static bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
 		return true;
 	return false;
 }
+EXPORT_SYMBOL(drm_encoder_crtc_ok);
 
 /*
  * Check the CRTC we're going to map each output to vs. its current
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index f43d556..5abae74 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -169,4 +169,7 @@ extern void drm_kms_helper_hotplug_event(struct drm_device *dev);
 extern void drm_kms_helper_poll_disable(struct drm_device *dev);
 extern void drm_kms_helper_poll_enable(struct drm_device *dev);
 
+extern bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
+				struct drm_crtc *crtc);
+
 #endif
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 09/81] drm: Export drm_crtc_prepare_encoders()
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (7 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 08/81] drm: Export drm_encoder_crtc_ok ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 10/81] drm: Refactor object property check code ville.syrjala
                   ` (73 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

---
 drivers/gpu/drm/drm_crtc_helper.c |    3 ++-
 include/drm/drm_crtc_helper.h     |    1 +
 2 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 0d62c94..30eb557 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -340,7 +340,7 @@ EXPORT_SYMBOL(drm_encoder_crtc_ok);
  * CRTC.  If they don't match, we have to disable the output and the CRTC
  * since the driver will have to re-route things.
  */
-static void
+void
 drm_crtc_prepare_encoders(struct drm_device *dev)
 {
 	struct drm_encoder_helper_funcs *encoder_funcs;
@@ -357,6 +357,7 @@ drm_crtc_prepare_encoders(struct drm_device *dev)
 			drm_encoder_disable(encoder);
 	}
 }
+EXPORT_SYMBOL(drm_crtc_prepare_encoders);
 
 /**
  * drm_crtc_helper_set_mode - internal helper to set a mode
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index 5abae74..7702a3a 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -171,5 +171,6 @@ extern void drm_kms_helper_poll_enable(struct drm_device *dev);
 
 extern bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
 				struct drm_crtc *crtc);
+extern void drm_crtc_prepare_encoders(struct drm_device *dev);
 
 #endif
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 10/81] drm: Refactor object property check code
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (8 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 09/81] drm: Export drm_crtc_prepare_encoders() ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 11/81] drm: Export mode<->umode conversion functions ville.syrjala
                   ` (72 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Refactor the code to check whether an object has a specific property
to a new function.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_crtc.c |   20 ++++++++++++++------
 1 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 2dd3649..0a9a7cb 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -3374,6 +3374,19 @@ out:
 	return ret;
 }
 
+static bool object_has_prop(const struct drm_mode_object *obj, u32 prop_id)
+{
+	int i;
+
+	if (!obj->properties)
+		return false;
+
+	for (i = 0; i < obj->properties->count; i++)
+		if (obj->properties->ids[i] == prop_id)
+			return true;
+	return false;
+}
+
 int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
 				    struct drm_file *file_priv)
 {
@@ -3382,7 +3395,6 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
 	struct drm_mode_object *prop_obj;
 	struct drm_property *property;
 	int ret = -EINVAL;
-	int i;
 
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		return -EINVAL;
@@ -3395,11 +3407,7 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
 	if (!arg_obj->properties)
 		goto out;
 
-	for (i = 0; i < arg_obj->properties->count; i++)
-		if (arg_obj->properties->ids[i] == arg->prop_id)
-			break;
-
-	if (i == arg_obj->properties->count)
+	if (!object_has_prop(arg_obj, arg->prop_id))
 		goto out;
 
 	prop_obj = drm_mode_object_find(dev, arg->prop_id,
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 11/81] drm: Export mode<->umode conversion functions
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (9 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 10/81] drm: Refactor object property check code ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 12/81] drm: Make blobs resizeable ville.syrjala
                   ` (71 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Export drm_crtc_convert_to_umode() and drm_crtc_convert_umode().

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_crtc.c |   10 ++++++----
 include/drm/drm_crtc.h     |    4 ++++
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 0a9a7cb..3709f8c 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1119,8 +1119,8 @@ EXPORT_SYMBOL(drm_mode_config_cleanup);
  * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to
  * the user.
  */
-static void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out,
-				      const struct drm_display_mode *in)
+void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out,
+			       const struct drm_display_mode *in)
 {
 	WARN(in->hdisplay > USHRT_MAX || in->hsync_start > USHRT_MAX ||
 	     in->hsync_end > USHRT_MAX || in->htotal > USHRT_MAX ||
@@ -1146,6 +1146,7 @@ static void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out,
 	strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
 	out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
 }
+EXPORT_SYMBOL(drm_crtc_convert_to_umode);
 
 /**
  * drm_crtc_convert_to_umode - convert a modeinfo into a drm_display_mode
@@ -1161,8 +1162,8 @@ static void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out,
  * RETURNS:
  * Zero on success, errno on failure.
  */
-static int drm_crtc_convert_umode(struct drm_display_mode *out,
-				  const struct drm_mode_modeinfo *in)
+int drm_crtc_convert_umode(struct drm_display_mode *out,
+			   const struct drm_mode_modeinfo *in)
 {
 	if (in->clock > INT_MAX || in->vrefresh > INT_MAX)
 		return -ERANGE;
@@ -1186,6 +1187,7 @@ static int drm_crtc_convert_umode(struct drm_display_mode *out,
 
 	return 0;
 }
+EXPORT_SYMBOL(drm_crtc_convert_umode);
 
 /**
  * drm_mode_getresources - get graphics configuration
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 28a972a..23f2f37 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -1090,6 +1090,10 @@ extern int drm_format_num_planes(uint32_t format);
 extern int drm_format_plane_cpp(uint32_t format, int plane);
 extern int drm_format_horz_chroma_subsampling(uint32_t format);
 extern int drm_format_vert_chroma_subsampling(uint32_t format);
+extern void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out,
+				      const struct drm_display_mode *in);
+extern int drm_crtc_convert_umode(struct drm_display_mode *out,
+				  const struct drm_mode_modeinfo *in);
 
 /**
  * drm_region - two dimensional region
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 12/81] drm: Make blobs resizeable
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (10 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 11/81] drm: Export mode<->umode conversion functions ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 13/81] drm: Add drm_flip helper ville.syrjala
                   ` (70 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

When first allocated blobs can be given a maximum size for which memory
is allocated. Later the data inside the blob can be replaced, assuming
that the maximum size is not exceeded.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_crtc.c |   45 ++++++++++++++++++++++++++++++++++++++-----
 include/drm/drm_crtc.h     |    8 ++++++-
 2 files changed, 46 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 3709f8c..aeda9f4 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -2926,6 +2926,9 @@ void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
 {
 	struct drm_property_enum *prop_enum, *pt;
 
+	if (!property)
+		return;
+
 	list_for_each_entry_safe(prop_enum, pt, &property->enum_blob_list, head) {
 		list_del(&prop_enum->head);
 		kfree(prop_enum);
@@ -3115,16 +3118,24 @@ done:
 	return ret;
 }
 
-struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int length,
-						   void *data)
+struct drm_property_blob *drm_property_create_blob(struct drm_device *dev,
+						   unsigned int length,
+						   unsigned int max_length,
+						   const void *data)
 {
 	struct drm_property_blob *blob;
 	int ret;
 
-	if (!length || !data)
+	if (!!length != !!data)
 		return NULL;
 
-	blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL);
+	if (max_length < length)
+		max_length = length;
+
+	if (max_length == 0)
+		return NULL;
+
+	blob = kzalloc(sizeof(struct drm_property_blob)+max_length, GFP_KERNEL);
 	if (!blob)
 		return NULL;
 
@@ -3134,18 +3145,40 @@ struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int l
 		return NULL;
 	}
 
+	blob->max_length = max_length;
 	blob->length = length;
 
-	memcpy(blob->data, data, length);
+	if (length)
+		memcpy(blob->data, data, length);
 
 	list_add_tail(&blob->head, &dev->mode_config.property_blob_list);
 	return blob;
 }
 EXPORT_SYMBOL(drm_property_create_blob);
 
+int drm_property_blob_replace_data(struct drm_property_blob *blob,
+				   unsigned int length, const void *data)
+{
+	if (!!length != !!data)
+		return -EINVAL;
+
+	if (length > blob->max_length)
+		return -ENOSPC;
+
+	blob->length = length;
+	if (length)
+		memcpy(blob->data, data, length);
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_property_blob_replace_data);
+
 void drm_property_destroy_blob(struct drm_device *dev,
 			       struct drm_property_blob *blob)
 {
+	if (!blob)
+		return;
+
 	drm_mode_object_put(dev, &blob->base);
 	list_del(&blob->head);
 	kfree(blob);
@@ -3204,7 +3237,7 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector,
 
 	size = EDID_LENGTH * (1 + edid->extensions);
 	connector->edid_blob_ptr = drm_property_create_blob(connector->dev,
-							    size, edid);
+							    size, 0, edid);
 	if (!connector->edid_blob_ptr)
 		return -EINVAL;
 
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 23f2f37..5b8b1b7 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -276,6 +276,7 @@ struct drm_property_blob {
 	struct drm_mode_object base;
 	struct list_head head;
 	unsigned int length;
+	unsigned int max_length;
 	unsigned char data[];
 };
 
@@ -972,7 +973,12 @@ struct drm_property *drm_property_create_range(struct drm_device *dev, int flags
 					 uint64_t min, uint64_t max);
 extern void drm_property_destroy(struct drm_device *dev, struct drm_property *property);
 extern struct drm_property_blob *drm_property_create_blob(struct drm_device *dev,
-							  int length, void *data);
+							  unsigned int level,
+							  unsigned int max_length,
+							  const void *data);
+extern int drm_property_blob_replace_data(struct drm_property_blob *blob,
+					  unsigned int length,
+					  const void *data);
 extern void drm_property_destroy_blob(struct drm_device *dev,
 				      struct drm_property_blob *blob);
 extern int drm_property_add_enum(struct drm_property *property, int index,
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 13/81] drm: Add drm_flip helper
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (11 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 12/81] drm: Make blobs resizeable ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 14/81] drm: Add mode_blob and connector_ids_blob to drm_crtc ville.syrjala
                   ` (69 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

The drm_flip mechanism can be used to implement robust page flipping
support, and also to synchronize the flips on multiple hardware
scanout engines (eg. CRTCs and overlays).

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/Makefile   |    2 +-
 drivers/gpu/drm/drm_flip.c |  376 ++++++++++++++++++++++++++++++++++++++++++++
 include/drm/drm_flip.h     |  244 ++++++++++++++++++++++++++++
 3 files changed, 621 insertions(+), 1 deletions(-)
 create mode 100644 drivers/gpu/drm/drm_flip.c
 create mode 100644 include/drm/drm_flip.h

diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 6f58c81..f2965de 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -12,7 +12,7 @@ drm-y       :=	drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
 		drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \
 		drm_crtc.o drm_modes.o drm_edid.o \
 		drm_info.o drm_debugfs.o drm_encoder_slave.o \
-		drm_trace_points.o drm_global.o drm_prime.o
+		drm_trace_points.o drm_global.o drm_prime.o drm_flip.o
 
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
diff --git a/drivers/gpu/drm/drm_flip.c b/drivers/gpu/drm/drm_flip.c
new file mode 100644
index 0000000..6ccc3f8
--- /dev/null
+++ b/drivers/gpu/drm/drm_flip.c
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Ville Syrjälä <ville.syrjala@linux.intel.com>
+ */
+
+#include <drm/drm_flip.h>
+
+static void drm_flip_driver_cleanup(struct work_struct *work)
+{
+	struct drm_flip *flip, *next;
+	struct drm_flip_driver *driver =
+		container_of(work, struct drm_flip_driver, cleanup_work);
+	LIST_HEAD(list);
+
+	spin_lock_irq(&driver->lock);
+
+	list_cut_position(&list,
+			  &driver->cleanup_list,
+			  driver->cleanup_list.prev);
+
+	spin_unlock_irq(&driver->lock);
+
+	if (list_empty(&list))
+		return;
+
+	list_for_each_entry_safe(flip, next, &list, list) {
+		struct drm_flip_helper *helper = flip->helper;
+
+		WARN_ON(!flip->finished);
+
+		helper->funcs->cleanup(flip);
+	}
+}
+
+static void drm_flip_driver_finish(struct work_struct *work)
+{
+	struct drm_flip *flip, *next;
+	struct drm_flip_driver *driver =
+		container_of(work, struct drm_flip_driver, finish_work);
+	LIST_HEAD(list);
+	bool need_cleanup = false;
+
+	spin_lock_irq(&driver->lock);
+
+	list_cut_position(&list,
+			  &driver->finish_list,
+			  driver->finish_list.prev);
+
+	spin_unlock_irq(&driver->lock);
+
+	if (list_empty(&list))
+		return;
+
+	list_for_each_entry_safe(flip, next, &list, list) {
+		struct drm_flip_helper *helper = flip->helper;
+
+		helper->funcs->finish(flip);
+
+		spin_lock_irq(&driver->lock);
+
+		flip->finished = true;
+
+		/*
+		 * It's possible that drm_flip_set_scanout() was called after we
+		 * pulled this flip from finish_list, in which case the flip
+		 * could be in need of cleanup, but not on cleanup_list.
+		 */
+		if (flip == helper->scanout_flip) {
+			list_del_init(&flip->list);
+		} else {
+			need_cleanup = true;
+			list_move_tail(&flip->list, &driver->cleanup_list);
+		}
+
+		spin_unlock_irq(&driver->lock);
+	}
+
+	if (need_cleanup)
+		queue_work(driver->wq, &driver->cleanup_work);
+}
+
+static bool drm_flip_set_scanout(struct drm_flip_helper *helper,
+				 struct drm_flip *flip)
+{
+	struct drm_flip_driver *driver = helper->driver;
+	struct drm_flip *old = helper->scanout_flip;
+
+	helper->scanout_flip = flip;
+
+	if (old && old->finished)
+		list_move_tail(&old->list, &driver->cleanup_list);
+
+	return old != NULL;
+}
+
+static bool drm_flip_complete(struct drm_flip *flip)
+{
+	struct drm_flip_helper *helper = flip->helper;
+	struct drm_flip_driver *driver = helper->driver;
+	bool need_cleanup = false;
+
+	helper->funcs->complete(flip);
+
+	if (flip->flipped) {
+		if (drm_flip_set_scanout(helper, flip))
+			need_cleanup = true;
+	}
+
+	list_add_tail(&flip->list, &driver->finish_list);
+
+	return need_cleanup;
+}
+
+void drm_flip_helper_init(struct drm_flip_helper *helper,
+			  struct drm_flip_driver *driver,
+			  const struct drm_flip_helper_funcs *funcs)
+{
+	helper->pending_flip = NULL;
+	helper->scanout_flip = NULL;
+	helper->driver = driver;
+	helper->funcs = funcs;
+}
+
+void drm_flip_helper_clear(struct drm_flip_helper *helper)
+{
+	unsigned long flags;
+	struct drm_flip_driver *driver = helper->driver;
+	struct drm_flip *pending_flip;
+	bool need_finish = false;
+	bool need_cleanup = false;
+
+	spin_lock_irqsave(&driver->lock, flags);
+
+	pending_flip = helper->pending_flip;
+
+	if (pending_flip) {
+		BUG_ON(pending_flip->helper != helper);
+
+		need_finish = true;
+
+		if (drm_flip_complete(pending_flip))
+			need_cleanup = true;
+
+		helper->pending_flip = NULL;
+	}
+
+	if (drm_flip_set_scanout(helper, NULL))
+		need_cleanup = true;
+
+	spin_unlock_irqrestore(&driver->lock, flags);
+
+	if (need_finish)
+		queue_work(driver->wq, &driver->finish_work);
+
+	if (need_cleanup)
+		queue_work(driver->wq, &driver->cleanup_work);
+}
+
+void drm_flip_helper_fini(struct drm_flip_helper *helper)
+{
+	struct drm_flip_driver *driver = helper->driver;
+
+	drm_flip_helper_clear(helper);
+
+	flush_work_sync(&driver->finish_work);
+	flush_work_sync(&driver->cleanup_work);
+}
+
+void drm_flip_helper_vblank(struct drm_flip_helper *helper)
+{
+	struct drm_flip_driver *driver = helper->driver;
+	struct drm_flip *pending_flip;
+	unsigned long flags;
+	bool need_finish = false;
+	bool need_cleanup = false;
+
+	spin_lock_irqsave(&driver->lock, flags);
+
+	pending_flip = helper->pending_flip;
+
+	if (pending_flip) {
+		BUG_ON(pending_flip->helper != helper);
+
+		if (helper->funcs->vblank(pending_flip))
+			pending_flip->flipped = true;
+
+		if (pending_flip->flipped) {
+			need_finish = true;
+
+			if (drm_flip_complete(pending_flip))
+				need_cleanup = true;
+
+			helper->pending_flip = NULL;
+		}
+	}
+
+	spin_unlock_irqrestore(&driver->lock, flags);
+
+	if (need_finish)
+		queue_work(driver->wq, &driver->finish_work);
+
+	if (need_cleanup)
+		queue_work(driver->wq, &driver->cleanup_work);
+}
+
+void drm_flip_driver_init(struct drm_flip_driver *driver,
+			  const struct drm_flip_driver_funcs *funcs)
+{
+	spin_lock_init(&driver->lock);
+
+	INIT_LIST_HEAD(&driver->finish_list);
+	INIT_LIST_HEAD(&driver->cleanup_list);
+
+	INIT_WORK(&driver->finish_work, drm_flip_driver_finish);
+	INIT_WORK(&driver->cleanup_work, drm_flip_driver_cleanup);
+
+	driver->funcs = funcs;
+
+	driver->wq = create_singlethread_workqueue("drm_flip");
+}
+
+void drm_flip_driver_fini(struct drm_flip_driver *driver)
+{
+	destroy_workqueue(driver->wq);
+
+	/* All the scheduled flips should be cleaned up by now. */
+	WARN_ON(!list_empty(&driver->finish_list));
+	WARN_ON(!list_empty(&driver->cleanup_list));
+}
+
+void drm_flip_driver_schedule_flips(struct drm_flip_driver *driver,
+				    struct list_head *flips)
+{
+	unsigned long flags;
+	struct drm_flip *flip, *next;
+	bool need_finish = false;
+	bool need_cleanup = false;
+
+	spin_lock_irqsave(&driver->lock, flags);
+
+	list_for_each_entry(flip, flips, list) {
+		struct drm_flip_helper *helper = flip->helper;
+		struct drm_flip *pending_flip = helper->pending_flip;
+
+		if (helper->funcs->flip(flip, pending_flip))
+			pending_flip->flipped = true;
+	}
+
+	if (driver->funcs->flush)
+		driver->funcs->flush(driver);
+
+	/* Complete all flips that got overridden */
+	list_for_each_entry_safe(flip, next, flips, list) {
+		struct drm_flip_helper *helper = flip->helper;
+		struct drm_flip *pending_flip = helper->pending_flip;
+
+		BUG_ON(helper->driver != driver);
+
+		if (pending_flip) {
+			BUG_ON(pending_flip->helper != helper);
+
+			need_finish = true;
+
+			if (drm_flip_complete(pending_flip))
+				need_cleanup = true;
+		}
+
+		list_del_init(&flip->list);
+		helper->pending_flip = flip;
+	}
+
+	spin_unlock_irqrestore(&driver->lock, flags);
+
+	if (need_finish)
+		queue_work(driver->wq, &driver->finish_work);
+
+	if (need_cleanup)
+		queue_work(driver->wq, &driver->cleanup_work);
+}
+
+void drm_flip_driver_prepare_flips(struct drm_flip_driver *driver,
+				   struct list_head *flips)
+{
+	struct drm_flip *flip;
+
+	list_for_each_entry(flip, flips, list) {
+		struct drm_flip_helper *helper = flip->helper;
+
+		if (helper->funcs->prepare)
+			helper->funcs->prepare(flip);
+	}
+}
+
+void drm_flip_driver_complete_flips(struct drm_flip_driver *driver,
+				    struct list_head *flips)
+{
+	unsigned long flags;
+	struct drm_flip *flip, *next;
+	bool need_finish = false;
+	bool need_cleanup = false;
+
+	spin_lock_irqsave(&driver->lock, flags);
+
+	/* first complete all pending flips */
+	list_for_each_entry(flip, flips, list) {
+		struct drm_flip_helper *helper = flip->helper;
+		struct drm_flip *pending_flip = helper->pending_flip;
+
+		BUG_ON(helper->driver != driver);
+
+		if (pending_flip) {
+			BUG_ON(pending_flip->helper != helper);
+
+			need_finish = true;
+
+			if (drm_flip_complete(pending_flip))
+				need_cleanup = true;
+
+			helper->pending_flip = NULL;
+		}
+	}
+
+	/* then complete all new flips as well */
+	list_for_each_entry_safe(flip, next, flips, list) {
+		list_del_init(&flip->list);
+
+		/*
+		 * This is the flip that gets scanned out
+		 * next time the hardware is fired up.
+		 */
+		flip->flipped = true;
+
+		need_finish = true;
+
+		if (drm_flip_complete(flip))
+			need_cleanup = true;
+	}
+
+	spin_unlock_irqrestore(&driver->lock, flags);
+
+	if (need_finish)
+		queue_work(driver->wq, &driver->finish_work);
+
+	if (need_cleanup)
+		queue_work(driver->wq, &driver->cleanup_work);
+}
+
+void drm_flip_init(struct drm_flip *flip,
+		   struct drm_flip_helper *helper)
+{
+	flip->helper = helper;
+	flip->flipped = false;
+	flip->finished = false;
+	INIT_LIST_HEAD(&flip->list);
+}
diff --git a/include/drm/drm_flip.h b/include/drm/drm_flip.h
new file mode 100644
index 0000000..4172d6e
--- /dev/null
+++ b/include/drm/drm_flip.h
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and iated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Ville Syrjälä <ville.syrjala@linux.intel.com>
+ */
+
+#ifndef DRM_FLIP_H
+#define DRM_FLIP_H
+
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+
+struct drm_flip;
+struct drm_flip_helper;
+struct drm_flip_driver;
+
+/* Driver callbacks for drm_flip_driver */
+struct drm_flip_driver_funcs {
+	/*
+	 * Optional callback, called after drm_flip_driver_schedule_flips()
+	 * has called drm_flip_helper::flip() for all the provided flips.
+	 * Can be used to:
+	 * - commit the flips atomically to the hardware, if the
+	 *   hardware provides some mechanism to do that.
+	 * - flush posted writes to make sure all the flips have reached
+	 *   the hardware
+	 * Called with drm_flip_driver::lock held.
+	 */
+	void (*flush)(struct drm_flip_driver *driver);
+};
+
+/*
+ * The driver needs one drm_flip_driver to
+ * coordinates the drm_flip mechanism.
+ */
+struct drm_flip_driver {
+	/* protects drm_flip_driver, drm_flip_helper, and drm_flip internals. */
+	spinlock_t lock;
+
+	/* list of drm_flips waiting to be finished, protected by 'lock' */
+	struct list_head finish_list;
+
+	/* list of drm_flips waiting to be cleaned up, protected by 'lock' */
+	struct list_head cleanup_list;
+
+	/* work used to finish the drm_flips */
+	struct work_struct finish_work;
+
+	/* work used to clean up the drm_flips */
+	struct work_struct cleanup_work;
+
+	/* driver provided callback functions */
+	const struct drm_flip_driver_funcs *funcs;
+
+	/* work queue for finish_work and cleanup_work */
+	struct workqueue_struct *wq;
+};
+
+/* Driver callbacks for drm_flip_helper */
+struct drm_flip_helper_funcs {
+	/*
+	 * Optional function to perform heavy but non-timing
+	 * critial preparations for the flip.
+	 * Called from drm_flip_driver_prepare_flips() with
+	 * no extra locks being held.
+	 */
+	void (*prepare)(struct drm_flip *flip);
+	/*
+	 * Instruct the hardware to flip on the next vblank.
+	 * Must return true, iff pending_flip exists, and has
+	 * actually flipped (ie. now being scanned out).
+	 * Otherwise must return false.
+	 * Called with drm_flip_driver::lock held.
+	 */
+	bool (*flip)(struct drm_flip *flip,
+		     struct drm_flip *pending_flip);
+	/*
+	 * Called from drm_flip_helper_vblank() if
+	 * pending_flip exists. Must return true, iff
+	 * pending_flip has actually flipped (ie. now
+	 * being scanned out). Otherwise must return false.
+	 * Called with drm_flip_driver::lock held.
+	 */
+	bool (*vblank)(struct drm_flip *pending_flip);
+
+	/*
+	 * The flip has just occured, or it got overwritten
+	 * by a more recent flip. If the flip occured, it is
+	 * now being scanned out, otherwise it is scheduled
+	 * for cleanup.
+	 * Can be called from drm_flip_driver_schedule_flips(),
+	 * drm_flip_driver_complete_flips(), or from
+	 * drm_flip_helper_vblank().
+	 * Called with drm_flip_driver::lock held.
+	 */
+	void (*complete)(struct drm_flip *flip);
+
+	/*
+	 * Perform finishing steps on the flip. Called from a workqueue
+	 * soon after the flip has completed. The flip's buffer may be
+	 * actively scanned out.
+	 * Called with no locks being held.
+	 */
+	void (*finish)(struct drm_flip *flip);
+
+	/*
+	 * Perform final cleanup on the flip. Called from a workqueue
+	 * after the flip's buffer is no longer being scanned out.
+	 * Called with no locks being held.
+	 */
+	void (*cleanup)(struct drm_flip *flip);
+
+};
+
+/*
+ * The driver needs one drm_flip_helper for each scanout engine it
+ * wants to operate through the drm_flip mechanism.
+ */
+struct drm_flip_helper {
+	/* drm_flip from the previous drm_flip_schedule() call */
+	struct drm_flip *pending_flip;
+	/* drm_flip whose buffer is being scanned out */
+	struct drm_flip *scanout_flip;
+	/* associated drm_flip_driver */
+	struct drm_flip_driver *driver;
+	/* driver provided callback functions */
+	const struct drm_flip_helper_funcs *funcs;
+};
+
+/*
+ * This structure represents a single page flip operation.
+ */
+struct drm_flip {
+	/* associated drm_flip_helper */
+	struct drm_flip_helper *helper;
+	/* has this flip occured? */
+	bool flipped;
+	/* has the finish work been executed for this flip? */
+	bool finished;
+	/* used to keep this flip on various lists */
+	struct list_head list;
+};
+
+/*
+ * Initialize the flip driver.
+ */
+void drm_flip_driver_init(struct drm_flip_driver *driver,
+			  const struct drm_flip_driver_funcs *funcs);
+
+/*
+ * Finalize the flip driver. This will block until all the
+ * pending finish and cleanup work has been completed.
+ */
+void drm_flip_driver_fini(struct drm_flip_driver *driver);
+
+/*
+ * Initialize flip helper.
+ */
+void drm_flip_helper_init(struct drm_flip_helper *helper,
+			  struct drm_flip_driver *driver,
+			  const struct drm_flip_helper_funcs *funcs);
+
+/*
+ * Clear flip helper state. This will forcefully complete the
+ * helper's pending flip (if any).
+ */
+void drm_flip_helper_clear(struct drm_flip_helper *helper);
+
+/*
+ * Finalize the flip helper. This will forcefully complete the
+ * helper's pending flip (if any), and wait for the finish and
+ * cleanup works to finish.
+ */
+void drm_flip_helper_fini(struct drm_flip_helper *helper);
+
+/*
+ * Call this from the driver's vblank handler for the scanout engine
+ * associated with this helper.
+ */
+void drm_flip_helper_vblank(struct drm_flip_helper *helper);
+
+/*
+ * This will call drm_flip_helper::prepare() (if provided) for all the
+ * drm_flips on the list. The purpose is to perform any non-timing critical
+ * preparation steps for the flips before taking locks or disabling interrupts.
+ */
+void drm_flip_driver_prepare_flips(struct drm_flip_driver *driver,
+				   struct list_head *flips);
+
+/*
+ * Schedule the flips on the list to occur on the next vblank.
+ *
+ * This will call drm_flip_helper::flip() for all the drm_flips on the list.
+ * It will then call drm_flip_driver::flush(), after which it will complete
+ * any pending_flip that got overridden by the new flips.
+ *
+ * Unless the hardware provides some mechanism to synchronize the flips, the
+ * time spent until drm_flip_driver::flush() is timing critical and the driver
+ * must somehow make sure it can complete the operation in a seemingly atomic
+ * fashion.
+ */
+void drm_flip_driver_schedule_flips(struct drm_flip_driver *driver,
+				    struct list_head *flips);
+
+/*
+ * This will complete any pending_flip and also all the flips
+ * on the provided list (in that order).
+ *
+ * Call this instead of drm_flip_driver_schedule_flips()
+ * eg. if the hardware powered down, and you just want to keep
+ * the drm_flip mechanim's state consistent w/o waking up the
+ * hardware.
+ */
+void drm_flip_driver_complete_flips(struct drm_flip_driver *driver,
+				    struct list_head *flips);
+
+/*
+ * Initialize the flip structure members.
+ */
+void drm_flip_init(struct drm_flip *flip,
+		   struct drm_flip_helper *helper);
+
+#endif
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 14/81] drm: Add mode_blob and connector_ids_blob to drm_crtc
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (12 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 13/81] drm: Add drm_flip helper ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 15/81] drm: Add the atomic modeset ioctl ville.syrjala
                   ` (68 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

These will be ued by standard properties MODE and CONNECTOR_IDS.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 include/drm/drm_crtc.h |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 5b8b1b7..d05d302 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -423,6 +423,9 @@ struct drm_crtc {
 	void *helper_private;
 
 	struct drm_object_properties properties;
+
+	struct drm_property_blob *mode_blob;
+	struct drm_property_blob *connector_ids_blob;
 };
 
 
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 15/81] drm: Add the atomic modeset ioctl
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (13 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 14/81] drm: Add mode_blob and connector_ids_blob to drm_crtc ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 16/81] drm/i915: Use drm_format_plane_cpp() rather than bits_per_pixel/8 ville.syrjala
                   ` (67 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

This new ioctl can be used to update an arbitrary set of object
properties in one operation.

The ioctl simply takes a list of object IDs and property IDs and their
values. For setting values of blob properties, the property value
indicates the length of the data, and the actual data is passed via
another blob pointer.

Three flags are currently supported to alter the behaviour of the ioctl:
- DRM_MODE_ATOMIC_TEST_ONLY indicates that the new state chould only be
  checked for validity, but not hardware state is to be modified.
- DRM_MODE_ATOMIC_EVENT requests that asynchronous completion events be
  sent back to user space. A new event type is added for this purpose.
- DRM_MODE_ATOMIC_NONBLOCK indicates that the operation must be
  completed asynchronously without blocking the the caller for
  significant amounts of time.

Internally the driver must implement the functions pointers in struct
drm_atomic_funcs to support the new ioctl.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_crtc.c  |  146 +++++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/drm_drv.c   |    1 +
 include/drm/drmP.h          |    8 +++
 include/drm/drm_crtc.h      |   13 ++++
 include/uapi/drm/drm.h      |   12 ++++
 include/uapi/drm/drm_mode.h |   17 +++++
 6 files changed, 197 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index aeda9f4..897ff46 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -4245,3 +4245,149 @@ int drm_calc_vscale(struct drm_region *src, struct drm_region *dst,
 	return vscale;
 }
 EXPORT_SYMBOL(drm_calc_vscale);
+
+int drm_mode_atomic_ioctl(struct drm_device *dev,
+			  void *data, struct drm_file *file_priv)
+{
+	struct drm_mode_atomic *arg = data;
+	uint32_t __user *objs_ptr = (uint32_t __user *)(unsigned long)(arg->objs_ptr);
+	uint32_t __user *count_props_ptr = (uint32_t __user *)(unsigned long)(arg->count_props_ptr);
+	uint32_t __user *props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr);
+	uint64_t __user *prop_values_ptr = (uint64_t __user *)(unsigned long)(arg->prop_values_ptr);
+	uint64_t __user *blob_values_ptr = (uint64_t __user *)(unsigned long)(arg->blob_values_ptr);
+	unsigned int copied_objs = 0;
+	unsigned int copied_props = 0;
+	unsigned int copied_blobs = 0;
+	void *state;
+	int ret = 0;
+	unsigned int i, j;
+
+	if (!dev->driver->atomic_funcs ||
+	    !dev->driver->atomic_funcs->begin ||
+	    !dev->driver->atomic_funcs->set ||
+	    !dev->driver->atomic_funcs->check ||
+	    !dev->driver->atomic_funcs->commit ||
+	    !dev->driver->atomic_funcs->end)
+		return -ENOSYS;
+
+	if (arg->flags & ~(DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_EVENT | DRM_MODE_ATOMIC_NONBLOCK))
+		return -EINVAL;
+
+	/* can't test and expect an event at the same time. */
+	if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY && arg->flags & DRM_MODE_ATOMIC_EVENT)
+		return -EINVAL;
+
+	mutex_lock(&dev->mode_config.mutex);
+
+	state = dev->driver->atomic_funcs->begin(dev, file_priv, arg->flags, arg->user_data);
+	if (IS_ERR(state)) {
+		ret = PTR_ERR(state);
+		goto unlock;
+	}
+
+	for (i = 0; i < arg->count_objs; i++) {
+		uint32_t obj_id, count_props;
+		struct drm_mode_object *obj;
+
+		if (get_user(obj_id, objs_ptr + copied_objs)) {
+			ret = -EFAULT;
+			goto out;
+		}
+
+		obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_ANY);
+		if (!obj || !obj->properties) {
+			ret = -ENOENT;
+			goto out;
+		}
+
+		if (get_user(count_props, count_props_ptr + copied_objs)) {
+			ret = -EFAULT;
+			goto out;
+		}
+
+		copied_objs++;
+
+		for (j = 0; j < count_props; j++) {
+			uint32_t prop_id;
+			uint64_t prop_value;
+			struct drm_mode_object *prop_obj;
+			struct drm_property *prop;
+			void *blob_data = NULL;
+
+			if (get_user(prop_id, props_ptr + copied_props)) {
+				ret = -EFAULT;
+				goto out;
+			}
+
+			if (!object_has_prop(obj, prop_id)) {
+				ret = -EINVAL;
+				goto out;
+			}
+
+			prop_obj = drm_mode_object_find(dev, prop_id, DRM_MODE_OBJECT_PROPERTY);
+			if (!prop_obj) {
+				ret = -ENOENT;
+				goto out;
+			}
+			prop = obj_to_property(prop_obj);
+
+			if (get_user(prop_value, prop_values_ptr + copied_props)) {
+				ret = -EFAULT;
+				goto out;
+			}
+
+			if (!drm_property_change_is_valid(prop, prop_value)) {
+				ret = -EINVAL;
+				goto out;
+			}
+
+			if (prop->flags & DRM_MODE_PROP_BLOB && prop_value) {
+				uint64_t blob_ptr;
+
+				if (get_user(blob_ptr, blob_values_ptr + copied_blobs)) {
+					ret = -EFAULT;
+					goto out;
+				}
+
+				blob_data = kmalloc(prop_value, GFP_KERNEL);
+				if (!blob_data) {
+					ret = -ENOMEM;
+					goto out;
+				}
+
+				if (copy_from_user(blob_data, (void __user *)(unsigned long)blob_ptr, prop_value)) {
+					kfree(blob_data);
+					ret = -EFAULT;
+					goto out;
+				}
+			}
+
+			/* User space sends the blob pointer even if we don't use it (length==0). */
+			if (prop->flags & DRM_MODE_PROP_BLOB)
+				copied_blobs++;
+
+			/* The driver will be in charge of blob_data from now on. */
+			ret = dev->driver->atomic_funcs->set(dev, state, obj, prop, prop_value, blob_data);
+			if (ret)
+				goto out;
+
+			copied_props++;
+		}
+	}
+
+	ret = dev->driver->atomic_funcs->check(dev, state);
+	if (ret)
+		goto out;
+
+	if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)
+		goto out;
+
+	ret = dev->driver->atomic_funcs->commit(dev, state);
+
+ out:
+	dev->driver->atomic_funcs->end(dev, state);
+ unlock:
+	mutex_unlock(&dev->mode_config.mutex);
+
+	return ret;
+}
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index be174ca..dbef305 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -166,6 +166,7 @@ static struct drm_ioctl_desc drm_ioctls[] = {
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATOMIC, drm_mode_atomic_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 };
 
 #define DRM_CORE_IOCTL_COUNT	ARRAY_SIZE( drm_ioctls )
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index fad21c9..1773812 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -958,6 +958,8 @@ struct drm_driver {
 
 	/* List of devices hanging off this driver */
 	struct list_head device_list;
+
+	const struct drm_atomic_funcs *atomic_funcs;
 };
 
 #define DRM_MINOR_UNASSIGNED 0
@@ -1051,6 +1053,12 @@ struct drm_pending_vblank_event {
 	struct drm_event_vblank event;
 };
 
+struct drm_pending_atomic_event {
+	struct drm_pending_event base;
+	int pipe;
+	struct drm_event_atomic event;
+};
+
 /**
  * DRM device structure. This structure represent a complete card that
  * may contain multiple heads.
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index d05d302..77f08a3 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -1092,6 +1092,8 @@ extern int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
 					     struct drm_file *file_priv);
 extern int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
 					   struct drm_file *file_priv);
+extern int drm_mode_atomic_ioctl(struct drm_device *dev,
+				 void *data, struct drm_file *file_priv);
 
 extern void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
 				 int *bpp);
@@ -1132,4 +1134,15 @@ extern int drm_calc_hscale(struct drm_region *src, struct drm_region *dst,
 extern int drm_calc_vscale(struct drm_region *src, struct drm_region *dst,
 			   int min_vscale, int max_vscale);
 
+struct drm_atomic_funcs {
+	void *(*begin)(struct drm_device *dev, struct drm_file *file,
+		       uint32_t flags, uint64_t user_data);
+	int (*set)(struct drm_device *dev, void *state,
+		   struct drm_mode_object *obj, struct drm_property *prop,
+		   uint64_t value, void *blob_data);
+	int (*check)(struct drm_device *dev, void *state);
+	int (*commit)(struct drm_device *dev, void *state);
+	void (*end)(struct drm_device *dev, void *state);
+};
+
 #endif /* __DRM_CRTC_H__ */
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
index 8d1e2bb..7b057ca 100644
--- a/include/uapi/drm/drm.h
+++ b/include/uapi/drm/drm.h
@@ -732,6 +732,7 @@ struct drm_prime_handle {
 #define DRM_IOCTL_MODE_ADDFB2		DRM_IOWR(0xB8, struct drm_mode_fb_cmd2)
 #define DRM_IOCTL_MODE_OBJ_GETPROPERTIES	DRM_IOWR(0xB9, struct drm_mode_obj_get_properties)
 #define DRM_IOCTL_MODE_OBJ_SETPROPERTY	DRM_IOWR(0xBA, struct drm_mode_obj_set_property)
+#define DRM_IOCTL_MODE_ATOMIC	DRM_IOWR(0xBB, struct drm_mode_atomic)
 
 /**
  * Device specific ioctls should only be in their respective headers
@@ -763,6 +764,7 @@ struct drm_event {
 
 #define DRM_EVENT_VBLANK 0x01
 #define DRM_EVENT_FLIP_COMPLETE 0x02
+#define DRM_EVENT_ATOMIC_COMPLETE 0x03
 
 struct drm_event_vblank {
 	struct drm_event base;
@@ -773,6 +775,16 @@ struct drm_event_vblank {
 	__u32 reserved;
 };
 
+struct drm_event_atomic {
+	struct drm_event base;
+	__u64 user_data;
+	__u32 tv_sec;
+	__u32 tv_usec;
+	__u32 sequence;
+	__u32 obj_id;
+	__u32 old_fb_id;
+};
+
 #define DRM_CAP_DUMB_BUFFER 0x1
 #define DRM_CAP_VBLANK_HIGH_CRTC 0x2
 #define DRM_CAP_DUMB_PREFERRED_DEPTH 0x3
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index 3d6301b..71f5e0d 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -460,4 +460,21 @@ struct drm_mode_destroy_dumb {
 	uint32_t handle;
 };
 
+
+#define DRM_MODE_ATOMIC_TEST_ONLY (1<<0)
+#define DRM_MODE_ATOMIC_EVENT (1<<1)
+#define DRM_MODE_ATOMIC_NONBLOCK (1<<2)
+
+/* FIXME come up with some sane error reporting mechanism? */
+struct drm_mode_atomic {
+	__u32 flags;
+	__u32 count_objs;
+	__u64 objs_ptr;
+	__u64 count_props_ptr;
+	__u64 props_ptr;
+	__u64 prop_values_ptr;
+	__u64 blob_values_ptr;
+	__u64 user_data;
+};
+
 #endif
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 16/81] drm/i915: Use drm_format_plane_cpp() rather than bits_per_pixel/8
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (14 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 15/81] drm: Add the atomic modeset ioctl ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 17/81] drm/i915: Implement proper clipping for video sprites ville.syrjala
                   ` (66 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

bits_per_pixel may not be populated for all pixel formats, so
let's just use drm_format_plane_cpp().

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 21dd4db..a4e71e5 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1991,6 +1991,7 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 	unsigned long linear_offset;
 	u32 dspcntr;
 	u32 reg;
+	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
 
 	switch (plane) {
 	case 0:
@@ -2049,13 +2050,12 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 
 	I915_WRITE(reg, dspcntr);
 
-	linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
+	linear_offset = y * fb->pitches[0] + x * cpp;
 
 	if (INTEL_INFO(dev)->gen >= 4) {
 		intel_crtc->dspaddr_offset =
 			intel_gen4_compute_offset_xtiled(&x, &y,
-							 fb->bits_per_pixel / 8,
-							 fb->pitches[0]);
+							 cpp, fb->pitches[0]);
 		linear_offset -= intel_crtc->dspaddr_offset;
 	} else {
 		intel_crtc->dspaddr_offset = linear_offset;
@@ -2088,6 +2088,7 @@ static int ironlake_update_plane(struct drm_crtc *crtc,
 	unsigned long linear_offset;
 	u32 dspcntr;
 	u32 reg;
+	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
 
 	switch (plane) {
 	case 0:
@@ -2144,11 +2145,10 @@ static int ironlake_update_plane(struct drm_crtc *crtc,
 
 	I915_WRITE(reg, dspcntr);
 
-	linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
+	linear_offset = y * fb->pitches[0] + x * cpp;
 	intel_crtc->dspaddr_offset =
 		intel_gen4_compute_offset_xtiled(&x, &y,
-						 fb->bits_per_pixel / 8,
-						 fb->pitches[0]);
+						 cpp, fb->pitches[0]);
 	linear_offset -= intel_crtc->dspaddr_offset;
 
 	DRM_DEBUG_KMS("Writing base %08X %08lX %d %d %d\n",
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 17/81] drm/i915: Implement proper clipping for video sprites
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (15 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 16/81] drm/i915: Use drm_format_plane_cpp() rather than bits_per_pixel/8 ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 18/81] drm/i915: Implement restore_fbdev_mode hook ville.syrjala
                   ` (65 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Properly clip the source when the destination gets clipped
by the pipe dimensions.

Sadly the video sprite hardware is rather limited so it can't do proper
sub-pixel postitioning. Resort to a best effort approach, where the
source coordinates are rounded to the nearest (macro)pixel boundary.

Also do some additional checking against various hardware limits.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_sprite.c |  171 +++++++++++++++++++++++------------
 1 files changed, 111 insertions(+), 60 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 827dcd4..77ca0da 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -120,11 +120,10 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
 	I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
 	I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
 
-	linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
+	linear_offset = y * fb->pitches[0] + x * pixel_size;
 	sprsurf_offset =
 		intel_gen4_compute_offset_xtiled(&x, &y,
-						 fb->bits_per_pixel / 8,
-						 fb->pitches[0]);
+						 pixel_size, fb->pitches[0]);
 	linear_offset -= sprsurf_offset;
 
 	/* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
@@ -286,11 +285,10 @@ ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
 	I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
 	I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
 
-	linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
+	linear_offset = y * fb->pitches[0] + x * pixel_size;
 	dvssurf_offset =
 		intel_gen4_compute_offset_xtiled(&x, &y,
-						 fb->bits_per_pixel / 8,
-						 fb->pitches[0]);
+						 pixel_size, fb->pitches[0]);
 	linear_offset -= dvssurf_offset;
 
 	if (obj->tiling_mode != I915_TILING_NONE)
@@ -409,6 +407,20 @@ ilk_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
 		key->flags = I915_SET_COLORKEY_NONE;
 }
 
+static bool
+format_is_yuv(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_YUYV:
+	case DRM_FORMAT_UYVY:
+	case DRM_FORMAT_VYUY:
+	case DRM_FORMAT_YVYU:
+		return true;
+	default:
+		return false;
+	}
+}
+
 static int
 intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 		   struct drm_framebuffer *fb, int crtc_x, int crtc_y,
@@ -420,35 +432,68 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_plane *intel_plane = to_intel_plane(plane);
-	struct intel_framebuffer *intel_fb;
-	struct drm_i915_gem_object *obj, *old_obj;
+	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+	struct drm_i915_gem_object *obj = intel_fb->obj;
+	struct drm_i915_gem_object *old_obj = intel_plane->obj;
 	int pipe = intel_plane->pipe;
 	enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
 								      pipe);
 	int ret = 0;
-	int x = src_x >> 16, y = src_y >> 16;
 	int primary_w = crtc->mode.hdisplay, primary_h = crtc->mode.vdisplay;
 	bool disable_primary = false;
-
-	intel_fb = to_intel_framebuffer(fb);
-	obj = intel_fb->obj;
-
-	old_obj = intel_plane->obj;
-
-	src_w = src_w >> 16;
-	src_h = src_h >> 16;
-
-	/* Pipe must be running... */
-	if (!(I915_READ(PIPECONF(cpu_transcoder)) & PIPECONF_ENABLE))
-		return -EINVAL;
-
-	if (crtc_x >= primary_w || crtc_y >= primary_h)
-		return -EINVAL;
+	bool visible;
+	int hscale, vscale;
+	int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
+	struct drm_region src = {
+		.x1 = src_x,
+		.x2 = src_x + src_w,
+		.y1 = src_y,
+		.y2 = src_y + src_h,
+	};
+	struct drm_region dst = {
+		.x1 = crtc_x,
+		.x2 = crtc_x + crtc_w,
+		.y1 = crtc_y,
+		.y2 = crtc_y + crtc_h,
+	};
+	const struct drm_region clip = {
+		.x2 = crtc->mode.hdisplay,
+		.y2 = crtc->mode.vdisplay,
+	};
 
 	/* Don't modify another pipe's plane */
 	if (intel_plane->pipe != intel_crtc->pipe)
 		return -EINVAL;
 
+	if (fb->width < 3 || fb->height < 3 || fb->pitches[0] > 16384)
+		return -EINVAL;
+
+	/*
+	 * We may not have a scaler, eg. HSW does not have it any more
+	 */
+	if (!intel_plane->can_scale && (((uint64_t) crtc_w << 16) != src_w ||
+					((uint64_t) crtc_h << 16) != src_h))
+		return -EINVAL;
+
+	/*
+	 * FIXME the following code does a bunch of fuzzy adjustments to the
+	 * coordinates and sizes. We probably need some way to decide whether
+	 * strict checking should be done instead.
+	 */
+	hscale = drm_calc_hscale(&src, &dst, 1, intel_plane->max_downscale << 16);
+	vscale = drm_calc_vscale(&src, &dst, 1, intel_plane->max_downscale << 16);
+
+	visible = drm_region_clip_scaled(&src, &dst, &clip, hscale, vscale);
+
+	crtc_x = dst.x1;
+	crtc_y = dst.y1;
+	crtc_w = drm_region_width(&dst);
+	crtc_h = drm_region_height(&dst);
+
+	/* HW doesn't seem to like smaller sprite, even when scaling */
+	if (crtc_w < 3 || crtc_h < 3)
+		visible = false;
+
 	/* Sprite planes can be linear or x-tiled surfaces */
 	switch (obj->tiling_mode) {
 		case I915_TILING_NONE:
@@ -459,43 +504,47 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	}
 
 	/*
-	 * Clamp the width & height into the visible area.  Note we don't
-	 * try to scale the source if part of the visible region is offscreen.
-	 * The caller must handle that by adjusting source offset and size.
+	 * Hardware doesn't handle subpixel coordinates.
+	 * Round to nearest (macro)pixel boundary.
 	 */
-	if ((crtc_x < 0) && ((crtc_x + crtc_w) > 0)) {
-		crtc_w += crtc_x;
-		crtc_x = 0;
+	if (format_is_yuv(fb->pixel_format)) {
+		src_x = ((src.x1 + 0x10000) >> 17) << 1;
+		src_w = (((src.x2 + 0x10000) >> 17) << 1) - src_x;
+	} else {
+		src_x = (src.x1 + 0x8000) >> 16;
+		src_w = ((src.x2 + 0x8000) >> 16) - src_x;
 	}
-	if ((crtc_x + crtc_w) <= 0) /* Nothing to display */
-		goto out;
-	if ((crtc_x + crtc_w) > primary_w)
-		crtc_w = primary_w - crtc_x;
+	src_y = (src.y1 + 0x8000) >> 16;
+	src_h = ((src.y2 + 0x8000) >> 16) - src_y;
 
-	if ((crtc_y < 0) && ((crtc_y + crtc_h) > 0)) {
-		crtc_h += crtc_y;
-		crtc_y = 0;
-	}
-	if ((crtc_y + crtc_h) <= 0) /* Nothing to display */
-		goto out;
-	if (crtc_y + crtc_h > primary_h)
-		crtc_h = primary_h - crtc_y;
+	/* Account for minimum source size when scaling */
+	if (visible && (src_w != crtc_w || src_h != crtc_h)) {
+		unsigned int min_w = format_is_yuv(fb->pixel_format) ? 4 : 3;
 
-	if (!crtc_w || !crtc_h) /* Again, nothing to display */
-		goto out;
+		if (src_w < min_w) {
+			src_w = min_w;
+			if (src_x > fb->width - src_w)
+				src_x = fb->width - src_w;
+		}
 
-	/*
-	 * We may not have a scaler, eg. HSW does not have it any more
-	 */
-	if (!intel_plane->can_scale && (crtc_w != src_w || crtc_h != src_h))
-		return -EINVAL;
+		/* FIXME interlacing */
+		if (src_h < 3) {
+			src_h = 3;
+			if (src_y > fb->height - src_h)
+				src_y = fb->height - src_h;
+		}
+	}
 
-	/*
-	 * We can take a larger source and scale it down, but
-	 * only so much...  16x is the max on SNB.
-	 */
-	if (((src_w * src_h) / (crtc_w * crtc_h)) > intel_plane->max_downscale)
-		return -EINVAL;
+	/* Check size restrictions when scaling */
+	if (visible && (src_w != crtc_w || src_h != crtc_h)) {
+		if (src_w > 2048 || src_h > 2048 ||
+		    src_w * cpp > 4096 - 64 || fb->pitches[0] > 4096)
+			return -EINVAL;
+	}
+
+	/* Pipe must be running... */
+	if (!(I915_READ(PIPECONF(pipe)) & PIPECONF_ENABLE))
+		return 0;
 
 	/*
 	 * If the sprite is completely covering the primary plane,
@@ -520,11 +569,14 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	if (!disable_primary)
 		intel_enable_primary(crtc);
 
-	intel_plane->update_plane(plane, fb, obj, crtc_x, crtc_y,
-				  crtc_w, crtc_h, x, y, src_w, src_h);
+	if (visible) {
+		intel_plane->update_plane(plane, fb, obj, crtc_x, crtc_y,
+					  crtc_w, crtc_h, src_x, src_y, src_w, src_h);
 
-	if (disable_primary)
-		intel_disable_primary(crtc);
+		if (disable_primary)
+			intel_disable_primary(crtc);
+	} else
+		intel_plane->disable_plane(plane);
 
 	/* Unpin old obj after new one is active to avoid ugliness */
 	if (old_obj) {
@@ -544,7 +596,6 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 
 out_unlock:
 	mutex_unlock(&dev->struct_mutex);
-out:
 	return ret;
 }
 
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 18/81] drm/i915: Implement restore_fbdev_mode hook
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (16 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 17/81] drm/i915: Implement proper clipping for video sprites ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 19/81] drm/i915: Split clipping and checking from update_plane hook ville.syrjala
                   ` (64 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Convert intel_fb_restore_mode to be useable as the
drm_fb_helper.restore_fbdev_mode hook. This will cause all planes to be
disabled when swithing back to fbcon.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_dma.c  |    2 +-
 drivers/gpu/drm/i915/intel_drv.h |    2 +-
 drivers/gpu/drm/i915/intel_fb.c  |   14 ++++++++++----
 3 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 6fec5d4..392c9a1 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1790,7 +1790,7 @@ void i915_driver_lastclose(struct drm_device * dev)
 		return;
 
 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-		intel_fb_restore_mode(dev);
+		intel_fb_restore_mode(&dev_priv->fbdev->helper);
 		vga_switcheroo_process_delayed_switch();
 		return;
 	}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 6724be8..16770cb 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -606,7 +606,7 @@ extern int intel_overlay_attrs(struct drm_device *dev, void *data,
 			       struct drm_file *file_priv);
 
 extern void intel_fb_output_poll_changed(struct drm_device *dev);
-extern void intel_fb_restore_mode(struct drm_device *dev);
+extern int intel_fb_restore_mode(struct drm_fb_helper *helper);
 
 extern void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
 			bool state);
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index b7773e5..3ab7967 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -195,6 +195,7 @@ static struct drm_fb_helper_funcs intel_fb_helper_funcs = {
 	.gamma_set = intel_crtc_fb_gamma_set,
 	.gamma_get = intel_crtc_fb_gamma_get,
 	.fb_probe = intel_fb_find_or_create_single,
+	.restore_fbdev_mode = intel_fb_restore_mode,
 };
 
 static void intel_fbdev_destroy(struct drm_device *dev,
@@ -275,22 +276,27 @@ void intel_fb_output_poll_changed(struct drm_device *dev)
 	drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper);
 }
 
-void intel_fb_restore_mode(struct drm_device *dev)
+int intel_fb_restore_mode(struct drm_fb_helper *helper)
 {
+	struct drm_device *dev = helper->dev;
 	int ret;
-	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_mode_config *config = &dev->mode_config;
 	struct drm_plane *plane;
 
 	mutex_lock(&dev->mode_config.mutex);
 
-	ret = drm_fb_helper_restore_fbdev_mode(&dev_priv->fbdev->helper);
-	if (ret)
+	ret = drm_fb_helper_restore_fbdev_mode(helper);
+	if (ret) {
 		DRM_DEBUG("failed to restore crtc mode\n");
+		goto out;
+	}
 
 	/* Be sure to shut off any planes that may be active */
 	list_for_each_entry(plane, &config->plane_list, head)
 		plane->funcs->disable_plane(plane);
 
+out:
 	mutex_unlock(&dev->mode_config.mutex);
+
+	return ret;
 }
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 19/81] drm/i915: Split clipping and checking from update_plane hook
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (17 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 18/81] drm/i915: Implement restore_fbdev_mode hook ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 20/81] drm/i915: Factor out i9xx_compute_clocks() like ironlake_compute_clocks() ville.syrjala
                   ` (63 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Split the update_plane() codepath into two separate steps. The first
step checkis and clips the plane, and the second step actually commits
the changes to the hardware. This allows the atomic modesetting code
to perform all checks before clobering hardware state.

The update_plane() hook is reduced to a thin wrapper calling both check
and commit functions.

Buffer (un)pinning is still being performed in the commit step. This
needs to be changed as well, so that the atomic modesetting code can
try to pin all new buffers before touching the hardware.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_drv.h    |   15 +-
 drivers/gpu/drm/i915/intel_sprite.c |  411 ++++++++++++++++++++++-------------
 2 files changed, 266 insertions(+), 160 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 16770cb..0d7c2fc 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -231,6 +231,15 @@ struct intel_crtc {
 	uint32_t ddi_pll_sel;
 };
 
+struct intel_plane_coords {
+	/* disabled or fully clipped? */
+	bool visible;
+	/* coordinates clipped against pipe dimensions */
+	int32_t crtc_x, crtc_y;
+	uint32_t crtc_w, crtc_h;
+	uint32_t src_x, src_y, src_w, src_h;
+};
+
 struct intel_plane {
 	struct drm_plane base;
 	enum pipe pipe;
@@ -240,11 +249,7 @@ struct intel_plane {
 	u32 lut_r[1024], lut_g[1024], lut_b[1024];
 	void (*update_plane)(struct drm_plane *plane,
 			     struct drm_framebuffer *fb,
-			     struct drm_i915_gem_object *obj,
-			     int crtc_x, int crtc_y,
-			     unsigned int crtc_w, unsigned int crtc_h,
-			     uint32_t x, uint32_t y,
-			     uint32_t src_w, uint32_t src_h);
+			     const struct intel_plane_coords *clip);
 	void (*disable_plane)(struct drm_plane *plane);
 	int (*update_colorkey)(struct drm_plane *plane,
 			       struct drm_intel_sprite_colorkey *key);
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 77ca0da..d64cefd 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -36,16 +36,189 @@
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 
+static bool
+format_is_yuv(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_YUYV:
+	case DRM_FORMAT_UYVY:
+	case DRM_FORMAT_VYUY:
+	case DRM_FORMAT_YVYU:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static void intel_clip_plane(const struct drm_plane *plane,
+			     const struct drm_crtc *crtc,
+			     const struct drm_framebuffer *fb,
+			     struct intel_plane_coords *coords)
+{
+	const struct intel_plane *intel_plane = to_intel_plane(plane);
+	const struct drm_display_mode *mode = &crtc->mode;
+	int hscale, vscale;
+	struct drm_region src = {
+		.x1 = coords->src_x,
+		.x2 = coords->src_x + coords->src_w,
+		.y1 = coords->src_y,
+		.y2 = coords->src_y + coords->src_h,
+	};
+	struct drm_region dst = {
+		.x1 = coords->crtc_x,
+		.x2 = coords->crtc_x + coords->crtc_w,
+		.y1 = coords->crtc_y,
+		.y2 = coords->crtc_y + coords->crtc_h,
+	};
+	const struct drm_region clip = {
+		.x2 = mode->hdisplay,
+		.y2 = mode->vdisplay,
+	};
+
+	hscale = drm_calc_hscale(&src, &dst, 1, intel_plane->max_downscale << 16);
+	vscale = drm_calc_vscale(&src, &dst, 1, intel_plane->max_downscale << 16);
+
+	coords->visible = drm_region_clip_scaled(&src, &dst, &clip, hscale, vscale);
+
+	coords->crtc_x = dst.x1;
+	coords->crtc_y = dst.y1;
+	coords->crtc_w = drm_region_width(&dst);
+	coords->crtc_h = drm_region_height(&dst);
+
+	/* HW doesn't seem to like smaller sprite, even when scaling */
+	/* FIXME return an error instead? */
+	if (coords->crtc_w < 3 || coords->crtc_h < 3)
+		coords->visible = false;
+
+	/*
+	 * Hardware doesn't handle subpixel coordinates.
+	 * Round to nearest (macro)pixel boundary.
+	 */
+	if (format_is_yuv(fb->pixel_format)) {
+		coords->src_x = ((src.x1 + 0x10000) >> 17) << 1;
+		coords->src_w = (((src.x2 + 0x10000) >> 17) << 1) - coords->src_x;
+	} else {
+		coords->src_x = (src.x1 + 0x8000) >> 16;
+		coords->src_w = ((src.x2 + 0x8000) >> 16) - coords->src_x;
+	}
+	coords->src_y = (src.y1 + 0x8000) >> 16;
+	coords->src_h = ((src.y2 + 0x8000) >> 16) - coords->src_y;
+
+	/* Account for minimum source size when scaling */
+	if (coords->visible && (coords->src_w != coords->crtc_w || coords->src_h != coords->crtc_h)) {
+		unsigned int min_w = format_is_yuv(fb->pixel_format) ? 4 : 3;
+
+		if (coords->src_w < min_w) {
+			coords->src_w = min_w;
+			if (coords->src_x > fb->width - coords->src_w)
+				coords->src_x = fb->width - coords->src_w;
+		}
+
+		/* FIXME interlacing */
+		if (coords->src_h < 3) {
+			coords->src_h = 3;
+			if (coords->src_y > fb->height - coords->src_h)
+				coords->src_y = fb->height - coords->src_h;
+		}
+	}
+}
+
+int intel_check_plane(const struct drm_plane *plane,
+		      const struct drm_crtc *crtc,
+		      const struct drm_framebuffer *fb,
+		      struct intel_plane_coords *coords)
+{
+	const struct intel_plane *intel_plane = to_intel_plane(plane);
+
+	if (fb) {
+		/* FIXME copy-pasted. refactor common code in drm_crtc.c */
+		uint32_t fb_width = fb->width << 16;
+		uint32_t fb_height = fb->height << 16;
+		int i;
+
+		for (i = 0; i < plane->format_count; i++) {
+			if (plane->format_types[i] == fb->pixel_format)
+				break;
+		}
+		if (i == plane->format_count)
+			return -EINVAL;
+
+		if (coords->src_w > fb_width ||
+		    coords->src_x > fb_width - coords->src_w ||
+		    coords->src_h > fb_height ||
+		    coords->src_y > fb_height - coords->src_h)
+			return -ENOSPC;
+
+		if (coords->crtc_w > INT_MAX ||
+		    coords->crtc_x > INT_MAX - (int32_t) coords->crtc_w ||
+		    coords->crtc_h > INT_MAX ||
+		    coords->crtc_y > INT_MAX - (int32_t) coords->crtc_h)
+			return -ERANGE;
+
+		if (fb->width < 3 || fb->height < 3 || fb->pitches[0] > 16384)
+			return -EINVAL;
+
+		/* Sprite planes can be linear or x-tiled surfaces */
+		switch (to_intel_framebuffer(fb)->obj->tiling_mode) {
+		case I915_TILING_NONE:
+		case I915_TILING_X:
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+
+	if (crtc) {
+		const struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+		/* Don't modify another pipe's plane */
+		if (intel_plane->pipe != intel_crtc->pipe)
+			return -EINVAL;
+	}
+
+	if (!fb || !crtc || !crtc->enabled) {
+		coords->visible = false;
+		return 0;
+	}
+
+	/*
+	 * We may not have a scaler, eg. HSW does not have it any more
+	 */
+	if (!intel_plane->can_scale && (((uint64_t) coords->crtc_w << 16) != coords->src_w ||
+					((uint64_t) coords->crtc_h << 16) != coords->src_h))
+		return -EINVAL;
+
+	intel_clip_plane(plane, crtc, fb, coords);
+
+	/* Check size restrictions when scaling */
+	if (coords->visible && (coords->src_w != coords->crtc_w || coords->src_h != coords->crtc_h)) {
+		unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
+
+		if (coords->src_w > 2048 || coords->src_h > 2048 ||
+		    coords->src_w * cpp > 4096 - 64 || fb->pitches[0] > 4096)
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
 static void
-ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
-		 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
-		 unsigned int crtc_w, unsigned int crtc_h,
-		 uint32_t x, uint32_t y,
-		 uint32_t src_w, uint32_t src_h)
+ivb_update_plane(struct drm_plane *plane,
+		 struct drm_framebuffer *fb,
+		 const struct intel_plane_coords *coords)
 {
 	struct drm_device *dev = plane->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_plane *intel_plane = to_intel_plane(plane);
+	const struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj;
+	int crtc_x = coords->crtc_x;
+	int crtc_y = coords->crtc_y;
+	unsigned int crtc_w = coords->crtc_w;
+	unsigned int crtc_h = coords->crtc_h;
+	uint32_t x = coords->src_x;
+	uint32_t y = coords->src_y;
+	uint32_t src_w = coords->src_w;
+	uint32_t src_h = coords->src_h;
 	int pipe = intel_plane->pipe;
 	u32 sprctl, sprscale = 0;
 	unsigned long sprsurf_offset, linear_offset;
@@ -218,15 +391,22 @@ ivb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
 }
 
 static void
-ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
-		 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
-		 unsigned int crtc_w, unsigned int crtc_h,
-		 uint32_t x, uint32_t y,
-		 uint32_t src_w, uint32_t src_h)
+ilk_update_plane(struct drm_plane *plane,
+		 struct drm_framebuffer *fb,
+		 const struct intel_plane_coords *coords)
 {
 	struct drm_device *dev = plane->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_plane *intel_plane = to_intel_plane(plane);
+	const struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj;
+	int crtc_x = coords->crtc_x;
+	int crtc_y = coords->crtc_y;
+	unsigned int crtc_w = coords->crtc_w;
+	unsigned int crtc_h = coords->crtc_h;
+	uint32_t x = coords->src_x;
+	uint32_t y = coords->src_y;
+	uint32_t src_w = coords->src_w;
+	uint32_t src_h = coords->src_h;
 	int pipe = intel_plane->pipe;
 	unsigned long dvssurf_offset, linear_offset;
 	u32 dvscntr, dvsscale;
@@ -407,151 +587,68 @@ ilk_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
 		key->flags = I915_SET_COLORKEY_NONE;
 }
 
-static bool
-format_is_yuv(uint32_t format)
-{
-	switch (format) {
-	case DRM_FORMAT_YUYV:
-	case DRM_FORMAT_UYVY:
-	case DRM_FORMAT_VYUY:
-	case DRM_FORMAT_YVYU:
-		return true;
-	default:
-		return false;
-	}
-}
-
 static int
-intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
-		   struct drm_framebuffer *fb, int crtc_x, int crtc_y,
-		   unsigned int crtc_w, unsigned int crtc_h,
-		   uint32_t src_x, uint32_t src_y,
-		   uint32_t src_w, uint32_t src_h)
+intel_disable_plane(struct drm_plane *plane)
+{
+	struct drm_device *dev = plane->dev;
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	int ret = 0;
+
+	if (plane->crtc)
+		intel_enable_primary(plane->crtc);
+
+	intel_plane->disable_plane(plane);
+
+	if (!intel_plane->obj)
+		goto out;
+
+	mutex_lock(&dev->struct_mutex);
+	intel_unpin_fb_obj(intel_plane->obj);
+	intel_plane->obj = NULL;
+	mutex_unlock(&dev->struct_mutex);
+out:
+
+	return ret;
+}
+
+int
+intel_commit_plane(struct drm_plane *plane,
+		   struct drm_crtc *crtc,
+		   struct drm_framebuffer *fb,
+		   const struct intel_plane_coords *coords)
 {
 	struct drm_device *dev = plane->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_plane *intel_plane = to_intel_plane(plane);
-	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
-	struct drm_i915_gem_object *obj = intel_fb->obj;
+	struct intel_framebuffer *intel_fb;
+	struct drm_i915_gem_object *obj;
 	struct drm_i915_gem_object *old_obj = intel_plane->obj;
 	int pipe = intel_plane->pipe;
-	enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
-								      pipe);
-	int ret = 0;
-	int primary_w = crtc->mode.hdisplay, primary_h = crtc->mode.vdisplay;
+	int ret;
+	int primary_w, primary_h;
 	bool disable_primary = false;
-	bool visible;
-	int hscale, vscale;
-	int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
-	struct drm_region src = {
-		.x1 = src_x,
-		.x2 = src_x + src_w,
-		.y1 = src_y,
-		.y2 = src_y + src_h,
-	};
-	struct drm_region dst = {
-		.x1 = crtc_x,
-		.x2 = crtc_x + crtc_w,
-		.y1 = crtc_y,
-		.y2 = crtc_y + crtc_h,
-	};
-	const struct drm_region clip = {
-		.x2 = crtc->mode.hdisplay,
-		.y2 = crtc->mode.vdisplay,
-	};
 
-	/* Don't modify another pipe's plane */
-	if (intel_plane->pipe != intel_crtc->pipe)
-		return -EINVAL;
-
-	if (fb->width < 3 || fb->height < 3 || fb->pitches[0] > 16384)
-		return -EINVAL;
-
-	/*
-	 * We may not have a scaler, eg. HSW does not have it any more
-	 */
-	if (!intel_plane->can_scale && (((uint64_t) crtc_w << 16) != src_w ||
-					((uint64_t) crtc_h << 16) != src_h))
-		return -EINVAL;
-
-	/*
-	 * FIXME the following code does a bunch of fuzzy adjustments to the
-	 * coordinates and sizes. We probably need some way to decide whether
-	 * strict checking should be done instead.
-	 */
-	hscale = drm_calc_hscale(&src, &dst, 1, intel_plane->max_downscale << 16);
-	vscale = drm_calc_vscale(&src, &dst, 1, intel_plane->max_downscale << 16);
-
-	visible = drm_region_clip_scaled(&src, &dst, &clip, hscale, vscale);
-
-	crtc_x = dst.x1;
-	crtc_y = dst.y1;
-	crtc_w = drm_region_width(&dst);
-	crtc_h = drm_region_height(&dst);
-
-	/* HW doesn't seem to like smaller sprite, even when scaling */
-	if (crtc_w < 3 || crtc_h < 3)
-		visible = false;
-
-	/* Sprite planes can be linear or x-tiled surfaces */
-	switch (obj->tiling_mode) {
-		case I915_TILING_NONE:
-		case I915_TILING_X:
-			break;
-		default:
-			return -EINVAL;
-	}
-
-	/*
-	 * Hardware doesn't handle subpixel coordinates.
-	 * Round to nearest (macro)pixel boundary.
-	 */
-	if (format_is_yuv(fb->pixel_format)) {
-		src_x = ((src.x1 + 0x10000) >> 17) << 1;
-		src_w = (((src.x2 + 0x10000) >> 17) << 1) - src_x;
-	} else {
-		src_x = (src.x1 + 0x8000) >> 16;
-		src_w = ((src.x2 + 0x8000) >> 16) - src_x;
-	}
-	src_y = (src.y1 + 0x8000) >> 16;
-	src_h = ((src.y2 + 0x8000) >> 16) - src_y;
-
-	/* Account for minimum source size when scaling */
-	if (visible && (src_w != crtc_w || src_h != crtc_h)) {
-		unsigned int min_w = format_is_yuv(fb->pixel_format) ? 4 : 3;
-
-		if (src_w < min_w) {
-			src_w = min_w;
-			if (src_x > fb->width - src_w)
-				src_x = fb->width - src_w;
-		}
-
-		/* FIXME interlacing */
-		if (src_h < 3) {
-			src_h = 3;
-			if (src_y > fb->height - src_h)
-				src_y = fb->height - src_h;
-		}
-	}
-
-	/* Check size restrictions when scaling */
-	if (visible && (src_w != crtc_w || src_h != crtc_h)) {
-		if (src_w > 2048 || src_h > 2048 ||
-		    src_w * cpp > 4096 - 64 || fb->pitches[0] > 4096)
-			return -EINVAL;
+	if (!coords->visible) {
+		intel_disable_plane(plane);
+		return 0;
 	}
 
+	/* FIXME this should happen anymore I suppose */
 	/* Pipe must be running... */
 	if (!(I915_READ(PIPECONF(pipe)) & PIPECONF_ENABLE))
 		return 0;
 
+	intel_fb = to_intel_framebuffer(fb);
+	obj = intel_fb->obj;
+	primary_w = crtc->mode.hdisplay;
+	primary_h = crtc->mode.vdisplay;
+
 	/*
 	 * If the sprite is completely covering the primary plane,
 	 * we can disable the primary and save power.
 	 */
-	if ((crtc_x == 0) && (crtc_y == 0) &&
-	    (crtc_w == primary_w) && (crtc_h == primary_h))
+	if ((coords->crtc_x == 0) && (coords->crtc_y == 0) &&
+	    (coords->crtc_w == primary_w) && (coords->crtc_h == primary_h))
 		disable_primary = true;
 
 	mutex_lock(&dev->struct_mutex);
@@ -569,9 +666,8 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	if (!disable_primary)
 		intel_enable_primary(crtc);
 
-	if (visible) {
-		intel_plane->update_plane(plane, fb, obj, crtc_x, crtc_y,
-					  crtc_w, crtc_h, src_x, src_y, src_w, src_h);
+	if (coords->visible) {
+		intel_plane->update_plane(plane, fb, coords);
 
 		if (disable_primary)
 			intel_disable_primary(crtc);
@@ -600,26 +696,31 @@ out_unlock:
 }
 
 static int
-intel_disable_plane(struct drm_plane *plane)
+intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+		   struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+		   unsigned int crtc_w, unsigned int crtc_h,
+		   uint32_t src_x, uint32_t src_y,
+		   uint32_t src_w, uint32_t src_h)
 {
-	struct drm_device *dev = plane->dev;
-	struct intel_plane *intel_plane = to_intel_plane(plane);
-	int ret = 0;
+	int ret;
+	struct intel_plane_coords coords = {
+		.crtc_x = crtc_x,
+		.crtc_y = crtc_y,
+		.crtc_w = crtc_w,
+		.crtc_h = crtc_h,
+		.src_x = src_x,
+		.src_y = src_y,
+		.src_w = src_w,
+		.src_h = src_h,
+	};
 
-	if (plane->crtc)
-		intel_enable_primary(plane->crtc);
-	intel_plane->disable_plane(plane);
+	ret = intel_check_plane(plane, crtc, fb, &coords);
+	if (ret)
+		return ret;
 
-	if (!intel_plane->obj)
-		goto out;
+	intel_commit_plane(plane, crtc, fb, &coords);
 
-	mutex_lock(&dev->struct_mutex);
-	intel_unpin_fb_obj(intel_plane->obj);
-	intel_plane->obj = NULL;
-	mutex_unlock(&dev->struct_mutex);
-out:
-
-	return ret;
+	return 0;
 }
 
 static void intel_destroy_plane(struct drm_plane *plane)
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 20/81] drm/i915: Factor out i9xx_compute_clocks() like ironlake_compute_clocks()
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (18 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 19/81] drm/i915: Split clipping and checking from update_plane hook ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 21/81] drm/i915: Consitify adjusted_mode parameter ville.syrjala
                   ` (62 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Split the clock stuff out.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |  128 ++++++++++++++++++++--------------
 1 files changed, 75 insertions(+), 53 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index a4e71e5..0fa9c2a 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4544,6 +4544,76 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc,
 		   ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
 }
 
+static bool i9xx_compute_clocks(struct drm_crtc *crtc,
+				struct drm_display_mode *adjusted_mode,
+				intel_clock_t *clock,
+				bool *has_reduced_clock,
+				intel_clock_t *reduced_clock,
+				int *refclk, int *num_connectors, bool *is_dp)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_encoder *encoder;
+	const intel_limit_t *limit;
+	bool ret, is_sdvo = false, is_tv = false, is_lvds = false;
+
+	*num_connectors = 0;
+
+	for_each_encoder_on_crtc(dev, crtc, encoder) {
+		switch (encoder->type) {
+		case INTEL_OUTPUT_LVDS:
+			is_lvds = true;
+			break;
+		case INTEL_OUTPUT_SDVO:
+		case INTEL_OUTPUT_HDMI:
+			is_sdvo = true;
+			if (encoder->needs_tv_clock)
+				is_tv = true;
+			break;
+		case INTEL_OUTPUT_TVOUT:
+			is_tv = true;
+			break;
+		case INTEL_OUTPUT_DISPLAYPORT:
+			*is_dp = true;
+			break;
+		}
+
+		(*num_connectors)++;
+	}
+
+	*refclk = i9xx_get_refclk(crtc, *num_connectors);
+
+	/*
+	 * Returns a set of divisors for the desired target clock with the given
+	 * refclk, or FALSE.  The returned values represent the clock equation:
+	 * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+	 */
+	limit = intel_limit(crtc, *refclk);
+	ret = limit->find_pll(limit, crtc, adjusted_mode->clock, *refclk, NULL,
+			      clock);
+	if (!ret)
+		return false;
+
+	if (is_lvds && dev_priv->lvds_downclock_avail) {
+		/*
+		 * Ensure we match the reduced clock's P to the target clock.
+		 * If the clocks don't match, we can't switch the display clock
+		 * by using the FP0/FP1. In such case we will disable the LVDS
+		 * downclock feature.
+		*/
+		*has_reduced_clock = limit->find_pll(limit, crtc,
+						     dev_priv->lvds_downclock,
+						     *refclk,
+						     clock,
+						     reduced_clock);
+	}
+
+	if (is_sdvo && is_tv)
+		i9xx_adjust_sdvo_tv_clock(adjusted_mode, clock);
+
+	return true;
+}
+
 static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 			      struct drm_display_mode *mode,
 			      struct drm_display_mode *adjusted_mode,
@@ -4558,44 +4628,13 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 	int refclk, num_connectors = 0;
 	intel_clock_t clock, reduced_clock;
 	u32 dspcntr, pipeconf;
-	bool ok, has_reduced_clock = false, is_sdvo = false;
-	bool is_lvds = false, is_tv = false, is_dp = false;
-	struct intel_encoder *encoder;
-	const intel_limit_t *limit;
+	bool ok, has_reduced_clock = false;
+	bool is_dp = false;
 	int ret;
 
-	for_each_encoder_on_crtc(dev, crtc, encoder) {
-		switch (encoder->type) {
-		case INTEL_OUTPUT_LVDS:
-			is_lvds = true;
-			break;
-		case INTEL_OUTPUT_SDVO:
-		case INTEL_OUTPUT_HDMI:
-			is_sdvo = true;
-			if (encoder->needs_tv_clock)
-				is_tv = true;
-			break;
-		case INTEL_OUTPUT_TVOUT:
-			is_tv = true;
-			break;
-		case INTEL_OUTPUT_DISPLAYPORT:
-			is_dp = true;
-			break;
-		}
-
-		num_connectors++;
-	}
-
-	refclk = i9xx_get_refclk(crtc, num_connectors);
-
-	/*
-	 * Returns a set of divisors for the desired target clock with the given
-	 * refclk, or FALSE.  The returned values represent the clock equation:
-	 * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
-	 */
-	limit = intel_limit(crtc, refclk);
-	ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, NULL,
-			     &clock);
+	ok = i9xx_compute_clocks(crtc, adjusted_mode, &clock,
+				 &has_reduced_clock, &reduced_clock,
+				 &refclk, &num_connectors, &is_dp);
 	if (!ok) {
 		DRM_ERROR("Couldn't find PLL settings for mode!\n");
 		return -EINVAL;
@@ -4604,23 +4643,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 	/* Ensure that the cursor is valid for the new mode before changing... */
 	intel_crtc_update_cursor(crtc, true);
 
-	if (is_lvds && dev_priv->lvds_downclock_avail) {
-		/*
-		 * Ensure we match the reduced clock's P to the target clock.
-		 * If the clocks don't match, we can't switch the display clock
-		 * by using the FP0/FP1. In such case we will disable the LVDS
-		 * downclock feature.
-		*/
-		has_reduced_clock = limit->find_pll(limit, crtc,
-						    dev_priv->lvds_downclock,
-						    refclk,
-						    &clock,
-						    &reduced_clock);
-	}
-
-	if (is_sdvo && is_tv)
-		i9xx_adjust_sdvo_tv_clock(adjusted_mode, &clock);
-
 	if (IS_GEN2(dev))
 		i8xx_update_pll(crtc, adjusted_mode, &clock,
 				has_reduced_clock ? &reduced_clock : NULL,
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 21/81] drm/i915: Consitify adjusted_mode parameter
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (19 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 20/81] drm/i915: Factor out i9xx_compute_clocks() like ironlake_compute_clocks() ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 22/81] drm/i915: Add intel_check_clock() ville.syrjala
                   ` (61 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

i9xx_adjust_sdvo_tv_clock(), i9xx_compute_clocks() and
ironlake_compute_clocks() do not modify the adjusted_mode passed in, so
pass it as const.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 0fa9c2a..2a2c664 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4159,7 +4159,7 @@ static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors)
 	return refclk;
 }
 
-static void i9xx_adjust_sdvo_tv_clock(struct drm_display_mode *adjusted_mode,
+static void i9xx_adjust_sdvo_tv_clock(const struct drm_display_mode *adjusted_mode,
 				      intel_clock_t *clock)
 {
 	/* SDVO TV has fixed PLL values depend on its clock range,
@@ -4545,7 +4545,7 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc,
 }
 
 static bool i9xx_compute_clocks(struct drm_crtc *crtc,
-				struct drm_display_mode *adjusted_mode,
+				const struct drm_display_mode *adjusted_mode,
 				intel_clock_t *clock,
 				bool *has_reduced_clock,
 				intel_clock_t *reduced_clock,
@@ -5135,7 +5135,7 @@ static void haswell_set_pipeconf(struct drm_crtc *crtc,
 }
 
 static bool ironlake_compute_clocks(struct drm_crtc *crtc,
-				    struct drm_display_mode *adjusted_mode,
+				    const struct drm_display_mode *adjusted_mode,
 				    intel_clock_t *clock,
 				    bool *has_reduced_clock,
 				    intel_clock_t *reduced_clock)
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 22/81] drm/i915: Add intel_check_clock()
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (20 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 21/81] drm/i915: Consitify adjusted_mode parameter ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 23/81] drm/i915: store cursor_handle in struct intel_crtc ville.syrjala
                   ` (60 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

intel_check_clock() can be used to check clock validity w/o modifying
hardware state.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h      |    2 ++
 drivers/gpu/drm/i915/intel_display.c |   34 ++++++++++++++++++++++++++++++++++
 2 files changed, 36 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index ab0bd29..c41982e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1719,6 +1719,8 @@ extern bool intel_fbc_enabled(struct drm_device *dev);
 extern void intel_disable_fbc(struct drm_device *dev);
 extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
 extern void intel_init_pch_refclk(struct drm_device *dev);
+extern int intel_check_clock(struct drm_crtc *crtc,
+			     const struct drm_display_mode *adjusted_mode);
 extern void gen6_set_rps(struct drm_device *dev, u8 val);
 extern void intel_detect_pch(struct drm_device *dev);
 extern int intel_trans_dp_port_sel(struct drm_crtc *crtc);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 2a2c664..dcd61fb 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5686,6 +5686,40 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
 	return ret;
 }
 
+int intel_check_clock(struct drm_crtc *crtc,
+		      const struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = crtc->dev;
+	intel_clock_t clock, reduced_clock;
+	bool has_reduced_clock = false;
+	bool ok;
+
+	if (IS_HASWELL(dev)) {
+		if (!intel_ddi_pll_mode_set(crtc, adjusted_mode->clock))
+			return -EINVAL;
+
+		if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
+			ok = ironlake_compute_clocks(crtc, adjusted_mode, &clock,
+						     &has_reduced_clock,
+						     &reduced_clock);
+		} else
+			ok = true;
+	} else if (HAS_PCH_SPLIT(dev)) {
+		ok = ironlake_compute_clocks(crtc, adjusted_mode, &clock,
+					     &has_reduced_clock, &reduced_clock);
+	} else {
+		int num_connectors = 0;
+		bool is_dp = false;
+		int refclk;
+
+		ok = i9xx_compute_clocks(crtc, adjusted_mode, &clock,
+					 &has_reduced_clock, &reduced_clock,
+					 &refclk, &num_connectors, &is_dp);
+	}
+
+	return ok ? 0 : -EINVAL;
+}
+
 static int intel_crtc_mode_set(struct drm_crtc *crtc,
 			       struct drm_display_mode *mode,
 			       struct drm_display_mode *adjusted_mode,
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 23/81] drm/i915: store cursor_handle in struct intel_crtc
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (21 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 22/81] drm/i915: Add intel_check_clock() ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 24/81] drm/i915: split cursor setting code into prepare/commit/unref parts ville.syrjala
                   ` (59 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ander Conselvan de Oliveira <conselvan2@gmail.com>

This way it is possible to check if the cursor changed without doing
any setup. Will be useful for the atomic modesetting api.
---
 drivers/gpu/drm/i915/intel_display.c |    1 +
 drivers/gpu/drm/i915/intel_drv.h     |    2 +-
 2 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index dcd61fb..2a32cb0 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6260,6 +6260,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
 	mutex_unlock(&dev->struct_mutex);
 
 	intel_crtc->cursor_addr = addr;
+	intel_crtc->cursor_handle = handle;
 	intel_crtc->cursor_bo = obj;
 	intel_crtc->cursor_width = width;
 	intel_crtc->cursor_height = height;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 0d7c2fc..e77202c 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -220,7 +220,7 @@ struct intel_crtc {
 	unsigned long dspaddr_offset;
 
 	struct drm_i915_gem_object *cursor_bo;
-	uint32_t cursor_addr;
+	uint32_t cursor_addr, cursor_handle;
 	int16_t cursor_x, cursor_y;
 	int16_t cursor_width, cursor_height;
 	bool cursor_visible;
-- 
1.7.8.6

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 24/81] drm/i915: split cursor setting code into prepare/commit/unref parts
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (22 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 23/81] drm/i915: store cursor_handle in struct intel_crtc ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 25/81] drm/i915: unstatic cursor functions for use with atomic modesetting ville.syrjala
                   ` (58 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ander Conselvan de Oliveira <conselvan2@gmail.com>

The atomic mode setting API will need to pin the cursor bo without
making changes to the current setup. Only on a later stage the cursor
registers can be written and the previous bo released.

This patch splits intel_crtc_cursor_set() into three parts: prepare,
commit and unref. intel_crtc_cursor_prepare() will pin the cursor bo
and return a gem object and the address to be written to the cursor
registers. intel_crtc_cursor_commit() takes that object and address
and actually changes the cursor. intel_crtc_cursor_unref() is used to
release the previous cursor bo.
---
 drivers/gpu/drm/i915/intel_display.c |   90 +++++++++++++++++++++++++--------
 1 files changed, 68 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 2a32cb0..0f25a07 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6173,10 +6173,12 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
 	}
 }
 
-static int intel_crtc_cursor_set(struct drm_crtc *crtc,
+static int intel_crtc_cursor_prepare(struct drm_crtc *crtc,
 				 struct drm_file *file,
 				 uint32_t handle,
-				 uint32_t width, uint32_t height)
+				 uint32_t width, uint32_t height,
+				 struct drm_i915_gem_object **obj_ret,
+				 uint32_t *addr_ret)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -6188,10 +6190,9 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
 	/* if we want to turn off the cursor ignore width and height */
 	if (!handle) {
 		DRM_DEBUG_KMS("cursor off\n");
-		addr = 0;
-		obj = NULL;
-		mutex_lock(&dev->struct_mutex);
-		goto finish;
+		*addr_ret = 0;
+		*obj_ret = NULL;
+		return 0;
 	}
 
 	/* Currently we only support 64x64 cursors */
@@ -6247,17 +6248,46 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
 	if (IS_GEN2(dev))
 		I915_WRITE(CURSIZE, (height << 12) | width);
 
- finish:
-	if (intel_crtc->cursor_bo) {
-		if (dev_priv->info->cursor_needs_physical) {
-			if (intel_crtc->cursor_bo != obj)
-				i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo);
-		} else
-			i915_gem_object_unpin(intel_crtc->cursor_bo);
-		drm_gem_object_unreference(&intel_crtc->cursor_bo->base);
-	}
+	mutex_unlock(&dev->struct_mutex);
+
+	*obj_ret = obj;
+	*addr_ret = addr;
+
+	return 0;
+fail_unpin:
+	i915_gem_object_unpin(obj);
+fail_locked:
+	mutex_unlock(&dev->struct_mutex);
+fail:
+	drm_gem_object_unreference_unlocked(&obj->base);
+	return ret;
+}
+
+static void intel_crtc_cursor_bo_unref(struct drm_crtc *crtc,
+				       struct drm_i915_gem_object *obj)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+	mutex_lock(&dev->struct_mutex);
+
+	if (dev_priv->info->cursor_needs_physical) {
+		if (obj != intel_crtc->cursor_bo)
+			i915_gem_detach_phys_object(dev, obj);
+	} else
+		i915_gem_object_unpin(obj);
+	drm_gem_object_unreference(&obj->base);
 
 	mutex_unlock(&dev->struct_mutex);
+}
+
+static void intel_crtc_cursor_commit(struct drm_crtc *crtc, uint32_t handle,
+				     uint32_t width, uint32_t height,
+				     struct drm_i915_gem_object *obj,
+				     uint32_t addr)
+{
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
 	intel_crtc->cursor_addr = addr;
 	intel_crtc->cursor_handle = handle;
@@ -6266,15 +6296,31 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
 	intel_crtc->cursor_height = height;
 
 	intel_crtc_update_cursor(crtc, true);
+}
+
+static int intel_crtc_cursor_set(struct drm_crtc *crtc,
+				 struct drm_file *file,
+				 uint32_t handle,
+				 uint32_t width, uint32_t height)
+{
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int ret;
+	struct drm_i915_gem_object *obj, *old_obj;
+	uint32_t addr;
+
+	ret = intel_crtc_cursor_prepare(crtc, file, handle, width, height,
+					&obj, &addr);
+	if (ret)
+		return ret;
+
+	old_obj = intel_crtc->cursor_bo;
+
+	intel_crtc_cursor_commit(crtc, handle, width, height, obj, addr);
+
+	if (old_obj)
+		intel_crtc_cursor_bo_unref(crtc, old_obj);
 
 	return 0;
-fail_unpin:
-	i915_gem_object_unpin(obj);
-fail_locked:
-	mutex_unlock(&dev->struct_mutex);
-fail:
-	drm_gem_object_unreference_unlocked(&obj->base);
-	return ret;
 }
 
 static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
-- 
1.7.8.6

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 25/81] drm/i915: unstatic cursor functions for use with atomic modesetting
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (23 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 24/81] drm/i915: split cursor setting code into prepare/commit/unref parts ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 26/81] drm/i915: Unstatic intel_finish_fb() ville.syrjala
                   ` (57 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ander Conselvan de Oliveira <conselvan2@gmail.com>

---
 drivers/gpu/drm/i915/intel_display.c |   24 ++++++++++++------------
 drivers/gpu/drm/i915/intel_drv.h     |   13 +++++++++++++
 2 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 0f25a07..2f72881 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6173,12 +6173,12 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
 	}
 }
 
-static int intel_crtc_cursor_prepare(struct drm_crtc *crtc,
-				 struct drm_file *file,
-				 uint32_t handle,
-				 uint32_t width, uint32_t height,
-				 struct drm_i915_gem_object **obj_ret,
-				 uint32_t *addr_ret)
+int intel_crtc_cursor_prepare(struct drm_crtc *crtc,
+			      struct drm_file *file,
+			      uint32_t handle,
+			      uint32_t width, uint32_t height,
+			      struct drm_i915_gem_object **obj_ret,
+			      uint32_t *addr_ret)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -6263,8 +6263,8 @@ fail:
 	return ret;
 }
 
-static void intel_crtc_cursor_bo_unref(struct drm_crtc *crtc,
-				       struct drm_i915_gem_object *obj)
+void intel_crtc_cursor_bo_unref(struct drm_crtc *crtc,
+				struct drm_i915_gem_object *obj)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -6282,10 +6282,10 @@ static void intel_crtc_cursor_bo_unref(struct drm_crtc *crtc,
 	mutex_unlock(&dev->struct_mutex);
 }
 
-static void intel_crtc_cursor_commit(struct drm_crtc *crtc, uint32_t handle,
-				     uint32_t width, uint32_t height,
-				     struct drm_i915_gem_object *obj,
-				     uint32_t addr)
+void intel_crtc_cursor_commit(struct drm_crtc *crtc, uint32_t handle,
+			      uint32_t width, uint32_t height,
+			      struct drm_i915_gem_object *obj,
+			      uint32_t addr)
 {
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index e77202c..785fa04 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -679,4 +679,17 @@ extern bool
 intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector);
 extern void intel_ddi_fdi_disable(struct drm_crtc *crtc);
 
+extern int intel_crtc_cursor_prepare(struct drm_crtc *crtc,
+				     struct drm_file *file,
+				     uint32_t handle,
+				     uint32_t width, uint32_t height,
+				     struct drm_i915_gem_object **obj_ret,
+				     uint32_t *addr_ret);
+extern void intel_crtc_cursor_bo_unref(struct drm_crtc *crtc,
+				       struct drm_i915_gem_object *obj);
+extern void intel_crtc_cursor_commit(struct drm_crtc *crtc, uint32_t handle,
+				     uint32_t width, uint32_t height,
+				     struct drm_i915_gem_object *obj,
+				     uint32_t addr);
+
 #endif /* __INTEL_DRV_H__ */
-- 
1.7.8.6

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 26/81] drm/i915: Unstatic intel_finish_fb()
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (24 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 25/81] drm/i915: unstatic cursor functions for use with atomic modesetting ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 27/81] drm/i915: Pull intel_pipe_set_base() out of the crtc_mode_set() functions ville.syrjala
                   ` (56 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

intel_finish_fb() will be used by the atomic modeset code, so make it
non-static.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |    2 +-
 drivers/gpu/drm/i915/intel_drv.h     |    1 +
 2 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 2f72881..a184b70 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2182,7 +2182,7 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 	return dev_priv->display.update_plane(crtc, fb, x, y);
 }
 
-static int
+int
 intel_finish_fb(struct drm_framebuffer *old_fb)
 {
 	struct drm_i915_gem_object *obj = to_intel_framebuffer(old_fb)->obj;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 785fa04..59ca0c3 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -590,6 +590,7 @@ extern int intel_pin_and_fence_fb_obj(struct drm_device *dev,
 				      struct drm_i915_gem_object *obj,
 				      struct intel_ring_buffer *pipelined);
 extern void intel_unpin_fb_obj(struct drm_i915_gem_object *obj);
+extern int intel_finish_fb(struct drm_framebuffer *old_fb);
 
 extern int intel_framebuffer_init(struct drm_device *dev,
 				  struct intel_framebuffer *ifb,
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 27/81] drm/i915: Pull intel_pipe_set_base() out of the crtc_mode_set() functions
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (25 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 26/81] drm/i915: Unstatic intel_finish_fb() ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 28/81] drm/i915: Unstatic intel_crtc_update_sarea() ville.syrjala
                   ` (55 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

intel_pipe_set_base() (un)pins the buffers, so it can't be called from
the atomic modeset paths. Pull the intel_pipe_set_base() and watermark
modifications out of i9xx_crtc_mode_set() and ironlake_crtc_mode_set()
into intel_crtc_mode_set(), so that the former two can be used from the
atomic modeset paths.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |   35 ++++++++++++---------------------
 1 files changed, 13 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index a184b70..6522e1e 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4630,7 +4630,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 	u32 dspcntr, pipeconf;
 	bool ok, has_reduced_clock = false;
 	bool is_dp = false;
-	int ret;
 
 	ok = i9xx_compute_clocks(crtc, adjusted_mode, &clock,
 				 &has_reduced_clock, &reduced_clock,
@@ -4738,11 +4737,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 	I915_WRITE(DSPCNTR(plane), dspcntr);
 	POSTING_READ(DSPCNTR(plane));
 
-	ret = intel_pipe_set_base(crtc, x, y, fb);
-
-	intel_update_watermarks(dev);
-
-	return ret;
+	return 0;
 }
 
 static void ironlake_init_pch_refclk(struct drm_device *dev)
@@ -5479,7 +5474,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	bool ok, has_reduced_clock = false;
 	bool is_lvds = false, is_dp = false, is_cpu_edp = false;
 	struct intel_encoder *encoder;
-	int ret;
 	bool dither, fdi_config_ok;
 
 	for_each_encoder_on_crtc(dev, crtc, encoder) {
@@ -5590,13 +5584,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE);
 	POSTING_READ(DSPCNTR(plane));
 
-	ret = intel_pipe_set_base(crtc, x, y, fb);
-
-	intel_update_watermarks(dev);
-
-	intel_update_linetime_watermarks(dev, pipe, adjusted_mode);
-
-	return fdi_config_ok ? ret : -EINVAL;
+	return fdi_config_ok ? 0 : -EINVAL;
 }
 
 static int haswell_crtc_mode_set(struct drm_crtc *crtc,
@@ -5613,7 +5601,6 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
 	int num_connectors = 0;
 	bool is_dp = false, is_cpu_edp = false;
 	struct intel_encoder *encoder;
-	int ret;
 	bool dither;
 
 	for_each_encoder_on_crtc(dev, crtc, encoder) {
@@ -5677,13 +5664,7 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
 	I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE);
 	POSTING_READ(DSPCNTR(plane));
 
-	ret = intel_pipe_set_base(crtc, x, y, fb);
-
-	intel_update_watermarks(dev);
-
-	intel_update_linetime_watermarks(dev, pipe, adjusted_mode);
-
-	return ret;
+	return 0;
 }
 
 int intel_check_clock(struct drm_crtc *crtc,
@@ -5738,6 +5719,16 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 
 	ret = dev_priv->display.crtc_mode_set(crtc, mode, adjusted_mode,
 					      x, y, fb);
+
+	if (!ret) {
+		ret = intel_pipe_set_base(crtc, x, y, fb);
+
+		intel_update_watermarks(dev);
+
+		if (HAS_PCH_SPLIT(dev))
+			intel_update_linetime_watermarks(dev, pipe, adjusted_mode);
+	}
+
 	drm_vblank_post_modeset(dev, pipe);
 
 	if (ret != 0)
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 28/81] drm/i915: Unstatic intel_crtc_update_sarea()
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (26 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 27/81] drm/i915: Pull intel_pipe_set_base() out of the crtc_mode_set() functions ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 29/81] drm/i915: Unstatic intel_crtc_update_sarea_pos() ville.syrjala
                   ` (54 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Make intel_crtc_update_sarea() available for the atomic mode setting
code.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |    4 ++--
 drivers/gpu/drm/i915/intel_drv.h     |    2 ++
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 6522e1e..9918dcb 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3652,8 +3652,8 @@ static void i9xx_crtc_off(struct drm_crtc *crtc)
 {
 }
 
-static void intel_crtc_update_sarea(struct drm_crtc *crtc,
-				    bool enabled)
+void intel_crtc_update_sarea(struct drm_crtc *crtc,
+			     bool enabled)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_master_private *master_priv;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 59ca0c3..c1fee22 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -693,4 +693,6 @@ extern void intel_crtc_cursor_commit(struct drm_crtc *crtc, uint32_t handle,
 				     struct drm_i915_gem_object *obj,
 				     uint32_t addr);
 
+extern void intel_crtc_update_sarea(struct drm_crtc *crtc, bool enabled);
+
 #endif /* __INTEL_DRV_H__ */
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 29/81] drm/i915: Unstatic intel_crtc_update_sarea_pos()
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (27 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 28/81] drm/i915: Unstatic intel_crtc_update_sarea() ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 30/81] drm/i915: Constify mode argument to intel_modeset_adjusted_mode() ville.syrjala
                   ` (53 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Make intel_crtc_update_sarea_pos() available to the atomic mode setting code.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |    2 +-
 drivers/gpu/drm/i915/intel_drv.h     |    1 +
 2 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 9918dcb..f7190d2 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2209,7 +2209,7 @@ intel_finish_fb(struct drm_framebuffer *old_fb)
 	return ret;
 }
 
-static void intel_crtc_update_sarea_pos(struct drm_crtc *crtc, int x, int y)
+void intel_crtc_update_sarea_pos(struct drm_crtc *crtc, int x, int y)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_master_private *master_priv;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index c1fee22..a7d8df8 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -694,5 +694,6 @@ extern void intel_crtc_cursor_commit(struct drm_crtc *crtc, uint32_t handle,
 				     uint32_t addr);
 
 extern void intel_crtc_update_sarea(struct drm_crtc *crtc, bool enabled);
+extern void intel_crtc_update_sarea_pos(struct drm_crtc *crtc, int x, int y);
 
 #endif /* __INTEL_DRV_H__ */
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 30/81] drm/i915: Constify mode argument to intel_modeset_adjusted_mode()
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (28 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 29/81] drm/i915: Unstatic intel_crtc_update_sarea_pos() ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 31/81] drm/i915: Unstatic intel_crtc_mode_fixup() ville.syrjala
                   ` (52 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

intel_modeset_adjusted_mode() doesn't modify the passed display mode. So
pass it as const.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f7190d2..dac80c4 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -7401,7 +7401,7 @@ static void intel_modeset_commit_output_state(struct drm_device *dev)
 
 static struct drm_display_mode *
 intel_modeset_adjusted_mode(struct drm_crtc *crtc,
-			    struct drm_display_mode *mode)
+			    const struct drm_display_mode *mode)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_display_mode *adjusted_mode;
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 31/81] drm/i915: Unstatic intel_crtc_mode_fixup()
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (29 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 30/81] drm/i915: Constify mode argument to intel_modeset_adjusted_mode() ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:15 ` [PATCH 32/81] drm/i915: Introduce intel_plane_regs ville.syrjala
                   ` (51 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Make intel_crtc_mode_fixup() available for the upcoming atomic
modesetting code.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |    6 +++---
 drivers/gpu/drm/i915/intel_drv.h     |    4 ++++
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index dac80c4..2c2fcda 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3851,9 +3851,9 @@ bool intel_connector_get_hw_state(struct intel_connector *connector)
 	return encoder->get_hw_state(encoder, &pipe);
 }
 
-static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
-				  const struct drm_display_mode *mode,
-				  struct drm_display_mode *adjusted_mode)
+bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
+			   const struct drm_display_mode *mode,
+			   struct drm_display_mode *adjusted_mode)
 {
 	struct drm_device *dev = crtc->dev;
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index a7d8df8..ee6c85f 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -696,4 +696,8 @@ extern void intel_crtc_cursor_commit(struct drm_crtc *crtc, uint32_t handle,
 extern void intel_crtc_update_sarea(struct drm_crtc *crtc, bool enabled);
 extern void intel_crtc_update_sarea_pos(struct drm_crtc *crtc, int x, int y);
 
+extern bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
+				  const struct drm_display_mode *mode,
+				  struct drm_display_mode *adjusted_mode);
+
 #endif /* __INTEL_DRV_H__ */
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 32/81] drm/i915: Introduce intel_plane_regs
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (30 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 31/81] drm/i915: Unstatic intel_crtc_mode_fixup() ville.syrjala
@ 2012-12-12 16:15 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 33/81] drm/i915: Split primary plane update_plane() into calc+commit phases ville.syrjala
                   ` (50 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:15 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

intel_plane_regs can be used to shadow all the typical plane registers.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_drv.h |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index ee6c85f..b11510a 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -194,6 +194,20 @@ struct intel_connector {
 	struct edid *edid;
 };
 
+struct intel_plane_regs {
+	u32 cntr;
+	u32 linoff;
+	u32 stride;
+	u32 pos;
+	u32 size;
+	u32 keyval;
+	u32 keymsk;
+	u32 surf;
+	u32 keymaxval;
+	u32 tileoff;
+	u32 scale;
+};
+
 struct intel_crtc {
 	struct drm_crtc base;
 	enum pipe pipe;
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 33/81] drm/i915: Split primary plane update_plane() into calc+commit phases
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (31 preceding siblings ...)
  2012-12-12 16:15 ` [PATCH 32/81] drm/i915: Introduce intel_plane_regs ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 34/81] drm/i915: Split sprite " ville.syrjala
                   ` (49 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Separate the part that calculates the register values from the part that
writes the registers. This will be useful in the atomic page flip code.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h      |    3 +
 drivers/gpu/drm/i915/intel_display.c |  154 ++++++++++++++++++++++------------
 drivers/gpu/drm/i915/intel_drv.h     |    1 +
 3 files changed, 105 insertions(+), 53 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index c41982e..66b3b64 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -297,6 +297,9 @@ struct drm_i915_display_funcs {
 			  struct drm_i915_gem_object *obj);
 	int (*update_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 			    int x, int y);
+	int (*calc_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb,
+			  int x, int y);
+	void (*commit_plane)(struct drm_crtc *crtc);
 	/* clock updates for mode set */
 	/* cursor updates */
 	/* render clock increase/decrease */
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 2c2fcda..c0db749 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1979,8 +1979,30 @@ unsigned long intel_gen4_compute_offset_xtiled(int *x, int *y,
 	return tile_rows * pitch * 8 + tiles * 4096;
 }
 
-static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
-			     int x, int y)
+static void intel_commit_plane(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int plane = intel_crtc->plane;
+	const struct intel_plane_regs *regs = &intel_crtc->primary_regs;
+
+	I915_WRITE(DSPCNTR(plane), regs->cntr);
+	I915_WRITE(DSPSTRIDE(plane), regs->stride);
+
+	if (IS_HASWELL(dev)) {
+		I915_WRITE(DSPOFFSET(plane), regs->tileoff);
+		I915_WRITE(DSPSURF(plane), regs->surf);
+	} else if (INTEL_INFO(dev)->gen >= 4) {
+		I915_WRITE(DSPTILEOFF(plane), regs->tileoff);
+		I915_WRITE(DSPLINOFF(plane), regs->linoff);
+		I915_WRITE(DSPSURF(plane), regs->surf);
+	} else
+		I915_WRITE(DSPADDR(plane), regs->linoff);
+}
+
+static int i9xx_calc_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
+			   int x, int y)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1989,9 +2011,8 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 	struct drm_i915_gem_object *obj;
 	int plane = intel_crtc->plane;
 	unsigned long linear_offset;
-	u32 dspcntr;
-	u32 reg;
 	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
+	struct intel_plane_regs *regs = &intel_crtc->primary_regs;
 
 	switch (plane) {
 	case 0:
@@ -2005,36 +2026,35 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 	intel_fb = to_intel_framebuffer(fb);
 	obj = intel_fb->obj;
 
-	reg = DSPCNTR(plane);
-	dspcntr = I915_READ(reg);
+	regs->cntr = I915_READ(DSPCNTR(plane));
 	/* Mask out pixel format bits in case we change it */
-	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
+	regs->cntr &= ~DISPPLANE_PIXFORMAT_MASK;
 	switch (fb->pixel_format) {
 	case DRM_FORMAT_C8:
-		dspcntr |= DISPPLANE_8BPP;
+		regs->cntr |= DISPPLANE_8BPP;
 		break;
 	case DRM_FORMAT_XRGB1555:
 	case DRM_FORMAT_ARGB1555:
-		dspcntr |= DISPPLANE_BGRX555;
+		regs->cntr |= DISPPLANE_BGRX555;
 		break;
 	case DRM_FORMAT_RGB565:
-		dspcntr |= DISPPLANE_BGRX565;
+		regs->cntr |= DISPPLANE_BGRX565;
 		break;
 	case DRM_FORMAT_XRGB8888:
 	case DRM_FORMAT_ARGB8888:
-		dspcntr |= DISPPLANE_BGRX888;
+		regs->cntr |= DISPPLANE_BGRX888;
 		break;
 	case DRM_FORMAT_XBGR8888:
 	case DRM_FORMAT_ABGR8888:
-		dspcntr |= DISPPLANE_RGBX888;
+		regs->cntr |= DISPPLANE_RGBX888;
 		break;
 	case DRM_FORMAT_XRGB2101010:
 	case DRM_FORMAT_ARGB2101010:
-		dspcntr |= DISPPLANE_BGRX101010;
+		regs->cntr |= DISPPLANE_BGRX101010;
 		break;
 	case DRM_FORMAT_XBGR2101010:
 	case DRM_FORMAT_ABGR2101010:
-		dspcntr |= DISPPLANE_RGBX101010;
+		regs->cntr |= DISPPLANE_RGBX101010;
 		break;
 	default:
 		DRM_ERROR("Unknown pixel format 0x%08x\n", fb->pixel_format);
@@ -2043,13 +2063,11 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 
 	if (INTEL_INFO(dev)->gen >= 4) {
 		if (obj->tiling_mode != I915_TILING_NONE)
-			dspcntr |= DISPPLANE_TILED;
+			regs->cntr |= DISPPLANE_TILED;
 		else
-			dspcntr &= ~DISPPLANE_TILED;
+			regs->cntr &= ~DISPPLANE_TILED;
 	}
 
-	I915_WRITE(reg, dspcntr);
-
 	linear_offset = y * fb->pitches[0] + x * cpp;
 
 	if (INTEL_INFO(dev)->gen >= 4) {
@@ -2063,21 +2081,37 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 
 	DRM_DEBUG_KMS("Writing base %08X %08lX %d %d %d\n",
 		      obj->gtt_offset, linear_offset, x, y, fb->pitches[0]);
-	I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
+	regs->stride = fb->pitches[0];
 	if (INTEL_INFO(dev)->gen >= 4) {
-		I915_MODIFY_DISPBASE(DSPSURF(plane),
-				     obj->gtt_offset + intel_crtc->dspaddr_offset);
-		I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
-		I915_WRITE(DSPLINOFF(plane), linear_offset);
+		regs->surf = I915_LO_DISPBASE(I915_READ(DSPSURF(plane))) |
+			(obj->gtt_offset + intel_crtc->dspaddr_offset);
+		regs->tileoff = (y << 16) | x;
+		regs->linoff = linear_offset;
 	} else
-		I915_WRITE(DSPADDR(plane), obj->gtt_offset + linear_offset);
-	POSTING_READ(reg);
+		regs->linoff = obj->gtt_offset + linear_offset;
 
 	return 0;
 }
 
-static int ironlake_update_plane(struct drm_crtc *crtc,
-				 struct drm_framebuffer *fb, int x, int y)
+static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
+			     int x, int y)
+{
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	int ret;
+
+	ret = i9xx_calc_plane(crtc, fb, x, y);
+	if (ret)
+		return ret;
+
+	intel_commit_plane(crtc);
+
+	POSTING_READ(DSPCNTR(to_intel_crtc(crtc)->plane));
+
+	return 0;
+}
+
+static int ironlake_calc_plane(struct drm_crtc *crtc,
+			       struct drm_framebuffer *fb, int x, int y)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -2086,9 +2120,8 @@ static int ironlake_update_plane(struct drm_crtc *crtc,
 	struct drm_i915_gem_object *obj;
 	int plane = intel_crtc->plane;
 	unsigned long linear_offset;
-	u32 dspcntr;
-	u32 reg;
 	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
+	struct intel_plane_regs *regs = &intel_crtc->primary_regs;
 
 	switch (plane) {
 	case 0:
@@ -2103,32 +2136,31 @@ static int ironlake_update_plane(struct drm_crtc *crtc,
 	intel_fb = to_intel_framebuffer(fb);
 	obj = intel_fb->obj;
 
-	reg = DSPCNTR(plane);
-	dspcntr = I915_READ(reg);
+	regs->cntr = I915_READ(DSPCNTR(plane));
 	/* Mask out pixel format bits in case we change it */
-	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
+	regs->cntr &= ~DISPPLANE_PIXFORMAT_MASK;
 	switch (fb->pixel_format) {
 	case DRM_FORMAT_C8:
-		dspcntr |= DISPPLANE_8BPP;
+		regs->cntr |= DISPPLANE_8BPP;
 		break;
 	case DRM_FORMAT_RGB565:
-		dspcntr |= DISPPLANE_BGRX565;
+		regs->cntr |= DISPPLANE_BGRX565;
 		break;
 	case DRM_FORMAT_XRGB8888:
 	case DRM_FORMAT_ARGB8888:
-		dspcntr |= DISPPLANE_BGRX888;
+		regs->cntr |= DISPPLANE_BGRX888;
 		break;
 	case DRM_FORMAT_XBGR8888:
 	case DRM_FORMAT_ABGR8888:
-		dspcntr |= DISPPLANE_RGBX888;
+		regs->cntr |= DISPPLANE_RGBX888;
 		break;
 	case DRM_FORMAT_XRGB2101010:
 	case DRM_FORMAT_ARGB2101010:
-		dspcntr |= DISPPLANE_BGRX101010;
+		regs->cntr |= DISPPLANE_BGRX101010;
 		break;
 	case DRM_FORMAT_XBGR2101010:
 	case DRM_FORMAT_ABGR2101010:
-		dspcntr |= DISPPLANE_RGBX101010;
+		regs->cntr |= DISPPLANE_RGBX101010;
 		break;
 	default:
 		DRM_ERROR("Unknown pixel format 0x%08x\n", fb->pixel_format);
@@ -2136,14 +2168,12 @@ static int ironlake_update_plane(struct drm_crtc *crtc,
 	}
 
 	if (obj->tiling_mode != I915_TILING_NONE)
-		dspcntr |= DISPPLANE_TILED;
+		regs->cntr |= DISPPLANE_TILED;
 	else
-		dspcntr &= ~DISPPLANE_TILED;
+		regs->cntr &= ~DISPPLANE_TILED;
 
 	/* must disable */
-	dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
-
-	I915_WRITE(reg, dspcntr);
+	regs->cntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
 
 	linear_offset = y * fb->pitches[0] + x * cpp;
 	intel_crtc->dspaddr_offset =
@@ -2153,16 +2183,28 @@ static int ironlake_update_plane(struct drm_crtc *crtc,
 
 	DRM_DEBUG_KMS("Writing base %08X %08lX %d %d %d\n",
 		      obj->gtt_offset, linear_offset, x, y, fb->pitches[0]);
-	I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
-	I915_MODIFY_DISPBASE(DSPSURF(plane),
-			     obj->gtt_offset + intel_crtc->dspaddr_offset);
-	if (IS_HASWELL(dev)) {
-		I915_WRITE(DSPOFFSET(plane), (y << 16) | x);
-	} else {
-		I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
-		I915_WRITE(DSPLINOFF(plane), linear_offset);
-	}
-	POSTING_READ(reg);
+	regs->stride = fb->pitches[0];
+	regs->surf = I915_LO_DISPBASE(I915_READ(DSPSURF(plane))) |
+		(obj->gtt_offset + intel_crtc->dspaddr_offset);
+	regs->tileoff = (y << 16) | x;
+	regs->linoff = linear_offset;
+
+	return 0;
+}
+
+static int ironlake_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
+				 int x, int y)
+{
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	int ret;
+
+	ret = ironlake_calc_plane(crtc, fb, x, y);
+	if (ret)
+		return ret;
+
+	intel_commit_plane(crtc);
+
+	POSTING_READ(DSPCNTR(to_intel_crtc(crtc)->plane));
 
 	return 0;
 }
@@ -8498,18 +8540,24 @@ static void intel_init_display(struct drm_device *dev)
 		dev_priv->display.crtc_disable = haswell_crtc_disable;
 		dev_priv->display.off = haswell_crtc_off;
 		dev_priv->display.update_plane = ironlake_update_plane;
+		dev_priv->display.calc_plane = ironlake_calc_plane;
+		dev_priv->display.commit_plane = intel_commit_plane;
 	} else if (HAS_PCH_SPLIT(dev)) {
 		dev_priv->display.crtc_mode_set = ironlake_crtc_mode_set;
 		dev_priv->display.crtc_enable = ironlake_crtc_enable;
 		dev_priv->display.crtc_disable = ironlake_crtc_disable;
 		dev_priv->display.off = ironlake_crtc_off;
 		dev_priv->display.update_plane = ironlake_update_plane;
+		dev_priv->display.calc_plane = ironlake_calc_plane;
+		dev_priv->display.commit_plane = intel_commit_plane;
 	} else {
 		dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set;
 		dev_priv->display.crtc_enable = i9xx_crtc_enable;
 		dev_priv->display.crtc_disable = i9xx_crtc_disable;
 		dev_priv->display.off = i9xx_crtc_off;
 		dev_priv->display.update_plane = i9xx_update_plane;
+		dev_priv->display.calc_plane = i9xx_calc_plane;
+		dev_priv->display.commit_plane = intel_commit_plane;
 	}
 
 	/* Returns the core display clock speed */
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index b11510a..4798f54 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -243,6 +243,7 @@ struct intel_crtc {
 	/* We can share PLLs across outputs if the timings match */
 	struct intel_pch_pll *pch_pll;
 	uint32_t ddi_pll_sel;
+	struct intel_plane_regs primary_regs;
 };
 
 struct intel_plane_coords {
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 34/81] drm/i915: Split sprite update_plane() into calc+commit phases
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (32 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 33/81] drm/i915: Split primary plane update_plane() into calc+commit phases ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 35/81] drm/i915: Implement atomic modesetting ville.syrjala
                   ` (48 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Separate the part that calculates the register values from the part that
writes the registers. This will be useful in the atomic page flip code.
Also move the watermark magic into a prepare function that can be
performed outside the critical parts of the atomic page flip code.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_drv.h    |    5 +
 drivers/gpu/drm/i915/intel_sprite.c |  416 ++++++++++++++++++++++-------------
 2 files changed, 273 insertions(+), 148 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 4798f54..05afdd1 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -270,6 +270,11 @@ struct intel_plane {
 			       struct drm_intel_sprite_colorkey *key);
 	void (*get_colorkey)(struct drm_plane *plane,
 			     struct drm_intel_sprite_colorkey *key);
+	void (*calc)(struct drm_plane *plane, struct drm_framebuffer *fb,
+		     const struct intel_plane_coords *clip);
+	void (*prepare)(struct drm_plane *plane);
+	void (*commit)(struct drm_plane *plane);
+	struct intel_plane_regs regs;
 };
 
 struct intel_watermark_params {
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index d64cefd..88644df 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -203,14 +203,13 @@ int intel_check_plane(const struct drm_plane *plane,
 }
 
 static void
-ivb_update_plane(struct drm_plane *plane,
-		 struct drm_framebuffer *fb,
-		 const struct intel_plane_coords *coords)
+ivb_calc_plane(struct drm_plane *plane,
+	       struct drm_framebuffer *fb,
+	       const struct intel_plane_coords *coords)
 {
 	struct drm_device *dev = plane->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_plane *intel_plane = to_intel_plane(plane);
-	const struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj;
+	const struct drm_i915_gem_object *obj;
 	int crtc_x = coords->crtc_x;
 	int crtc_y = coords->crtc_y;
 	unsigned int crtc_w = coords->crtc_w;
@@ -219,48 +218,56 @@ ivb_update_plane(struct drm_plane *plane,
 	uint32_t y = coords->src_y;
 	uint32_t src_w = coords->src_w;
 	uint32_t src_h = coords->src_h;
-	int pipe = intel_plane->pipe;
-	u32 sprctl, sprscale = 0;
 	unsigned long sprsurf_offset, linear_offset;
-	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
+	int pixel_size;
+	struct intel_plane_regs *regs = &intel_plane->regs;
 
-	sprctl = I915_READ(SPRCTL(pipe));
+	if (!coords->visible) {
+		regs->cntr &= ~SPRITE_ENABLE;
+		/* Disable the scaler */
+		regs->scale = 0;
+		return;
+	}
+
+	obj = to_intel_framebuffer(fb)->obj;
+	pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 
 	/* Mask out pixel format bits in case we change it */
-	sprctl &= ~SPRITE_PIXFORMAT_MASK;
-	sprctl &= ~SPRITE_RGB_ORDER_RGBX;
-	sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK;
-	sprctl &= ~SPRITE_TILED;
+	regs->cntr &= ~(SPRITE_PIXFORMAT_MASK |
+			SPRITE_RGB_ORDER_RGBX |
+			SPRITE_YUV_BYTE_ORDER_MASK |
+			SPRITE_TILED |
+			SPRITE_ENABLE);
 
 	switch (fb->pixel_format) {
 	case DRM_FORMAT_XBGR8888:
-		sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
+		regs->cntr |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
 		break;
 	case DRM_FORMAT_XRGB8888:
-		sprctl |= SPRITE_FORMAT_RGBX888;
+		regs->cntr |= SPRITE_FORMAT_RGBX888;
 		break;
 	case DRM_FORMAT_YUYV:
-		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
+		regs->cntr |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
 		break;
 	case DRM_FORMAT_YVYU:
-		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
+		regs->cntr |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
 		break;
 	case DRM_FORMAT_UYVY:
-		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
+		regs->cntr |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
 		break;
 	case DRM_FORMAT_VYUY:
-		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
+		regs->cntr |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
 		break;
 	default:
 		BUG();
 	}
 
 	if (obj->tiling_mode != I915_TILING_NONE)
-		sprctl |= SPRITE_TILED;
+		regs->cntr |= SPRITE_TILED;
 
 	/* must disable */
-	sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
-	sprctl |= SPRITE_ENABLE;
+	regs->cntr |= SPRITE_TRICKLE_FEED_DISABLE;
+	regs->cntr |= SPRITE_ENABLE;
 
 	/* Sizes are 0 based */
 	src_w--;
@@ -268,20 +275,80 @@ ivb_update_plane(struct drm_plane *plane,
 	crtc_w--;
 	crtc_h--;
 
-	intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size);
+	regs->scale = 0;
+	if (crtc_w != src_w || crtc_h != src_h)
+		regs->scale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
+
+	regs->stride = fb->pitches[0];
+	regs->pos = (crtc_y << 16) | crtc_x;
+
+	linear_offset = y * fb->pitches[0] + x * pixel_size;
+	sprsurf_offset =
+		intel_gen4_compute_offset_xtiled(&x, &y,
+						 pixel_size, fb->pitches[0]);
+	linear_offset -= sprsurf_offset;
+
+	/* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
+	 * register */
+	if (IS_HASWELL(dev) || obj->tiling_mode != I915_TILING_NONE)
+		regs->tileoff = (y << 16) | x;
+	else
+		regs->linoff = linear_offset;
+
+	regs->size = (crtc_h << 16) | crtc_w;
+	regs->surf = I915_LO_DISPBASE(regs->surf) | (obj->gtt_offset + sprsurf_offset);
+}
+
+static void
+ivb_commit_plane(struct drm_plane *plane)
+{
+	struct drm_device *dev = plane->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	int pipe = intel_plane->pipe;
+	const struct intel_plane_regs *regs = &intel_plane->regs;
+
+	I915_WRITE(SPRKEYVAL(pipe), regs->keyval);
+	I915_WRITE(SPRKEYMAX(pipe), regs->keymaxval);
+	I915_WRITE(SPRKEYMSK(pipe), regs->keymsk);
+	I915_WRITE(SPRSTRIDE(pipe), regs->stride);
+	I915_WRITE(SPRPOS(pipe), regs->pos);
+	if (IS_HASWELL(dev)) {
+		I915_WRITE(SPROFFSET(pipe), regs->tileoff);
+	} else {
+		I915_WRITE(SPRTILEOFF(pipe), regs->tileoff);
+		I915_WRITE(SPRLINOFF(pipe), regs->linoff);
+	}
+	I915_WRITE(SPRSIZE(pipe), regs->size);
+	if (intel_plane->can_scale)
+		I915_WRITE(SPRSCALE(pipe), regs->scale);
+	I915_WRITE(SPRCTL(pipe), regs->cntr);
+	I915_WRITE(SPRSURF(pipe), regs->surf);
+}
+
+static void
+ivb_prepare_plane(struct drm_plane *plane)
+{
+	struct drm_device *dev = plane->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	int pipe = intel_plane->pipe;
+	int pixel_size = plane->fb ? drm_format_plane_cpp(plane->fb->pixel_format, 0) : 0;
+	const struct intel_plane_regs *regs = &intel_plane->regs;
+
+	intel_update_sprite_watermarks(dev, pipe, regs->size & 0xffff, pixel_size);
 
 	/*
 	 * IVB workaround: must disable low power watermarks for at least
 	 * one frame before enabling scaling.  LP watermarks can be re-enabled
 	 * when scaling is disabled.
 	 */
-	if (crtc_w != src_w || crtc_h != src_h) {
+	if (regs->scale & SPRITE_SCALE_ENABLE) {
 		if (!dev_priv->sprite_scaling_enabled) {
 			dev_priv->sprite_scaling_enabled = true;
 			intel_update_watermarks(dev);
 			intel_wait_for_vblank(dev, pipe);
 		}
-		sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
 	} else {
 		if (dev_priv->sprite_scaling_enabled) {
 			dev_priv->sprite_scaling_enabled = false;
@@ -289,30 +356,21 @@ ivb_update_plane(struct drm_plane *plane,
 			intel_update_watermarks(dev);
 		}
 	}
-
-	I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
-	I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
-
-	linear_offset = y * fb->pitches[0] + x * pixel_size;
-	sprsurf_offset =
-		intel_gen4_compute_offset_xtiled(&x, &y,
-						 pixel_size, fb->pitches[0]);
-	linear_offset -= sprsurf_offset;
-
-	/* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
-	 * register */
-	if (IS_HASWELL(dev))
-		I915_WRITE(SPROFFSET(pipe), (y << 16) | x);
-	else if (obj->tiling_mode != I915_TILING_NONE)
-		I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
-	else
-		I915_WRITE(SPRLINOFF(pipe), linear_offset);
-
-	I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
-	if (intel_plane->can_scale)
-		I915_WRITE(SPRSCALE(pipe), sprscale);
-	I915_WRITE(SPRCTL(pipe), sprctl);
-	I915_MODIFY_DISPBASE(SPRSURF(pipe), obj->gtt_offset + sprsurf_offset);
+}
+
+static void
+ivb_update_plane(struct drm_plane *plane,
+		 struct drm_framebuffer *fb,
+		 const struct intel_plane_coords *coords)
+{
+	struct drm_device *dev = plane->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	int pipe = intel_plane->pipe;
+
+	ivb_calc_plane(plane, fb, coords);
+	ivb_prepare_plane(plane);
+	ivb_commit_plane(plane);
 	POSTING_READ(SPRSURF(pipe));
 }
 
@@ -323,13 +381,12 @@ ivb_disable_plane(struct drm_plane *plane)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_plane *intel_plane = to_intel_plane(plane);
 	int pipe = intel_plane->pipe;
+	struct intel_plane_regs *regs = &intel_plane->regs;
 
-	I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE);
+	regs->cntr &= ~SPRITE_ENABLE;
 	/* Can't leave the scaler enabled... */
-	if (intel_plane->can_scale)
-		I915_WRITE(SPRSCALE(pipe), 0);
-	/* Activate double buffered register update */
-	I915_MODIFY_DISPBASE(SPRSURF(pipe), 0);
+	regs->scale = 0;
+	ivb_commit_plane(plane);
 	POSTING_READ(SPRSURF(pipe));
 
 	dev_priv->sprite_scaling_enabled = false;
@@ -342,63 +399,52 @@ ivb_update_colorkey(struct drm_plane *plane,
 {
 	struct drm_device *dev = plane->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_plane *intel_plane;
-	u32 sprctl;
-	int ret = 0;
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	struct intel_plane_regs *regs = &intel_plane->regs;
 
-	intel_plane = to_intel_plane(plane);
+	regs->keyval = key->min_value;
+	regs->keymaxval = key->max_value;
+	regs->keymsk = key->channel_mask;
 
-	I915_WRITE(SPRKEYVAL(intel_plane->pipe), key->min_value);
-	I915_WRITE(SPRKEYMAX(intel_plane->pipe), key->max_value);
-	I915_WRITE(SPRKEYMSK(intel_plane->pipe), key->channel_mask);
-
-	sprctl = I915_READ(SPRCTL(intel_plane->pipe));
-	sprctl &= ~(SPRITE_SOURCE_KEY | SPRITE_DEST_KEY);
+	regs->cntr &= ~(SPRITE_SOURCE_KEY | SPRITE_DEST_KEY);
 	if (key->flags & I915_SET_COLORKEY_DESTINATION)
-		sprctl |= SPRITE_DEST_KEY;
+		regs->cntr |= SPRITE_DEST_KEY;
 	else if (key->flags & I915_SET_COLORKEY_SOURCE)
-		sprctl |= SPRITE_SOURCE_KEY;
-	I915_WRITE(SPRCTL(intel_plane->pipe), sprctl);
+		regs->cntr |= SPRITE_SOURCE_KEY;
 
+	ivb_commit_plane(plane);
 	POSTING_READ(SPRKEYMSK(intel_plane->pipe));
 
-	return ret;
+	return 0;
 }
 
 static void
 ivb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
 {
-	struct drm_device *dev = plane->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_plane *intel_plane;
-	u32 sprctl;
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	const struct intel_plane_regs *regs = &intel_plane->regs;
 
-	intel_plane = to_intel_plane(plane);
-
-	key->min_value = I915_READ(SPRKEYVAL(intel_plane->pipe));
-	key->max_value = I915_READ(SPRKEYMAX(intel_plane->pipe));
-	key->channel_mask = I915_READ(SPRKEYMSK(intel_plane->pipe));
+	key->min_value = regs->keyval;
+	key->max_value = regs->keymaxval;
+	key->channel_mask = regs->keymsk;
 	key->flags = 0;
 
-	sprctl = I915_READ(SPRCTL(intel_plane->pipe));
-
-	if (sprctl & SPRITE_DEST_KEY)
+	if (regs->cntr & SPRITE_DEST_KEY)
 		key->flags = I915_SET_COLORKEY_DESTINATION;
-	else if (sprctl & SPRITE_SOURCE_KEY)
+	else if (regs->cntr & SPRITE_SOURCE_KEY)
 		key->flags = I915_SET_COLORKEY_SOURCE;
 	else
 		key->flags = I915_SET_COLORKEY_NONE;
 }
 
 static void
-ilk_update_plane(struct drm_plane *plane,
-		 struct drm_framebuffer *fb,
-		 const struct intel_plane_coords *coords)
+ilk_calc_plane(struct drm_plane *plane,
+	       struct drm_framebuffer *fb,
+	       const struct intel_plane_coords *coords)
 {
 	struct drm_device *dev = plane->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_plane *intel_plane = to_intel_plane(plane);
-	const struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj;
+	const struct drm_i915_gem_object *obj;
 	int crtc_x = coords->crtc_x;
 	int crtc_y = coords->crtc_y;
 	unsigned int crtc_w = coords->crtc_w;
@@ -407,48 +453,56 @@ ilk_update_plane(struct drm_plane *plane,
 	uint32_t y = coords->src_y;
 	uint32_t src_w = coords->src_w;
 	uint32_t src_h = coords->src_h;
-	int pipe = intel_plane->pipe;
 	unsigned long dvssurf_offset, linear_offset;
-	u32 dvscntr, dvsscale;
-	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
+	int pixel_size;
+	struct intel_plane_regs *regs = &intel_plane->regs;
 
-	dvscntr = I915_READ(DVSCNTR(pipe));
+	if (!coords->visible) {
+		regs->cntr &= ~DVS_ENABLE;
+		/* Disable the scaler */
+		regs->scale = 0;
+		return;
+	}
+
+	obj = to_intel_framebuffer(fb)->obj;
+	pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 
 	/* Mask out pixel format bits in case we change it */
-	dvscntr &= ~DVS_PIXFORMAT_MASK;
-	dvscntr &= ~DVS_RGB_ORDER_XBGR;
-	dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK;
-	dvscntr &= ~DVS_TILED;
+	regs->cntr &= ~(DVS_PIXFORMAT_MASK |
+			DVS_RGB_ORDER_XBGR |
+			DVS_YUV_BYTE_ORDER_MASK |
+			DVS_TILED |
+			DVS_ENABLE);
 
 	switch (fb->pixel_format) {
 	case DRM_FORMAT_XBGR8888:
-		dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
+		regs->cntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
 		break;
 	case DRM_FORMAT_XRGB8888:
-		dvscntr |= DVS_FORMAT_RGBX888;
+		regs->cntr |= DVS_FORMAT_RGBX888;
 		break;
 	case DRM_FORMAT_YUYV:
-		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
+		regs->cntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
 		break;
 	case DRM_FORMAT_YVYU:
-		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
+		regs->cntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
 		break;
 	case DRM_FORMAT_UYVY:
-		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
+		regs->cntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
 		break;
 	case DRM_FORMAT_VYUY:
-		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
+		regs->cntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
 		break;
 	default:
 		BUG();
 	}
 
 	if (obj->tiling_mode != I915_TILING_NONE)
-		dvscntr |= DVS_TILED;
+		regs->cntr |= DVS_TILED;
 
 	if (IS_GEN6(dev))
-		dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
-	dvscntr |= DVS_ENABLE;
+		regs->cntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
+	regs->cntr |= DVS_ENABLE;
 
 	/* Sizes are 0 based */
 	src_w--;
@@ -456,14 +510,12 @@ ilk_update_plane(struct drm_plane *plane,
 	crtc_w--;
 	crtc_h--;
 
-	intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size);
-
-	dvsscale = 0;
+	regs->scale = 0;
 	if (IS_GEN5(dev) || crtc_w != src_w || crtc_h != src_h)
-		dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
+		regs->scale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
 
-	I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
-	I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
+	regs->stride = fb->pitches[0];
+	regs->pos = (crtc_y << 16) | crtc_x;
 
 	linear_offset = y * fb->pitches[0] + x * pixel_size;
 	dvssurf_offset =
@@ -472,14 +524,61 @@ ilk_update_plane(struct drm_plane *plane,
 	linear_offset -= dvssurf_offset;
 
 	if (obj->tiling_mode != I915_TILING_NONE)
-		I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
+		regs->tileoff = (y << 16) | x;
 	else
-		I915_WRITE(DVSLINOFF(pipe), linear_offset);
+		regs->linoff = linear_offset;
 
-	I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
-	I915_WRITE(DVSSCALE(pipe), dvsscale);
-	I915_WRITE(DVSCNTR(pipe), dvscntr);
-	I915_MODIFY_DISPBASE(DVSSURF(pipe), obj->gtt_offset + dvssurf_offset);
+	regs->size = (crtc_h << 16) | crtc_w;
+	regs->surf = I915_LO_DISPBASE(regs->surf) | (obj->gtt_offset + dvssurf_offset);
+}
+
+static void
+ilk_prepare_plane(struct drm_plane *plane)
+{
+	struct drm_device *dev = plane->dev;
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	int pipe = intel_plane->pipe;
+	int pixel_size = plane->fb ? drm_format_plane_cpp(plane->fb->pixel_format, 0) : 0;
+	const struct intel_plane_regs *regs = &intel_plane->regs;
+
+	intel_update_sprite_watermarks(dev, pipe, regs->size & 0xffff, pixel_size);
+}
+
+static void
+ilk_commit_plane(struct drm_plane *plane)
+{
+	struct drm_device *dev = plane->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	int pipe = intel_plane->pipe;
+	const struct intel_plane_regs *regs = &intel_plane->regs;
+
+	I915_WRITE(DVSKEYVAL(pipe), regs->keyval);
+	I915_WRITE(DVSKEYMAX(pipe), regs->keymaxval);
+	I915_WRITE(DVSKEYMSK(pipe), regs->keymsk);
+	I915_WRITE(DVSSTRIDE(pipe), regs->stride);
+	I915_WRITE(DVSPOS(pipe), regs->pos);
+	I915_WRITE(DVSTILEOFF(pipe), regs->tileoff);
+	I915_WRITE(DVSLINOFF(pipe), regs->linoff);
+	I915_WRITE(DVSSIZE(pipe), regs->size);
+	I915_WRITE(DVSSCALE(pipe), regs->scale);
+	I915_WRITE(DVSCNTR(pipe), regs->cntr);
+	I915_WRITE(DVSSURF(pipe), regs->surf);
+}
+
+static void
+ilk_update_plane(struct drm_plane *plane,
+		 struct drm_framebuffer *fb,
+		 const struct intel_plane_coords *coords)
+{
+	struct drm_device *dev = plane->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	int pipe = intel_plane->pipe;
+
+	ilk_calc_plane(plane, fb, coords);
+	ilk_prepare_plane(plane);
+	ilk_commit_plane(plane);
 	POSTING_READ(DVSSURF(pipe));
 }
 
@@ -490,21 +589,34 @@ ilk_disable_plane(struct drm_plane *plane)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_plane *intel_plane = to_intel_plane(plane);
 	int pipe = intel_plane->pipe;
+	struct intel_plane_regs *regs = &intel_plane->regs;
 
-	I915_WRITE(DVSCNTR(pipe), I915_READ(DVSCNTR(pipe)) & ~DVS_ENABLE);
+	regs->cntr &= ~DVS_ENABLE;
 	/* Disable the scaler */
-	I915_WRITE(DVSSCALE(pipe), 0);
-	/* Flush double buffered register updates */
-	I915_MODIFY_DISPBASE(DVSSURF(pipe), 0);
+	regs->scale = 0;
+	ilk_commit_plane(plane);
 	POSTING_READ(DVSSURF(pipe));
 }
 
+void intel_calc_sprite(struct drm_plane *plane,
+		       struct drm_framebuffer *fb,
+		       const struct intel_plane_coords *coords)
+{
+	struct drm_device *dev = plane->dev;
+
+	if (INTEL_INFO(dev)->gen >= 7)
+		ivb_calc_plane(plane, fb, coords);
+	else
+		ilk_calc_plane(plane, fb, coords);
+}
+
 static void
 intel_enable_primary(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_plane_regs *regs = &intel_crtc->primary_regs;
 	int reg = DSPCNTR(intel_crtc->plane);
 
 	if (!intel_crtc->primary_disabled)
@@ -513,7 +625,8 @@ intel_enable_primary(struct drm_crtc *crtc)
 	intel_crtc->primary_disabled = false;
 	intel_update_fbc(dev);
 
-	I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE);
+	regs->cntr = I915_READ(reg) | DISPLAY_PLANE_ENABLE;
+	dev_priv->display.commit_plane(crtc);
 }
 
 static void
@@ -522,12 +635,14 @@ intel_disable_primary(struct drm_crtc *crtc)
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_plane_regs *regs = &intel_crtc->primary_regs;
 	int reg = DSPCNTR(intel_crtc->plane);
 
 	if (intel_crtc->primary_disabled)
 		return;
 
-	I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE);
+	regs->cntr = I915_READ(reg) & ~DISPLAY_PLANE_ENABLE;
+	dev_priv->display.commit_plane(crtc);
 
 	intel_crtc->primary_disabled = true;
 	intel_update_fbc(dev);
@@ -539,49 +654,39 @@ ilk_update_colorkey(struct drm_plane *plane,
 {
 	struct drm_device *dev = plane->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_plane *intel_plane;
-	u32 dvscntr;
-	int ret = 0;
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	struct intel_plane_regs *regs = &intel_plane->regs;
 
-	intel_plane = to_intel_plane(plane);
+	regs->keyval = key->min_value;
+	regs->keymaxval = key->max_value;
+	regs->keymsk = key->channel_mask;
 
-	I915_WRITE(DVSKEYVAL(intel_plane->pipe), key->min_value);
-	I915_WRITE(DVSKEYMAX(intel_plane->pipe), key->max_value);
-	I915_WRITE(DVSKEYMSK(intel_plane->pipe), key->channel_mask);
-
-	dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
-	dvscntr &= ~(DVS_SOURCE_KEY | DVS_DEST_KEY);
+	regs->cntr &= ~(DVS_SOURCE_KEY | DVS_DEST_KEY);
 	if (key->flags & I915_SET_COLORKEY_DESTINATION)
-		dvscntr |= DVS_DEST_KEY;
+		regs->cntr |= DVS_DEST_KEY;
 	else if (key->flags & I915_SET_COLORKEY_SOURCE)
-		dvscntr |= DVS_SOURCE_KEY;
-	I915_WRITE(DVSCNTR(intel_plane->pipe), dvscntr);
+		regs->cntr |= DVS_SOURCE_KEY;
 
+	ilk_commit_plane(plane);
 	POSTING_READ(DVSKEYMSK(intel_plane->pipe));
 
-	return ret;
+	return 0;
 }
 
 static void
 ilk_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
 {
-	struct drm_device *dev = plane->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_plane *intel_plane;
-	u32 dvscntr;
+	struct intel_plane *intel_plane = to_intel_plane(plane);
+	const struct intel_plane_regs *regs = &intel_plane->regs;
 
-	intel_plane = to_intel_plane(plane);
-
-	key->min_value = I915_READ(DVSKEYVAL(intel_plane->pipe));
-	key->max_value = I915_READ(DVSKEYMAX(intel_plane->pipe));
-	key->channel_mask = I915_READ(DVSKEYMSK(intel_plane->pipe));
+	key->min_value = regs->keyval;
+	key->max_value = regs->keymaxval;
+	key->channel_mask = regs->keymsk;
 	key->flags = 0;
 
-	dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
-
-	if (dvscntr & DVS_DEST_KEY)
+	if (regs->cntr & DVS_DEST_KEY)
 		key->flags = I915_SET_COLORKEY_DESTINATION;
-	else if (dvscntr & DVS_SOURCE_KEY)
+	else if (regs->cntr & DVS_SOURCE_KEY)
 		key->flags = I915_SET_COLORKEY_SOURCE;
 	else
 		key->flags = I915_SET_COLORKEY_NONE;
@@ -819,6 +924,7 @@ static uint32_t snb_plane_formats[] = {
 int
 intel_plane_init(struct drm_device *dev, enum pipe pipe)
 {
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_plane *intel_plane;
 	unsigned long possible_crtcs;
 	const uint32_t *plane_formats;
@@ -842,6 +948,13 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe)
 		intel_plane->update_colorkey = ilk_update_colorkey;
 		intel_plane->get_colorkey = ilk_get_colorkey;
 
+		intel_plane->calc = ilk_calc_plane;
+		intel_plane->prepare = ilk_prepare_plane;
+		intel_plane->commit = ilk_commit_plane;
+
+		intel_plane->regs.cntr = I915_READ(DVSCNTR(pipe));
+		intel_plane->regs.surf = I915_READ(DVSSURF(pipe));
+
 		if (IS_GEN6(dev)) {
 			plane_formats = snb_plane_formats;
 			num_plane_formats = ARRAY_SIZE(snb_plane_formats);
@@ -862,6 +975,13 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe)
 		intel_plane->update_colorkey = ivb_update_colorkey;
 		intel_plane->get_colorkey = ivb_get_colorkey;
 
+		intel_plane->calc = ivb_calc_plane;
+		intel_plane->prepare = ivb_prepare_plane;
+		intel_plane->commit = ivb_commit_plane;
+
+		intel_plane->regs.cntr = I915_READ(SPRCTL(pipe));
+		intel_plane->regs.surf = I915_READ(SPRSURF(pipe));
+
 		plane_formats = snb_plane_formats;
 		num_plane_formats = ARRAY_SIZE(snb_plane_formats);
 		break;
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 35/81] drm/i915: Implement atomic modesetting
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (33 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 34/81] drm/i915: Split sprite " ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 36/81] drm/i915: Add support for atomic modesetting completion events ville.syrjala
                   ` (47 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Implement the mandatory hooks for the atomic modeset ioctl.

The code first makes a backup of the current state, then proceeds to
modify the state as properties are modified. After all the properties
have been handled the new state is checked, and if everything checks
out, the new state is commited to hardware. Finally we clean up any
temporary storage.

In theory everything is checked before the hardware state is clobbered,
so there should be no need for rollback. But as the current modesetting
code can still return errors from some of of the operation, the rollback
code is included.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/Makefile        |    1 +
 drivers/gpu/drm/i915/intel_atomic.c  | 1625 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_display.c |    5 +
 drivers/gpu/drm/i915/intel_drv.h     |    3 +
 include/drm/drm_crtc.h               |    2 +
 5 files changed, 1636 insertions(+), 0 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/intel_atomic.c

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 0f2c549..cca14e4 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -16,6 +16,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \
 	  i915_gem_tiling.o \
 	  i915_sysfs.o \
 	  i915_trace_points.o \
+	  intel_atomic.o \
 	  intel_display.o \
 	  intel_crt.o \
 	  intel_lvds.o \
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
new file mode 100644
index 0000000..4899f8c
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -0,0 +1,1625 @@
+/*
+ * Copyright (C) 2011-2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Ville Syrjälä <ville.syrjala@linux.intel.com>
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+
+#include "intel_drv.h"
+
+static struct drm_property *prop_src_x;
+static struct drm_property *prop_src_y;
+static struct drm_property *prop_src_w;
+static struct drm_property *prop_src_h;
+static struct drm_property *prop_crtc_x;
+static struct drm_property *prop_crtc_y;
+static struct drm_property *prop_crtc_w;
+static struct drm_property *prop_crtc_h;
+static struct drm_property *prop_fb_id;
+static struct drm_property *prop_crtc_id;
+static struct drm_property *prop_mode;
+static struct drm_property *prop_connector_ids;
+static struct drm_property *prop_cursor_id;
+static struct drm_property *prop_cursor_x;
+static struct drm_property *prop_cursor_y;
+static struct drm_property *prop_cursor_w;
+static struct drm_property *prop_cursor_h;
+
+struct intel_plane_state {
+	struct drm_plane *plane;
+	struct intel_plane_coords coords;
+	bool dirty;
+	bool pinned;
+	bool changed;
+
+	struct {
+		struct drm_crtc *crtc;
+		struct drm_framebuffer *fb;
+		uint32_t src_x, src_y, src_w, src_h;
+		int32_t crtc_x, crtc_y;
+		uint32_t crtc_w, crtc_h;
+	} old;
+};
+
+struct intel_crtc_state {
+	struct drm_crtc *crtc;
+	bool mode_dirty;
+	bool fb_dirty;
+	bool cursor_dirty;
+	bool active_dirty;
+	bool pinned;
+	bool cursor_pinned;
+	unsigned long connectors_bitmask;
+	unsigned long encoders_bitmask;
+	bool changed;
+
+	struct {
+		bool enabled;
+		struct drm_display_mode mode;
+		struct drm_framebuffer *fb;
+		int x, y;
+		unsigned long connectors_bitmask;
+		unsigned long encoders_bitmask;
+
+		struct drm_i915_gem_object *cursor_bo;
+		uint32_t cursor_handle;
+		int16_t cursor_x, cursor_y;
+		int16_t cursor_width, cursor_height;
+		bool cursor_visible;
+	} old;
+};
+
+struct intel_atomic_state {
+	struct drm_file *file;
+	struct intel_plane_state *plane;
+	struct intel_crtc_state *crtc;
+	bool dirty;
+	bool restore_state;
+	bool restore_hw;
+	unsigned int flags;
+	uint64_t user_data;
+	struct drm_plane *saved_planes;
+	struct intel_crtc *saved_crtcs;
+	struct drm_connector *saved_connectors;
+	struct drm_encoder *saved_encoders;
+};
+
+static void update_connectors_bitmask(struct drm_crtc *crtc,
+				      unsigned long *connectors_bitmask)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_connector *connector;
+	unsigned int i = 0;
+
+	*connectors_bitmask = 0;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		if (connector->encoder && connector->encoder->crtc == crtc)
+			__set_bit(i, connectors_bitmask);
+
+		i++;
+	}
+}
+
+static void update_encoders_bitmask(struct drm_crtc *crtc,
+				    unsigned long *encoders_bitmask)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_encoder *encoder;
+	unsigned int i = 0;
+
+	*encoders_bitmask = 0;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		if (encoder->crtc == crtc)
+			__set_bit(i, encoders_bitmask);
+
+		i++;
+	}
+}
+
+static int process_connectors(struct intel_crtc_state *s, const uint32_t *ids, int count_ids)
+{
+	struct drm_crtc *crtc = s->crtc;
+	struct drm_device *dev = crtc->dev;
+	struct drm_connector *connectors[count_ids];
+	struct drm_connector *connector;
+	struct drm_encoder *encoder;
+	int i;
+
+	for (i = 0; i < count_ids; i++) {
+		struct drm_encoder *encoder;
+		const struct drm_connector_helper_funcs *connector_funcs;
+		struct drm_mode_object *obj;
+		int j;
+
+		/* don't accept duplicates */
+		for (j = i + 1; j < count_ids; j++)
+			if (ids[i] == ids[j])
+				return -EINVAL;
+
+		obj = drm_mode_object_find(dev, ids[i], DRM_MODE_OBJECT_CONNECTOR);
+		if (!obj) {
+			DRM_DEBUG_KMS("Unknown connector ID %u\n", ids[i]);
+			return -ENOENT;
+		}
+
+		connector = obj_to_connector(obj);
+		connector_funcs = connector->helper_private;
+
+		encoder = connector_funcs->best_encoder(connector);
+
+		if (!drm_encoder_crtc_ok(encoder, crtc))
+			return -EINVAL;
+
+		connectors[i] = connector;
+	}
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		const struct drm_connector_helper_funcs *connector_funcs =
+			connector->helper_private;
+
+		for (i = 0; i < count_ids; i++) {
+			if (connector == connectors[i])
+				break;
+		}
+
+		/* this connector isn't in the set */
+		if (i == count_ids) {
+			/* remove the link to the encoder if this crtc was set to drive it */
+			if (connector->encoder && connector->encoder->crtc == crtc)
+				connector->encoder = NULL;
+			continue;
+		}
+
+		encoder = connector_funcs->best_encoder(connector);
+
+		connector->encoder = encoder;
+		encoder->crtc = crtc;
+	}
+
+	/* prune dangling encoder->crtc links pointing to this crtc  */
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		if (encoder->crtc == crtc && !drm_helper_encoder_in_use(encoder))
+			encoder->crtc = NULL;
+	}
+
+	update_connectors_bitmask(s->crtc, &s->connectors_bitmask);
+	update_encoders_bitmask(s->crtc, &s->encoders_bitmask);
+
+	return 0;
+}
+
+static size_t intel_atomic_state_size(const struct drm_device *dev)
+{
+	struct intel_atomic_state *state;
+	unsigned int num_connector = dev->mode_config.num_connector;
+	unsigned int num_encoder = dev->mode_config.num_encoder;
+	unsigned int num_crtc = dev->mode_config.num_crtc;
+	unsigned int num_plane = dev->mode_config.num_plane;
+
+	return sizeof *state +
+		num_crtc * sizeof state->crtc[0] +
+		num_plane * sizeof state->plane[0] +
+		num_connector * sizeof state->saved_connectors[0] +
+		num_encoder * sizeof state->saved_encoders[0] +
+		num_crtc * sizeof state->saved_crtcs[0] +
+		num_plane * sizeof state->saved_planes[0];
+}
+
+
+static void populate_old(struct drm_device *dev)
+{
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
+		encoder->old_crtc = encoder->crtc;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+		connector->old_encoder = connector->encoder;
+}
+
+static void *intel_atomic_begin(struct drm_device *dev, struct drm_file *file,
+				uint32_t flags, uint64_t user_data)
+{
+	struct intel_atomic_state *state;
+	struct drm_plane *plane;
+	struct drm_crtc *crtc;
+	struct drm_connector *connector;
+	struct drm_encoder *encoder;
+	unsigned int num_connector = dev->mode_config.num_connector;
+	unsigned int num_encoder = dev->mode_config.num_encoder;
+	unsigned int num_crtc = dev->mode_config.num_crtc;
+	unsigned int num_plane = dev->mode_config.num_plane;
+	int i;
+
+	state = kzalloc(intel_atomic_state_size(dev), GFP_KERNEL);
+	if (!state)
+		return ERR_PTR(-ENOMEM);
+
+	state->flags = flags;
+	state->file = file;
+	state->user_data = user_data;
+
+	state->crtc = (struct intel_crtc_state *)(state + 1);
+	state->plane = (struct intel_plane_state  *)(state->crtc + num_crtc);
+
+	state->saved_connectors = (struct drm_connector *)(state->plane + num_plane);
+	state->saved_encoders = (struct drm_encoder *)(state->saved_connectors + num_connector);
+	state->saved_crtcs = (struct intel_crtc *)(state->saved_encoders + num_encoder);
+	state->saved_planes = (struct drm_plane *)(state->saved_crtcs + num_crtc);
+
+	populate_old(dev);
+
+	i = 0;
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		struct intel_crtc_state *s = &state->crtc[i++];
+		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+		s->crtc = crtc;
+		s->old.cursor_bo = intel_crtc->cursor_bo;
+		s->old.cursor_x = intel_crtc->cursor_x;
+		s->old.cursor_y = intel_crtc->cursor_y;
+		s->old.cursor_width = intel_crtc->cursor_width;
+		s->old.cursor_height = intel_crtc->cursor_height;
+		s->old.cursor_visible = intel_crtc->cursor_visible;
+
+		/* save current config */
+		s->old.enabled = crtc->enabled;
+		s->old.mode = crtc->mode;
+		s->old.fb = crtc->fb;
+		s->old.x = crtc->x;
+		s->old.y = crtc->y;
+
+		update_connectors_bitmask(crtc, &s->connectors_bitmask);
+		update_encoders_bitmask(crtc, &s->encoders_bitmask);
+
+		s->old.connectors_bitmask = s->connectors_bitmask;
+		s->old.encoders_bitmask = s->encoders_bitmask;
+	}
+
+	i = 0;
+	list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
+		struct intel_plane_state *s = &state->plane[i++];
+
+		s->plane = plane;
+
+		/* save current config */
+		s->old.crtc = plane->crtc;
+		s->old.fb = plane->fb;
+		s->old.src_x = plane->src_x;
+		s->old.src_y = plane->src_y;
+		s->old.src_w = plane->src_w;
+		s->old.src_h = plane->src_h;
+		s->old.crtc_x = plane->crtc_x;
+		s->old.crtc_y = plane->crtc_y;
+		s->old.crtc_w = plane->crtc_w;
+		s->old.crtc_h = plane->crtc_h;
+	}
+
+	i = 0;
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+		state->saved_connectors[i++] = *connector;
+	i = 0;
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
+		state->saved_encoders[i++] = *encoder;
+	i = 0;
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+		state->saved_crtcs[i++] = *intel_crtc;
+	}
+	i = 0;
+	list_for_each_entry(plane, &dev->mode_config.plane_list, head)
+		state->saved_planes[i++] = *plane;
+
+	state->file = file;
+
+	return state;
+}
+
+static int plane_set(struct intel_atomic_state *s,
+		     struct intel_plane_state *state,
+		     struct drm_property *prop,
+		     uint64_t value)
+{
+	struct drm_plane *plane = state->plane;
+	struct drm_mode_object *obj;
+
+	state->changed = true;
+
+	if (prop == prop_src_x) {
+		plane->src_x = value;
+	} else if (prop == prop_src_y) {
+		plane->src_y = value;
+	} else if (prop == prop_src_w) {
+		plane->src_w = value;
+	} else if (prop == prop_src_h) {
+		plane->src_h = value;
+	} else if (prop == prop_crtc_x) {
+		plane->crtc_x = value;
+	} else if (prop == prop_crtc_y) {
+		plane->crtc_y = value;
+	} else if (prop == prop_crtc_w) {
+		plane->crtc_w = value;
+	} else if (prop == prop_crtc_h) {
+		plane->crtc_h = value;
+	} else if (prop == prop_crtc_id) {
+		if (value) {
+			obj = drm_mode_object_find(plane->dev, value, DRM_MODE_OBJECT_CRTC);
+			if (!obj) {
+				DRM_DEBUG_KMS("Unknown CRTC ID %llu\n", value);
+				return -ENOENT;
+			}
+			plane->crtc = obj_to_crtc(obj);
+		} else
+			plane->crtc = NULL;
+	} else if (prop == prop_fb_id) {
+		if (value) {
+			obj = drm_mode_object_find(plane->dev, value, DRM_MODE_OBJECT_FB);
+			if (!obj) {
+				DRM_DEBUG_KMS("Unknown framebuffer ID %llu\n", value);
+				return -ENOENT;
+			}
+			plane->fb = obj_to_fb(obj);
+		} else
+			plane->fb = NULL;
+	} else
+		return -ENOENT;
+
+	s->restore_state = true;
+
+	return 0;
+}
+
+static int crtc_set(struct intel_atomic_state *s,
+		    struct intel_crtc_state *state,
+		    struct drm_property *prop,
+		    uint64_t value, const void *blob_data)
+{
+	struct drm_crtc *crtc = state->crtc;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct drm_mode_object *obj;
+
+	state->changed = true;
+
+	if (prop == prop_src_x) {
+		crtc->x = value;
+	} else if (prop == prop_src_y) {
+		crtc->y = value;
+	} else if (prop == prop_mode) {
+		const struct drm_mode_modeinfo *umode = blob_data;
+
+		if (value != 0 && value != sizeof *umode) {
+			DRM_DEBUG_KMS("Invalid mode length\n");
+			return -EINVAL;
+		}
+
+		if (value) {
+			struct drm_display_mode *mode;
+			int ret;
+
+			mode = drm_mode_create(crtc->dev);
+			if (!mode)
+				return -ENOMEM;
+
+			ret = drm_crtc_convert_umode(mode, umode);
+			if (ret) {
+				DRM_DEBUG_KMS("Invalid mode\n");
+				drm_mode_debug_printmodeline(mode);
+				drm_mode_destroy(crtc->dev, mode);
+				return ret;
+			}
+
+			drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
+
+			crtc->mode = *mode;
+			crtc->enabled = true;
+			drm_mode_destroy(crtc->dev, mode);
+		} else
+			crtc->enabled = false;
+	} else if (prop == prop_fb_id) {
+		if (value) {
+			obj = drm_mode_object_find(crtc->dev, value, DRM_MODE_OBJECT_FB);
+			if (!obj) {
+				DRM_DEBUG_KMS("Unknown framebuffer ID %llu\n", value);
+				return -ENOENT;
+			}
+			crtc->fb = obj_to_fb(obj);
+		} else
+			crtc->fb = NULL;
+	} else if (prop == prop_connector_ids) {
+		const uint32_t *ids = blob_data;
+		uint64_t count_ids = value / sizeof(uint32_t);
+		int ret;
+
+		if (value & 3) {
+			DRM_DEBUG_KMS("Invalid connectors length\n");
+			return -EINVAL;
+		}
+
+		if (count_ids > crtc->dev->mode_config.num_connector) {
+			DRM_DEBUG_KMS("Too many connectors specified\n");
+			return -ERANGE;
+		}
+
+		ret = process_connectors(state, ids, count_ids);
+		if (ret)
+			return ret;
+	} else if (prop == prop_cursor_id) {
+		intel_crtc->cursor_handle = value;
+	} else if (prop == prop_cursor_x) {
+		intel_crtc->cursor_x = value;
+	} else if (prop == prop_cursor_y) {
+		intel_crtc->cursor_y = value;
+	} else if (prop == prop_cursor_w) {
+		if (value != 0 && value != 64) {
+			DRM_DEBUG_KMS("only 64x64 cursor sprites are supported\n");
+			return -EINVAL;
+		}
+		intel_crtc->cursor_width = value;
+	} else if (prop == prop_cursor_h) {
+		if (value != 0 && value != 64) {
+			DRM_DEBUG_KMS("only 64x64 cursor sprites are supported\n");
+			return -EINVAL;
+		}
+		intel_crtc->cursor_height = value;
+	} else
+		return -ENOENT;
+
+	s->restore_state = true;
+
+	return 0;
+}
+
+static void crtc_compute_dirty(struct intel_atomic_state *s,
+			       struct intel_crtc_state *state)
+{
+	struct drm_crtc *crtc = state->crtc;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+	/* if no properties were specified nothing is dirty */
+	if (!state->changed)
+		return;
+
+	/* fb/pan changed? */
+	if (crtc->x != state->old.x ||
+	    crtc->y != state->old.y ||
+	    crtc->fb != state->old.fb) {
+		/* FIXME do we need a full modeset sometimes? */
+		state->fb_dirty = true;
+	}
+
+	/* enabled <-> disabled? */
+	if (crtc->enabled != state->old.enabled) {
+		state->mode_dirty = true;
+		state->active_dirty = true;
+	}
+
+	/* mode changed? */
+	if (crtc->enabled && state->old.enabled &&
+	    !drm_mode_equal(&crtc->mode, &state->old.mode)) {
+		state->mode_dirty = true;
+
+		if (crtc->mode.hdisplay != state->old.mode.hdisplay ||
+		    crtc->mode.vdisplay != state->old.mode.vdisplay)
+			state->active_dirty = true;
+	}
+
+	/* connectors changed? */
+	if (state->connectors_bitmask != state->old.connectors_bitmask ||
+	    state->encoders_bitmask != state->old.encoders_bitmask)
+		state->mode_dirty = true;
+
+	/* cursor changed? */
+	if (intel_crtc->cursor_handle != state->old.cursor_handle ||
+	    intel_crtc->cursor_x != state->old.cursor_x ||
+	    intel_crtc->cursor_y != state->old.cursor_y ||
+	    intel_crtc->cursor_width != state->old.cursor_width ||
+	    intel_crtc->cursor_height != state->old.cursor_height)
+		state->cursor_dirty = true;
+
+	if (state->fb_dirty || state->mode_dirty || state->cursor_dirty)
+		s->dirty = true;
+}
+
+static void plane_compute_dirty(struct intel_atomic_state *s,
+				struct intel_plane_state *state)
+{
+	struct drm_plane *plane = state->plane;
+
+	/* if no properties were specified nothing is dirty */
+	if (!state->changed)
+		return;
+
+	if (plane->src_x != state->old.src_x ||
+	    plane->src_y != state->old.src_x ||
+	    plane->src_w != state->old.src_x ||
+	    plane->src_h != state->old.src_x ||
+	    plane->crtc_x != state->old.crtc_x ||
+	    plane->crtc_y != state->old.crtc_y ||
+	    plane->crtc_w != state->old.crtc_w ||
+	    plane->crtc_h != state->old.crtc_h ||
+	    plane->crtc != state->old.crtc ||
+	    plane->fb != state->old.fb)
+		state->dirty = true;
+
+	if (state->dirty)
+		s->dirty = true;
+}
+
+static struct intel_plane_state *get_plane_state(const struct drm_device *dev,
+						 struct intel_atomic_state *state,
+						 const struct drm_plane *plane)
+{
+	int i;
+
+	for (i = 0; i < dev->mode_config.num_plane; i++)
+		if (plane == state->plane[i].plane)
+			return &state->plane[i];
+
+	return NULL;
+}
+
+static struct intel_crtc_state *get_crtc_state(const struct drm_device *dev,
+					       struct intel_atomic_state *state,
+					       const struct drm_crtc *crtc)
+{
+	int i;
+
+	for (i = 0; i < dev->mode_config.num_crtc; i++)
+		if (crtc == state->crtc[i].crtc)
+			return &state->crtc[i];
+
+	return NULL;
+}
+
+static void crtc_prepare(struct intel_crtc_state *st,
+			 struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_encoder *intel_encoder;
+
+	dev_priv->display.crtc_disable(&intel_crtc->base);
+
+	/* FIXME need to check where this stuff is used really */
+	list_for_each_entry(intel_encoder, &dev->mode_config.encoder_list, base.head) {
+		if (intel_encoder->base.crtc == crtc)
+			intel_encoder->connectors_active = false;
+	}
+}
+
+static int crtc_set_base(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	return dev_priv->display.update_plane(crtc, crtc->fb, crtc->x, crtc->y);
+}
+
+static int crtc_mode_set(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_encoder *encoder;
+	int pipe = to_intel_crtc(crtc)->pipe;
+	int ret;
+
+	if (!crtc->enabled) {
+		dev_priv->display.off(crtc);
+		return 0;
+	}
+
+	drm_vblank_pre_modeset(dev, pipe);
+
+	ret = dev_priv->display.crtc_mode_set(crtc, &crtc->mode, &crtc->hwmode,
+					      crtc->x, crtc->y, crtc->fb);
+	if (!ret)
+		ret = dev_priv->display.update_plane(crtc, crtc->fb, crtc->x, crtc->y);
+
+	if (!ret) {
+		intel_update_watermarks(dev);
+
+		if (HAS_PCH_SPLIT(dev))
+			intel_update_linetime_watermarks(dev, pipe, &crtc->hwmode);
+	}
+
+	drm_vblank_post_modeset(dev, pipe);
+
+	if (ret)
+		return ret;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		const struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
+
+		if (encoder->crtc != crtc)
+			continue;
+
+		encoder_funcs->mode_set(encoder, &crtc->mode, &crtc->hwmode);
+	}
+
+	return 0;
+}
+
+static void crtc_commit(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_encoder *intel_encoder;
+
+	if (!crtc->enabled)
+		return;
+
+	dev_priv->display.crtc_enable(&intel_crtc->base);
+
+	/* FIXME need to check where this stuff is used really */
+	/* FIXME need to update DPMS state somewhere */
+	list_for_each_entry(intel_encoder, &dev->mode_config.encoder_list, base.head) {
+		if (intel_encoder->base.crtc == crtc)
+			intel_encoder->connectors_active = true;
+	}
+}
+
+static void unpin_cursors(struct drm_device *dev,
+			  struct intel_atomic_state *s)
+{
+	int i;
+
+	for (i = 0; i < dev->mode_config.num_crtc; i++) {
+		struct intel_crtc_state *st = &s->crtc[i];
+		struct drm_crtc *crtc = st->crtc;
+		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+		if (!st->cursor_pinned)
+			continue;
+
+		intel_crtc_cursor_bo_unref(crtc, intel_crtc->cursor_bo);
+
+		st->cursor_pinned = false;
+	}
+}
+
+static int pin_cursors(struct drm_device *dev,
+			struct intel_atomic_state *s)
+{
+	int i, ret;
+
+	for (i = 0; i < dev->mode_config.num_crtc; i++) {
+		struct intel_crtc_state *st = &s->crtc[i];
+		struct drm_crtc *crtc = st->crtc;
+		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+		if (!st->cursor_dirty)
+			continue;
+
+		ret = intel_crtc_cursor_prepare(crtc, s->file,
+						intel_crtc->cursor_handle,
+						intel_crtc->cursor_width,
+						intel_crtc->cursor_height,
+						&intel_crtc->cursor_bo,
+						&intel_crtc->cursor_addr);
+		if (ret)
+			goto unpin;
+
+		st->cursor_pinned = true;
+	}
+
+	return 0;
+
+unpin:
+	unpin_cursors(dev, s);
+
+	return ret;
+}
+
+static void unpin_old_cursors(struct drm_device *dev,
+			      struct intel_atomic_state *s)
+{
+	int i;
+
+	for (i = 0; i < dev->mode_config.num_crtc; i++) {
+		struct intel_crtc_state *st = &s->crtc[i];
+		struct drm_crtc *crtc = st->crtc;
+
+		if (!st->cursor_dirty)
+			continue;
+
+		if (!st->old.cursor_bo)
+			continue;
+
+		intel_crtc_cursor_bo_unref(crtc, st->old.cursor_bo);
+	}
+}
+
+static void unpin_fbs(struct drm_device *dev,
+		      struct intel_atomic_state *s)
+{
+	int i;
+
+	for (i = dev->mode_config.num_plane - 1; i >= 0; i--) {
+		struct intel_plane_state *st = &s->plane[i];
+		struct drm_plane *plane = st->plane;
+		struct drm_i915_gem_object *obj;
+
+		if (!st->pinned)
+			continue;
+
+		obj = to_intel_framebuffer(plane->fb)->obj;
+
+		mutex_lock(&dev->struct_mutex);
+		intel_unpin_fb_obj(obj);
+		mutex_unlock(&dev->struct_mutex);
+
+		st->pinned = false;
+	}
+
+	for (i = dev->mode_config.num_crtc - 1; i >= 0; i--) {
+		struct intel_crtc_state *st = &s->crtc[i];
+		struct drm_crtc *crtc = st->crtc;
+		struct drm_i915_gem_object *obj;
+
+		if (!st->pinned)
+			continue;
+
+		obj = to_intel_framebuffer(crtc->fb)->obj;
+
+		mutex_lock(&dev->struct_mutex);
+		intel_unpin_fb_obj(obj);
+		mutex_unlock(&dev->struct_mutex);
+
+		st->pinned = false;
+	}
+}
+
+static int pin_fbs(struct drm_device *dev,
+		   struct intel_atomic_state *s)
+{
+	int i, ret;
+
+	for (i = 0; i < dev->mode_config.num_crtc; i++) {
+		struct intel_crtc_state *st = &s->crtc[i];
+		struct drm_crtc *crtc = st->crtc;
+		struct drm_i915_gem_object *obj;
+
+		if (!st->fb_dirty)
+			continue;
+
+		if (!crtc->fb)
+			continue;
+
+		obj = to_intel_framebuffer(crtc->fb)->obj;
+
+		mutex_lock(&dev->struct_mutex);
+		ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
+		mutex_unlock(&dev->struct_mutex);
+
+		if (ret)
+			goto unpin;
+
+		st->pinned = true;
+	}
+
+	for (i = 0; i < dev->mode_config.num_plane; i++) {
+		struct intel_plane_state *st = &s->plane[i];
+		struct drm_plane *plane = st->plane;
+		struct drm_i915_gem_object *obj;
+
+		if (!st->dirty)
+			continue;
+
+		if (!plane->fb)
+			continue;
+
+		obj = to_intel_framebuffer(plane->fb)->obj;
+
+		mutex_lock(&dev->struct_mutex);
+		ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
+		mutex_unlock(&dev->struct_mutex);
+
+		if (ret)
+			goto unpin;
+
+		st->pinned = true;
+	}
+
+	return 0;
+
+ unpin:
+	unpin_fbs(dev, s);
+
+	return ret;
+}
+
+static void unpin_old_fbs(struct drm_device *dev,
+			  struct intel_atomic_state *s)
+{
+	int i;
+
+	for (i = 0; i < dev->mode_config.num_crtc; i++) {
+		struct intel_crtc_state *st = &s->crtc[i];
+		struct drm_i915_gem_object *obj;
+
+		if (!st->fb_dirty)
+			continue;
+
+		if (!st->old.fb)
+			continue;
+
+		obj = to_intel_framebuffer(st->old.fb)->obj;
+
+		mutex_lock(&dev->struct_mutex);
+		intel_unpin_fb_obj(obj);
+		mutex_unlock(&dev->struct_mutex);
+	}
+
+	for (i = 0; i < dev->mode_config.num_plane; i++) {
+		struct intel_plane_state *st = &s->plane[i];
+		struct drm_i915_gem_object *obj;
+
+		if (!st->dirty)
+			continue;
+
+		if (!st->old.fb)
+			continue;
+
+		obj = to_intel_framebuffer(st->old.fb)->obj;
+
+		mutex_lock(&dev->struct_mutex);
+		intel_unpin_fb_obj(obj);
+		mutex_unlock(&dev->struct_mutex);
+	}
+}
+
+static void update_plane_obj(struct drm_device *dev,
+			     struct intel_atomic_state *s)
+{
+	int i;
+
+	for (i = 0; i < dev->mode_config.num_plane; i++) {
+		struct intel_plane_state *st = &s->plane[i];
+		struct drm_plane *plane = st->plane;
+		struct intel_plane *intel_plane = to_intel_plane(plane);
+
+		if (!st->dirty)
+			continue;
+
+		if (plane->fb)
+			intel_plane->obj = to_intel_framebuffer(plane->fb)->obj;
+		else
+			intel_plane->obj = NULL;
+	}
+}
+
+/* FIXME need to refactor the sprite code some more */
+int intel_disable_plane_nopin(struct drm_plane *plane);
+int intel_commit_plane_nopin(struct drm_plane *plane,
+			     struct drm_crtc *crtc,
+			     struct drm_framebuffer *fb,
+			     const struct intel_plane_coords *coords);
+
+static void swap_old_new(struct drm_device *dev,
+			 struct intel_atomic_state *s)
+{
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+	int i;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
+		swap(encoder->crtc, encoder->old_crtc);
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+		swap(connector->encoder, connector->old_encoder);
+
+	for (i = 0; i < dev->mode_config.num_crtc; i++) {
+		struct intel_crtc_state *st = &s->crtc[i];
+		struct drm_crtc *crtc = st->crtc;
+
+		swap(crtc->enabled, st->old.enabled);
+	}
+}
+
+static int apply_config(struct drm_device *dev,
+			struct intel_atomic_state *s)
+{
+	int i, ret;
+
+	/*
+	 * FIXME
+`	 * Hackish way to make crtc_disable() see the current
+	 * state (actually just some select pieces of it).
+	 */
+	swap_old_new(dev, s);
+
+	for (i = 0; i < dev->mode_config.num_crtc; i++) {
+		struct intel_crtc_state *st = &s->crtc[i];
+
+		mutex_lock(&dev->struct_mutex);
+
+		if (st->mode_dirty) {
+			/* wait for pending MI_WAIT_FOR_EVENTs */
+			if (st->old.fb)
+				intel_finish_fb(st->old.fb);
+		}
+
+		mutex_unlock(&dev->struct_mutex);
+
+		if (!st->mode_dirty)
+			continue;
+
+		crtc_prepare(st, st->crtc);
+	}
+
+	/* Undo the hack above. */
+	swap_old_new(dev, s);
+
+	for (i = 0; i < dev->mode_config.num_crtc; i++) {
+		struct intel_crtc_state *st = &s->crtc[i];
+
+		if (!st->mode_dirty)
+			continue;
+
+		ret = crtc_mode_set(st->crtc);
+		if (ret)
+			return ret;
+	}
+
+	for (i = 0; i < dev->mode_config.num_crtc; i++) {
+		struct intel_crtc_state *st = &s->crtc[i];
+		struct drm_crtc *crtc = st->crtc;
+		int j;
+
+		if (st->mode_dirty)
+			crtc_commit(crtc);
+		else if (st->fb_dirty) {
+			ret = crtc_set_base(st->crtc);
+			if (ret)
+				return ret;
+		}
+
+		/*
+		 * FIXME these should happen alongside the primary plane setup
+		 * which occurs inside the crtc_enable() hook.
+		 */
+
+		if (st->cursor_dirty) {
+			struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+			intel_crtc_cursor_commit(crtc,
+						 intel_crtc->cursor_handle,
+						 intel_crtc->cursor_width,
+						 intel_crtc->cursor_height,
+						 intel_crtc->cursor_bo,
+						 intel_crtc->cursor_addr);
+		}
+
+		for (j = 0; j < dev->mode_config.num_plane; j++) {
+			struct intel_plane_state *pst = &s->plane[j];
+			struct drm_plane *plane = pst->plane;
+			struct intel_plane *intel_plane = to_intel_plane(plane);
+
+			if (!pst->dirty)
+				continue;
+
+			if (pst->coords.visible && plane->crtc == crtc)
+				intel_plane->update_plane(plane, plane->fb, &pst->coords);
+			else if (!pst->coords.visible && pst->old.crtc == crtc)
+				intel_plane->disable_plane(plane);
+		}
+	}
+
+	/* don't restore the old state in end() */
+	s->dirty = false;
+	s->restore_state = false;
+
+	return 0;
+}
+
+static void restore_state(struct drm_device *dev,
+			  struct intel_atomic_state *s)
+{
+	int i;
+	struct drm_connector *connector;
+	struct drm_encoder *encoder;
+	struct drm_crtc *crtc;
+	struct drm_plane *plane;
+
+	i = 0;
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+		*connector = s->saved_connectors[i++];
+	i = 0;
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
+		*encoder = s->saved_encoders[i++];
+	i = 0;
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+		intel_crtc->base = s->saved_crtcs[i].base;
+		intel_crtc->cursor_bo = s->saved_crtcs[i].cursor_bo;
+		intel_crtc->cursor_addr = s->saved_crtcs[i].cursor_addr;
+		intel_crtc->cursor_handle = s->saved_crtcs[i].cursor_handle;
+		intel_crtc->cursor_x = s->saved_crtcs[i].cursor_x;
+		intel_crtc->cursor_y = s->saved_crtcs[i].cursor_y;
+		intel_crtc->cursor_width = s->saved_crtcs[i].cursor_width;
+		intel_crtc->cursor_height = s->saved_crtcs[i].cursor_height;
+		intel_crtc->cursor_visible = s->saved_crtcs[i].cursor_visible;
+
+		i++;
+	}
+	i = 0;
+	list_for_each_entry(plane, &dev->mode_config.plane_list, head)
+		*plane = s->saved_planes[i++];
+
+	/* FIXME props etc. */
+
+	/* was the hardware state clobbered? */
+	if (s->restore_hw)
+		apply_config(dev, s);
+}
+
+static int intel_atomic_set(struct drm_device *dev, void *state,
+			    struct drm_mode_object *obj,
+			    struct drm_property *prop,
+			    uint64_t value, void *blob_data)
+{
+	struct intel_atomic_state *s = state;
+	int ret = -EINVAL;
+
+	switch (obj->type) {
+	case DRM_MODE_OBJECT_PLANE:
+		ret = plane_set(s, get_plane_state(dev, s, obj_to_plane(obj)), prop, value);
+		break;
+	case DRM_MODE_OBJECT_CRTC:
+		ret = crtc_set(s, get_crtc_state(dev, s, obj_to_crtc(obj)), prop, value, blob_data);
+		break;
+	default:
+		break;
+	}
+
+	kfree(blob_data);
+
+	return ret;
+}
+
+int intel_check_plane(const struct drm_plane *plane,
+		      const struct drm_crtc *crtc,
+		      const struct drm_framebuffer *fb,
+		      struct intel_plane_coords *st);
+
+static void dirty_planes(const struct drm_device *dev,
+			 struct intel_atomic_state *state,
+			 const struct drm_crtc *crtc)
+{
+	int i;
+
+	for (i = 0; i < dev->mode_config.num_plane; i++) {
+		struct intel_plane_state *s = &state->plane[i];
+
+		if (s->plane->crtc == crtc)
+			s->dirty = true;
+	}
+}
+
+static int check_crtc(struct intel_crtc_state *s)
+{
+	struct drm_crtc *crtc = s->crtc;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct drm_encoder *encoder;
+	struct drm_framebuffer *fb = crtc->fb;
+	int ret;
+
+	/* must have a fb and connectors if we have a mode, and vice versa */
+	if (crtc->enabled) {
+		if (!fb)
+			return -EINVAL;
+		if (!drm_helper_crtc_in_use(crtc))
+			return -EINVAL;
+	} else {
+		if (fb)
+			return -EINVAL;
+		if (drm_helper_crtc_in_use(crtc))
+			return -EINVAL;
+	}
+
+	if (crtc->enabled) {
+		if (crtc->mode.hdisplay > fb->width ||
+		    crtc->mode.vdisplay > fb->height ||
+		    crtc->x > fb->width - crtc->mode.hdisplay ||
+		    crtc->y > fb->height - crtc->mode.vdisplay)
+			return -ENOSPC;
+	}
+
+	if (fb) {
+		/* FIXME refactor and check */
+		switch (fb->pixel_format) {
+		case DRM_FORMAT_C8:
+		case DRM_FORMAT_RGB565:
+		case DRM_FORMAT_XRGB8888:
+		case DRM_FORMAT_ARGB8888:
+		case DRM_FORMAT_XBGR8888:
+		case DRM_FORMAT_ABGR8888:
+		case DRM_FORMAT_XRGB2101010:
+		case DRM_FORMAT_ARGB2101010:
+		case DRM_FORMAT_XBGR2101010:
+		case DRM_FORMAT_ABGR2101010:
+		case DRM_FORMAT_XRGB1555:
+		case DRM_FORMAT_ARGB1555:
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+
+	if (intel_crtc->cursor_visible &&
+	    (intel_crtc->cursor_width != 64 ||
+	     intel_crtc->cursor_height != 64)) {
+		return -EINVAL;
+	}
+
+	if (!crtc->enabled || !s->mode_dirty)
+		return 0;
+
+	crtc->hwmode = crtc->mode;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		const struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
+
+		if (encoder->crtc != crtc)
+			continue;
+
+		if (!encoder_funcs->mode_fixup(encoder, &crtc->mode, &crtc->hwmode))
+			return -EINVAL;
+	}
+
+	if (!intel_crtc_mode_fixup(crtc, &crtc->mode, &crtc->hwmode))
+		return -EINVAL;
+
+	ret = intel_check_clock(crtc, &crtc->hwmode);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int intel_atomic_check(struct drm_device *dev, void *state)
+{
+	struct intel_atomic_state *s = state;
+	int ret;
+	int i;
+
+	for (i = 0; i < dev->mode_config.num_crtc; i++) {
+		struct intel_crtc_state *st = &s->crtc[i];
+
+		crtc_compute_dirty(s, st);
+	}
+
+	for (i = 0; i < dev->mode_config.num_crtc; i++) {
+		struct intel_plane_state *st = &s->plane[i];
+
+		plane_compute_dirty(s, st);
+	}
+
+	if (!s->dirty)
+		return 0;
+
+	for (i = 0; i < dev->mode_config.num_crtc; i++) {
+		struct intel_crtc_state *st = &s->crtc[i];
+
+		if (!st->fb_dirty && !st->mode_dirty && !st->cursor_dirty)
+			continue;
+
+		if (st->mode_dirty && s->flags & DRM_MODE_ATOMIC_NONBLOCK)
+			return -EAGAIN;
+
+		ret = check_crtc(st);
+		if (ret)
+			return ret;
+
+		/*
+		 * Mark all planes on this CRTC as dirty if the active video
+		 * area changed so that the planes will get reclipped correctly.
+		 *
+		 * Also any modesetting will disable+enable the pipe, so the
+		 * plane needs to be re-enabled afterwards too.
+		 * TODO: there's no need to redo the clipping in such cases
+		 * if the computed values were cached, the could be commited
+		 * directly.
+		 */
+		if (st->active_dirty || st->mode_dirty)
+			dirty_planes(dev, s, st->crtc);
+	}
+
+	/* check for conflicts in encoder/connector assignment */
+	for (i = 0; i < dev->mode_config.num_crtc; i++) {
+		struct intel_crtc_state *st = &s->crtc[i];
+		int j;
+
+		for (j = i + 1; j < dev->mode_config.num_crtc; j++) {
+			struct intel_crtc_state *st2 = &s->crtc[j];
+
+			if (st->connectors_bitmask & st2->connectors_bitmask)
+				return -EINVAL;
+
+			if (st->encoders_bitmask & st2->encoders_bitmask)
+				return -EINVAL;
+		}
+	}
+
+	for (i = 0; i < dev->mode_config.num_plane; i++) {
+		struct intel_plane_state *st = &s->plane[i];
+		const struct drm_plane *plane = st->plane;
+
+		if (!st->dirty)
+			continue;
+
+		st->coords.crtc_x = plane->crtc_x;
+		st->coords.crtc_y = plane->crtc_y;
+		st->coords.crtc_w = plane->crtc_w;
+		st->coords.crtc_h = plane->crtc_h;
+
+		st->coords.src_x = plane->src_x;
+		st->coords.src_y = plane->src_y;
+		st->coords.src_w = plane->src_w;
+		st->coords.src_h = plane->src_h;
+
+		ret = intel_check_plane(plane, plane->crtc, plane->fb, &st->coords);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static void update_plane_props(struct drm_plane *plane)
+{
+	struct drm_mode_object *obj = &plane->base;
+
+	drm_object_property_set_value(obj, prop_src_x, plane->src_x);
+	drm_object_property_set_value(obj, prop_src_y, plane->src_y);
+	drm_object_property_set_value(obj, prop_src_w, plane->src_w);
+	drm_object_property_set_value(obj, prop_src_h, plane->src_h);
+
+	drm_object_property_set_value(obj, prop_crtc_x, plane->crtc_x);
+	drm_object_property_set_value(obj, prop_crtc_y, plane->crtc_y);
+	drm_object_property_set_value(obj, prop_crtc_w, plane->crtc_w);
+	drm_object_property_set_value(obj, prop_crtc_h, plane->crtc_h);
+
+	drm_object_property_set_value(obj, prop_fb_id, plane->fb ? plane->fb->base.id : 0);
+	drm_object_property_set_value(obj, prop_crtc_id, plane->crtc ? plane->crtc->base.id : 0);
+}
+
+static int update_prop_connector_ids(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_connector *connector;
+	uint64_t value = 0;
+	int i = 0;
+	uint32_t connector_ids[dev->mode_config.num_connector];
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		if (connector->encoder && connector->encoder->crtc == crtc)
+			connector_ids[i++] = connector->base.id;
+	}
+
+	if (i) {
+		drm_property_blob_replace_data(crtc->connector_ids_blob,
+					       i * sizeof connector_ids[0], connector_ids);
+		value = crtc->connector_ids_blob->base.id;
+	} else
+		drm_property_blob_replace_data(crtc->connector_ids_blob, 0, NULL);
+
+	drm_object_property_set_value(&crtc->base, prop_connector_ids, value);
+
+	return 0;
+}
+
+static int update_prop_mode(struct drm_crtc *crtc)
+{
+	uint64_t value = 0;
+
+	if (crtc->enabled) {
+		struct drm_mode_modeinfo umode;
+
+		drm_crtc_convert_to_umode(&umode, &crtc->mode);
+		drm_property_blob_replace_data(crtc->mode_blob, sizeof umode, &umode);
+		value = crtc->mode_blob->base.id;
+	} else
+		drm_property_blob_replace_data(crtc->mode_blob, 0, NULL);
+
+	drm_object_property_set_value(&crtc->base, prop_mode, value);
+
+	return 0;
+}
+
+static void update_crtc_props(struct drm_crtc *crtc)
+{
+	struct drm_mode_object *obj = &crtc->base;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+	drm_object_property_set_value(obj, prop_src_x, crtc->x);
+	drm_object_property_set_value(obj, prop_src_y, crtc->y);
+
+	drm_object_property_set_value(obj, prop_fb_id, crtc->fb ? crtc->fb->base.id : 0);
+
+	drm_object_property_set_value(obj, prop_cursor_id, intel_crtc->cursor_handle);
+	drm_object_property_set_value(obj, prop_cursor_x, intel_crtc->cursor_x);
+	drm_object_property_set_value(obj, prop_cursor_y, intel_crtc->cursor_y);
+	drm_object_property_set_value(obj, prop_cursor_w, intel_crtc->cursor_width);
+	drm_object_property_set_value(obj, prop_cursor_h, intel_crtc->cursor_height);
+
+	update_prop_mode(crtc);
+	update_prop_connector_ids(crtc);
+}
+
+static void update_props(struct drm_device *dev,
+			 struct intel_atomic_state *s)
+{
+	int i;
+
+	for (i = 0; i < dev->mode_config.num_crtc; i++) {
+		struct intel_crtc_state *st = &s->crtc[i];
+
+		if (!st->fb_dirty && !st->mode_dirty)
+			continue;
+
+		update_crtc_props(st->crtc);
+	}
+
+	for (i = 0; i < dev->mode_config.num_plane; i++) {
+		struct intel_plane_state *st = &s->plane[i];
+
+		if (!st->dirty)
+			continue;
+
+		update_plane_props(st->plane);
+	}
+}
+
+static void update_crtc(struct drm_device *dev,
+			struct intel_atomic_state *s)
+{
+	int i;
+
+	for (i = 0; i < dev->mode_config.num_crtc; i++) {
+		struct intel_crtc_state *st = &s->crtc[i];
+		struct drm_crtc *crtc = st->crtc;
+
+		/* FIXME is this OK? */
+		if (st->fb_dirty && !st->mode_dirty) {
+			mutex_lock(&dev->struct_mutex);
+			intel_update_fbc(dev);
+			mutex_unlock(&dev->struct_mutex);
+		}
+
+		if (st->mode_dirty) {
+			drm_calc_timestamping_constants(crtc);
+			intel_crtc_update_sarea(crtc, crtc->enabled);
+		}
+
+		if (st->fb_dirty)
+			intel_crtc_update_sarea_pos(crtc, crtc->x, crtc->y);
+	}
+}
+
+static int intel_atomic_commit(struct drm_device *dev, void *state)
+{
+	struct intel_atomic_state *s = state;
+	int ret;
+
+	if (s->flags & DRM_MODE_ATOMIC_NONBLOCK)
+		return -ENOSYS;
+
+	if (s->flags & DRM_MODE_ATOMIC_EVENT)
+		return -ENOSYS;
+
+	if (!s->dirty)
+		return 0;
+
+	ret = pin_fbs(dev, s);
+	if (ret)
+		return ret;
+
+	ret = pin_cursors(dev, s);
+	if (ret)
+		return ret;
+
+	/* apply in a blocking manner */
+	ret = apply_config(dev, s);
+	if (ret) {
+		unpin_cursors(dev, s);
+		unpin_fbs(dev, s);
+		s->restore_hw = true;
+		return ret;
+	}
+
+	unpin_old_cursors(dev, s);
+	unpin_old_fbs(dev, s);
+
+	update_plane_obj(dev, s);
+
+	update_crtc(dev, s);
+
+	update_props(dev, s);
+
+	return 0;
+}
+
+static void intel_atomic_end(struct drm_device *dev, void *state)
+{
+	struct intel_atomic_state *s = state;
+
+	/* restore the state of all objects */
+	if (s->restore_state)
+		restore_state(dev, state);
+
+	kfree(state);
+}
+
+static const struct drm_atomic_funcs intel_atomic_funcs = {
+	.begin = intel_atomic_begin,
+	.set = intel_atomic_set,
+	.check = intel_atomic_check,
+	.commit = intel_atomic_commit,
+	.end = intel_atomic_end,
+};
+
+static struct {
+	struct drm_property **prop;
+	const char *name;
+	uint64_t min;
+	uint64_t max;
+} props[] = {
+	{ &prop_src_x, "SRC_X", 0, UINT_MAX },
+	{ &prop_src_y, "SRC_Y", 0, UINT_MAX },
+	{ &prop_src_w, "SRC_W", 0, UINT_MAX },
+	{ &prop_src_h, "SRC_H", 0, UINT_MAX },
+
+	{ &prop_crtc_x, "CRTC_X", INT_MIN, INT_MAX },
+	{ &prop_crtc_y, "CRTC_Y", INT_MIN, INT_MAX },
+	{ &prop_crtc_w, "CRTC_W", 0, INT_MAX },
+	{ &prop_crtc_h, "CRTC_H", 0, INT_MAX },
+
+	{ &prop_fb_id, "FB_ID", 0, UINT_MAX },
+	{ &prop_crtc_id, "CRTC_ID", 0, UINT_MAX },
+
+	{ &prop_cursor_id, "CURSOR_ID", 0, UINT_MAX },
+	{ &prop_cursor_w, "CURSOR_W", 0, UINT_MAX },
+	{ &prop_cursor_h, "CURSOR_H", 0, UINT_MAX },
+	{ &prop_cursor_x, "CURSOR_X", INT_MIN, INT_MAX },
+	{ &prop_cursor_y, "CURSOR_Y", INT_MIN, INT_MAX },
+};
+
+int intel_atomic_init(struct drm_device *dev)
+{
+	struct drm_crtc *crtc;
+	struct drm_plane *plane;
+	int ret = -ENOMEM;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(props); i++) {
+		*props[i].prop =
+			drm_property_create_range(dev, 0, props[i].name,
+						  props[i].min, props[i].max);
+		if (!*props[i].prop)
+			goto out;
+	}
+
+	/* FIXME create special object ID list property type? */
+	prop_connector_ids = drm_property_create(dev, DRM_MODE_PROP_BLOB, "CONNECTOR_IDS", 0);
+	if (!prop_connector_ids)
+		goto out;
+
+	prop_mode = drm_property_create(dev, DRM_MODE_PROP_BLOB, "MODE", 0);
+	if (!prop_mode)
+		goto out;
+
+	list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
+		struct drm_mode_object *obj = &plane->base;
+
+		drm_object_attach_property(obj, prop_src_x, 0);
+		drm_object_attach_property(obj, prop_src_y, 0);
+		drm_object_attach_property(obj, prop_src_w, 0);
+		drm_object_attach_property(obj, prop_src_h, 0);
+
+		drm_object_attach_property(obj, prop_crtc_x, 0);
+		drm_object_attach_property(obj, prop_crtc_y, 0);
+		drm_object_attach_property(obj, prop_crtc_w, 0);
+		drm_object_attach_property(obj, prop_crtc_h, 0);
+
+		drm_object_attach_property(obj, prop_fb_id, 0);
+		drm_object_attach_property(obj, prop_crtc_id, 0);
+
+		update_plane_props(plane);
+	}
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		struct drm_mode_object *obj = &crtc->base;
+
+		drm_object_attach_property(obj, prop_src_x, 0);
+		drm_object_attach_property(obj, prop_src_y, 0);
+
+		drm_object_attach_property(obj, prop_fb_id, 0);
+		drm_object_attach_property(obj, prop_mode, 0);
+		drm_object_attach_property(obj, prop_connector_ids, 0);
+
+		drm_object_attach_property(obj, prop_cursor_id, 0);
+		drm_object_attach_property(obj, prop_cursor_x, 0);
+		drm_object_attach_property(obj, prop_cursor_y, 0);
+		drm_object_attach_property(obj, prop_cursor_w, 0);
+		drm_object_attach_property(obj, prop_cursor_h, 0);
+
+		crtc->mode_blob = drm_property_create_blob(dev, 0, sizeof(struct drm_mode_modeinfo), NULL);
+		if (!crtc->mode_blob)
+			goto out;
+
+		crtc->connector_ids_blob = drm_property_create_blob(dev, 0,
+								    dev->mode_config.num_connector * sizeof(uint32_t), NULL);
+		if (!crtc->connector_ids_blob)
+			goto out;
+
+		update_crtc_props(crtc);
+	}
+
+	dev->driver->atomic_funcs = &intel_atomic_funcs;
+
+	return 0;
+
+ out:
+	drm_property_destroy(dev, prop_mode);
+	drm_property_destroy(dev, prop_connector_ids);
+
+	while (i--)
+		drm_property_destroy(dev, *props[i].prop);
+
+	return ret;
+}
+
+void intel_atomic_fini(struct drm_device *dev)
+{
+	struct drm_crtc *crtc;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		drm_property_destroy_blob(dev, crtc->mode_blob);
+		drm_property_destroy_blob(dev, crtc->connector_ids_blob);
+	}
+
+	drm_property_destroy(dev, prop_connector_ids);
+	drm_property_destroy(dev, prop_mode);
+	drm_property_destroy(dev, prop_crtc_id);
+	drm_property_destroy(dev, prop_fb_id);
+
+	drm_property_destroy(dev, prop_crtc_h);
+	drm_property_destroy(dev, prop_crtc_w);
+	drm_property_destroy(dev, prop_crtc_y);
+	drm_property_destroy(dev, prop_crtc_x);
+
+	drm_property_destroy(dev, prop_src_h);
+	drm_property_destroy(dev, prop_src_w);
+	drm_property_destroy(dev, prop_src_y);
+	drm_property_destroy(dev, prop_src_x);
+}
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index c0db749..62e2a56 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -8409,6 +8409,9 @@ static void intel_setup_outputs(struct drm_device *dev)
 			intel_encoder_clones(encoder);
 	}
 
+	/* FIXME error handling */
+	intel_atomic_init(dev);
+
 	intel_init_pch_refclk(dev);
 
 	drm_helper_move_panel_connectors_to_head(dev);
@@ -9187,6 +9190,8 @@ void intel_modeset_cleanup(struct drm_device *dev)
 	/* flush any delayed tasks or pending work */
 	flush_scheduled_work();
 
+	intel_atomic_fini(dev);
+
 	drm_mode_config_cleanup(dev);
 }
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 05afdd1..103d104 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -720,4 +720,7 @@ extern bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
 				  const struct drm_display_mode *mode,
 				  struct drm_display_mode *adjusted_mode);
 
+extern int intel_atomic_init(struct drm_device *dev);
+extern void intel_atomic_fini(struct drm_device *dev);
+
 #endif /* __INTEL_DRV_H__ */
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 77f08a3..897c110 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -509,6 +509,7 @@ struct drm_encoder {
 	struct drm_crtc *crtc;
 	const struct drm_encoder_funcs *funcs;
 	void *helper_private;
+	struct drm_crtc *old_crtc;
 };
 
 enum drm_connector_force {
@@ -614,6 +615,7 @@ struct drm_connector {
 	int audio_latency[2];
 	int null_edid_counter; /* needed to workaround some HW bugs where we get all 0s */
 	unsigned bad_edid_counter;
+	struct drm_encoder *old_encoder;
 };
 
 /**
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 36/81] drm/i915: Add support for atomic modesetting completion events
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (34 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 35/81] drm/i915: Implement atomic modesetting ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 37/81] drm/i915: Add atomic page flip support ville.syrjala
                   ` (46 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Send completion events when the atomic modesetting operations has
finished succesfully.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_atomic.c |  195 ++++++++++++++++++++++++++++++++++-
 1 files changed, 192 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 4899f8c..3adb140 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -53,6 +53,7 @@ struct intel_plane_state {
 	bool dirty;
 	bool pinned;
 	bool changed;
+	struct drm_pending_atomic_event *event;
 
 	struct {
 		struct drm_crtc *crtc;
@@ -74,6 +75,7 @@ struct intel_crtc_state {
 	unsigned long connectors_bitmask;
 	unsigned long encoders_bitmask;
 	bool changed;
+	struct drm_pending_atomic_event *event;
 
 	struct {
 		bool enabled;
@@ -922,6 +924,111 @@ int intel_commit_plane_nopin(struct drm_plane *plane,
 			     struct drm_framebuffer *fb,
 			     const struct intel_plane_coords *coords);
 
+static struct drm_pending_atomic_event *alloc_event(struct drm_device *dev,
+						    struct drm_file *file_priv,
+						    uint64_t user_data)
+{
+	struct drm_pending_atomic_event *e;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->event_lock, flags);
+
+	if (file_priv->event_space < sizeof e->event) {
+		spin_unlock_irqrestore(&dev->event_lock, flags);
+		return ERR_PTR(-ENOSPC);
+	}
+
+	file_priv->event_space -= sizeof e->event;
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+
+	e = kzalloc(sizeof *e, GFP_KERNEL);
+	if (!e) {
+		spin_lock_irqsave(&dev->event_lock, flags);
+		file_priv->event_space += sizeof e->event;
+		spin_unlock_irqrestore(&dev->event_lock, flags);
+
+		return ERR_PTR(-ENOMEM);
+	}
+
+	e->event.base.type = DRM_EVENT_ATOMIC_COMPLETE;
+	e->event.base.length = sizeof e->event;
+	e->event.user_data = user_data;
+	e->base.event = &e->event.base;
+	e->base.file_priv = file_priv;
+	e->base.destroy = (void (*) (struct drm_pending_event *)) kfree;
+
+	return e;
+}
+
+static void free_event(struct drm_pending_atomic_event *e)
+{
+	e->base.file_priv->event_space += sizeof e->event;
+	kfree(e);
+}
+
+static void queue_event(struct drm_device *dev, struct drm_crtc *crtc,
+			struct drm_pending_atomic_event *e)
+{
+	struct timeval tvbl;
+
+	if (crtc) {
+		int pipe = to_intel_crtc(crtc)->pipe;
+
+		/* FIXME this is wrong for flips that are completed not at vblank */
+		e->event.sequence = drm_vblank_count_and_time(dev, pipe, &tvbl);
+		e->event.tv_sec = tvbl.tv_sec;
+		e->event.tv_usec = tvbl.tv_usec;
+	} else {
+		e->event.sequence = 0;
+		e->event.tv_sec = 0;
+		e->event.tv_usec = 0;
+	}
+
+	list_add_tail(&e->base.link, &e->base.file_priv->event_list);
+	wake_up_interruptible(&e->base.file_priv->event_wait);
+}
+
+static void queue_remaining_events(struct drm_device *dev, struct intel_atomic_state *s)
+{
+	int i;
+
+	for (i = 0; i < dev->mode_config.num_crtc; i++) {
+		struct intel_crtc_state *st = &s->crtc[i];
+
+		if (st->event) {
+			if (st->old.fb)
+				st->event->event.old_fb_id = st->old.fb->base.id;
+
+			spin_lock_irq(&dev->event_lock);
+			queue_event(dev, st->crtc, st->event);
+			spin_unlock_irq(&dev->event_lock);
+
+			st->event = NULL;
+		}
+	}
+
+	for (i = 0; i < dev->mode_config.num_plane; i++) {
+		struct intel_plane_state *st = &s->plane[i];
+		struct drm_crtc *crtc;
+
+		if (!st->event)
+			continue;
+
+		crtc = st->plane->crtc;
+		if (!crtc)
+			crtc = st->old.crtc;
+
+		if (st->old.fb)
+			st->event->event.old_fb_id = st->old.fb->base.id;
+
+		spin_lock_irq(&dev->event_lock);
+		queue_event(dev, crtc, st->event);
+		spin_unlock_irq(&dev->event_lock);
+
+		st->event = NULL;
+	}
+}
+
 static void swap_old_new(struct drm_device *dev,
 			 struct intel_atomic_state *s)
 {
@@ -1426,6 +1533,73 @@ static void update_crtc(struct drm_device *dev,
 	}
 }
 
+static int alloc_flip_data(struct drm_device *dev, struct intel_atomic_state *s)
+{
+	int i;
+
+	for (i = 0; i < dev->mode_config.num_crtc; i++) {
+		struct intel_crtc_state *st = &s->crtc[i];
+
+		if (st->changed && s->flags & DRM_MODE_ATOMIC_EVENT) {
+			struct drm_pending_atomic_event *e;
+
+			e = alloc_event(dev, s->file, s->user_data);
+			if (IS_ERR(e))
+				return PTR_ERR(e);
+
+			e->event.obj_id = st->crtc->base.id;
+
+			st->event = e;
+		}
+	}
+
+
+	for (i = 0; i < dev->mode_config.num_plane; i++) {
+		struct intel_plane_state *st = &s->plane[i];
+
+		if (st->changed && s->flags & DRM_MODE_ATOMIC_EVENT) {
+			struct drm_pending_atomic_event *e;
+
+			e = alloc_event(dev, s->file, s->user_data);
+			if (IS_ERR(e))
+				return PTR_ERR(e);
+
+			e->event.obj_id = st->plane->base.id;
+
+			st->event = e;
+		}
+	}
+
+	return 0;
+}
+
+static void free_flip_data(struct drm_device *dev, struct intel_atomic_state *s)
+{
+	int i;
+
+	for (i = 0; i < dev->mode_config.num_crtc; i++) {
+		struct intel_crtc_state *st = &s->crtc[i];
+
+		if (st->event) {
+			spin_lock_irq(&dev->event_lock);
+			free_event(st->event);
+			spin_unlock_irq(&dev->event_lock);
+			st->event = NULL;
+		}
+	}
+
+	for (i = 0; i < dev->mode_config.num_plane; i++) {
+		struct intel_plane_state *st = &s->plane[i];
+
+		if (st->event) {
+			spin_lock_irq(&dev->event_lock);
+			free_event(st->event);
+			spin_unlock_irq(&dev->event_lock);
+			st->event = NULL;
+		}
+	}
+}
+
 static int intel_atomic_commit(struct drm_device *dev, void *state)
 {
 	struct intel_atomic_state *s = state;
@@ -1434,12 +1608,13 @@ static int intel_atomic_commit(struct drm_device *dev, void *state)
 	if (s->flags & DRM_MODE_ATOMIC_NONBLOCK)
 		return -ENOSYS;
 
-	if (s->flags & DRM_MODE_ATOMIC_EVENT)
-		return -ENOSYS;
-
 	if (!s->dirty)
 		return 0;
 
+	ret = alloc_flip_data(dev, s);
+	if (ret)
+		return ret;
+
 	ret = pin_fbs(dev, s);
 	if (ret)
 		return ret;
@@ -1460,6 +1635,17 @@ static int intel_atomic_commit(struct drm_device *dev, void *state)
 	unpin_old_cursors(dev, s);
 	unpin_old_fbs(dev, s);
 
+	/*
+	 * Either we took the blocking code path, or perhaps the state of
+	 * some objects didn't actually change? Nonetheless the user wanted
+	 * events for all objects he touched, so queue up any events that
+	 * are still pending.
+	 *
+	 * FIXME this needs more work. If the previous flip is still pending
+	 * we shouldn't send this event until that flip completes.
+	 */
+	queue_remaining_events(dev, s);
+
 	update_plane_obj(dev, s);
 
 	update_crtc(dev, s);
@@ -1473,6 +1659,9 @@ static void intel_atomic_end(struct drm_device *dev, void *state)
 {
 	struct intel_atomic_state *s = state;
 
+	/* don't send events when restoring old state */
+	free_flip_data(dev, state);
+
 	/* restore the state of all objects */
 	if (s->restore_state)
 		restore_state(dev, state);
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 37/81] drm/i915: Add atomic page flip support
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (35 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 36/81] drm/i915: Add support for atomic modesetting completion events ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 38/81] drm/i915: Unstatic intel_enable_primary() and intel_disable_primary() ville.syrjala
                   ` (45 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Add support for the DRM_MODE_ATOMIC_NONBLOCK flag.

The drm_flip helper provides the necessary logic to track the
progress of the flips. drm_flip is driven by a few extra calls
from the interrupt handling and crtc_disable code paths.

Since the hardware doesn't provide inter-plane synchronization, some
extra software magic is required to avoid flips for multiple planes
ending up on the wrong sides of the vblank leading edge.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_dma.c      |    3 +
 drivers/gpu/drm/i915/i915_drv.h      |    4 +
 drivers/gpu/drm/i915/i915_irq.c      |   16 +-
 drivers/gpu/drm/i915/intel_atomic.c  |  622 +++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_display.c |    2 +
 drivers/gpu/drm/i915/intel_drv.h     |    7 +
 6 files changed, 637 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 392c9a1..8501bf3 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1764,6 +1764,8 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file)
 
 	idr_init(&file_priv->context_idr);
 
+	INIT_LIST_HEAD(&file_priv->pending_flips);
+
 	return 0;
 }
 
@@ -1804,6 +1806,7 @@ void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
 {
 	i915_gem_context_close(dev, file_priv);
 	i915_gem_release(dev, file_priv);
+	intel_atomic_free_events(dev, file_priv);
 }
 
 void i915_driver_postclose(struct drm_device *dev, struct drm_file *file)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 66b3b64..0bafe7f 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -38,6 +38,7 @@
 #include <linux/io-mapping.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
+#include <drm/drm_flip.h>
 #include <drm/intel-gtt.h>
 #include <linux/backlight.h>
 #include <linux/intel-iommu.h>
@@ -957,6 +958,8 @@ typedef struct drm_i915_private {
 	/* Old dri1 support infrastructure, beware the dragons ya fools entering
 	 * here! */
 	struct i915_dri1_state dri1;
+
+	struct drm_flip_driver flip_driver;
 } drm_i915_private_t;
 
 /* Iterate over initialised rings */
@@ -1179,6 +1182,7 @@ struct drm_i915_file_private {
 		struct list_head request_list;
 	} mm;
 	struct idr context_idr;
+	struct list_head pending_flips;
 };
 
 #define INTEL_INFO(dev)	(((struct drm_i915_private *) (dev)->dev_private)->info)
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index d02e022..430f201 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -581,8 +581,10 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
 		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
 		for_each_pipe(pipe) {
-			if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS)
+			if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) {
 				drm_handle_vblank(dev, pipe);
+				intel_atomic_handle_vblank(dev, pipe);
+			}
 
 			if (pipe_stats[pipe] & PLANE_FLIPDONE_INT_STATUS_VLV) {
 				intel_prepare_page_flip(dev, pipe);
@@ -727,8 +729,10 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg)
 			intel_opregion_gse_intr(dev);
 
 		for (i = 0; i < 3; i++) {
-			if (de_iir & (DE_PIPEA_VBLANK_IVB << (5 * i)))
+			if (de_iir & (DE_PIPEA_VBLANK_IVB << (5 * i))) {
 				drm_handle_vblank(dev, i);
+				intel_atomic_handle_vblank(dev, i);
+			}
 			if (de_iir & (DE_PLANEA_FLIP_DONE_IVB << (5 * i))) {
 				intel_prepare_page_flip(dev, i);
 				intel_finish_page_flip_plane(dev, i);
@@ -807,11 +811,15 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
 	if (de_iir & DE_GSE)
 		intel_opregion_gse_intr(dev);
 
-	if (de_iir & DE_PIPEA_VBLANK)
+	if (de_iir & DE_PIPEA_VBLANK) {
 		drm_handle_vblank(dev, 0);
+		intel_atomic_handle_vblank(dev, 0);
+	}
 
-	if (de_iir & DE_PIPEB_VBLANK)
+	if (de_iir & DE_PIPEB_VBLANK) {
 		drm_handle_vblank(dev, 1);
+		intel_atomic_handle_vblank(dev, 1);
+	}
 
 	if (de_iir & DE_PLANEA_FLIP_DONE) {
 		intel_prepare_page_flip(dev, 0);
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 3adb140..238a843 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -26,6 +26,7 @@
 
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
+#include <drm/drm_flip.h>
 
 #include "intel_drv.h"
 
@@ -47,6 +48,20 @@ static struct drm_property *prop_cursor_y;
 static struct drm_property *prop_cursor_w;
 static struct drm_property *prop_cursor_h;
 
+struct intel_flip {
+	struct drm_flip base;
+	u32 vbl_count;
+	bool vblank_ref;
+	bool has_cursor;
+	struct drm_crtc *crtc;
+	struct drm_plane *plane;
+	struct drm_i915_gem_object *old_bo;
+	struct drm_i915_gem_object *old_cursor_bo;
+	struct drm_pending_atomic_event *event;
+	uint32_t old_fb_id;
+	struct list_head pending_head;
+};
+
 struct intel_plane_state {
 	struct drm_plane *plane;
 	struct intel_plane_coords coords;
@@ -54,6 +69,7 @@ struct intel_plane_state {
 	bool pinned;
 	bool changed;
 	struct drm_pending_atomic_event *event;
+	struct intel_flip *flip;
 
 	struct {
 		struct drm_crtc *crtc;
@@ -76,6 +92,7 @@ struct intel_crtc_state {
 	unsigned long encoders_bitmask;
 	bool changed;
 	struct drm_pending_atomic_event *event;
+	struct intel_flip *flip;
 
 	struct {
 		bool enabled;
@@ -966,6 +983,22 @@ static void free_event(struct drm_pending_atomic_event *e)
 	kfree(e);
 }
 
+void intel_atomic_free_events(struct drm_device *dev, struct drm_file *file)
+{
+	struct drm_i915_file_private *file_priv = file->driver_priv;
+	struct intel_flip *intel_flip, *next;
+
+	spin_lock_irq(&dev->event_lock);
+
+	list_for_each_entry_safe(intel_flip, next, &file_priv->pending_flips, pending_head) {
+		free_event(intel_flip->event);
+		intel_flip->event = NULL;
+		list_del_init(&intel_flip->pending_head);
+	}
+
+	spin_unlock_irq(&dev->event_lock);
+}
+
 static void queue_event(struct drm_device *dev, struct drm_crtc *crtc,
 			struct drm_pending_atomic_event *e)
 {
@@ -1533,6 +1566,60 @@ static void update_crtc(struct drm_device *dev,
 	}
 }
 
+static void atomic_pipe_commit(struct drm_device *dev,
+			       struct intel_atomic_state *state,
+			       int pipe);
+
+static int apply_nonblocking(struct drm_device *dev, struct intel_atomic_state *s)
+{
+	struct intel_crtc *intel_crtc;
+	int i;
+
+	for (i = 0; i < dev->mode_config.num_crtc; i++) {
+		struct intel_crtc_state *st = &s->crtc[i];
+		struct intel_crtc *intel_crtc = to_intel_crtc(st->crtc);
+		struct drm_i915_gem_object *obj;
+
+		if (!st->old.fb)
+			continue;
+
+		obj = to_intel_framebuffer(st->old.fb)->obj;
+
+		/* Only one bit per plane in pending_flips */
+		if (atomic_read(&obj->pending_flip) & (1 << intel_crtc->plane))
+			return -EBUSY;
+	}
+
+	for (i = 0; i < dev->mode_config.num_plane; i++) {
+		struct intel_plane_state *st = &s->plane[i];
+		struct intel_plane *intel_plane = to_intel_plane(st->plane);
+		struct drm_i915_gem_object *obj;
+
+		if (!st->old.fb)
+			continue;
+
+		obj = to_intel_framebuffer(st->old.fb)->obj;
+
+		if (!st->old.fb)
+			continue;
+
+		obj = to_intel_framebuffer(st->old.fb)->obj;
+
+		/* Only one bit per plane in pending_flips */
+		if (atomic_read(&obj->pending_flip) & (1 << (16 + intel_plane->pipe)))
+			return -EBUSY;
+	}
+
+	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head)
+		atomic_pipe_commit(dev, s, intel_crtc->pipe);
+
+	/* don't restore the old state in end() */
+	s->dirty = false;
+	s->restore_state = false;
+
+	return 0;
+}
+
 static int alloc_flip_data(struct drm_device *dev, struct intel_atomic_state *s)
 {
 	int i;
@@ -1551,6 +1638,13 @@ static int alloc_flip_data(struct drm_device *dev, struct intel_atomic_state *s)
 
 			st->event = e;
 		}
+
+		if (!st->fb_dirty && !st->mode_dirty && !st->cursor_dirty)
+			continue;
+
+		st->flip = kzalloc(sizeof *st->flip, GFP_KERNEL);
+		if (!st->flip)
+			return -ENOMEM;
 	}
 
 
@@ -1568,6 +1662,13 @@ static int alloc_flip_data(struct drm_device *dev, struct intel_atomic_state *s)
 
 			st->event = e;
 		}
+
+		if (!st->dirty)
+			continue;
+
+		st->flip = kzalloc(sizeof *st->flip, GFP_KERNEL);
+		if (!st->flip)
+			return -ENOMEM;
 	}
 
 	return 0;
@@ -1586,6 +1687,9 @@ static void free_flip_data(struct drm_device *dev, struct intel_atomic_state *s)
 			spin_unlock_irq(&dev->event_lock);
 			st->event = NULL;
 		}
+
+		kfree(st->flip);
+		st->flip = NULL;
 	}
 
 	for (i = 0; i < dev->mode_config.num_plane; i++) {
@@ -1597,6 +1701,9 @@ static void free_flip_data(struct drm_device *dev, struct intel_atomic_state *s)
 			spin_unlock_irq(&dev->event_lock);
 			st->event = NULL;
 		}
+
+		kfree(st->flip);
+		st->flip = NULL;
 	}
 }
 
@@ -1605,9 +1712,6 @@ static int intel_atomic_commit(struct drm_device *dev, void *state)
 	struct intel_atomic_state *s = state;
 	int ret;
 
-	if (s->flags & DRM_MODE_ATOMIC_NONBLOCK)
-		return -ENOSYS;
-
 	if (!s->dirty)
 		return 0;
 
@@ -1623,17 +1727,27 @@ static int intel_atomic_commit(struct drm_device *dev, void *state)
 	if (ret)
 		return ret;
 
-	/* apply in a blocking manner */
-	ret = apply_config(dev, s);
-	if (ret) {
-		unpin_cursors(dev, s);
-		unpin_fbs(dev, s);
-		s->restore_hw = true;
-		return ret;
-	}
+	/* try to apply in a non blocking manner */
+	if (s->flags & DRM_MODE_ATOMIC_NONBLOCK) {
+		ret = apply_nonblocking(dev, s);
+		if (ret) {
+			unpin_cursors(dev, s);
+			unpin_fbs(dev, s);
+			return ret;
+		}
+	} else {
+		/* apply in a blocking manner */
+		ret = apply_config(dev, s);
+		if (ret) {
+			unpin_cursors(dev, s);
+			unpin_fbs(dev, s);
+			s->restore_hw = true;
+			return ret;
+		}
 
-	unpin_old_cursors(dev, s);
-	unpin_old_fbs(dev, s);
+		unpin_old_cursors(dev, s);
+		unpin_old_fbs(dev, s);
+	}
 
 	/*
 	 * Either we took the blocking code path, or perhaps the state of
@@ -1703,6 +1817,9 @@ static struct {
 	{ &prop_cursor_y, "CURSOR_Y", INT_MIN, INT_MAX },
 };
 
+static void intel_flip_init(struct drm_device *dev);
+static void intel_flip_fini(struct drm_device *dev);
+
 int intel_atomic_init(struct drm_device *dev)
 {
 	struct drm_crtc *crtc;
@@ -1776,6 +1893,8 @@ int intel_atomic_init(struct drm_device *dev)
 
 	dev->driver->atomic_funcs = &intel_atomic_funcs;
 
+	intel_flip_init(dev);
+
 	return 0;
 
  out:
@@ -1792,6 +1911,8 @@ void intel_atomic_fini(struct drm_device *dev)
 {
 	struct drm_crtc *crtc;
 
+	intel_flip_fini(dev);
+
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		drm_property_destroy_blob(dev, crtc->mode_blob);
 		drm_property_destroy_blob(dev, crtc->connector_ids_blob);
@@ -1812,3 +1933,478 @@ void intel_atomic_fini(struct drm_device *dev)
 	drm_property_destroy(dev, prop_src_y);
 	drm_property_destroy(dev, prop_src_x);
 }
+
+enum {
+	/* somwehat arbitrary value */
+	INTEL_VBL_CNT_TIMEOUT = 5,
+};
+
+static void intel_flip_complete(struct drm_flip *flip)
+{
+	struct intel_flip *intel_flip =
+		container_of(flip, struct intel_flip, base);
+	struct drm_device *dev = intel_flip->crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc = intel_flip->crtc;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int pipe = intel_crtc->pipe;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->event_lock, flags);
+
+	if (intel_flip->event) {
+		list_del_init(&intel_flip->pending_head);
+		intel_flip->event->event.old_fb_id = intel_flip->old_fb_id;
+		queue_event(dev, crtc, intel_flip->event);
+	}
+
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+
+	if (intel_flip->vblank_ref)
+		drm_vblank_put(dev, pipe);
+
+	/* Possibly allow rendering to old_bo again */
+	if (intel_flip->old_bo) {
+		if (intel_flip->plane) {
+			struct intel_plane *intel_plane = to_intel_plane(intel_flip->plane);
+			atomic_clear_mask(1 << (16 + intel_plane->pipe), &intel_flip->old_bo->pending_flip.counter);
+		} else
+			atomic_clear_mask(1 << intel_crtc->plane, &intel_flip->old_bo->pending_flip.counter);
+
+		if (atomic_read(&intel_flip->old_bo->pending_flip) == 0)
+			wake_up(&dev_priv->pending_flip_queue);
+	}
+}
+
+static void intel_flip_finish(struct drm_flip *flip)
+{
+	struct intel_flip *intel_flip =
+		container_of(flip, struct intel_flip, base);
+	struct drm_device *dev = intel_flip->crtc->dev;
+
+	if (intel_flip->old_bo) {
+		mutex_lock(&dev->struct_mutex);
+
+		intel_unpin_fb_obj(intel_flip->old_bo);
+
+		drm_gem_object_unreference(&intel_flip->old_bo->base);
+
+		mutex_unlock(&dev->struct_mutex);
+	}
+
+	if (intel_flip->old_cursor_bo)
+		intel_crtc_cursor_bo_unref(intel_flip->crtc, intel_flip->old_cursor_bo);
+}
+
+static void intel_flip_cleanup(struct drm_flip *flip)
+{
+	struct intel_flip *intel_flip =
+		container_of(flip, struct intel_flip, base);
+
+	kfree(intel_flip);
+}
+
+static void intel_flip_driver_flush(struct drm_flip_driver *driver)
+{
+	struct drm_i915_private *dev_priv =
+		container_of(driver, struct drm_i915_private, flip_driver);
+
+	/* Flush posted writes */
+	I915_READ(PIPEDSL(PIPE_A));
+}
+
+static bool intel_have_new_frmcount(struct drm_device *dev)
+{
+	return IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5;
+}
+
+static u32 get_vbl_count(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int pipe = intel_crtc->pipe;
+
+	if (intel_have_new_frmcount(dev)) {
+		return I915_READ(PIPE_FRMCOUNT_GM45(pipe));
+	} else  {
+		u32 high, low1, low2, dsl;
+		unsigned int timeout = 0;
+
+		/*
+		 * FIXME check where the frame counter increments, and if
+		 * it happens in the middle of some line, take appropriate
+		 * measures to get a sensible reading.
+		 */
+
+		/* All reads must be satisfied during the same frame */
+		do {
+			low1 = I915_READ(PIPEFRAMEPIXEL(pipe)) >> PIPE_FRAME_LOW_SHIFT;
+			high = I915_READ(PIPEFRAME(pipe)) << 8;
+			dsl = I915_READ(PIPEDSL(pipe));
+			low2 = I915_READ(PIPEFRAMEPIXEL(pipe)) >> PIPE_FRAME_LOW_SHIFT;
+		} while (low1 != low2 && timeout++ < INTEL_VBL_CNT_TIMEOUT);
+
+		if (timeout >= INTEL_VBL_CNT_TIMEOUT)
+			dev_warn(dev->dev,
+				 "Timed out while determining VBL count for pipe %d\n", pipe);
+
+		return ((high | low2) +
+			((dsl >= crtc->hwmode.crtc_vdisplay) &&
+			 (dsl < crtc->hwmode.crtc_vtotal - 1))) & 0xffffff;
+	}
+}
+
+static unsigned int usecs_to_scanlines(struct drm_crtc *crtc,
+				       unsigned int usecs)
+{
+	/* paranoia */
+	if (!crtc->hwmode.crtc_htotal)
+		return 1;
+
+	return DIV_ROUND_UP(usecs * crtc->hwmode.clock,
+			    1000 * crtc->hwmode.crtc_htotal);
+}
+
+static void intel_pipe_vblank_evade(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int pipe = intel_crtc->pipe;
+	/* FIXME needs to be calibrated sensibly */
+	u32 min = crtc->hwmode.crtc_vdisplay - usecs_to_scanlines(crtc, 50);
+	u32 max = crtc->hwmode.crtc_vdisplay - 1;
+	long timeout = msecs_to_jiffies(3);
+	u32 val;
+
+	bool vblank_ref = drm_vblank_get(dev, pipe) == 0;
+
+	intel_crtc->vbl_received = false;
+
+	val = I915_READ(PIPEDSL(pipe));
+
+	while (val >= min && val <= max && timeout > 0) {
+		local_irq_enable();
+
+		timeout = wait_event_timeout(intel_crtc->vbl_wait,
+					     intel_crtc->vbl_received,
+					     timeout);
+
+		local_irq_disable();
+
+		intel_crtc->vbl_received = false;
+
+		val = I915_READ(PIPEDSL(pipe));
+	}
+
+	if (vblank_ref)
+		drm_vblank_put(dev, pipe);
+
+	if (val >= min && val <= max)
+		dev_warn(dev->dev,
+			 "Page flipping close to vblank start (DSL=%u, VBL=%u)\n",
+			 val, crtc->hwmode.crtc_vdisplay);
+}
+
+static bool vbl_count_after_eq_new(u32 a, u32 b)
+{
+	return !((a - b) & 0x80000000);
+}
+
+static bool vbl_count_after_eq(u32 a, u32 b)
+{
+	return !((a - b) & 0x800000);
+}
+
+static bool intel_vbl_check(struct drm_flip *pending_flip, u32 vbl_count)
+{
+	struct intel_flip *old_intel_flip =
+		container_of(pending_flip, struct intel_flip, base);
+	struct drm_device *dev = old_intel_flip->crtc->dev;
+
+	if (intel_have_new_frmcount(dev))
+		return vbl_count_after_eq_new(vbl_count, old_intel_flip->vbl_count);
+	else
+		return vbl_count_after_eq(vbl_count, old_intel_flip->vbl_count);
+}
+
+static void intel_flip_prepare(struct drm_flip *flip)
+{
+	struct intel_flip *intel_flip =
+		container_of(flip, struct intel_flip, base);
+
+	if (intel_flip->plane) {
+		struct drm_plane *plane = intel_flip->plane;
+		struct intel_plane *intel_plane = to_intel_plane(plane);
+
+		intel_plane->prepare(plane);
+	}
+}
+
+static bool intel_flip_flip(struct drm_flip *flip,
+			    struct drm_flip *pending_flip)
+{
+	struct intel_flip *intel_flip = container_of(flip, struct intel_flip, base);
+	struct drm_crtc *crtc = intel_flip->crtc;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	int pipe = intel_crtc->pipe;
+	u32 vbl_count;
+
+	intel_flip->vblank_ref = drm_vblank_get(dev, pipe) == 0;
+
+	vbl_count = get_vbl_count(crtc);
+
+	/* arm all the double buffer registers */
+	if (intel_flip->plane) {
+		struct drm_plane *plane = intel_flip->plane;
+		struct intel_plane *intel_plane = to_intel_plane(plane);
+
+		intel_plane->commit(plane);
+	} else {
+		struct drm_i915_private *dev_priv = dev->dev_private;
+
+		dev_priv->display.commit_plane(crtc);
+	}
+
+	if (intel_flip->has_cursor)
+		intel_crtc_cursor_commit(crtc,
+					 intel_crtc->cursor_handle,
+					 intel_crtc->cursor_width,
+					 intel_crtc->cursor_height,
+					 intel_crtc->cursor_bo,
+					 intel_crtc->cursor_addr);
+
+	/* This flip will happen on the next vblank */
+	if (intel_have_new_frmcount(dev))
+		intel_flip->vbl_count = vbl_count + 1;
+	else
+		intel_flip->vbl_count = (vbl_count + 1) & 0xffffff;
+
+	if (pending_flip) {
+		struct intel_flip *old_intel_flip =
+			container_of(pending_flip, struct intel_flip, base);
+		bool flipped = intel_vbl_check(pending_flip, vbl_count);
+
+		if (!flipped) {
+			swap(intel_flip->old_fb_id, old_intel_flip->old_fb_id);
+			swap(intel_flip->old_bo, old_intel_flip->old_bo);
+			swap(intel_flip->old_cursor_bo, old_intel_flip->old_cursor_bo);
+		}
+
+		return flipped;
+	}
+
+	return false;
+}
+
+static bool intel_flip_vblank(struct drm_flip *pending_flip)
+{
+	struct intel_flip *old_intel_flip =
+		container_of(pending_flip, struct intel_flip, base);
+	u32 vbl_count = get_vbl_count(old_intel_flip->crtc);
+
+	return intel_vbl_check(pending_flip, vbl_count);
+}
+
+static const struct drm_flip_helper_funcs intel_flip_funcs = {
+	.prepare = intel_flip_prepare,
+	.flip = intel_flip_flip,
+	.vblank = intel_flip_vblank,
+	.complete = intel_flip_complete,
+	.finish = intel_flip_finish,
+	.cleanup = intel_flip_cleanup,
+};
+
+static const struct drm_flip_driver_funcs intel_flip_driver_funcs = {
+	.flush = intel_flip_driver_flush,
+};
+
+static void intel_flip_init(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc;
+	struct intel_plane *intel_plane;
+
+	drm_flip_driver_init(&dev_priv->flip_driver, &intel_flip_driver_funcs);
+
+	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) {
+		init_waitqueue_head(&intel_crtc->vbl_wait);
+
+		drm_flip_helper_init(&intel_crtc->flip_helper,
+				     &dev_priv->flip_driver, &intel_flip_funcs);
+	}
+
+	list_for_each_entry(intel_plane, &dev->mode_config.plane_list, base.head)
+		drm_flip_helper_init(&intel_plane->flip_helper,
+				     &dev_priv->flip_driver, &intel_flip_funcs);
+}
+
+static void intel_flip_fini(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc;
+	struct intel_plane *intel_plane;
+
+	list_for_each_entry(intel_plane, &dev->mode_config.plane_list, base.head)
+		drm_flip_helper_fini(&intel_plane->flip_helper);
+
+	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head)
+		drm_flip_helper_fini(&intel_crtc->flip_helper);
+
+	drm_flip_driver_fini(&dev_priv->flip_driver);
+}
+
+static void atomic_pipe_commit(struct drm_device *dev,
+			       struct intel_atomic_state *state,
+			       int pipe)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_file_private *file_priv = state->file->driver_priv;
+	LIST_HEAD(flips);
+	int i;
+	bool pipe_enabled = to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe))->active;
+
+	for (i = 0; i < dev->mode_config.num_crtc; i++) {
+		struct intel_crtc_state *st = &state->crtc[i];
+		struct drm_crtc *crtc = st->crtc;
+		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+		struct intel_flip *intel_flip;
+
+		if (!st->fb_dirty && !st->cursor_dirty)
+			continue;
+
+		if (intel_crtc->pipe != pipe)
+			continue;
+
+		intel_flip = st->flip;
+		st->flip = NULL;
+
+		drm_flip_init(&intel_flip->base, &intel_crtc->flip_helper);
+
+		if (st->event) {
+			intel_flip->event = st->event;
+			st->event = NULL;
+			/* need to keep track of it in case process exits */
+			spin_lock_irq(&dev->event_lock);
+			list_add_tail(&intel_flip->pending_head,
+				      &file_priv->pending_flips);
+			spin_unlock_irq(&dev->event_lock);
+		}
+
+		intel_flip->crtc = crtc;
+
+		/* should already be checked so can't fail */
+		/* FIXME refactor the failing parts? */
+		dev_priv->display.calc_plane(crtc, crtc->fb, crtc->x, crtc->y);
+
+		if (st->cursor_dirty) {
+			intel_flip->has_cursor = true;
+			intel_flip->old_cursor_bo = st->old.cursor_bo;
+		}
+
+		if (st->old.fb) {
+			intel_flip->old_fb_id = st->old.fb->base.id;
+			intel_flip->old_bo = to_intel_framebuffer(st->old.fb)->obj;
+
+			mutex_lock(&dev->struct_mutex);
+			drm_gem_object_reference(&intel_flip->old_bo->base);
+			mutex_unlock(&dev->struct_mutex);
+
+			/*
+			 * Block clients from rendering to the new back buffer until
+			 * the flip occurs and the object is no longer visible.
+			 */
+			atomic_set_mask(1 << intel_crtc->plane,
+					&intel_flip->old_bo->pending_flip.counter);
+		}
+
+		list_add_tail(&intel_flip->base.list, &flips);
+	}
+
+	for (i = 0; i < dev->mode_config.num_plane; i++) {
+		struct intel_plane_state *st = &state->plane[i];
+		struct drm_plane *plane = st->plane;
+		struct intel_plane *intel_plane = to_intel_plane(plane);
+		struct intel_flip *intel_flip;
+
+		if (!st->dirty)
+			continue;
+
+		if (intel_plane->pipe != pipe)
+			continue;
+
+		intel_flip = st->flip;
+		st->flip = NULL;
+
+		drm_flip_init(&intel_flip->base, &intel_plane->flip_helper);
+
+		if (st->event) {
+			intel_flip->event = st->event;
+			st->event = NULL;
+			/* need to keep track of it in case process exits */
+			spin_lock_irq(&dev->event_lock);
+			list_add_tail(&intel_flip->pending_head,
+				      &file_priv->pending_flips);
+			spin_unlock_irq(&dev->event_lock);
+		}
+
+		intel_flip->crtc = intel_get_crtc_for_pipe(dev, pipe);
+		intel_flip->plane = plane;
+
+		intel_plane->calc(plane, plane->fb, &st->coords);
+
+		if (st->old.fb) {
+			intel_flip->old_fb_id = st->old.fb->base.id;
+			intel_flip->old_bo = to_intel_framebuffer(st->old.fb)->obj;
+
+			mutex_lock(&dev->struct_mutex);
+			drm_gem_object_reference(&intel_flip->old_bo->base);
+			mutex_unlock(&dev->struct_mutex);
+
+			/*
+			 * Block clients from rendering to the new back buffer until
+			 * the flip occurs and the object is no longer visible.
+			 */
+			atomic_set_mask(1 << (16 + intel_plane->pipe),
+					&intel_flip->old_bo->pending_flip.counter);
+		}
+
+		list_add_tail(&intel_flip->base.list, &flips);
+	}
+
+	if (list_empty(&flips))
+		return;
+
+	if (!pipe_enabled) {
+		drm_flip_driver_complete_flips(&dev_priv->flip_driver, &flips);
+		return;
+	}
+
+	drm_flip_driver_prepare_flips(&dev_priv->flip_driver, &flips);
+
+	local_irq_disable();
+
+	intel_pipe_vblank_evade(intel_get_crtc_for_pipe(dev, pipe));
+
+	drm_flip_driver_schedule_flips(&dev_priv->flip_driver, &flips);
+
+	local_irq_enable();
+}
+
+void intel_atomic_handle_vblank(struct drm_device *dev, int pipe)
+{
+	struct intel_crtc *intel_crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe));
+	struct intel_plane *intel_plane;
+
+	intel_crtc->vbl_received = true;
+	wake_up(&intel_crtc->vbl_wait);
+
+	drm_flip_helper_vblank(&intel_crtc->flip_helper);
+
+	list_for_each_entry(intel_plane, &dev->mode_config.plane_list, base.head) {
+		if (intel_plane->pipe == pipe)
+			drm_flip_helper_vblank(&intel_plane->flip_helper);
+	}
+}
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 62e2a56..7394aca 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3554,6 +3554,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
 		encoder->disable(encoder);
 
 	intel_crtc_wait_for_pending_flips(crtc);
+	drm_flip_helper_clear(&intel_crtc->flip_helper);
 	drm_vblank_off(dev, pipe);
 	intel_crtc_update_cursor(crtc, false);
 
@@ -3674,6 +3675,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
 
 	/* Give the overlay scaler a chance to disable if it's on this pipe */
 	intel_crtc_wait_for_pending_flips(crtc);
+	drm_flip_helper_clear(&intel_crtc->flip_helper);
 	drm_vblank_off(dev, pipe);
 	intel_crtc_dpms_overlay(intel_crtc, false);
 	intel_crtc_update_cursor(crtc, false);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 103d104..cd37428 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -32,6 +32,7 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_dp_helper.h>
+#include <drm/drm_flip.h>
 
 #define _wait_for(COND, MS, W) ({ \
 	unsigned long timeout__ = jiffies + msecs_to_jiffies(MS);	\
@@ -244,6 +245,9 @@ struct intel_crtc {
 	struct intel_pch_pll *pch_pll;
 	uint32_t ddi_pll_sel;
 	struct intel_plane_regs primary_regs;
+	struct drm_flip_helper flip_helper;
+	wait_queue_head_t vbl_wait;
+	bool vbl_received;
 };
 
 struct intel_plane_coords {
@@ -275,6 +279,7 @@ struct intel_plane {
 	void (*prepare)(struct drm_plane *plane);
 	void (*commit)(struct drm_plane *plane);
 	struct intel_plane_regs regs;
+	struct drm_flip_helper flip_helper;
 };
 
 struct intel_watermark_params {
@@ -722,5 +727,7 @@ extern bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
 
 extern int intel_atomic_init(struct drm_device *dev);
 extern void intel_atomic_fini(struct drm_device *dev);
+extern void intel_atomic_free_events(struct drm_device *dev, struct drm_file *file);
+extern void intel_atomic_handle_vblank(struct drm_device *dev, int pipe);
 
 #endif /* __INTEL_DRV_H__ */
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 38/81] drm/i915: Unstatic intel_enable_primary() and intel_disable_primary()
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (36 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 37/81] drm/i915: Add atomic page flip support ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 39/81] drm/i915: Respect primary_disabled in crtc_enable() ville.syrjala
                   ` (44 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

intel_enable_primary() and intel_disable_primary() are needed in the
atomic mode setting code.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_drv.h    |    3 +++
 drivers/gpu/drm/i915/intel_sprite.c |    4 ++--
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index cd37428..92a9518 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -730,4 +730,7 @@ extern void intel_atomic_fini(struct drm_device *dev);
 extern void intel_atomic_free_events(struct drm_device *dev, struct drm_file *file);
 extern void intel_atomic_handle_vblank(struct drm_device *dev, int pipe);
 
+extern void intel_enable_primary(struct drm_crtc *crtc);
+extern void intel_disable_primary(struct drm_crtc *crtc);
+
 #endif /* __INTEL_DRV_H__ */
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 88644df..693b265 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -610,7 +610,7 @@ void intel_calc_sprite(struct drm_plane *plane,
 		ilk_calc_plane(plane, fb, coords);
 }
 
-static void
+void
 intel_enable_primary(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
@@ -629,7 +629,7 @@ intel_enable_primary(struct drm_crtc *crtc)
 	dev_priv->display.commit_plane(crtc);
 }
 
-static void
+void
 intel_disable_primary(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 39/81] drm/i915: Respect primary_disabled in crtc_enable()
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (37 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 38/81] drm/i915: Unstatic intel_enable_primary() and intel_disable_primary() ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 40/81] drm/i915: Enable/disable primary plane in calc_plane() ville.syrjala
                   ` (43 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Check primary_disabled state before enabling the primary plane in
crtc_enable() hooks.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |    9 ++++++---
 1 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 7394aca..957907c 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3349,7 +3349,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	intel_crtc_load_lut(crtc);
 
 	intel_enable_pipe(dev_priv, pipe, is_pch_port);
-	intel_enable_plane(dev_priv, plane, pipe);
+	if (!intel_crtc->primary_disabled)
+		intel_enable_plane(dev_priv, plane, pipe);
 
 	if (is_pch_port)
 		ironlake_pch_enable(crtc);
@@ -3429,7 +3430,8 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
 	intel_ddi_enable_pipe_func(crtc);
 
 	intel_enable_pipe(dev_priv, pipe, is_pch_port);
-	intel_enable_plane(dev_priv, plane, pipe);
+	if (!intel_crtc->primary_disabled)
+		intel_enable_plane(dev_priv, plane, pipe);
 
 	if (is_pch_port)
 		lpt_pch_enable(crtc);
@@ -3644,7 +3646,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 
 	intel_enable_pll(dev_priv, pipe);
 	intel_enable_pipe(dev_priv, pipe, false);
-	intel_enable_plane(dev_priv, plane, pipe);
+	if (!intel_crtc->primary_disabled)
+		intel_enable_plane(dev_priv, plane, pipe);
 
 	intel_crtc_load_lut(crtc);
 	intel_update_fbc(dev);
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 40/81] drm/i915: Enable/disable primary plane in calc_plane()
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (38 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 39/81] drm/i915: Respect primary_disabled in crtc_enable() ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 41/81] drm/i915: Add primary plane disable logic to atomic mode setting code ville.syrjala
                   ` (42 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Check the active and primary_disabled flags and set the
DISPLAY_PLANE_ENABLE bit accordingly in calc_plane() hook for the
primary plane.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 957907c..9903456 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2068,6 +2068,11 @@ static int i9xx_calc_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 			regs->cntr &= ~DISPPLANE_TILED;
 	}
 
+	if (intel_crtc->active && !intel_crtc->primary_disabled)
+		regs->cntr |= DISPLAY_PLANE_ENABLE;
+	else
+		regs->cntr &= ~DISPLAY_PLANE_ENABLE;
+
 	linear_offset = y * fb->pitches[0] + x * cpp;
 
 	if (INTEL_INFO(dev)->gen >= 4) {
@@ -2175,6 +2180,11 @@ static int ironlake_calc_plane(struct drm_crtc *crtc,
 	/* must disable */
 	regs->cntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
 
+	if (intel_crtc->active && !intel_crtc->primary_disabled)
+		regs->cntr |= DISPLAY_PLANE_ENABLE;
+	else
+		regs->cntr &= ~DISPLAY_PLANE_ENABLE;
+
 	linear_offset = y * fb->pitches[0] + x * cpp;
 	intel_crtc->dspaddr_offset =
 		intel_gen4_compute_offset_xtiled(&x, &y,
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 41/81] drm/i915: Add primary plane disable logic to atomic mode setting code
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (39 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 40/81] drm/i915: Enable/disable primary plane in calc_plane() ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 42/81] drm: Add missing EXPORT_SYMBOL()s for drm_flip ville.syrjala
                   ` (41 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Enable/disable the primary plane accordingly when the sprite plane
coverage changes.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_atomic.c |   41 +++++++++++++++++++++++++++++++++++
 1 files changed, 41 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 238a843..41885fa 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -93,6 +93,7 @@ struct intel_crtc_state {
 	bool changed;
 	struct drm_pending_atomic_event *event;
 	struct intel_flip *flip;
+	bool primary_disabled;
 
 	struct {
 		bool enabled;
@@ -318,6 +319,8 @@ static void *intel_atomic_begin(struct drm_device *dev, struct drm_file *file,
 
 		s->old.connectors_bitmask = s->connectors_bitmask;
 		s->old.encoders_bitmask = s->encoders_bitmask;
+
+		s->primary_disabled = intel_crtc->primary_disabled;
 	}
 
 	i = 0;
@@ -1157,6 +1160,9 @@ static int apply_config(struct drm_device *dev,
 						 intel_crtc->cursor_addr);
 		}
 
+		if (!st->primary_disabled)
+			intel_enable_primary(crtc);
+
 		for (j = 0; j < dev->mode_config.num_plane; j++) {
 			struct intel_plane_state *pst = &s->plane[j];
 			struct drm_plane *plane = pst->plane;
@@ -1170,6 +1176,9 @@ static int apply_config(struct drm_device *dev,
 			else if (!pst->coords.visible && pst->old.crtc == crtc)
 				intel_plane->disable_plane(plane);
 		}
+
+		if (st->primary_disabled)
+			intel_disable_primary(crtc);
 	}
 
 	/* don't restore the old state in end() */
@@ -1207,6 +1216,7 @@ static void restore_state(struct drm_device *dev,
 		intel_crtc->cursor_width = s->saved_crtcs[i].cursor_width;
 		intel_crtc->cursor_height = s->saved_crtcs[i].cursor_height;
 		intel_crtc->cursor_visible = s->saved_crtcs[i].cursor_visible;
+		intel_crtc->primary_disabled = s->saved_crtcs[i].primary_disabled;
 
 		i++;
 	}
@@ -1346,6 +1356,28 @@ static int check_crtc(struct intel_crtc_state *s)
 	return 0;
 }
 
+static void update_primary_visibility(struct drm_device *dev,
+				      struct intel_atomic_state *s,
+				      const struct drm_crtc *crtc,
+				      const struct drm_plane *plane,
+				      const struct intel_plane_coords *coords)
+{
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	bool primary_disabled =
+		coords->visible &&
+		coords->crtc_x == 0 &&
+		coords->crtc_y == 0 &&
+		coords->crtc_w == crtc->mode.hdisplay &&
+		coords->crtc_h == crtc->mode.vdisplay;
+
+	if (primary_disabled != intel_crtc->primary_disabled) {
+		struct intel_crtc_state *st = get_crtc_state(dev, s, crtc);
+		st->fb_dirty = true;
+		st->primary_disabled = primary_disabled;
+		s->dirty = true;
+	}
+}
+
 static int intel_atomic_check(struct drm_device *dev, void *state)
 {
 	struct intel_atomic_state *s = state;
@@ -1430,6 +1462,12 @@ static int intel_atomic_check(struct drm_device *dev, void *state)
 		ret = intel_check_plane(plane, plane->crtc, plane->fb, &st->coords);
 		if (ret)
 			return ret;
+
+		/* FIXME doesn't correctly handle cases where plane moves between crtcs */
+		if (plane->crtc)
+			update_primary_visibility(dev, s, plane->crtc, plane, &st->coords);
+		else if (st->old.crtc)
+			update_primary_visibility(dev, s, st->old.crtc, plane, &st->coords);
 	}
 
 	return 0;
@@ -2295,6 +2333,9 @@ static void atomic_pipe_commit(struct drm_device *dev,
 
 		intel_flip->crtc = crtc;
 
+		/* update primary_disabled befoer calc_plane() */
+		intel_crtc->primary_disabled = st->primary_disabled;
+
 		/* should already be checked so can't fail */
 		/* FIXME refactor the failing parts? */
 		dev_priv->display.calc_plane(crtc, crtc->fb, crtc->x, crtc->y);
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 42/81] drm: Add missing EXPORT_SYMBOL()s for drm_flip
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (40 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 41/81] drm/i915: Add primary plane disable logic to atomic mode setting code ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 43/81] drm/i915: Clear flip helpers for sprites too ville.syrjala
                   ` (40 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>

---
 drivers/gpu/drm/drm_flip.c |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/drm_flip.c b/drivers/gpu/drm/drm_flip.c
index 6ccc3f8..a20e6a4 100644
--- a/drivers/gpu/drm/drm_flip.c
+++ b/drivers/gpu/drm/drm_flip.c
@@ -24,6 +24,7 @@
  * Ville Syrjälä <ville.syrjala@linux.intel.com>
  */
 
+#include <linux/export.h>
 #include <drm/drm_flip.h>
 
 static void drm_flip_driver_cleanup(struct work_struct *work)
@@ -141,6 +142,7 @@ void drm_flip_helper_init(struct drm_flip_helper *helper,
 	helper->driver = driver;
 	helper->funcs = funcs;
 }
+EXPORT_SYMBOL(drm_flip_helper_init);
 
 void drm_flip_helper_clear(struct drm_flip_helper *helper)
 {
@@ -176,6 +178,7 @@ void drm_flip_helper_clear(struct drm_flip_helper *helper)
 	if (need_cleanup)
 		queue_work(driver->wq, &driver->cleanup_work);
 }
+EXPORT_SYMBOL(drm_flip_helper_clear);
 
 void drm_flip_helper_fini(struct drm_flip_helper *helper)
 {
@@ -186,6 +189,7 @@ void drm_flip_helper_fini(struct drm_flip_helper *helper)
 	flush_work_sync(&driver->finish_work);
 	flush_work_sync(&driver->cleanup_work);
 }
+EXPORT_SYMBOL(drm_flip_helper_fini);
 
 void drm_flip_helper_vblank(struct drm_flip_helper *helper)
 {
@@ -223,6 +227,7 @@ void drm_flip_helper_vblank(struct drm_flip_helper *helper)
 	if (need_cleanup)
 		queue_work(driver->wq, &driver->cleanup_work);
 }
+EXPORT_SYMBOL(drm_flip_helper_vblank);
 
 void drm_flip_driver_init(struct drm_flip_driver *driver,
 			  const struct drm_flip_driver_funcs *funcs)
@@ -239,6 +244,7 @@ void drm_flip_driver_init(struct drm_flip_driver *driver,
 
 	driver->wq = create_singlethread_workqueue("drm_flip");
 }
+EXPORT_SYMBOL(drm_flip_driver_init);
 
 void drm_flip_driver_fini(struct drm_flip_driver *driver)
 {
@@ -248,6 +254,7 @@ void drm_flip_driver_fini(struct drm_flip_driver *driver)
 	WARN_ON(!list_empty(&driver->finish_list));
 	WARN_ON(!list_empty(&driver->cleanup_list));
 }
+EXPORT_SYMBOL(drm_flip_driver_fini);
 
 void drm_flip_driver_schedule_flips(struct drm_flip_driver *driver,
 				    struct list_head *flips)
@@ -298,6 +305,7 @@ void drm_flip_driver_schedule_flips(struct drm_flip_driver *driver,
 	if (need_cleanup)
 		queue_work(driver->wq, &driver->cleanup_work);
 }
+EXPORT_SYMBOL(drm_flip_driver_schedule_flips);
 
 void drm_flip_driver_prepare_flips(struct drm_flip_driver *driver,
 				   struct list_head *flips)
@@ -311,6 +319,7 @@ void drm_flip_driver_prepare_flips(struct drm_flip_driver *driver,
 			helper->funcs->prepare(flip);
 	}
 }
+EXPORT_SYMBOL(drm_flip_driver_prepare_flips);
 
 void drm_flip_driver_complete_flips(struct drm_flip_driver *driver,
 				    struct list_head *flips)
@@ -365,6 +374,7 @@ void drm_flip_driver_complete_flips(struct drm_flip_driver *driver,
 	if (need_cleanup)
 		queue_work(driver->wq, &driver->cleanup_work);
 }
+EXPORT_SYMBOL(drm_flip_driver_complete_flips);
 
 void drm_flip_init(struct drm_flip *flip,
 		   struct drm_flip_helper *helper)
@@ -374,3 +384,4 @@ void drm_flip_init(struct drm_flip *flip,
 	flip->finished = false;
 	INIT_LIST_HEAD(&flip->list);
 }
+EXPORT_SYMBOL(drm_flip_init);
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 43/81] drm/i915: Clear flip helpers for sprites too
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (41 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 42/81] drm: Add missing EXPORT_SYMBOL()s for drm_flip ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 44/81] drm/i915: Refactor property handling in atomic code ville.syrjala
                   ` (39 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Don't leave stale flips hanging around the sprites' flip helpers
when the crtc is being disabled.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_atomic.c  |   15 +++++++++++++++
 drivers/gpu/drm/i915/intel_display.c |    4 ++--
 drivers/gpu/drm/i915/intel_drv.h     |    1 +
 3 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 41885fa..41fd0d5 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -2449,3 +2449,18 @@ void intel_atomic_handle_vblank(struct drm_device *dev, int pipe)
 			drm_flip_helper_vblank(&intel_plane->flip_helper);
 	}
 }
+
+void intel_atomic_clear_flips(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_plane *intel_plane;
+	int pipe = intel_crtc->pipe;
+
+	drm_flip_helper_clear(&intel_crtc->flip_helper);
+
+	list_for_each_entry(intel_plane, &dev->mode_config.plane_list, base.head) {
+		if (intel_plane->pipe == pipe)
+			drm_flip_helper_clear(&intel_plane->flip_helper);
+	}
+}
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 9903456..566bf29 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3566,7 +3566,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
 		encoder->disable(encoder);
 
 	intel_crtc_wait_for_pending_flips(crtc);
-	drm_flip_helper_clear(&intel_crtc->flip_helper);
+	intel_atomic_clear_flips(crtc);
 	drm_vblank_off(dev, pipe);
 	intel_crtc_update_cursor(crtc, false);
 
@@ -3688,7 +3688,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
 
 	/* Give the overlay scaler a chance to disable if it's on this pipe */
 	intel_crtc_wait_for_pending_flips(crtc);
-	drm_flip_helper_clear(&intel_crtc->flip_helper);
+	intel_atomic_clear_flips(crtc);
 	drm_vblank_off(dev, pipe);
 	intel_crtc_dpms_overlay(intel_crtc, false);
 	intel_crtc_update_cursor(crtc, false);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 92a9518..5b0789f 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -729,6 +729,7 @@ extern int intel_atomic_init(struct drm_device *dev);
 extern void intel_atomic_fini(struct drm_device *dev);
 extern void intel_atomic_free_events(struct drm_device *dev, struct drm_file *file);
 extern void intel_atomic_handle_vblank(struct drm_device *dev, int pipe);
+extern void intel_atomic_clear_flips(struct drm_crtc *crtc);
 
 extern void intel_enable_primary(struct drm_crtc *crtc);
 extern void intel_disable_primary(struct drm_crtc *crtc);
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 44/81] drm/i915: Refactor property handling in atomic code
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (42 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 43/81] drm/i915: Clear flip helpers for sprites too ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 45/81] drm/i915: Move standard properties under mode_config ville.syrjala
                   ` (38 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Move the property code around a bit to make it easier to move it out to
the drm core later.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_atomic.c |  423 ++++++++++++++++++++---------------
 drivers/gpu/drm/i915/intel_drv.h    |    3 +
 include/drm/drm_crtc.h              |   12 +
 3 files changed, 252 insertions(+), 186 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 41fd0d5..0e37cf5 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -1473,87 +1473,6 @@ static int intel_atomic_check(struct drm_device *dev, void *state)
 	return 0;
 }
 
-static void update_plane_props(struct drm_plane *plane)
-{
-	struct drm_mode_object *obj = &plane->base;
-
-	drm_object_property_set_value(obj, prop_src_x, plane->src_x);
-	drm_object_property_set_value(obj, prop_src_y, plane->src_y);
-	drm_object_property_set_value(obj, prop_src_w, plane->src_w);
-	drm_object_property_set_value(obj, prop_src_h, plane->src_h);
-
-	drm_object_property_set_value(obj, prop_crtc_x, plane->crtc_x);
-	drm_object_property_set_value(obj, prop_crtc_y, plane->crtc_y);
-	drm_object_property_set_value(obj, prop_crtc_w, plane->crtc_w);
-	drm_object_property_set_value(obj, prop_crtc_h, plane->crtc_h);
-
-	drm_object_property_set_value(obj, prop_fb_id, plane->fb ? plane->fb->base.id : 0);
-	drm_object_property_set_value(obj, prop_crtc_id, plane->crtc ? plane->crtc->base.id : 0);
-}
-
-static int update_prop_connector_ids(struct drm_crtc *crtc)
-{
-	struct drm_device *dev = crtc->dev;
-	struct drm_connector *connector;
-	uint64_t value = 0;
-	int i = 0;
-	uint32_t connector_ids[dev->mode_config.num_connector];
-
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		if (connector->encoder && connector->encoder->crtc == crtc)
-			connector_ids[i++] = connector->base.id;
-	}
-
-	if (i) {
-		drm_property_blob_replace_data(crtc->connector_ids_blob,
-					       i * sizeof connector_ids[0], connector_ids);
-		value = crtc->connector_ids_blob->base.id;
-	} else
-		drm_property_blob_replace_data(crtc->connector_ids_blob, 0, NULL);
-
-	drm_object_property_set_value(&crtc->base, prop_connector_ids, value);
-
-	return 0;
-}
-
-static int update_prop_mode(struct drm_crtc *crtc)
-{
-	uint64_t value = 0;
-
-	if (crtc->enabled) {
-		struct drm_mode_modeinfo umode;
-
-		drm_crtc_convert_to_umode(&umode, &crtc->mode);
-		drm_property_blob_replace_data(crtc->mode_blob, sizeof umode, &umode);
-		value = crtc->mode_blob->base.id;
-	} else
-		drm_property_blob_replace_data(crtc->mode_blob, 0, NULL);
-
-	drm_object_property_set_value(&crtc->base, prop_mode, value);
-
-	return 0;
-}
-
-static void update_crtc_props(struct drm_crtc *crtc)
-{
-	struct drm_mode_object *obj = &crtc->base;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
-	drm_object_property_set_value(obj, prop_src_x, crtc->x);
-	drm_object_property_set_value(obj, prop_src_y, crtc->y);
-
-	drm_object_property_set_value(obj, prop_fb_id, crtc->fb ? crtc->fb->base.id : 0);
-
-	drm_object_property_set_value(obj, prop_cursor_id, intel_crtc->cursor_handle);
-	drm_object_property_set_value(obj, prop_cursor_x, intel_crtc->cursor_x);
-	drm_object_property_set_value(obj, prop_cursor_y, intel_crtc->cursor_y);
-	drm_object_property_set_value(obj, prop_cursor_w, intel_crtc->cursor_width);
-	drm_object_property_set_value(obj, prop_cursor_h, intel_crtc->cursor_height);
-
-	update_prop_mode(crtc);
-	update_prop_connector_ids(crtc);
-}
-
 static void update_props(struct drm_device *dev,
 			 struct intel_atomic_state *s)
 {
@@ -1565,7 +1484,7 @@ static void update_props(struct drm_device *dev,
 		if (!st->fb_dirty && !st->mode_dirty)
 			continue;
 
-		update_crtc_props(st->crtc);
+		intel_crtc_update_properties(st->crtc);
 	}
 
 	for (i = 0; i < dev->mode_config.num_plane; i++) {
@@ -1574,7 +1493,7 @@ static void update_props(struct drm_device *dev,
 		if (!st->dirty)
 			continue;
 
-		update_plane_props(st->plane);
+		drm_plane_update_properties(st->plane);
 	}
 }
 
@@ -1829,32 +1748,6 @@ static const struct drm_atomic_funcs intel_atomic_funcs = {
 	.end = intel_atomic_end,
 };
 
-static struct {
-	struct drm_property **prop;
-	const char *name;
-	uint64_t min;
-	uint64_t max;
-} props[] = {
-	{ &prop_src_x, "SRC_X", 0, UINT_MAX },
-	{ &prop_src_y, "SRC_Y", 0, UINT_MAX },
-	{ &prop_src_w, "SRC_W", 0, UINT_MAX },
-	{ &prop_src_h, "SRC_H", 0, UINT_MAX },
-
-	{ &prop_crtc_x, "CRTC_X", INT_MIN, INT_MAX },
-	{ &prop_crtc_y, "CRTC_Y", INT_MIN, INT_MAX },
-	{ &prop_crtc_w, "CRTC_W", 0, INT_MAX },
-	{ &prop_crtc_h, "CRTC_H", 0, INT_MAX },
-
-	{ &prop_fb_id, "FB_ID", 0, UINT_MAX },
-	{ &prop_crtc_id, "CRTC_ID", 0, UINT_MAX },
-
-	{ &prop_cursor_id, "CURSOR_ID", 0, UINT_MAX },
-	{ &prop_cursor_w, "CURSOR_W", 0, UINT_MAX },
-	{ &prop_cursor_h, "CURSOR_H", 0, UINT_MAX },
-	{ &prop_cursor_x, "CURSOR_X", INT_MIN, INT_MAX },
-	{ &prop_cursor_y, "CURSOR_Y", INT_MIN, INT_MAX },
-};
-
 static void intel_flip_init(struct drm_device *dev);
 static void intel_flip_fini(struct drm_device *dev);
 
@@ -1862,71 +1755,25 @@ int intel_atomic_init(struct drm_device *dev)
 {
 	struct drm_crtc *crtc;
 	struct drm_plane *plane;
-	int ret = -ENOMEM;
-	unsigned int i;
+	int ret;
 
-	for (i = 0; i < ARRAY_SIZE(props); i++) {
-		*props[i].prop =
-			drm_property_create_range(dev, 0, props[i].name,
-						  props[i].min, props[i].max);
-		if (!*props[i].prop)
-			goto out;
-	}
-
-	/* FIXME create special object ID list property type? */
-	prop_connector_ids = drm_property_create(dev, DRM_MODE_PROP_BLOB, "CONNECTOR_IDS", 0);
-	if (!prop_connector_ids)
-		goto out;
-
-	prop_mode = drm_property_create(dev, DRM_MODE_PROP_BLOB, "MODE", 0);
-	if (!prop_mode)
+	ret = drm_mode_create_properties(dev);
+	if (ret)
 		goto out;
 
 	list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
-		struct drm_mode_object *obj = &plane->base;
-
-		drm_object_attach_property(obj, prop_src_x, 0);
-		drm_object_attach_property(obj, prop_src_y, 0);
-		drm_object_attach_property(obj, prop_src_w, 0);
-		drm_object_attach_property(obj, prop_src_h, 0);
-
-		drm_object_attach_property(obj, prop_crtc_x, 0);
-		drm_object_attach_property(obj, prop_crtc_y, 0);
-		drm_object_attach_property(obj, prop_crtc_w, 0);
-		drm_object_attach_property(obj, prop_crtc_h, 0);
-
-		drm_object_attach_property(obj, prop_fb_id, 0);
-		drm_object_attach_property(obj, prop_crtc_id, 0);
-
-		update_plane_props(plane);
+		drm_plane_attach_properties(plane);
+		drm_plane_update_properties(plane);
 	}
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		struct drm_mode_object *obj = &crtc->base;
+		intel_crtc_attach_properties(crtc);
 
-		drm_object_attach_property(obj, prop_src_x, 0);
-		drm_object_attach_property(obj, prop_src_y, 0);
+		ret = drm_crtc_create_blobs(crtc);
+		if (ret)
+			goto destroy_props;
 
-		drm_object_attach_property(obj, prop_fb_id, 0);
-		drm_object_attach_property(obj, prop_mode, 0);
-		drm_object_attach_property(obj, prop_connector_ids, 0);
-
-		drm_object_attach_property(obj, prop_cursor_id, 0);
-		drm_object_attach_property(obj, prop_cursor_x, 0);
-		drm_object_attach_property(obj, prop_cursor_y, 0);
-		drm_object_attach_property(obj, prop_cursor_w, 0);
-		drm_object_attach_property(obj, prop_cursor_h, 0);
-
-		crtc->mode_blob = drm_property_create_blob(dev, 0, sizeof(struct drm_mode_modeinfo), NULL);
-		if (!crtc->mode_blob)
-			goto out;
-
-		crtc->connector_ids_blob = drm_property_create_blob(dev, 0,
-								    dev->mode_config.num_connector * sizeof(uint32_t), NULL);
-		if (!crtc->connector_ids_blob)
-			goto out;
-
-		update_crtc_props(crtc);
+		intel_crtc_update_properties(crtc);
 	}
 
 	dev->driver->atomic_funcs = &intel_atomic_funcs;
@@ -1935,12 +1782,9 @@ int intel_atomic_init(struct drm_device *dev)
 
 	return 0;
 
+ destroy_props:
+	drm_mode_destroy_properties(dev);
  out:
-	drm_property_destroy(dev, prop_mode);
-	drm_property_destroy(dev, prop_connector_ids);
-
-	while (i--)
-		drm_property_destroy(dev, *props[i].prop);
 
 	return ret;
 }
@@ -1952,24 +1796,10 @@ void intel_atomic_fini(struct drm_device *dev)
 	intel_flip_fini(dev);
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		drm_property_destroy_blob(dev, crtc->mode_blob);
-		drm_property_destroy_blob(dev, crtc->connector_ids_blob);
+		drm_crtc_destroy_blobs(crtc);
 	}
 
-	drm_property_destroy(dev, prop_connector_ids);
-	drm_property_destroy(dev, prop_mode);
-	drm_property_destroy(dev, prop_crtc_id);
-	drm_property_destroy(dev, prop_fb_id);
-
-	drm_property_destroy(dev, prop_crtc_h);
-	drm_property_destroy(dev, prop_crtc_w);
-	drm_property_destroy(dev, prop_crtc_y);
-	drm_property_destroy(dev, prop_crtc_x);
-
-	drm_property_destroy(dev, prop_src_h);
-	drm_property_destroy(dev, prop_src_w);
-	drm_property_destroy(dev, prop_src_y);
-	drm_property_destroy(dev, prop_src_x);
+	drm_mode_destroy_properties(dev);
 }
 
 enum {
@@ -2464,3 +2294,224 @@ void intel_atomic_clear_flips(struct drm_crtc *crtc)
 			drm_flip_helper_clear(&intel_plane->flip_helper);
 	}
 }
+
+static void drm_crtc_update_connector_ids_property(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_connector *connector;
+	uint64_t value = 0;
+	int i = 0;
+	uint32_t connector_ids[dev->mode_config.num_connector];
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		if (connector->encoder && connector->encoder->crtc == crtc)
+			connector_ids[i++] = connector->base.id;
+	}
+
+	if (i) {
+		drm_property_blob_replace_data(crtc->connector_ids_blob,
+					       i * sizeof connector_ids[0], connector_ids);
+		value = crtc->connector_ids_blob->base.id;
+	} else
+		drm_property_blob_replace_data(crtc->connector_ids_blob, 0, NULL);
+
+	drm_object_property_set_value(&crtc->base, prop_connector_ids, value);
+}
+
+static void drm_crtc_update_mode_property(struct drm_crtc *crtc)
+{
+	uint64_t value = 0;
+
+	if (crtc->enabled) {
+		struct drm_mode_modeinfo umode;
+
+		drm_crtc_convert_to_umode(&umode, &crtc->mode);
+		drm_property_blob_replace_data(crtc->mode_blob, sizeof umode, &umode);
+		value = crtc->mode_blob->base.id;
+	} else
+		drm_property_blob_replace_data(crtc->mode_blob, 0, NULL);
+
+	drm_object_property_set_value(&crtc->base, prop_mode, value);
+}
+
+void drm_crtc_update_properties(struct drm_crtc *crtc)
+{
+	struct drm_mode_object *obj = &crtc->base;
+
+	drm_object_property_set_value(obj, prop_src_x, crtc->x);
+	drm_object_property_set_value(obj, prop_src_y, crtc->y);
+	drm_object_property_set_value(obj, prop_fb_id, crtc->fb ? crtc->fb->base.id : 0);
+
+	drm_crtc_update_mode_property(crtc);
+	drm_crtc_update_connector_ids_property(crtc);
+}
+
+void intel_crtc_update_properties(struct drm_crtc *crtc)
+{
+	struct drm_mode_object *obj = &crtc->base;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+	drm_crtc_update_properties(crtc);
+
+	drm_object_property_set_value(obj, prop_cursor_id, intel_crtc->cursor_handle);
+	drm_object_property_set_value(obj, prop_cursor_x, intel_crtc->cursor_x);
+	drm_object_property_set_value(obj, prop_cursor_y, intel_crtc->cursor_y);
+	drm_object_property_set_value(obj, prop_cursor_w, intel_crtc->cursor_width);
+	drm_object_property_set_value(obj, prop_cursor_h, intel_crtc->cursor_height);
+}
+
+void drm_plane_update_properties(struct drm_plane *plane)
+{
+	struct drm_mode_object *obj = &plane->base;
+
+	drm_object_property_set_value(obj, prop_src_x, plane->src_x);
+	drm_object_property_set_value(obj, prop_src_y, plane->src_y);
+	drm_object_property_set_value(obj, prop_src_w, plane->src_w);
+	drm_object_property_set_value(obj, prop_src_h, plane->src_h);
+
+	drm_object_property_set_value(obj, prop_crtc_x, plane->crtc_x);
+	drm_object_property_set_value(obj, prop_crtc_y, plane->crtc_y);
+	drm_object_property_set_value(obj, prop_crtc_w, plane->crtc_w);
+	drm_object_property_set_value(obj, prop_crtc_h, plane->crtc_h);
+
+	drm_object_property_set_value(obj, prop_fb_id, plane->fb ? plane->fb->base.id : 0);
+	drm_object_property_set_value(obj, prop_crtc_id, plane->crtc ? plane->crtc->base.id : 0);
+}
+
+int drm_crtc_create_blobs(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+
+	crtc->mode_blob = drm_property_create_blob(dev, 0, sizeof(struct drm_mode_modeinfo), NULL);
+	if (!crtc->mode_blob)
+		return -ENOMEM;
+
+	crtc->connector_ids_blob = drm_property_create_blob(dev, 0, dev->mode_config.num_connector * sizeof(uint32_t), NULL);
+	if (!crtc->connector_ids_blob)
+		return -ENOMEM;
+
+	return 0;
+}
+
+void drm_crtc_destroy_blobs(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+
+	drm_property_destroy_blob(dev, crtc->mode_blob);
+	drm_property_destroy_blob(dev, crtc->connector_ids_blob);
+}
+
+void drm_mode_destroy_properties(struct drm_device *dev)
+{
+	drm_property_destroy(dev, prop_connector_ids);
+	drm_property_destroy(dev, prop_mode);
+	drm_property_destroy(dev, prop_crtc_id);
+	drm_property_destroy(dev, prop_fb_id);
+
+	drm_property_destroy(dev, prop_crtc_h);
+	drm_property_destroy(dev, prop_crtc_w);
+	drm_property_destroy(dev, prop_crtc_y);
+	drm_property_destroy(dev, prop_crtc_x);
+
+	drm_property_destroy(dev, prop_src_h);
+	drm_property_destroy(dev, prop_src_w);
+	drm_property_destroy(dev, prop_src_y);
+	drm_property_destroy(dev, prop_src_x);
+}
+
+static struct {
+	struct drm_property **prop;
+	const char *name;
+	uint64_t min;
+	uint64_t max;
+} props[] = {
+	{ &prop_src_x, "SRC_X", 0, UINT_MAX },
+	{ &prop_src_y, "SRC_Y", 0, UINT_MAX },
+	{ &prop_src_w, "SRC_W", 0, UINT_MAX },
+	{ &prop_src_h, "SRC_H", 0, UINT_MAX },
+
+	{ &prop_crtc_x, "CRTC_X", INT_MIN, INT_MAX },
+	{ &prop_crtc_y, "CRTC_Y", INT_MIN, INT_MAX },
+	{ &prop_crtc_w, "CRTC_W", 0, INT_MAX },
+	{ &prop_crtc_h, "CRTC_H", 0, INT_MAX },
+
+	{ &prop_fb_id, "FB_ID", 0, UINT_MAX },
+	{ &prop_crtc_id, "CRTC_ID", 0, UINT_MAX },
+
+	{ &prop_cursor_id, "CURSOR_ID", 0, UINT_MAX },
+	{ &prop_cursor_w, "CURSOR_W", 0, UINT_MAX },
+	{ &prop_cursor_h, "CURSOR_H", 0, UINT_MAX },
+	{ &prop_cursor_x, "CURSOR_X", INT_MIN, INT_MAX },
+	{ &prop_cursor_y, "CURSOR_Y", INT_MIN, INT_MAX },
+};
+
+int drm_mode_create_properties(struct drm_device *dev)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(props); i++) {
+		*props[i].prop = drm_property_create_range(dev, 0, props[i].name, props[i].min, props[i].max);
+		if (!*props[i].prop)
+			goto out;
+	}
+
+	/* FIXME create special object ID list property type? */
+	prop_connector_ids = drm_property_create(dev, DRM_MODE_PROP_BLOB, "CONNECTOR_IDS", 0);
+	if (!prop_connector_ids)
+		goto out;
+
+	prop_mode = drm_property_create(dev, DRM_MODE_PROP_BLOB, "MODE", 0);
+	if (!prop_mode)
+		goto out;
+
+	return 0;
+
+ out:
+	drm_property_destroy(dev, prop_mode);
+	drm_property_destroy(dev, prop_connector_ids);
+
+	while (i--)
+		drm_property_destroy(dev, *props[i].prop);
+
+	return -ENOMEM; /* FIXME? */
+}
+
+void drm_plane_attach_properties(struct drm_plane *plane)
+{
+	struct drm_mode_object *obj = &plane->base;
+
+	drm_object_attach_property(obj, prop_src_x, 0);
+	drm_object_attach_property(obj, prop_src_y, 0);
+	drm_object_attach_property(obj, prop_src_w, 0);
+	drm_object_attach_property(obj, prop_src_h, 0);
+	drm_object_attach_property(obj, prop_crtc_x, 0);
+	drm_object_attach_property(obj, prop_crtc_y, 0);
+	drm_object_attach_property(obj, prop_crtc_w, 0);
+	drm_object_attach_property(obj, prop_crtc_h, 0);
+	drm_object_attach_property(obj, prop_fb_id, 0);
+	drm_object_attach_property(obj, prop_crtc_id, 0);
+}
+
+void drm_crtc_attach_properties(struct drm_crtc *crtc)
+{
+	struct drm_mode_object *obj = &crtc->base;
+
+	drm_object_attach_property(obj, prop_src_x, 0);
+	drm_object_attach_property(obj, prop_src_y, 0);
+	drm_object_attach_property(obj, prop_fb_id, 0);
+	drm_object_attach_property(obj, prop_mode, 0);
+	drm_object_attach_property(obj, prop_connector_ids, 0);
+}
+
+void intel_crtc_attach_properties(struct drm_crtc *crtc)
+{
+	struct drm_mode_object *obj = &crtc->base;
+
+	drm_crtc_attach_properties(crtc);
+
+	drm_object_attach_property(obj, prop_cursor_id, 0);
+	drm_object_attach_property(obj, prop_cursor_x, 0);
+	drm_object_attach_property(obj, prop_cursor_y, 0);
+	drm_object_attach_property(obj, prop_cursor_w, 0);
+	drm_object_attach_property(obj, prop_cursor_h, 0);
+}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 5b0789f..1230c1b 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -734,4 +734,7 @@ extern void intel_atomic_clear_flips(struct drm_crtc *crtc);
 extern void intel_enable_primary(struct drm_crtc *crtc);
 extern void intel_disable_primary(struct drm_crtc *crtc);
 
+extern void intel_crtc_attach_properties(struct drm_crtc *crtc);
+extern void intel_crtc_update_properties(struct drm_crtc *crtc);
+
 #endif /* __INTEL_DRV_H__ */
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 897c110..74fb5a8 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -1147,4 +1147,16 @@ struct drm_atomic_funcs {
 	void (*end)(struct drm_device *dev, void *state);
 };
 
+extern int drm_mode_create_properties(struct drm_device *dev);
+extern void drm_mode_destroy_properties(struct drm_device *dev);
+
+extern int drm_crtc_create_blobs(struct drm_crtc *crtc);
+extern void drm_crtc_destroy_blobs(struct drm_crtc *crtc);
+
+extern void drm_crtc_attach_properties(struct drm_crtc *crtc);
+extern void drm_plane_attach_properties(struct drm_plane *plane);
+
+extern void drm_crtc_update_properties(struct drm_crtc *crtc);
+extern void drm_plane_update_properties(struct drm_plane *plane);
+
 #endif /* __DRM_CRTC_H__ */
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 45/81] drm/i915: Move standard properties under mode_config
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (43 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 44/81] drm/i915: Refactor property handling in atomic code ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 46/81] drm_crtc_helper: Update standard crtc properties after modeset ville.syrjala
                   ` (37 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Standard connector properties are kept in the mode_config structure.
Move the CRTC and plane properties there as well.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_atomic.c |  293 +++++++++++++++++++----------------
 include/drm/drm_crtc.h              |   19 +++
 2 files changed, 175 insertions(+), 137 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 0e37cf5..0def947 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -30,24 +30,6 @@
 
 #include "intel_drv.h"
 
-static struct drm_property *prop_src_x;
-static struct drm_property *prop_src_y;
-static struct drm_property *prop_src_w;
-static struct drm_property *prop_src_h;
-static struct drm_property *prop_crtc_x;
-static struct drm_property *prop_crtc_y;
-static struct drm_property *prop_crtc_w;
-static struct drm_property *prop_crtc_h;
-static struct drm_property *prop_fb_id;
-static struct drm_property *prop_crtc_id;
-static struct drm_property *prop_mode;
-static struct drm_property *prop_connector_ids;
-static struct drm_property *prop_cursor_id;
-static struct drm_property *prop_cursor_x;
-static struct drm_property *prop_cursor_y;
-static struct drm_property *prop_cursor_w;
-static struct drm_property *prop_cursor_h;
-
 struct intel_flip {
 	struct drm_flip base;
 	u32 vbl_count;
@@ -368,27 +350,28 @@ static int plane_set(struct intel_atomic_state *s,
 		     uint64_t value)
 {
 	struct drm_plane *plane = state->plane;
+	struct drm_mode_config *config = &plane->dev->mode_config;
 	struct drm_mode_object *obj;
 
 	state->changed = true;
 
-	if (prop == prop_src_x) {
+	if (prop == config->src_x_prop) {
 		plane->src_x = value;
-	} else if (prop == prop_src_y) {
+	} else if (prop == config->src_y_prop) {
 		plane->src_y = value;
-	} else if (prop == prop_src_w) {
+	} else if (prop == config->src_w_prop) {
 		plane->src_w = value;
-	} else if (prop == prop_src_h) {
+	} else if (prop == config->src_h_prop) {
 		plane->src_h = value;
-	} else if (prop == prop_crtc_x) {
+	} else if (prop == config->crtc_x_prop) {
 		plane->crtc_x = value;
-	} else if (prop == prop_crtc_y) {
+	} else if (prop == config->crtc_y_prop) {
 		plane->crtc_y = value;
-	} else if (prop == prop_crtc_w) {
+	} else if (prop == config->crtc_w_prop) {
 		plane->crtc_w = value;
-	} else if (prop == prop_crtc_h) {
+	} else if (prop == config->crtc_h_prop) {
 		plane->crtc_h = value;
-	} else if (prop == prop_crtc_id) {
+	} else if (prop == config->crtc_id_prop) {
 		if (value) {
 			obj = drm_mode_object_find(plane->dev, value, DRM_MODE_OBJECT_CRTC);
 			if (!obj) {
@@ -398,7 +381,7 @@ static int plane_set(struct intel_atomic_state *s,
 			plane->crtc = obj_to_crtc(obj);
 		} else
 			plane->crtc = NULL;
-	} else if (prop == prop_fb_id) {
+	} else if (prop == config->fb_id_prop) {
 		if (value) {
 			obj = drm_mode_object_find(plane->dev, value, DRM_MODE_OBJECT_FB);
 			if (!obj) {
@@ -422,16 +405,17 @@ static int crtc_set(struct intel_atomic_state *s,
 		    uint64_t value, const void *blob_data)
 {
 	struct drm_crtc *crtc = state->crtc;
+	struct drm_mode_config *config = &crtc->dev->mode_config;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct drm_mode_object *obj;
 
 	state->changed = true;
 
-	if (prop == prop_src_x) {
+	if (prop == config->src_x_prop) {
 		crtc->x = value;
-	} else if (prop == prop_src_y) {
+	} else if (prop == config->src_y_prop) {
 		crtc->y = value;
-	} else if (prop == prop_mode) {
+	} else if (prop == config->mode_prop) {
 		const struct drm_mode_modeinfo *umode = blob_data;
 
 		if (value != 0 && value != sizeof *umode) {
@@ -462,7 +446,7 @@ static int crtc_set(struct intel_atomic_state *s,
 			drm_mode_destroy(crtc->dev, mode);
 		} else
 			crtc->enabled = false;
-	} else if (prop == prop_fb_id) {
+	} else if (prop == config->fb_id_prop) {
 		if (value) {
 			obj = drm_mode_object_find(crtc->dev, value, DRM_MODE_OBJECT_FB);
 			if (!obj) {
@@ -472,7 +456,7 @@ static int crtc_set(struct intel_atomic_state *s,
 			crtc->fb = obj_to_fb(obj);
 		} else
 			crtc->fb = NULL;
-	} else if (prop == prop_connector_ids) {
+	} else if (prop == config->connector_ids_prop) {
 		const uint32_t *ids = blob_data;
 		uint64_t count_ids = value / sizeof(uint32_t);
 		int ret;
@@ -482,7 +466,7 @@ static int crtc_set(struct intel_atomic_state *s,
 			return -EINVAL;
 		}
 
-		if (count_ids > crtc->dev->mode_config.num_connector) {
+		if (count_ids > config->num_connector) {
 			DRM_DEBUG_KMS("Too many connectors specified\n");
 			return -ERANGE;
 		}
@@ -490,19 +474,19 @@ static int crtc_set(struct intel_atomic_state *s,
 		ret = process_connectors(state, ids, count_ids);
 		if (ret)
 			return ret;
-	} else if (prop == prop_cursor_id) {
+	} else if (prop == config->cursor_id_prop) {
 		intel_crtc->cursor_handle = value;
-	} else if (prop == prop_cursor_x) {
+	} else if (prop == config->cursor_x_prop) {
 		intel_crtc->cursor_x = value;
-	} else if (prop == prop_cursor_y) {
+	} else if (prop == config->cursor_y_prop) {
 		intel_crtc->cursor_y = value;
-	} else if (prop == prop_cursor_w) {
+	} else if (prop == config->cursor_w_prop) {
 		if (value != 0 && value != 64) {
 			DRM_DEBUG_KMS("only 64x64 cursor sprites are supported\n");
 			return -EINVAL;
 		}
 		intel_crtc->cursor_width = value;
-	} else if (prop == prop_cursor_h) {
+	} else if (prop == config->cursor_h_prop) {
 		if (value != 0 && value != 64) {
 			DRM_DEBUG_KMS("only 64x64 cursor sprites are supported\n");
 			return -EINVAL;
@@ -2297,13 +2281,13 @@ void intel_atomic_clear_flips(struct drm_crtc *crtc)
 
 static void drm_crtc_update_connector_ids_property(struct drm_crtc *crtc)
 {
-	struct drm_device *dev = crtc->dev;
+	struct drm_mode_config *config = &crtc->dev->mode_config;
 	struct drm_connector *connector;
 	uint64_t value = 0;
 	int i = 0;
-	uint32_t connector_ids[dev->mode_config.num_connector];
+	uint32_t connector_ids[config->num_connector];
 
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+	list_for_each_entry(connector, &config->connector_list, head) {
 		if (connector->encoder && connector->encoder->crtc == crtc)
 			connector_ids[i++] = connector->base.id;
 	}
@@ -2315,11 +2299,12 @@ static void drm_crtc_update_connector_ids_property(struct drm_crtc *crtc)
 	} else
 		drm_property_blob_replace_data(crtc->connector_ids_blob, 0, NULL);
 
-	drm_object_property_set_value(&crtc->base, prop_connector_ids, value);
+	drm_object_property_set_value(&crtc->base, config->connector_ids_prop, value);
 }
 
 static void drm_crtc_update_mode_property(struct drm_crtc *crtc)
 {
+	struct drm_mode_config *config = &crtc->dev->mode_config;
 	uint64_t value = 0;
 
 	if (crtc->enabled) {
@@ -2331,16 +2316,17 @@ static void drm_crtc_update_mode_property(struct drm_crtc *crtc)
 	} else
 		drm_property_blob_replace_data(crtc->mode_blob, 0, NULL);
 
-	drm_object_property_set_value(&crtc->base, prop_mode, value);
+	drm_object_property_set_value(&crtc->base, config->mode_prop, value);
 }
 
 void drm_crtc_update_properties(struct drm_crtc *crtc)
 {
 	struct drm_mode_object *obj = &crtc->base;
+	struct drm_mode_config *config = &crtc->dev->mode_config;
 
-	drm_object_property_set_value(obj, prop_src_x, crtc->x);
-	drm_object_property_set_value(obj, prop_src_y, crtc->y);
-	drm_object_property_set_value(obj, prop_fb_id, crtc->fb ? crtc->fb->base.id : 0);
+	drm_object_property_set_value(obj, config->src_x_prop, crtc->x);
+	drm_object_property_set_value(obj, config->src_y_prop, crtc->y);
+	drm_object_property_set_value(obj, config->fb_id_prop, crtc->fb ? crtc->fb->base.id : 0);
 
 	drm_crtc_update_mode_property(crtc);
 	drm_crtc_update_connector_ids_property(crtc);
@@ -2349,33 +2335,35 @@ void drm_crtc_update_properties(struct drm_crtc *crtc)
 void intel_crtc_update_properties(struct drm_crtc *crtc)
 {
 	struct drm_mode_object *obj = &crtc->base;
+	struct drm_mode_config *config = &crtc->dev->mode_config;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
 	drm_crtc_update_properties(crtc);
 
-	drm_object_property_set_value(obj, prop_cursor_id, intel_crtc->cursor_handle);
-	drm_object_property_set_value(obj, prop_cursor_x, intel_crtc->cursor_x);
-	drm_object_property_set_value(obj, prop_cursor_y, intel_crtc->cursor_y);
-	drm_object_property_set_value(obj, prop_cursor_w, intel_crtc->cursor_width);
-	drm_object_property_set_value(obj, prop_cursor_h, intel_crtc->cursor_height);
+	drm_object_property_set_value(obj, config->cursor_id_prop, intel_crtc->cursor_handle);
+	drm_object_property_set_value(obj, config->cursor_x_prop, intel_crtc->cursor_x);
+	drm_object_property_set_value(obj, config->cursor_y_prop, intel_crtc->cursor_y);
+	drm_object_property_set_value(obj, config->cursor_w_prop, intel_crtc->cursor_width);
+	drm_object_property_set_value(obj, config->cursor_h_prop, intel_crtc->cursor_height);
 }
 
 void drm_plane_update_properties(struct drm_plane *plane)
 {
 	struct drm_mode_object *obj = &plane->base;
+	struct drm_mode_config *config = &plane->dev->mode_config;
 
-	drm_object_property_set_value(obj, prop_src_x, plane->src_x);
-	drm_object_property_set_value(obj, prop_src_y, plane->src_y);
-	drm_object_property_set_value(obj, prop_src_w, plane->src_w);
-	drm_object_property_set_value(obj, prop_src_h, plane->src_h);
+	drm_object_property_set_value(obj, config->src_x_prop, plane->src_x);
+	drm_object_property_set_value(obj, config->src_y_prop, plane->src_y);
+	drm_object_property_set_value(obj, config->src_w_prop, plane->src_w);
+	drm_object_property_set_value(obj, config->src_h_prop, plane->src_h);
 
-	drm_object_property_set_value(obj, prop_crtc_x, plane->crtc_x);
-	drm_object_property_set_value(obj, prop_crtc_y, plane->crtc_y);
-	drm_object_property_set_value(obj, prop_crtc_w, plane->crtc_w);
-	drm_object_property_set_value(obj, prop_crtc_h, plane->crtc_h);
+	drm_object_property_set_value(obj, config->crtc_x_prop, plane->crtc_x);
+	drm_object_property_set_value(obj, config->crtc_y_prop, plane->crtc_y);
+	drm_object_property_set_value(obj, config->crtc_w_prop, plane->crtc_w);
+	drm_object_property_set_value(obj, config->crtc_h_prop, plane->crtc_h);
 
-	drm_object_property_set_value(obj, prop_fb_id, plane->fb ? plane->fb->base.id : 0);
-	drm_object_property_set_value(obj, prop_crtc_id, plane->crtc ? plane->crtc->base.id : 0);
+	drm_object_property_set_value(obj, config->fb_id_prop, plane->fb ? plane->fb->base.id : 0);
+	drm_object_property_set_value(obj, config->crtc_id_prop, plane->crtc ? plane->crtc->base.id : 0);
 }
 
 int drm_crtc_create_blobs(struct drm_crtc *crtc)
@@ -2401,77 +2389,105 @@ void drm_crtc_destroy_blobs(struct drm_crtc *crtc)
 	drm_property_destroy_blob(dev, crtc->connector_ids_blob);
 }
 
+void drm_property_destroy_null(struct drm_device *dev, struct drm_property **prop)
+{
+	drm_property_destroy(dev, *prop);
+	*prop = NULL;
+}
+
 void drm_mode_destroy_properties(struct drm_device *dev)
 {
-	drm_property_destroy(dev, prop_connector_ids);
-	drm_property_destroy(dev, prop_mode);
-	drm_property_destroy(dev, prop_crtc_id);
-	drm_property_destroy(dev, prop_fb_id);
-
-	drm_property_destroy(dev, prop_crtc_h);
-	drm_property_destroy(dev, prop_crtc_w);
-	drm_property_destroy(dev, prop_crtc_y);
-	drm_property_destroy(dev, prop_crtc_x);
-
-	drm_property_destroy(dev, prop_src_h);
-	drm_property_destroy(dev, prop_src_w);
-	drm_property_destroy(dev, prop_src_y);
-	drm_property_destroy(dev, prop_src_x);
+	struct drm_mode_config *config = &dev->mode_config;
+
+	drm_property_destroy_null(dev, &config->cursor_h_prop);
+	drm_property_destroy_null(dev, &config->cursor_w_prop);
+	drm_property_destroy_null(dev, &config->cursor_y_prop);
+	drm_property_destroy_null(dev, &config->cursor_x_prop);
+	drm_property_destroy_null(dev, &config->cursor_id_prop);
+
+	drm_property_destroy_null(dev, &config->connector_ids_prop);
+	drm_property_destroy_null(dev, &config->mode_prop);
+
+	drm_property_destroy_null(dev, &config->crtc_id_prop);
+	drm_property_destroy_null(dev, &config->fb_id_prop);
+
+	drm_property_destroy_null(dev, &config->crtc_h_prop);
+	drm_property_destroy_null(dev, &config->crtc_w_prop);
+	drm_property_destroy_null(dev, &config->crtc_y_prop);
+	drm_property_destroy_null(dev, &config->crtc_x_prop);
+
+	drm_property_destroy_null(dev, &config->src_h_prop);
+	drm_property_destroy_null(dev, &config->src_w_prop);
+	drm_property_destroy_null(dev, &config->src_y_prop);
+	drm_property_destroy_null(dev, &config->src_x_prop);
 }
 
-static struct {
-	struct drm_property **prop;
-	const char *name;
-	uint64_t min;
-	uint64_t max;
-} props[] = {
-	{ &prop_src_x, "SRC_X", 0, UINT_MAX },
-	{ &prop_src_y, "SRC_Y", 0, UINT_MAX },
-	{ &prop_src_w, "SRC_W", 0, UINT_MAX },
-	{ &prop_src_h, "SRC_H", 0, UINT_MAX },
-
-	{ &prop_crtc_x, "CRTC_X", INT_MIN, INT_MAX },
-	{ &prop_crtc_y, "CRTC_Y", INT_MIN, INT_MAX },
-	{ &prop_crtc_w, "CRTC_W", 0, INT_MAX },
-	{ &prop_crtc_h, "CRTC_H", 0, INT_MAX },
-
-	{ &prop_fb_id, "FB_ID", 0, UINT_MAX },
-	{ &prop_crtc_id, "CRTC_ID", 0, UINT_MAX },
-
-	{ &prop_cursor_id, "CURSOR_ID", 0, UINT_MAX },
-	{ &prop_cursor_w, "CURSOR_W", 0, UINT_MAX },
-	{ &prop_cursor_h, "CURSOR_H", 0, UINT_MAX },
-	{ &prop_cursor_x, "CURSOR_X", INT_MIN, INT_MAX },
-	{ &prop_cursor_y, "CURSOR_Y", INT_MIN, INT_MAX },
-};
-
 int drm_mode_create_properties(struct drm_device *dev)
 {
-	int i;
+	struct drm_mode_config *config = &dev->mode_config;
 
-	for (i = 0; i < ARRAY_SIZE(props); i++) {
-		*props[i].prop = drm_property_create_range(dev, 0, props[i].name, props[i].min, props[i].max);
-		if (!*props[i].prop)
-			goto out;
-	}
+	config->src_x_prop = drm_property_create_range(dev, 0, "SRC_X", 0, UINT_MAX);
+	if (!config->src_x_prop)
+		goto out;
+	config->src_y_prop = drm_property_create_range(dev, 0, "SRC_Y", 0, UINT_MAX);
+	if (!config->src_y_prop)
+		goto out;
+	config->src_w_prop = drm_property_create_range(dev, 0, "SRC_W", 0, UINT_MAX);
+	if (!config->src_w_prop)
+		goto out;
+	config->src_h_prop = drm_property_create_range(dev, 0, "SRC_H", 0, UINT_MAX);
+	if (!config->src_h_prop)
+		goto out;
+
+	config->crtc_x_prop = drm_property_create_range(dev, 0, "CRTC_X", INT_MIN, INT_MAX);
+	if (!config->crtc_x_prop)
+		goto out;
+	config->crtc_y_prop = drm_property_create_range(dev, 0, "CRTC_Y", INT_MIN, INT_MAX);
+	if (!config->crtc_y_prop)
+		goto out;
+	config->crtc_w_prop = drm_property_create_range(dev, 0, "CRTC_W", 0, UINT_MAX);
+	if (!config->crtc_w_prop)
+		goto out;
+	config->crtc_h_prop = drm_property_create_range(dev, 0, "CRTC_H", 0, UINT_MAX);
+	if (!config->crtc_h_prop)
+		goto out;
+
+	config->fb_id_prop = drm_property_create_range(dev, 0, "FB_ID", 0, UINT_MAX);
+	if (!config->fb_id_prop)
+		goto out;
+	config->crtc_id_prop = drm_property_create_range(dev, 0, "CRTC_ID", 0, UINT_MAX);
+	if (!config->crtc_id_prop)
+		goto out;
+
+	config->cursor_id_prop = drm_property_create_range(dev, 0, "CURSOR_ID", 0, UINT_MAX);
+	if (!config->cursor_id_prop)
+		goto out;
+	config->cursor_x_prop = drm_property_create_range(dev, 0, "CURSOR_X", INT_MIN, INT_MAX);
+	if (!config->cursor_x_prop)
+		goto out;
+	config->cursor_y_prop = drm_property_create_range(dev, 0, "CURSOR_Y", INT_MIN, INT_MAX);
+	if (!config->cursor_y_prop)
+		goto out;
+	config->cursor_w_prop = drm_property_create_range(dev, 0, "CURSOR_W", 0, UINT_MAX);
+	if (!config->cursor_w_prop)
+		goto out;
+	config->cursor_h_prop = drm_property_create_range(dev, 0, "CURSOR_H", 0, UINT_MAX);
+	if (!config->cursor_h_prop)
+		goto out;
 
 	/* FIXME create special object ID list property type? */
-	prop_connector_ids = drm_property_create(dev, DRM_MODE_PROP_BLOB, "CONNECTOR_IDS", 0);
-	if (!prop_connector_ids)
+	config->connector_ids_prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, "CONNECTOR_IDS", 0);
+	if (!config->connector_ids_prop)
 		goto out;
 
-	prop_mode = drm_property_create(dev, DRM_MODE_PROP_BLOB, "MODE", 0);
-	if (!prop_mode)
+	config->mode_prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, "MODE", 0);
+	if (!config->mode_prop)
 		goto out;
 
 	return 0;
 
  out:
-	drm_property_destroy(dev, prop_mode);
-	drm_property_destroy(dev, prop_connector_ids);
-
-	while (i--)
-		drm_property_destroy(dev, *props[i].prop);
+	drm_mode_destroy_properties(dev);
 
 	return -ENOMEM; /* FIXME? */
 }
@@ -2479,39 +2495,42 @@ int drm_mode_create_properties(struct drm_device *dev)
 void drm_plane_attach_properties(struct drm_plane *plane)
 {
 	struct drm_mode_object *obj = &plane->base;
+	struct drm_mode_config *config = &plane->dev->mode_config;
 
-	drm_object_attach_property(obj, prop_src_x, 0);
-	drm_object_attach_property(obj, prop_src_y, 0);
-	drm_object_attach_property(obj, prop_src_w, 0);
-	drm_object_attach_property(obj, prop_src_h, 0);
-	drm_object_attach_property(obj, prop_crtc_x, 0);
-	drm_object_attach_property(obj, prop_crtc_y, 0);
-	drm_object_attach_property(obj, prop_crtc_w, 0);
-	drm_object_attach_property(obj, prop_crtc_h, 0);
-	drm_object_attach_property(obj, prop_fb_id, 0);
-	drm_object_attach_property(obj, prop_crtc_id, 0);
+	drm_object_attach_property(obj, config->src_x_prop, 0);
+	drm_object_attach_property(obj, config->src_y_prop, 0);
+	drm_object_attach_property(obj, config->src_w_prop, 0);
+	drm_object_attach_property(obj, config->src_h_prop, 0);
+	drm_object_attach_property(obj, config->crtc_x_prop, 0);
+	drm_object_attach_property(obj, config->crtc_y_prop, 0);
+	drm_object_attach_property(obj, config->crtc_w_prop, 0);
+	drm_object_attach_property(obj, config->crtc_h_prop, 0);
+	drm_object_attach_property(obj, config->fb_id_prop, 0);
+	drm_object_attach_property(obj, config->crtc_id_prop, 0);
 }
 
 void drm_crtc_attach_properties(struct drm_crtc *crtc)
 {
 	struct drm_mode_object *obj = &crtc->base;
+	struct drm_mode_config *config = &crtc->dev->mode_config;
 
-	drm_object_attach_property(obj, prop_src_x, 0);
-	drm_object_attach_property(obj, prop_src_y, 0);
-	drm_object_attach_property(obj, prop_fb_id, 0);
-	drm_object_attach_property(obj, prop_mode, 0);
-	drm_object_attach_property(obj, prop_connector_ids, 0);
+	drm_object_attach_property(obj, config->src_x_prop, 0);
+	drm_object_attach_property(obj, config->src_y_prop, 0);
+	drm_object_attach_property(obj, config->fb_id_prop, 0);
+	drm_object_attach_property(obj, config->mode_prop, 0);
+	drm_object_attach_property(obj, config->connector_ids_prop, 0);
 }
 
 void intel_crtc_attach_properties(struct drm_crtc *crtc)
 {
 	struct drm_mode_object *obj = &crtc->base;
+	struct drm_mode_config *config = &crtc->dev->mode_config;
 
 	drm_crtc_attach_properties(crtc);
 
-	drm_object_attach_property(obj, prop_cursor_id, 0);
-	drm_object_attach_property(obj, prop_cursor_x, 0);
-	drm_object_attach_property(obj, prop_cursor_y, 0);
-	drm_object_attach_property(obj, prop_cursor_w, 0);
-	drm_object_attach_property(obj, prop_cursor_h, 0);
+	drm_object_attach_property(obj, config->cursor_id_prop, 0);
+	drm_object_attach_property(obj, config->cursor_x_prop, 0);
+	drm_object_attach_property(obj, config->cursor_y_prop, 0);
+	drm_object_attach_property(obj, config->cursor_w_prop, 0);
+	drm_object_attach_property(obj, config->cursor_h_prop, 0);
 }
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 74fb5a8..c8cea87 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -835,6 +835,25 @@ struct drm_mode_config {
 	struct drm_property *dithering_mode_property;
 	struct drm_property *dirty_info_property;
 
+	/* CRTC/plane properties */
+	struct drm_property *src_x_prop;
+	struct drm_property *src_y_prop;
+	struct drm_property *src_w_prop;
+	struct drm_property *src_h_prop;
+	struct drm_property *crtc_x_prop;
+	struct drm_property *crtc_y_prop;
+	struct drm_property *crtc_w_prop;
+	struct drm_property *crtc_h_prop;
+	struct drm_property *fb_id_prop;
+	struct drm_property *crtc_id_prop;
+	struct drm_property *mode_prop;
+	struct drm_property *connector_ids_prop;
+	struct drm_property *cursor_id_prop;
+	struct drm_property *cursor_x_prop;
+	struct drm_property *cursor_y_prop;
+	struct drm_property *cursor_w_prop;
+	struct drm_property *cursor_h_prop;
+
 	/* dumb ioctl parameters */
 	uint32_t preferred_depth, prefer_shadow;
 };
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 46/81] drm_crtc_helper: Update standard crtc properties after modeset
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (44 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 45/81] drm/i915: Move standard properties under mode_config ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 47/81] drm: Update standard plane properties after update_plane/disable_plane ville.syrjala
                   ` (36 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Keep the new CRTC properties when doing modeset through the legacy code
paths.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_crtc_helper.c |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 30eb557..19444cd 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -782,6 +782,11 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
 	kfree(save_connectors);
 	kfree(save_encoders);
 	kfree(save_crtcs);
+
+	/* changes in one CRTC can affect the others */
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+		drm_crtc_update_properties(crtc);
+
 	return 0;
 
 fail:
@@ -810,6 +815,11 @@ fail:
 	kfree(save_connectors);
 	kfree(save_encoders);
 	kfree(save_crtcs);
+
+	/* changes in one CRTC can affect the others */
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+		drm_crtc_update_properties(crtc);
+
 	return ret;
 }
 EXPORT_SYMBOL(drm_crtc_helper_set_config);
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 47/81] drm: Update standard plane properties after update_plane/disable_plane
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (45 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 46/81] drm_crtc_helper: Update standard crtc properties after modeset ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 48/81] drm/i915: Update CRTC properties after modeset ville.syrjala
                   ` (35 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Keep the new plane properties when doing operations through the legacy
code paths.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_crtc.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 897ff46..9d8738f 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -407,6 +407,8 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
 			/* disconnect the plane from the fb and crtc: */
 			plane->fb = NULL;
 			plane->crtc = NULL;
+
+			drm_plane_update_properties(plane);
 		}
 	}
 
@@ -1780,6 +1782,8 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
 		plane->funcs->disable_plane(plane);
 		plane->crtc = NULL;
 		plane->fb = NULL;
+
+		drm_plane_update_properties(plane);
 		goto out;
 	}
 
@@ -1863,6 +1867,8 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
 		plane->src_y = plane_req->src_y;
 		plane->src_w = plane_req->src_w;
 		plane->src_h = plane_req->src_h;
+
+		drm_plane_update_properties(plane);
 	}
 
 out:
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 48/81] drm/i915: Update CRTC properties after modeset
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (46 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 47/81] drm: Update standard plane properties after update_plane/disable_plane ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 49/81] drm: Move standard crtc/plane prop handling to drm_crtc.c ville.syrjala
                   ` (34 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Update cursor related CRTC properties after a modeset. The cursor
properties aren't handled by the drm core since not all CRTCs have
cursors.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |   15 +++++++++++++++
 1 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 566bf29..321c840 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6368,6 +6368,8 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
 	if (old_obj)
 		intel_crtc_cursor_bo_unref(crtc, old_obj);
 
+	intel_crtc_update_properties(crtc);
+
 	return 0;
 }
 
@@ -6380,6 +6382,8 @@ static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
 
 	intel_crtc_update_cursor(crtc, true);
 
+	intel_crtc_update_properties(crtc);
+
 	return 0;
 }
 
@@ -7341,6 +7345,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
 
 	trace_i915_flip_request(intel_crtc->plane, obj);
 
+	intel_crtc_update_properties(crtc);
+
 	return 0;
 
 cleanup_pending:
@@ -8067,6 +8073,7 @@ next_encoder:
 static int intel_crtc_set_config(struct drm_mode_set *set)
 {
 	struct drm_device *dev;
+	struct drm_crtc *crtc;
 	struct drm_mode_set save_set;
 	struct intel_set_config *config;
 	int ret;
@@ -8140,6 +8147,10 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 
 	intel_set_config_free(config);
 
+	/* changes in one CRTC can affect the others */
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+		intel_crtc_update_properties(crtc);
+
 	return 0;
 
 fail:
@@ -8151,6 +8162,10 @@ fail:
 			    save_set.x, save_set.y, save_set.fb))
 		DRM_ERROR("failed to restore config after modeset failure\n");
 
+	/* changes in one CRTC can affect the others */
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+		intel_crtc_update_properties(crtc);
+
 out_config:
 	intel_set_config_free(config);
 	return ret;
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 49/81] drm: Move standard crtc/plane prop handling to drm_crtc.c
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (47 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 48/81] drm/i915: Update CRTC properties after modeset ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 50/81] drm/i915: Use intel_best_encoder() directly ville.syrjala
                   ` (33 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Move some of the property code to drm_crtc.c since it should be shared
by everyone.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_crtc.c           |  235 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_atomic.c  |  256 ----------------------------------
 drivers/gpu/drm/i915/intel_display.c |   29 ++++
 3 files changed, 264 insertions(+), 256 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 9d8738f..527b35b 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -4397,3 +4397,238 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
 
 	return ret;
 }
+
+static void drm_crtc_update_connector_ids_property(struct drm_crtc *crtc)
+{
+	struct drm_mode_config *config = &crtc->dev->mode_config;
+	struct drm_connector *connector;
+	uint64_t value = 0;
+	int i = 0;
+	uint32_t connector_ids[config->num_connector];
+
+	list_for_each_entry(connector, &config->connector_list, head) {
+		if (connector->encoder && connector->encoder->crtc == crtc)
+			connector_ids[i++] = connector->base.id;
+	}
+
+	if (i) {
+		drm_property_blob_replace_data(crtc->connector_ids_blob,
+					       i * sizeof connector_ids[0], connector_ids);
+		value = crtc->connector_ids_blob->base.id;
+	} else
+		drm_property_blob_replace_data(crtc->connector_ids_blob, 0, NULL);
+
+	drm_object_property_set_value(&crtc->base, config->connector_ids_prop, value);
+}
+
+static void drm_crtc_update_mode_property(struct drm_crtc *crtc)
+{
+	struct drm_mode_config *config = &crtc->dev->mode_config;
+	uint64_t value = 0;
+
+	if (crtc->enabled) {
+		struct drm_mode_modeinfo umode;
+
+		drm_crtc_convert_to_umode(&umode, &crtc->mode);
+		drm_property_blob_replace_data(crtc->mode_blob, sizeof umode, &umode);
+		value = crtc->mode_blob->base.id;
+	} else
+		drm_property_blob_replace_data(crtc->mode_blob, 0, NULL);
+
+	drm_object_property_set_value(&crtc->base, config->mode_prop, value);
+}
+
+void drm_crtc_update_properties(struct drm_crtc *crtc)
+{
+	struct drm_mode_object *obj = &crtc->base;
+	struct drm_mode_config *config = &crtc->dev->mode_config;
+
+	drm_object_property_set_value(obj, config->src_x_prop, crtc->x);
+	drm_object_property_set_value(obj, config->src_y_prop, crtc->y);
+	drm_object_property_set_value(obj, config->fb_id_prop, crtc->fb ? crtc->fb->base.id : 0);
+
+	drm_crtc_update_mode_property(crtc);
+	drm_crtc_update_connector_ids_property(crtc);
+}
+EXPORT_SYMBOL(drm_crtc_update_properties);
+
+void drm_plane_update_properties(struct drm_plane *plane)
+{
+	struct drm_mode_object *obj = &plane->base;
+	struct drm_mode_config *config = &plane->dev->mode_config;
+
+	drm_object_property_set_value(obj, config->src_x_prop, plane->src_x);
+	drm_object_property_set_value(obj, config->src_y_prop, plane->src_y);
+	drm_object_property_set_value(obj, config->src_w_prop, plane->src_w);
+	drm_object_property_set_value(obj, config->src_h_prop, plane->src_h);
+
+	drm_object_property_set_value(obj, config->crtc_x_prop, plane->crtc_x);
+	drm_object_property_set_value(obj, config->crtc_y_prop, plane->crtc_y);
+	drm_object_property_set_value(obj, config->crtc_w_prop, plane->crtc_w);
+	drm_object_property_set_value(obj, config->crtc_h_prop, plane->crtc_h);
+
+	drm_object_property_set_value(obj, config->fb_id_prop, plane->fb ? plane->fb->base.id : 0);
+	drm_object_property_set_value(obj, config->crtc_id_prop, plane->crtc ? plane->crtc->base.id : 0);
+}
+EXPORT_SYMBOL(drm_plane_update_properties);
+
+int drm_crtc_create_blobs(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+
+	crtc->mode_blob = drm_property_create_blob(dev, 0, sizeof(struct drm_mode_modeinfo), NULL);
+	if (!crtc->mode_blob)
+		return -ENOMEM;
+
+	crtc->connector_ids_blob = drm_property_create_blob(dev, 0, dev->mode_config.num_connector * sizeof(uint32_t), NULL);
+	if (!crtc->connector_ids_blob)
+		return -ENOMEM;
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_crtc_create_blobs);
+
+void drm_crtc_destroy_blobs(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+
+	drm_property_destroy_blob(dev, crtc->mode_blob);
+	drm_property_destroy_blob(dev, crtc->connector_ids_blob);
+}
+EXPORT_SYMBOL(drm_crtc_destroy_blobs);
+
+static void drm_property_destroy_null(struct drm_device *dev, struct drm_property **prop)
+{
+	drm_property_destroy(dev, *prop);
+	*prop = NULL;
+}
+
+void drm_mode_destroy_properties(struct drm_device *dev)
+{
+	struct drm_mode_config *config = &dev->mode_config;
+
+	drm_property_destroy_null(dev, &config->cursor_h_prop);
+	drm_property_destroy_null(dev, &config->cursor_w_prop);
+	drm_property_destroy_null(dev, &config->cursor_y_prop);
+	drm_property_destroy_null(dev, &config->cursor_x_prop);
+	drm_property_destroy_null(dev, &config->cursor_id_prop);
+
+	drm_property_destroy_null(dev, &config->connector_ids_prop);
+	drm_property_destroy_null(dev, &config->mode_prop);
+
+	drm_property_destroy_null(dev, &config->crtc_id_prop);
+	drm_property_destroy_null(dev, &config->fb_id_prop);
+
+	drm_property_destroy_null(dev, &config->crtc_h_prop);
+	drm_property_destroy_null(dev, &config->crtc_w_prop);
+	drm_property_destroy_null(dev, &config->crtc_y_prop);
+	drm_property_destroy_null(dev, &config->crtc_x_prop);
+
+	drm_property_destroy_null(dev, &config->src_h_prop);
+	drm_property_destroy_null(dev, &config->src_w_prop);
+	drm_property_destroy_null(dev, &config->src_y_prop);
+	drm_property_destroy_null(dev, &config->src_x_prop);
+}
+EXPORT_SYMBOL(drm_mode_destroy_properties);
+
+int drm_mode_create_properties(struct drm_device *dev)
+{
+	struct drm_mode_config *config = &dev->mode_config;
+
+	config->src_x_prop = drm_property_create_range(dev, 0, "SRC_X", 0, UINT_MAX);
+	if (!config->src_x_prop)
+		goto out;
+	config->src_y_prop = drm_property_create_range(dev, 0, "SRC_Y", 0, UINT_MAX);
+	if (!config->src_y_prop)
+		goto out;
+	config->src_w_prop = drm_property_create_range(dev, 0, "SRC_W", 0, UINT_MAX);
+	if (!config->src_w_prop)
+		goto out;
+	config->src_h_prop = drm_property_create_range(dev, 0, "SRC_H", 0, UINT_MAX);
+	if (!config->src_h_prop)
+		goto out;
+
+	config->crtc_x_prop = drm_property_create_range(dev, 0, "CRTC_X", INT_MIN, INT_MAX);
+	if (!config->crtc_x_prop)
+		goto out;
+	config->crtc_y_prop = drm_property_create_range(dev, 0, "CRTC_Y", INT_MIN, INT_MAX);
+	if (!config->crtc_y_prop)
+		goto out;
+	config->crtc_w_prop = drm_property_create_range(dev, 0, "CRTC_W", 0, UINT_MAX);
+	if (!config->crtc_w_prop)
+		goto out;
+	config->crtc_h_prop = drm_property_create_range(dev, 0, "CRTC_H", 0, UINT_MAX);
+	if (!config->crtc_h_prop)
+		goto out;
+
+	config->fb_id_prop = drm_property_create_range(dev, 0, "FB_ID", 0, UINT_MAX);
+	if (!config->fb_id_prop)
+		goto out;
+	config->crtc_id_prop = drm_property_create_range(dev, 0, "CRTC_ID", 0, UINT_MAX);
+	if (!config->crtc_id_prop)
+		goto out;
+
+	config->cursor_id_prop = drm_property_create_range(dev, 0, "CURSOR_ID", 0, UINT_MAX);
+	if (!config->cursor_id_prop)
+		goto out;
+	config->cursor_x_prop = drm_property_create_range(dev, 0, "CURSOR_X", INT_MIN, INT_MAX);
+	if (!config->cursor_x_prop)
+		goto out;
+	config->cursor_y_prop = drm_property_create_range(dev, 0, "CURSOR_Y", INT_MIN, INT_MAX);
+	if (!config->cursor_y_prop)
+		goto out;
+	config->cursor_w_prop = drm_property_create_range(dev, 0, "CURSOR_W", 0, UINT_MAX);
+	if (!config->cursor_w_prop)
+		goto out;
+	config->cursor_h_prop = drm_property_create_range(dev, 0, "CURSOR_H", 0, UINT_MAX);
+	if (!config->cursor_h_prop)
+		goto out;
+
+	/* FIXME create special object ID list property type? */
+	config->connector_ids_prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, "CONNECTOR_IDS", 0);
+	if (!config->connector_ids_prop)
+		goto out;
+
+	config->mode_prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, "MODE", 0);
+	if (!config->mode_prop)
+		goto out;
+
+	return 0;
+
+ out:
+	drm_mode_destroy_properties(dev);
+
+	return -ENOMEM; /* FIXME? */
+}
+EXPORT_SYMBOL(drm_mode_create_properties);
+
+void drm_plane_attach_properties(struct drm_plane *plane)
+{
+	struct drm_mode_object *obj = &plane->base;
+	struct drm_mode_config *config = &plane->dev->mode_config;
+
+	drm_object_attach_property(obj, config->src_x_prop, 0);
+	drm_object_attach_property(obj, config->src_y_prop, 0);
+	drm_object_attach_property(obj, config->src_w_prop, 0);
+	drm_object_attach_property(obj, config->src_h_prop, 0);
+	drm_object_attach_property(obj, config->crtc_x_prop, 0);
+	drm_object_attach_property(obj, config->crtc_y_prop, 0);
+	drm_object_attach_property(obj, config->crtc_w_prop, 0);
+	drm_object_attach_property(obj, config->crtc_h_prop, 0);
+	drm_object_attach_property(obj, config->fb_id_prop, 0);
+	drm_object_attach_property(obj, config->crtc_id_prop, 0);
+}
+EXPORT_SYMBOL(drm_plane_attach_properties);
+
+void drm_crtc_attach_properties(struct drm_crtc *crtc)
+{
+	struct drm_mode_object *obj = &crtc->base;
+	struct drm_mode_config *config = &crtc->dev->mode_config;
+
+	drm_object_attach_property(obj, config->src_x_prop, 0);
+	drm_object_attach_property(obj, config->src_y_prop, 0);
+	drm_object_attach_property(obj, config->fb_id_prop, 0);
+	drm_object_attach_property(obj, config->mode_prop, 0);
+	drm_object_attach_property(obj, config->connector_ids_prop, 0);
+}
+EXPORT_SYMBOL(drm_crtc_attach_properties);
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 0def947..6dd07fb 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -2278,259 +2278,3 @@ void intel_atomic_clear_flips(struct drm_crtc *crtc)
 			drm_flip_helper_clear(&intel_plane->flip_helper);
 	}
 }
-
-static void drm_crtc_update_connector_ids_property(struct drm_crtc *crtc)
-{
-	struct drm_mode_config *config = &crtc->dev->mode_config;
-	struct drm_connector *connector;
-	uint64_t value = 0;
-	int i = 0;
-	uint32_t connector_ids[config->num_connector];
-
-	list_for_each_entry(connector, &config->connector_list, head) {
-		if (connector->encoder && connector->encoder->crtc == crtc)
-			connector_ids[i++] = connector->base.id;
-	}
-
-	if (i) {
-		drm_property_blob_replace_data(crtc->connector_ids_blob,
-					       i * sizeof connector_ids[0], connector_ids);
-		value = crtc->connector_ids_blob->base.id;
-	} else
-		drm_property_blob_replace_data(crtc->connector_ids_blob, 0, NULL);
-
-	drm_object_property_set_value(&crtc->base, config->connector_ids_prop, value);
-}
-
-static void drm_crtc_update_mode_property(struct drm_crtc *crtc)
-{
-	struct drm_mode_config *config = &crtc->dev->mode_config;
-	uint64_t value = 0;
-
-	if (crtc->enabled) {
-		struct drm_mode_modeinfo umode;
-
-		drm_crtc_convert_to_umode(&umode, &crtc->mode);
-		drm_property_blob_replace_data(crtc->mode_blob, sizeof umode, &umode);
-		value = crtc->mode_blob->base.id;
-	} else
-		drm_property_blob_replace_data(crtc->mode_blob, 0, NULL);
-
-	drm_object_property_set_value(&crtc->base, config->mode_prop, value);
-}
-
-void drm_crtc_update_properties(struct drm_crtc *crtc)
-{
-	struct drm_mode_object *obj = &crtc->base;
-	struct drm_mode_config *config = &crtc->dev->mode_config;
-
-	drm_object_property_set_value(obj, config->src_x_prop, crtc->x);
-	drm_object_property_set_value(obj, config->src_y_prop, crtc->y);
-	drm_object_property_set_value(obj, config->fb_id_prop, crtc->fb ? crtc->fb->base.id : 0);
-
-	drm_crtc_update_mode_property(crtc);
-	drm_crtc_update_connector_ids_property(crtc);
-}
-
-void intel_crtc_update_properties(struct drm_crtc *crtc)
-{
-	struct drm_mode_object *obj = &crtc->base;
-	struct drm_mode_config *config = &crtc->dev->mode_config;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
-	drm_crtc_update_properties(crtc);
-
-	drm_object_property_set_value(obj, config->cursor_id_prop, intel_crtc->cursor_handle);
-	drm_object_property_set_value(obj, config->cursor_x_prop, intel_crtc->cursor_x);
-	drm_object_property_set_value(obj, config->cursor_y_prop, intel_crtc->cursor_y);
-	drm_object_property_set_value(obj, config->cursor_w_prop, intel_crtc->cursor_width);
-	drm_object_property_set_value(obj, config->cursor_h_prop, intel_crtc->cursor_height);
-}
-
-void drm_plane_update_properties(struct drm_plane *plane)
-{
-	struct drm_mode_object *obj = &plane->base;
-	struct drm_mode_config *config = &plane->dev->mode_config;
-
-	drm_object_property_set_value(obj, config->src_x_prop, plane->src_x);
-	drm_object_property_set_value(obj, config->src_y_prop, plane->src_y);
-	drm_object_property_set_value(obj, config->src_w_prop, plane->src_w);
-	drm_object_property_set_value(obj, config->src_h_prop, plane->src_h);
-
-	drm_object_property_set_value(obj, config->crtc_x_prop, plane->crtc_x);
-	drm_object_property_set_value(obj, config->crtc_y_prop, plane->crtc_y);
-	drm_object_property_set_value(obj, config->crtc_w_prop, plane->crtc_w);
-	drm_object_property_set_value(obj, config->crtc_h_prop, plane->crtc_h);
-
-	drm_object_property_set_value(obj, config->fb_id_prop, plane->fb ? plane->fb->base.id : 0);
-	drm_object_property_set_value(obj, config->crtc_id_prop, plane->crtc ? plane->crtc->base.id : 0);
-}
-
-int drm_crtc_create_blobs(struct drm_crtc *crtc)
-{
-	struct drm_device *dev = crtc->dev;
-
-	crtc->mode_blob = drm_property_create_blob(dev, 0, sizeof(struct drm_mode_modeinfo), NULL);
-	if (!crtc->mode_blob)
-		return -ENOMEM;
-
-	crtc->connector_ids_blob = drm_property_create_blob(dev, 0, dev->mode_config.num_connector * sizeof(uint32_t), NULL);
-	if (!crtc->connector_ids_blob)
-		return -ENOMEM;
-
-	return 0;
-}
-
-void drm_crtc_destroy_blobs(struct drm_crtc *crtc)
-{
-	struct drm_device *dev = crtc->dev;
-
-	drm_property_destroy_blob(dev, crtc->mode_blob);
-	drm_property_destroy_blob(dev, crtc->connector_ids_blob);
-}
-
-void drm_property_destroy_null(struct drm_device *dev, struct drm_property **prop)
-{
-	drm_property_destroy(dev, *prop);
-	*prop = NULL;
-}
-
-void drm_mode_destroy_properties(struct drm_device *dev)
-{
-	struct drm_mode_config *config = &dev->mode_config;
-
-	drm_property_destroy_null(dev, &config->cursor_h_prop);
-	drm_property_destroy_null(dev, &config->cursor_w_prop);
-	drm_property_destroy_null(dev, &config->cursor_y_prop);
-	drm_property_destroy_null(dev, &config->cursor_x_prop);
-	drm_property_destroy_null(dev, &config->cursor_id_prop);
-
-	drm_property_destroy_null(dev, &config->connector_ids_prop);
-	drm_property_destroy_null(dev, &config->mode_prop);
-
-	drm_property_destroy_null(dev, &config->crtc_id_prop);
-	drm_property_destroy_null(dev, &config->fb_id_prop);
-
-	drm_property_destroy_null(dev, &config->crtc_h_prop);
-	drm_property_destroy_null(dev, &config->crtc_w_prop);
-	drm_property_destroy_null(dev, &config->crtc_y_prop);
-	drm_property_destroy_null(dev, &config->crtc_x_prop);
-
-	drm_property_destroy_null(dev, &config->src_h_prop);
-	drm_property_destroy_null(dev, &config->src_w_prop);
-	drm_property_destroy_null(dev, &config->src_y_prop);
-	drm_property_destroy_null(dev, &config->src_x_prop);
-}
-
-int drm_mode_create_properties(struct drm_device *dev)
-{
-	struct drm_mode_config *config = &dev->mode_config;
-
-	config->src_x_prop = drm_property_create_range(dev, 0, "SRC_X", 0, UINT_MAX);
-	if (!config->src_x_prop)
-		goto out;
-	config->src_y_prop = drm_property_create_range(dev, 0, "SRC_Y", 0, UINT_MAX);
-	if (!config->src_y_prop)
-		goto out;
-	config->src_w_prop = drm_property_create_range(dev, 0, "SRC_W", 0, UINT_MAX);
-	if (!config->src_w_prop)
-		goto out;
-	config->src_h_prop = drm_property_create_range(dev, 0, "SRC_H", 0, UINT_MAX);
-	if (!config->src_h_prop)
-		goto out;
-
-	config->crtc_x_prop = drm_property_create_range(dev, 0, "CRTC_X", INT_MIN, INT_MAX);
-	if (!config->crtc_x_prop)
-		goto out;
-	config->crtc_y_prop = drm_property_create_range(dev, 0, "CRTC_Y", INT_MIN, INT_MAX);
-	if (!config->crtc_y_prop)
-		goto out;
-	config->crtc_w_prop = drm_property_create_range(dev, 0, "CRTC_W", 0, UINT_MAX);
-	if (!config->crtc_w_prop)
-		goto out;
-	config->crtc_h_prop = drm_property_create_range(dev, 0, "CRTC_H", 0, UINT_MAX);
-	if (!config->crtc_h_prop)
-		goto out;
-
-	config->fb_id_prop = drm_property_create_range(dev, 0, "FB_ID", 0, UINT_MAX);
-	if (!config->fb_id_prop)
-		goto out;
-	config->crtc_id_prop = drm_property_create_range(dev, 0, "CRTC_ID", 0, UINT_MAX);
-	if (!config->crtc_id_prop)
-		goto out;
-
-	config->cursor_id_prop = drm_property_create_range(dev, 0, "CURSOR_ID", 0, UINT_MAX);
-	if (!config->cursor_id_prop)
-		goto out;
-	config->cursor_x_prop = drm_property_create_range(dev, 0, "CURSOR_X", INT_MIN, INT_MAX);
-	if (!config->cursor_x_prop)
-		goto out;
-	config->cursor_y_prop = drm_property_create_range(dev, 0, "CURSOR_Y", INT_MIN, INT_MAX);
-	if (!config->cursor_y_prop)
-		goto out;
-	config->cursor_w_prop = drm_property_create_range(dev, 0, "CURSOR_W", 0, UINT_MAX);
-	if (!config->cursor_w_prop)
-		goto out;
-	config->cursor_h_prop = drm_property_create_range(dev, 0, "CURSOR_H", 0, UINT_MAX);
-	if (!config->cursor_h_prop)
-		goto out;
-
-	/* FIXME create special object ID list property type? */
-	config->connector_ids_prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, "CONNECTOR_IDS", 0);
-	if (!config->connector_ids_prop)
-		goto out;
-
-	config->mode_prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, "MODE", 0);
-	if (!config->mode_prop)
-		goto out;
-
-	return 0;
-
- out:
-	drm_mode_destroy_properties(dev);
-
-	return -ENOMEM; /* FIXME? */
-}
-
-void drm_plane_attach_properties(struct drm_plane *plane)
-{
-	struct drm_mode_object *obj = &plane->base;
-	struct drm_mode_config *config = &plane->dev->mode_config;
-
-	drm_object_attach_property(obj, config->src_x_prop, 0);
-	drm_object_attach_property(obj, config->src_y_prop, 0);
-	drm_object_attach_property(obj, config->src_w_prop, 0);
-	drm_object_attach_property(obj, config->src_h_prop, 0);
-	drm_object_attach_property(obj, config->crtc_x_prop, 0);
-	drm_object_attach_property(obj, config->crtc_y_prop, 0);
-	drm_object_attach_property(obj, config->crtc_w_prop, 0);
-	drm_object_attach_property(obj, config->crtc_h_prop, 0);
-	drm_object_attach_property(obj, config->fb_id_prop, 0);
-	drm_object_attach_property(obj, config->crtc_id_prop, 0);
-}
-
-void drm_crtc_attach_properties(struct drm_crtc *crtc)
-{
-	struct drm_mode_object *obj = &crtc->base;
-	struct drm_mode_config *config = &crtc->dev->mode_config;
-
-	drm_object_attach_property(obj, config->src_x_prop, 0);
-	drm_object_attach_property(obj, config->src_y_prop, 0);
-	drm_object_attach_property(obj, config->fb_id_prop, 0);
-	drm_object_attach_property(obj, config->mode_prop, 0);
-	drm_object_attach_property(obj, config->connector_ids_prop, 0);
-}
-
-void intel_crtc_attach_properties(struct drm_crtc *crtc)
-{
-	struct drm_mode_object *obj = &crtc->base;
-	struct drm_mode_config *config = &crtc->dev->mode_config;
-
-	drm_crtc_attach_properties(crtc);
-
-	drm_object_attach_property(obj, config->cursor_id_prop, 0);
-	drm_object_attach_property(obj, config->cursor_x_prop, 0);
-	drm_object_attach_property(obj, config->cursor_y_prop, 0);
-	drm_object_attach_property(obj, config->cursor_w_prop, 0);
-	drm_object_attach_property(obj, config->cursor_h_prop, 0);
-}
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 321c840..451cc3d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -9372,3 +9372,32 @@ intel_display_print_error_state(struct seq_file *m,
 	}
 }
 #endif
+
+void intel_crtc_update_properties(struct drm_crtc *crtc)
+{
+	struct drm_mode_object *obj = &crtc->base;
+	struct drm_mode_config *config = &crtc->dev->mode_config;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+	drm_crtc_update_properties(crtc);
+
+	drm_object_property_set_value(obj, config->cursor_id_prop, intel_crtc->cursor_handle);
+	drm_object_property_set_value(obj, config->cursor_x_prop, intel_crtc->cursor_x);
+	drm_object_property_set_value(obj, config->cursor_y_prop, intel_crtc->cursor_y);
+	drm_object_property_set_value(obj, config->cursor_w_prop, intel_crtc->cursor_width);
+	drm_object_property_set_value(obj, config->cursor_h_prop, intel_crtc->cursor_height);
+}
+
+void intel_crtc_attach_properties(struct drm_crtc *crtc)
+{
+	struct drm_mode_object *obj = &crtc->base;
+	struct drm_mode_config *config = &crtc->dev->mode_config;
+
+	drm_crtc_attach_properties(crtc);
+
+	drm_object_attach_property(obj, config->cursor_id_prop, 0);
+	drm_object_attach_property(obj, config->cursor_x_prop, 0);
+	drm_object_attach_property(obj, config->cursor_y_prop, 0);
+	drm_object_attach_property(obj, config->cursor_w_prop, 0);
+	drm_object_attach_property(obj, config->cursor_h_prop, 0);
+}
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 50/81] drm/i915: Use intel_best_encoder() directly
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (48 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 49/81] drm: Move standard crtc/plane prop handling to drm_crtc.c ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 51/81] drm/i915: Unstatic intel_modeset_update_staged_output_state() ville.syrjala
                   ` (32 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

All connectors use intel_best_encoder() as their best_encoder() func, so
just call it directly w/o the indirection.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_atomic.c |   10 ++--------
 1 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 6dd07fb..e58ec3f 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -152,8 +152,6 @@ static int process_connectors(struct intel_crtc_state *s, const uint32_t *ids, i
 	int i;
 
 	for (i = 0; i < count_ids; i++) {
-		struct drm_encoder *encoder;
-		const struct drm_connector_helper_funcs *connector_funcs;
 		struct drm_mode_object *obj;
 		int j;
 
@@ -169,9 +167,8 @@ static int process_connectors(struct intel_crtc_state *s, const uint32_t *ids, i
 		}
 
 		connector = obj_to_connector(obj);
-		connector_funcs = connector->helper_private;
 
-		encoder = connector_funcs->best_encoder(connector);
+		encoder = intel_best_encoder(connector);
 
 		if (!drm_encoder_crtc_ok(encoder, crtc))
 			return -EINVAL;
@@ -180,9 +177,6 @@ static int process_connectors(struct intel_crtc_state *s, const uint32_t *ids, i
 	}
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		const struct drm_connector_helper_funcs *connector_funcs =
-			connector->helper_private;
-
 		for (i = 0; i < count_ids; i++) {
 			if (connector == connectors[i])
 				break;
@@ -196,7 +190,7 @@ static int process_connectors(struct intel_crtc_state *s, const uint32_t *ids, i
 			continue;
 		}
 
-		encoder = connector_funcs->best_encoder(connector);
+		encoder = intel_best_encoder(connector);
 
 		connector->encoder = encoder;
 		encoder->crtc = crtc;
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 51/81] drm/i915: Unstatic intel_modeset_update_staged_output_state()
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (49 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 50/81] drm/i915: Use intel_best_encoder() directly ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 52/81] drm/i915: Update new_crtc and new_encoder fields after atomic modeset ville.syrjala
                   ` (31 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

The atomic code needs intel_modeset_update_staged_output_state().

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |    2 +-
 drivers/gpu/drm/i915/intel_drv.h     |    2 ++
 2 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 451cc3d..c84a839 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -7423,7 +7423,7 @@ static bool intel_encoder_crtc_ok(struct drm_encoder *encoder,
  * Updates the staged output configuration state, e.g. after we've read out the
  * current hw state.
  */
-static void intel_modeset_update_staged_output_state(struct drm_device *dev)
+void intel_modeset_update_staged_output_state(struct drm_device *dev)
 {
 	struct intel_encoder *encoder;
 	struct intel_connector *connector;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 1230c1b..24dc192 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -737,4 +737,6 @@ extern void intel_disable_primary(struct drm_crtc *crtc);
 extern void intel_crtc_attach_properties(struct drm_crtc *crtc);
 extern void intel_crtc_update_properties(struct drm_crtc *crtc);
 
+extern void intel_modeset_update_staged_output_state(struct drm_device *dev);
+
 #endif /* __INTEL_DRV_H__ */
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 52/81] drm/i915: Update new_crtc and new_encoder fields after atomic modeset
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (50 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 51/81] drm/i915: Unstatic intel_modeset_update_staged_output_state() ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 53/81] drm/i915: Update connector DPMS state after an " ville.syrjala
                   ` (30 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

The i915 modeset logic requires that these be kept in sync with
the other crtc and encoder pointers.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_atomic.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index e58ec3f..c5558cc 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -1701,6 +1701,8 @@ static int intel_atomic_commit(struct drm_device *dev, void *state)
 
 	update_props(dev, s);
 
+	intel_modeset_update_staged_output_state(dev);
+
 	return 0;
 }
 
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 53/81] drm/i915: Update connector DPMS state after an atomic modeset
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (51 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 52/81] drm/i915: Update new_crtc and new_encoder fields after atomic modeset ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 54/81] drm/i915: Kill the pending_flip counter manipulations ville.syrjala
                   ` (29 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Update the connector DPMS state after atomic modeset operations.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_atomic.c |   31 +++++++++++++++++++++++++++++++
 1 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index c5558cc..1fce359 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -1475,6 +1475,36 @@ static void update_props(struct drm_device *dev,
 	}
 }
 
+/*
+ * FIXME
+ * Perhaps atomic modeset shouldn't actually change the DPMS state,
+ * unless explicitly asked to do so. That's the way we treat everything
+ * else, so it makes sense. Although the dpms property is already a bit
+ * special in the legacy codepaths, so maybe we should follow the same
+ * pattern. Ie. a modeset forces DPMS to on (which is what we do here).
+ */
+static void update_connector_dpms(struct drm_device *dev, struct drm_crtc *crtc)
+{
+	struct drm_connector *connector;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		int dpms = connector->dpms;
+
+		if (connector->encoder && connector->encoder->crtc == crtc)
+			dpms = DRM_MODE_DPMS_ON;
+		else if (!connector->encoder || !connector->encoder->crtc)
+			dpms = DRM_MODE_DPMS_OFF;
+
+		if (connector->dpms == dpms)
+			continue;
+
+		connector->dpms = dpms;
+		drm_connector_property_set_value(connector,
+						 dev->mode_config.dpms_property,
+						 dpms);
+	}
+}
+
 static void update_crtc(struct drm_device *dev,
 			struct intel_atomic_state *s)
 {
@@ -1494,6 +1524,7 @@ static void update_crtc(struct drm_device *dev,
 		if (st->mode_dirty) {
 			drm_calc_timestamping_constants(crtc);
 			intel_crtc_update_sarea(crtc, crtc->enabled);
+			update_connector_dpms(dev, crtc);
 		}
 
 		if (st->fb_dirty)
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 54/81] drm/i915: Kill the pending_flip counter manipulations
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (52 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 53/81] drm/i915: Update connector DPMS state after an " ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 55/81] drm/i915: Don't mark cursor as pinned, when we don't have a cursor bo ville.syrjala
                   ` (28 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

The pending_flip counter is probably going to be remove entirely,
along with i915_gem_execbuffer_wait_for_flips() so don't even try to
use it.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_atomic.c |   74 +----------------------------------
 1 files changed, 2 insertions(+), 72 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 1fce359..ac7fe88 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -1536,45 +1536,9 @@ static void atomic_pipe_commit(struct drm_device *dev,
 			       struct intel_atomic_state *state,
 			       int pipe);
 
-static int apply_nonblocking(struct drm_device *dev, struct intel_atomic_state *s)
+static void apply_nonblocking(struct drm_device *dev, struct intel_atomic_state *s)
 {
 	struct intel_crtc *intel_crtc;
-	int i;
-
-	for (i = 0; i < dev->mode_config.num_crtc; i++) {
-		struct intel_crtc_state *st = &s->crtc[i];
-		struct intel_crtc *intel_crtc = to_intel_crtc(st->crtc);
-		struct drm_i915_gem_object *obj;
-
-		if (!st->old.fb)
-			continue;
-
-		obj = to_intel_framebuffer(st->old.fb)->obj;
-
-		/* Only one bit per plane in pending_flips */
-		if (atomic_read(&obj->pending_flip) & (1 << intel_crtc->plane))
-			return -EBUSY;
-	}
-
-	for (i = 0; i < dev->mode_config.num_plane; i++) {
-		struct intel_plane_state *st = &s->plane[i];
-		struct intel_plane *intel_plane = to_intel_plane(st->plane);
-		struct drm_i915_gem_object *obj;
-
-		if (!st->old.fb)
-			continue;
-
-		obj = to_intel_framebuffer(st->old.fb)->obj;
-
-		if (!st->old.fb)
-			continue;
-
-		obj = to_intel_framebuffer(st->old.fb)->obj;
-
-		/* Only one bit per plane in pending_flips */
-		if (atomic_read(&obj->pending_flip) & (1 << (16 + intel_plane->pipe)))
-			return -EBUSY;
-	}
 
 	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head)
 		atomic_pipe_commit(dev, s, intel_crtc->pipe);
@@ -1582,8 +1546,6 @@ static int apply_nonblocking(struct drm_device *dev, struct intel_atomic_state *
 	/* don't restore the old state in end() */
 	s->dirty = false;
 	s->restore_state = false;
-
-	return 0;
 }
 
 static int alloc_flip_data(struct drm_device *dev, struct intel_atomic_state *s)
@@ -1695,12 +1657,7 @@ static int intel_atomic_commit(struct drm_device *dev, void *state)
 
 	/* try to apply in a non blocking manner */
 	if (s->flags & DRM_MODE_ATOMIC_NONBLOCK) {
-		ret = apply_nonblocking(dev, s);
-		if (ret) {
-			unpin_cursors(dev, s);
-			unpin_fbs(dev, s);
-			return ret;
-		}
+		apply_nonblocking(dev, s);
 	} else {
 		/* apply in a blocking manner */
 		ret = apply_config(dev, s);
@@ -1823,7 +1780,6 @@ static void intel_flip_complete(struct drm_flip *flip)
 	struct intel_flip *intel_flip =
 		container_of(flip, struct intel_flip, base);
 	struct drm_device *dev = intel_flip->crtc->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_crtc *crtc = intel_flip->crtc;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe;
@@ -1841,18 +1797,6 @@ static void intel_flip_complete(struct drm_flip *flip)
 
 	if (intel_flip->vblank_ref)
 		drm_vblank_put(dev, pipe);
-
-	/* Possibly allow rendering to old_bo again */
-	if (intel_flip->old_bo) {
-		if (intel_flip->plane) {
-			struct intel_plane *intel_plane = to_intel_plane(intel_flip->plane);
-			atomic_clear_mask(1 << (16 + intel_plane->pipe), &intel_flip->old_bo->pending_flip.counter);
-		} else
-			atomic_clear_mask(1 << intel_crtc->plane, &intel_flip->old_bo->pending_flip.counter);
-
-		if (atomic_read(&intel_flip->old_bo->pending_flip) == 0)
-			wake_up(&dev_priv->pending_flip_queue);
-	}
 }
 
 static void intel_flip_finish(struct drm_flip *flip)
@@ -2193,13 +2137,6 @@ static void atomic_pipe_commit(struct drm_device *dev,
 			mutex_lock(&dev->struct_mutex);
 			drm_gem_object_reference(&intel_flip->old_bo->base);
 			mutex_unlock(&dev->struct_mutex);
-
-			/*
-			 * Block clients from rendering to the new back buffer until
-			 * the flip occurs and the object is no longer visible.
-			 */
-			atomic_set_mask(1 << intel_crtc->plane,
-					&intel_flip->old_bo->pending_flip.counter);
 		}
 
 		list_add_tail(&intel_flip->base.list, &flips);
@@ -2244,13 +2181,6 @@ static void atomic_pipe_commit(struct drm_device *dev,
 			mutex_lock(&dev->struct_mutex);
 			drm_gem_object_reference(&intel_flip->old_bo->base);
 			mutex_unlock(&dev->struct_mutex);
-
-			/*
-			 * Block clients from rendering to the new back buffer until
-			 * the flip occurs and the object is no longer visible.
-			 */
-			atomic_set_mask(1 << (16 + intel_plane->pipe),
-					&intel_flip->old_bo->pending_flip.counter);
 		}
 
 		list_add_tail(&intel_flip->base.list, &flips);
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 55/81] drm/i915: Don't mark cursor as pinned, when we don't have a cursor bo
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (53 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 54/81] drm/i915: Kill the pending_flip counter manipulations ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 56/81] drm/i915: Fix sprite_scaling_enabled for multiple sprites ville.syrjala
                   ` (27 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Avoids a NULL pointer dereference if the atomic modeset fails.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_atomic.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index ac7fe88..98af0ae 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -726,7 +726,8 @@ static int pin_cursors(struct drm_device *dev,
 		if (ret)
 			goto unpin;
 
-		st->cursor_pinned = true;
+		if (intel_crtc->cursor_bo)
+			st->cursor_pinned = true;
 	}
 
 	return 0;
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 56/81] drm/i915: Fix sprite_scaling_enabled for multiple sprites
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (54 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 55/81] drm/i915: Don't mark cursor as pinned, when we don't have a cursor bo ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 57/81] drm/i915: Fix hiding the cursor with atomic ioctl ville.syrjala
                   ` (26 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

We have more than one sprite, so a boolean simply won't cut it.
Turn sprite_scaling_enabled into a bitmask and track the state
of sprite scaler for each sprite independently.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h     |    2 +-
 drivers/gpu/drm/i915/intel_sprite.c |   11 ++++++-----
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 0bafe7f..6f865bf 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -729,7 +729,7 @@ typedef struct drm_i915_private {
 
 	/* overlay */
 	struct intel_overlay *overlay;
-	bool sprite_scaling_enabled;
+	unsigned int sprite_scaling_enabled;
 
 	/* LVDS info */
 	int backlight_level;  /* restore backlight to this value */
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 693b265..ce3b950 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -345,15 +345,16 @@ ivb_prepare_plane(struct drm_plane *plane)
 	 */
 	if (regs->scale & SPRITE_SCALE_ENABLE) {
 		if (!dev_priv->sprite_scaling_enabled) {
-			dev_priv->sprite_scaling_enabled = true;
+			dev_priv->sprite_scaling_enabled |= 1 << pipe;
 			intel_update_watermarks(dev);
 			intel_wait_for_vblank(dev, pipe);
 		}
 	} else {
-		if (dev_priv->sprite_scaling_enabled) {
-			dev_priv->sprite_scaling_enabled = false;
+		if (dev_priv->sprite_scaling_enabled & (1 << pipe)) {
+			dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
 			/* potentially re-enable LP watermarks */
-			intel_update_watermarks(dev);
+			if (!dev_priv->sprite_scaling_enabled)
+				intel_update_watermarks(dev);
 		}
 	}
 }
@@ -389,7 +390,7 @@ ivb_disable_plane(struct drm_plane *plane)
 	ivb_commit_plane(plane);
 	POSTING_READ(SPRSURF(pipe));
 
-	dev_priv->sprite_scaling_enabled = false;
+	dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
 	intel_update_watermarks(dev);
 }
 
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 57/81] drm/i915: Fix hiding the cursor with atomic ioctl
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (55 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 56/81] drm/i915: Fix sprite_scaling_enabled for multiple sprites ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 58/81] drm/i915: Fix plane src rectangle dirty check ville.syrjala
                   ` (25 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>

intel_crtc->cursor_visible is only changed on the commit phase, so the
check for visibility was considering the previous state. Change this to
intel_crtc->cursor_handle instead.
---
 drivers/gpu/drm/i915/intel_atomic.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 98af0ae..c4cec40 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -1304,7 +1304,7 @@ static int check_crtc(struct intel_crtc_state *s)
 		}
 	}
 
-	if (intel_crtc->cursor_visible &&
+	if (intel_crtc->cursor_handle &&
 	    (intel_crtc->cursor_width != 64 ||
 	     intel_crtc->cursor_height != 64)) {
 		return -EINVAL;
-- 
1.7.8.6

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 58/81] drm/i915: Fix plane src rectangle dirty check
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (56 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 57/81] drm/i915: Fix hiding the cursor with atomic ioctl ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 59/81] drm/i915: Send atomic completion events even if nothing changed ville.syrjala
                   ` (24 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_atomic.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index c4cec40..bfc0563 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -555,9 +555,9 @@ static void plane_compute_dirty(struct intel_atomic_state *s,
 		return;
 
 	if (plane->src_x != state->old.src_x ||
-	    plane->src_y != state->old.src_x ||
-	    plane->src_w != state->old.src_x ||
-	    plane->src_h != state->old.src_x ||
+	    plane->src_y != state->old.src_y ||
+	    plane->src_w != state->old.src_w ||
+	    plane->src_h != state->old.src_h ||
 	    plane->crtc_x != state->old.crtc_x ||
 	    plane->crtc_y != state->old.crtc_y ||
 	    plane->crtc_w != state->old.crtc_w ||
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 59/81] drm/i915: Send atomic completion events even if nothing changed
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (57 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 58/81] drm/i915: Fix plane src rectangle dirty check ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 60/81] drm/i915: Unpin old fbs only when appropriate ville.syrjala
                   ` (23 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_atomic.c |    8 +++++---
 1 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index bfc0563..a119896 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -1641,13 +1641,15 @@ static int intel_atomic_commit(struct drm_device *dev, void *state)
 	struct intel_atomic_state *s = state;
 	int ret;
 
-	if (!s->dirty)
-		return 0;
-
 	ret = alloc_flip_data(dev, s);
 	if (ret)
 		return ret;
 
+	if (!s->dirty) {
+		queue_remaining_events(dev, s);
+		return 0;
+	}
+
 	ret = pin_fbs(dev, s);
 	if (ret)
 		return ret;
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 60/81] drm/i915: Unpin old fbs only when appropriate
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (58 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 59/81] drm/i915: Send atomic completion events even if nothing changed ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 61/81] drm/i915: Remove stale prototypes form atomic code ville.syrjala
                   ` (22 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Don't unpin the old fb after flips, unless a new fb was pinned, or we're
disabling the plane/crtc.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_atomic.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index a119896..b795cb2 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -2133,8 +2133,10 @@ static void atomic_pipe_commit(struct drm_device *dev,
 			intel_flip->old_cursor_bo = st->old.cursor_bo;
 		}
 
-		if (st->old.fb) {
+		if (st->old.fb)
 			intel_flip->old_fb_id = st->old.fb->base.id;
+
+		if (st->fb_dirty && st->old.fb) {
 			intel_flip->old_bo = to_intel_framebuffer(st->old.fb)->obj;
 
 			mutex_lock(&dev->struct_mutex);
@@ -2177,8 +2179,10 @@ static void atomic_pipe_commit(struct drm_device *dev,
 
 		intel_plane->calc(plane, plane->fb, &st->coords);
 
-		if (st->old.fb) {
+		if (st->old.fb)
 			intel_flip->old_fb_id = st->old.fb->base.id;
+
+		if (st->dirty && st->old.fb) {
 			intel_flip->old_bo = to_intel_framebuffer(st->old.fb)->obj;
 
 			mutex_lock(&dev->struct_mutex);
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 61/81] drm/i915: Remove stale prototypes form atomic code
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (59 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 60/81] drm/i915: Unpin old fbs only when appropriate ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 62/81] drm/i915: Unstatic i915_gem_check_olr() ville.syrjala
                   ` (21 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

These function no longer exist.
---
 drivers/gpu/drm/i915/intel_atomic.c |    7 -------
 1 files changed, 0 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index b795cb2..7a7695b 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -916,13 +916,6 @@ static void update_plane_obj(struct drm_device *dev,
 	}
 }
 
-/* FIXME need to refactor the sprite code some more */
-int intel_disable_plane_nopin(struct drm_plane *plane);
-int intel_commit_plane_nopin(struct drm_plane *plane,
-			     struct drm_crtc *crtc,
-			     struct drm_framebuffer *fb,
-			     const struct intel_plane_coords *coords);
-
 static struct drm_pending_atomic_event *alloc_event(struct drm_device *dev,
 						    struct drm_file *file_priv,
 						    uint64_t user_data)
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 62/81] drm/i915: Unstatic i915_gem_check_olr()
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (60 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 61/81] drm/i915: Remove stale prototypes form atomic code ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 63/81] drm/i915: Refactor atomic flip code ville.syrjala
                   ` (20 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Atomic code might need i915_gem_check_olr().

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h |    1 +
 drivers/gpu/drm/i915/i915_gem.c |    2 +-
 2 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 6f865bf..6bb8b3f 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1520,6 +1520,7 @@ void i915_gem_retire_requests(struct drm_device *dev);
 void i915_gem_retire_requests_ring(struct intel_ring_buffer *ring);
 int __must_check i915_gem_check_wedge(struct drm_i915_private *dev_priv,
 				      bool interruptible);
+int i915_gem_check_olr(struct intel_ring_buffer *ring, u32 seqno);
 
 void i915_gem_reset(struct drm_device *dev);
 void i915_gem_clflush_object(struct drm_i915_gem_object *obj);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 9530592..f2f63ba 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -969,7 +969,7 @@ i915_gem_check_wedge(struct drm_i915_private *dev_priv,
  * Compare seqno against outstanding lazy request. Emit a request if they are
  * equal.
  */
-static int
+int
 i915_gem_check_olr(struct intel_ring_buffer *ring, u32 seqno)
 {
 	int ret;
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 63/81] drm/i915: Refactor atomic flip code
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (61 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 62/81] drm/i915: Unstatic i915_gem_check_olr() ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 64/81] drm/i915: Implement a non-blocking GPU synchronization mechanism for atomic page flips ville.syrjala
                   ` (19 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Collect the part which takes care of issuing the flips to a new
function. This makes the following patch nicer to look at.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_atomic.c |   37 ++++++++++++++++++++--------------
 1 files changed, 22 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 7a7695b..33357ec 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -2075,15 +2075,35 @@ static void intel_flip_fini(struct drm_device *dev)
 	drm_flip_driver_fini(&dev_priv->flip_driver);
 }
 
+static void intel_atomic_schedule_flips(struct drm_i915_private *dev_priv,
+					struct intel_crtc *intel_crtc,
+					struct list_head *flips)
+{
+	if (!intel_crtc->active) {
+		drm_flip_driver_complete_flips(&dev_priv->flip_driver, flips);
+		return;
+	}
+
+	drm_flip_driver_prepare_flips(&dev_priv->flip_driver, flips);
+
+	local_irq_disable();
+
+	intel_pipe_vblank_evade(&intel_crtc->base);
+
+	drm_flip_driver_schedule_flips(&dev_priv->flip_driver, flips);
+
+	local_irq_enable();
+}
+
 static void atomic_pipe_commit(struct drm_device *dev,
 			       struct intel_atomic_state *state,
 			       int pipe)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_file_private *file_priv = state->file->driver_priv;
+	struct intel_crtc *intel_crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe));
 	LIST_HEAD(flips);
 	int i;
-	bool pipe_enabled = to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe))->active;
 
 	for (i = 0; i < dev->mode_config.num_crtc; i++) {
 		struct intel_crtc_state *st = &state->crtc[i];
@@ -2189,20 +2209,7 @@ static void atomic_pipe_commit(struct drm_device *dev,
 	if (list_empty(&flips))
 		return;
 
-	if (!pipe_enabled) {
-		drm_flip_driver_complete_flips(&dev_priv->flip_driver, &flips);
-		return;
-	}
-
-	drm_flip_driver_prepare_flips(&dev_priv->flip_driver, &flips);
-
-	local_irq_disable();
-
-	intel_pipe_vblank_evade(intel_get_crtc_for_pipe(dev, pipe));
-
-	drm_flip_driver_schedule_flips(&dev_priv->flip_driver, &flips);
-
-	local_irq_enable();
+	intel_atomic_schedule_flips(dev_priv, intel_crtc, &flips);
 }
 
 void intel_atomic_handle_vblank(struct drm_device *dev, int pipe)
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 64/81] drm/i915: Implement a non-blocking GPU synchronization mechanism for atomic page flips
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (62 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 63/81] drm/i915: Refactor atomic flip code ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 65/81] drm/i915: Release all atomic flips when GPU hangs ville.syrjala
                   ` (18 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

After the atomic flip has been split up into individual flip requests
for each scanout engine, put each such request into a FIFO. Then for
each flip request add new request to the ring(s) in order to get an
interrupt once the GPU has finished whatever it was doing with the
new front buffer. Once the flip requests associated with the same
atomic flip and the same pipe at the head of the queue are ready,
pull them from the queue and issue the flips to the hardware.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h     |    8 ++
 drivers/gpu/drm/i915/i915_irq.c     |    2 +
 drivers/gpu/drm/i915/intel_atomic.c |  215 ++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_drv.h    |    1 +
 4 files changed, 222 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 6bb8b3f..80b4b30 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -960,6 +960,14 @@ typedef struct drm_i915_private {
 	struct i915_dri1_state dri1;
 
 	struct drm_flip_driver flip_driver;
+
+	struct {
+		struct list_head list;
+		spinlock_t lock;
+		struct work_struct work;
+		struct workqueue_struct *wq;
+		unsigned int next_flip_seq;
+	} flip;
 } drm_i915_private_t;
 
 /* Iterate over initialised rings */
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 430f201..2f0dce2 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -349,6 +349,8 @@ static void notify_ring(struct drm_device *dev,
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
+	intel_atomic_notify_ring(dev, ring);
+
 	if (ring->obj == NULL)
 		return;
 
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 33357ec..2ebceec 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -30,6 +30,8 @@
 
 #include "intel_drv.h"
 
+#define USE_WRITE_SEQNO
+
 struct intel_flip {
 	struct drm_flip base;
 	u32 vbl_count;
@@ -42,6 +44,9 @@ struct intel_flip {
 	struct drm_pending_atomic_event *event;
 	uint32_t old_fb_id;
 	struct list_head pending_head;
+	struct intel_ring_buffer *ring;
+	u32 seqno;
+	unsigned int flip_seq;
 };
 
 struct intel_plane_state {
@@ -801,6 +806,7 @@ static int pin_fbs(struct drm_device *dev,
 		   struct intel_atomic_state *s)
 {
 	int i, ret;
+	bool nonblock = s->flags & DRM_MODE_ATOMIC_NONBLOCK;
 
 	for (i = 0; i < dev->mode_config.num_crtc; i++) {
 		struct intel_crtc_state *st = &s->crtc[i];
@@ -816,7 +822,7 @@ static int pin_fbs(struct drm_device *dev,
 		obj = to_intel_framebuffer(crtc->fb)->obj;
 
 		mutex_lock(&dev->struct_mutex);
-		ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
+		ret = intel_pin_and_fence_fb_obj(dev, obj, nonblock ? obj->ring : NULL);
 		mutex_unlock(&dev->struct_mutex);
 
 		if (ret)
@@ -839,7 +845,7 @@ static int pin_fbs(struct drm_device *dev,
 		obj = to_intel_framebuffer(plane->fb)->obj;
 
 		mutex_lock(&dev->struct_mutex);
-		ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
+		ret = intel_pin_and_fence_fb_obj(dev, obj, nonblock ? obj->ring : NULL);
 		mutex_unlock(&dev->struct_mutex);
 
 		if (ret)
@@ -2040,6 +2046,8 @@ static const struct drm_flip_driver_funcs intel_flip_driver_funcs = {
 	.flush = intel_flip_driver_flush,
 };
 
+static void intel_atomic_process_flips_work(struct work_struct *work);
+
 static void intel_flip_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -2058,6 +2066,11 @@ static void intel_flip_init(struct drm_device *dev)
 	list_for_each_entry(intel_plane, &dev->mode_config.plane_list, base.head)
 		drm_flip_helper_init(&intel_plane->flip_helper,
 				     &dev_priv->flip_driver, &intel_flip_funcs);
+
+	INIT_LIST_HEAD(&dev_priv->flip.list);
+	spin_lock_init(&dev_priv->flip.lock);
+	INIT_WORK(&dev_priv->flip.work, intel_atomic_process_flips_work);
+	dev_priv->flip.wq = create_singlethread_workqueue("intel_flip");
 }
 
 static void intel_flip_fini(struct drm_device *dev)
@@ -2075,6 +2088,30 @@ static void intel_flip_fini(struct drm_device *dev)
 	drm_flip_driver_fini(&dev_priv->flip_driver);
 }
 
+static bool intel_atomic_postpone_flip(struct intel_flip *intel_flip)
+{
+	struct intel_ring_buffer *ring = intel_flip->ring;
+	int ret;
+
+	ret = i915_gem_check_olr(ring, intel_flip->seqno);
+	if (WARN_ON(ret)) {
+		intel_flip->ring = NULL;
+		return false;
+	}
+
+	if (i915_seqno_passed(ring->get_seqno(ring, true), intel_flip->seqno)) {
+		intel_flip->ring = NULL;
+		return false;
+	}
+
+	if (WARN_ON(!ring->irq_get(ring))) {
+		intel_flip->ring = NULL;
+		return false;
+	}
+
+	return true;
+}
+
 static void intel_atomic_schedule_flips(struct drm_i915_private *dev_priv,
 					struct intel_crtc *intel_crtc,
 					struct list_head *flips)
@@ -2095,15 +2132,120 @@ static void intel_atomic_schedule_flips(struct drm_i915_private *dev_priv,
 	local_irq_enable();
 }
 
+static  bool intel_atomic_flips_ready(struct drm_device *dev, unsigned int flip_seq)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_flip *intel_flip;
+
+	/* check if all flips w/ same flip_seq are ready */
+	list_for_each_entry(intel_flip, &dev_priv->flip.list, base.list) {
+		if (intel_flip->flip_seq != flip_seq)
+			break;
+
+		if (intel_flip->ring)
+			return false;
+	}
+
+	return true;
+}
+
+static void intel_atomic_process_flips_work(struct work_struct *work)
+{
+	struct drm_i915_private *dev_priv = container_of(work, struct drm_i915_private, flip.work);
+	struct drm_device *dev = dev_priv->dev;
+
+	for (;;) {
+		struct intel_flip *intel_flip, *next;
+		unsigned int flip_seq;
+		struct intel_crtc *intel_crtc;
+		LIST_HEAD(flips);
+		unsigned long flags;
+
+		if (list_empty(&dev_priv->flip.list))
+			return;
+
+		spin_lock_irqsave(&dev_priv->flip.lock, flags);
+
+		intel_flip = list_first_entry(&dev_priv->flip.list, struct intel_flip, base.list);
+		flip_seq = intel_flip->flip_seq;
+		intel_crtc = to_intel_crtc(intel_flip->crtc);
+
+		if (intel_atomic_flips_ready(dev, flip_seq)) {
+			list_for_each_entry_safe(intel_flip, next, &dev_priv->flip.list, base.list) {
+				if (intel_flip->flip_seq != flip_seq)
+					break;
+				list_move_tail(&intel_flip->base.list, &flips);
+			}
+		}
+
+		spin_unlock_irqrestore(&dev_priv->flip.lock, flags);
+
+		if (list_empty(&flips))
+			return;
+
+		mutex_lock(&dev->mode_config.mutex);
+		intel_atomic_schedule_flips(dev_priv, intel_crtc, &flips);
+		mutex_unlock(&dev->mode_config.mutex);
+	}
+}
+
+static void intel_atomic_check_flips_ready(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_flip *intel_flip;
+
+	if (list_empty(&dev_priv->flip.list))
+		return;
+
+	intel_flip = list_first_entry(&dev_priv->flip.list, struct intel_flip, base.list);
+	if (intel_atomic_flips_ready(dev, intel_flip->flip_seq))
+		queue_work(dev_priv->flip.wq, &dev_priv->flip.work);
+}
+
+void intel_atomic_notify_ring(struct drm_device *dev,
+			      struct intel_ring_buffer *ring)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_flip *intel_flip;
+	unsigned long flags;
+	u32 seqno;
+
+	if (list_empty(&dev_priv->flip.list))
+		return;
+
+	seqno = ring->get_seqno(ring, false);
+
+	spin_lock_irqsave(&dev_priv->flip.lock, flags);
+
+	list_for_each_entry(intel_flip, &dev_priv->flip.list, base.list) {
+		if (ring != intel_flip->ring)
+			continue;
+
+		if (i915_seqno_passed(seqno, intel_flip->seqno)) {
+			intel_flip->ring = NULL;
+			ring->irq_put(ring);
+		}
+	}
+
+	intel_atomic_check_flips_ready(dev);
+
+	spin_unlock_irqrestore(&dev_priv->flip.lock, flags);
+}
+
 static void atomic_pipe_commit(struct drm_device *dev,
 			       struct intel_atomic_state *state,
 			       int pipe)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_file_private *file_priv = state->file->driver_priv;
-	struct intel_crtc *intel_crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe));
 	LIST_HEAD(flips);
 	int i;
+	/* FIXME treat flips for all pipes as one set for GPU sync */
+	unsigned int flip_seq = dev_priv->flip.next_flip_seq++;
+	struct intel_flip *intel_flip, *next;
+	unsigned long flags;
+	struct intel_ring_buffer *ring;
+	unsigned int rings_mask = 0;
 
 	for (i = 0; i < dev->mode_config.num_crtc; i++) {
 		struct intel_crtc_state *st = &state->crtc[i];
@@ -2122,6 +2264,8 @@ static void atomic_pipe_commit(struct drm_device *dev,
 
 		drm_flip_init(&intel_flip->base, &intel_crtc->flip_helper);
 
+		intel_flip->flip_seq = flip_seq;
+
 		if (st->event) {
 			intel_flip->event = st->event;
 			st->event = NULL;
@@ -2134,6 +2278,19 @@ static void atomic_pipe_commit(struct drm_device *dev,
 
 		intel_flip->crtc = crtc;
 
+		if (crtc->fb) {
+			struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc->fb)->obj;
+
+			mutex_lock(&dev->struct_mutex);
+#ifdef USE_WRITE_SEQNO
+			intel_flip->seqno = obj->last_write_seqno;
+#else
+			intel_flip->seqno = obj->last_read_seqno;
+#endif
+			intel_flip->ring = obj->ring;
+			mutex_unlock(&dev->struct_mutex);
+		}
+
 		/* update primary_disabled befoer calc_plane() */
 		intel_crtc->primary_disabled = st->primary_disabled;
 
@@ -2177,6 +2334,8 @@ static void atomic_pipe_commit(struct drm_device *dev,
 
 		drm_flip_init(&intel_flip->base, &intel_plane->flip_helper);
 
+		intel_flip->flip_seq = flip_seq;
+
 		if (st->event) {
 			intel_flip->event = st->event;
 			st->event = NULL;
@@ -2190,6 +2349,19 @@ static void atomic_pipe_commit(struct drm_device *dev,
 		intel_flip->crtc = intel_get_crtc_for_pipe(dev, pipe);
 		intel_flip->plane = plane;
 
+		if (plane->fb) {
+			struct drm_i915_gem_object *obj = to_intel_framebuffer(plane->fb)->obj;
+
+			mutex_lock(&dev->struct_mutex);
+#ifdef USE_WRITE_SEQNO
+			intel_flip->seqno = obj->last_write_seqno;
+#else
+			intel_flip->seqno = obj->last_read_seqno;
+#endif
+			intel_flip->ring = obj->ring;
+			mutex_unlock(&dev->struct_mutex);
+		}
+
 		intel_plane->calc(plane, plane->fb, &st->coords);
 
 		if (st->old.fb)
@@ -2209,7 +2381,42 @@ static void atomic_pipe_commit(struct drm_device *dev,
 	if (list_empty(&flips))
 		return;
 
-	intel_atomic_schedule_flips(dev_priv, intel_crtc, &flips);
+	mutex_lock(&dev->struct_mutex);
+
+	list_for_each_entry(intel_flip, &flips, base.list) {
+		struct intel_ring_buffer *ring = intel_flip->ring;
+
+		if (!ring)
+			continue;
+
+		if (intel_atomic_postpone_flip(intel_flip))
+			rings_mask |= intel_ring_flag(ring);
+	}
+
+	spin_lock_irqsave(&dev_priv->flip.lock, flags);
+
+	list_for_each_entry_safe(intel_flip, next, &flips, base.list)
+		list_move_tail(&intel_flip->base.list, &dev_priv->flip.list);
+
+	/* if no rings are involved, we can avoid checking seqnos */
+	if (rings_mask == 0)
+		intel_atomic_check_flips_ready(dev);
+
+	spin_unlock_irqrestore(&dev_priv->flip.lock, flags);
+
+	mutex_unlock(&dev->struct_mutex);
+
+	if (rings_mask == 0)
+		return;
+
+	/*
+	 * Double check to catch cases where the irq
+	 * fired before the flip was placed onto flip.list.
+	 */
+	for_each_ring(ring, dev_priv, i) {
+		if (rings_mask & intel_ring_flag(ring))
+			intel_atomic_notify_ring(dev, ring);
+	}
 }
 
 void intel_atomic_handle_vblank(struct drm_device *dev, int pipe)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 24dc192..446fa1c 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -730,6 +730,7 @@ extern void intel_atomic_fini(struct drm_device *dev);
 extern void intel_atomic_free_events(struct drm_device *dev, struct drm_file *file);
 extern void intel_atomic_handle_vblank(struct drm_device *dev, int pipe);
 extern void intel_atomic_clear_flips(struct drm_crtc *crtc);
+extern void intel_atomic_notify_ring(struct drm_device *dev, struct intel_ring_buffer *ring);
 
 extern void intel_enable_primary(struct drm_crtc *crtc);
 extern void intel_disable_primary(struct drm_crtc *crtc);
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 65/81] drm/i915: Release all atomic flips when GPU hangs
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (63 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 64/81] drm/i915: Implement a non-blocking GPU synchronization mechanism for atomic page flips ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 66/81] drm/i915: Make a copy of the calculated plane regs ville.syrjala
                   ` (17 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

If the GPU hangs, release all pending atomic flips from the queue.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_irq.c     |    1 +
 drivers/gpu/drm/i915/intel_atomic.c |   29 +++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h    |    1 +
 3 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 2f0dce2..47d6067 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1486,6 +1486,7 @@ void i915_handle_error(struct drm_device *dev, bool wedged)
 		 */
 		for_each_ring(ring, dev_priv, i)
 			wake_up_all(&ring->irq_queue);
+		intel_atomic_wedged(dev);
 	}
 
 	queue_work(dev_priv->wq, &dev_priv->error_work);
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 2ebceec..f59be7f 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -2232,6 +2232,30 @@ void intel_atomic_notify_ring(struct drm_device *dev,
 	spin_unlock_irqrestore(&dev_priv->flip.lock, flags);
 }
 
+void intel_atomic_wedged(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_flip *intel_flip;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev_priv->flip.lock, flags);
+
+	list_for_each_entry(intel_flip, &dev_priv->flip.list, base.list) {
+		struct intel_ring_buffer *ring = intel_flip->ring;
+
+		if (ring) {
+			intel_flip->ring = NULL;
+			ring->irq_put(ring);
+		}
+	}
+
+	/* all flips are "ready" so no need to check with intel_atomic_flips_ready() */
+	if (!list_empty(&dev_priv->flip.list))
+		queue_work(dev_priv->flip.wq, &dev_priv->flip.work);
+
+	spin_unlock_irqrestore(&dev_priv->flip.lock, flags);
+}
+
 static void atomic_pipe_commit(struct drm_device *dev,
 			       struct intel_atomic_state *state,
 			       int pipe)
@@ -2409,6 +2433,11 @@ static void atomic_pipe_commit(struct drm_device *dev,
 	if (rings_mask == 0)
 		return;
 
+	if (atomic_read(&dev_priv->mm.wedged)) {
+		intel_atomic_wedged(dev);
+		return;
+	}
+
 	/*
 	 * Double check to catch cases where the irq
 	 * fired before the flip was placed onto flip.list.
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 446fa1c..33fac47 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -731,6 +731,7 @@ extern void intel_atomic_free_events(struct drm_device *dev, struct drm_file *fi
 extern void intel_atomic_handle_vblank(struct drm_device *dev, int pipe);
 extern void intel_atomic_clear_flips(struct drm_crtc *crtc);
 extern void intel_atomic_notify_ring(struct drm_device *dev, struct intel_ring_buffer *ring);
+extern void intel_atomic_wedged(struct drm_device *dev);
 
 extern void intel_enable_primary(struct drm_crtc *crtc);
 extern void intel_disable_primary(struct drm_crtc *crtc);
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 66/81] drm/i915: Make a copy of the calculated plane regs
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (64 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 65/81] drm/i915: Release all atomic flips when GPU hangs ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 67/81] drm/i915: Clear pending flips in haswell_crtc_disable() ville.syrjala
                   ` (16 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

The register values are computed when the flip ioctl is issued, and
they're used only after we've waited for the GPU to finish rendering.
The computed values are store in the intel_crtc and intel_plane structs,
so issuing another flip before the previous one has been fully completed
would clobber those stored registers. Fix the problem by making a copy
of the calculated register values inside the intel_flip structure. The
copy is then used when it's time to commit the registers to the hardware.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h      |    4 +++-
 drivers/gpu/drm/i915/intel_atomic.c  |    8 ++++++--
 drivers/gpu/drm/i915/intel_display.c |   14 ++++++++------
 drivers/gpu/drm/i915/intel_drv.h     |    2 +-
 drivers/gpu/drm/i915/intel_sprite.c  |   24 ++++++++++++------------
 5 files changed, 30 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 80b4b30..d8e8a4f 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -269,6 +269,8 @@ struct drm_i915_error_state {
 	struct intel_display_error_state *display;
 };
 
+struct intel_plane_regs;
+
 struct drm_i915_display_funcs {
 	bool (*fbc_enabled)(struct drm_device *dev);
 	void (*enable_fbc)(struct drm_crtc *crtc, unsigned long interval);
@@ -300,7 +302,7 @@ struct drm_i915_display_funcs {
 			    int x, int y);
 	int (*calc_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 			  int x, int y);
-	void (*commit_plane)(struct drm_crtc *crtc);
+	void (*commit_plane)(struct drm_crtc *crtc, const struct intel_plane_regs *regs);
 	/* clock updates for mode set */
 	/* cursor updates */
 	/* render clock increase/decrease */
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index f59be7f..e52d92a 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -47,6 +47,8 @@ struct intel_flip {
 	struct intel_ring_buffer *ring;
 	u32 seqno;
 	unsigned int flip_seq;
+	/* FIXME need cursor regs too */
+	struct intel_plane_regs regs;
 };
 
 struct intel_plane_state {
@@ -1986,11 +1988,11 @@ static bool intel_flip_flip(struct drm_flip *flip,
 		struct drm_plane *plane = intel_flip->plane;
 		struct intel_plane *intel_plane = to_intel_plane(plane);
 
-		intel_plane->commit(plane);
+		intel_plane->commit(plane, &intel_flip->regs);
 	} else {
 		struct drm_i915_private *dev_priv = dev->dev_private;
 
-		dev_priv->display.commit_plane(crtc);
+		dev_priv->display.commit_plane(crtc, &intel_flip->regs);
 	}
 
 	if (intel_flip->has_cursor)
@@ -2321,6 +2323,7 @@ static void atomic_pipe_commit(struct drm_device *dev,
 		/* should already be checked so can't fail */
 		/* FIXME refactor the failing parts? */
 		dev_priv->display.calc_plane(crtc, crtc->fb, crtc->x, crtc->y);
+		intel_flip->regs = intel_crtc->primary_regs;
 
 		if (st->cursor_dirty) {
 			intel_flip->has_cursor = true;
@@ -2387,6 +2390,7 @@ static void atomic_pipe_commit(struct drm_device *dev,
 		}
 
 		intel_plane->calc(plane, plane->fb, &st->coords);
+		intel_flip->regs = intel_plane->regs;
 
 		if (st->old.fb)
 			intel_flip->old_fb_id = st->old.fb->base.id;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index c84a839..390251d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1979,13 +1979,13 @@ unsigned long intel_gen4_compute_offset_xtiled(int *x, int *y,
 	return tile_rows * pitch * 8 + tiles * 4096;
 }
 
-static void intel_commit_plane(struct drm_crtc *crtc)
+static void intel_commit_plane(struct drm_crtc *crtc,
+			       const struct intel_plane_regs *regs)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int plane = intel_crtc->plane;
-	const struct intel_plane_regs *regs = &intel_crtc->primary_regs;
 
 	I915_WRITE(DSPCNTR(plane), regs->cntr);
 	I915_WRITE(DSPSTRIDE(plane), regs->stride);
@@ -2102,15 +2102,16 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 			     int x, int y)
 {
 	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int ret;
 
 	ret = i9xx_calc_plane(crtc, fb, x, y);
 	if (ret)
 		return ret;
 
-	intel_commit_plane(crtc);
+	intel_commit_plane(crtc, &intel_crtc->primary_regs);
 
-	POSTING_READ(DSPCNTR(to_intel_crtc(crtc)->plane));
+	POSTING_READ(DSPCNTR(intel_crtc->plane));
 
 	return 0;
 }
@@ -2206,15 +2207,16 @@ static int ironlake_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *
 				 int x, int y)
 {
 	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int ret;
 
 	ret = ironlake_calc_plane(crtc, fb, x, y);
 	if (ret)
 		return ret;
 
-	intel_commit_plane(crtc);
+	intel_commit_plane(crtc, &intel_crtc->primary_regs);
 
-	POSTING_READ(DSPCNTR(to_intel_crtc(crtc)->plane));
+	POSTING_READ(DSPCNTR(intel_crtc->plane));
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 33fac47..e39a10b 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -277,7 +277,7 @@ struct intel_plane {
 	void (*calc)(struct drm_plane *plane, struct drm_framebuffer *fb,
 		     const struct intel_plane_coords *clip);
 	void (*prepare)(struct drm_plane *plane);
-	void (*commit)(struct drm_plane *plane);
+	void (*commit)(struct drm_plane *plane, const struct intel_plane_regs *regs);
 	struct intel_plane_regs regs;
 	struct drm_flip_helper flip_helper;
 };
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index ce3b950..d960e19 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -300,13 +300,13 @@ ivb_calc_plane(struct drm_plane *plane,
 }
 
 static void
-ivb_commit_plane(struct drm_plane *plane)
+ivb_commit_plane(struct drm_plane *plane,
+		 const struct intel_plane_regs *regs)
 {
 	struct drm_device *dev = plane->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_plane *intel_plane = to_intel_plane(plane);
 	int pipe = intel_plane->pipe;
-	const struct intel_plane_regs *regs = &intel_plane->regs;
 
 	I915_WRITE(SPRKEYVAL(pipe), regs->keyval);
 	I915_WRITE(SPRKEYMAX(pipe), regs->keymaxval);
@@ -371,7 +371,7 @@ ivb_update_plane(struct drm_plane *plane,
 
 	ivb_calc_plane(plane, fb, coords);
 	ivb_prepare_plane(plane);
-	ivb_commit_plane(plane);
+	ivb_commit_plane(plane, &intel_plane->regs);
 	POSTING_READ(SPRSURF(pipe));
 }
 
@@ -387,7 +387,7 @@ ivb_disable_plane(struct drm_plane *plane)
 	regs->cntr &= ~SPRITE_ENABLE;
 	/* Can't leave the scaler enabled... */
 	regs->scale = 0;
-	ivb_commit_plane(plane);
+	ivb_commit_plane(plane, regs);
 	POSTING_READ(SPRSURF(pipe));
 
 	dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
@@ -413,7 +413,7 @@ ivb_update_colorkey(struct drm_plane *plane,
 	else if (key->flags & I915_SET_COLORKEY_SOURCE)
 		regs->cntr |= SPRITE_SOURCE_KEY;
 
-	ivb_commit_plane(plane);
+	ivb_commit_plane(plane, regs);
 	POSTING_READ(SPRKEYMSK(intel_plane->pipe));
 
 	return 0;
@@ -546,13 +546,13 @@ ilk_prepare_plane(struct drm_plane *plane)
 }
 
 static void
-ilk_commit_plane(struct drm_plane *plane)
+ilk_commit_plane(struct drm_plane *plane,
+		 const struct intel_plane_regs *regs)
 {
 	struct drm_device *dev = plane->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_plane *intel_plane = to_intel_plane(plane);
 	int pipe = intel_plane->pipe;
-	const struct intel_plane_regs *regs = &intel_plane->regs;
 
 	I915_WRITE(DVSKEYVAL(pipe), regs->keyval);
 	I915_WRITE(DVSKEYMAX(pipe), regs->keymaxval);
@@ -579,7 +579,7 @@ ilk_update_plane(struct drm_plane *plane,
 
 	ilk_calc_plane(plane, fb, coords);
 	ilk_prepare_plane(plane);
-	ilk_commit_plane(plane);
+	ilk_commit_plane(plane, &intel_plane->regs);
 	POSTING_READ(DVSSURF(pipe));
 }
 
@@ -595,7 +595,7 @@ ilk_disable_plane(struct drm_plane *plane)
 	regs->cntr &= ~DVS_ENABLE;
 	/* Disable the scaler */
 	regs->scale = 0;
-	ilk_commit_plane(plane);
+	ilk_commit_plane(plane, regs);
 	POSTING_READ(DVSSURF(pipe));
 }
 
@@ -627,7 +627,7 @@ intel_enable_primary(struct drm_crtc *crtc)
 	intel_update_fbc(dev);
 
 	regs->cntr = I915_READ(reg) | DISPLAY_PLANE_ENABLE;
-	dev_priv->display.commit_plane(crtc);
+	dev_priv->display.commit_plane(crtc, regs);
 }
 
 void
@@ -643,7 +643,7 @@ intel_disable_primary(struct drm_crtc *crtc)
 		return;
 
 	regs->cntr = I915_READ(reg) & ~DISPLAY_PLANE_ENABLE;
-	dev_priv->display.commit_plane(crtc);
+	dev_priv->display.commit_plane(crtc, regs);
 
 	intel_crtc->primary_disabled = true;
 	intel_update_fbc(dev);
@@ -668,7 +668,7 @@ ilk_update_colorkey(struct drm_plane *plane,
 	else if (key->flags & I915_SET_COLORKEY_SOURCE)
 		regs->cntr |= DVS_SOURCE_KEY;
 
-	ilk_commit_plane(plane);
+	ilk_commit_plane(plane, regs);
 	POSTING_READ(DVSKEYMSK(intel_plane->pipe));
 
 	return 0;
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 67/81] drm/i915: Clear pending flips in haswell_crtc_disable()
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (65 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 66/81] drm/i915: Make a copy of the calculated plane regs ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 68/81] drm/i915: Drop all flips waiting for the GPU when the CRTC is about to be disabled ville.syrjala
                   ` (15 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 390251d..2f518be 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3486,6 +3486,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 		encoder->disable(encoder);
 
 	intel_crtc_wait_for_pending_flips(crtc);
+	intel_atomic_clear_flips(crtc);
 	drm_vblank_off(dev, pipe);
 	intel_crtc_update_cursor(crtc, false);
 
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 68/81] drm/i915: Drop all flips waiting for the GPU when the CRTC is about to be disabled
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (66 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 67/81] drm/i915: Clear pending flips in haswell_crtc_disable() ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 69/81] drm/i915: Refactor flip preaparation ville.syrjala
                   ` (14 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_atomic.c |   36 +++++++++++++++++++++++++++++++++++
 1 files changed, 36 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index e52d92a..36446d1 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -2471,9 +2471,23 @@ void intel_atomic_handle_vblank(struct drm_device *dev, int pipe)
 void intel_atomic_clear_flips(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_plane *intel_plane;
+	struct intel_flip *intel_flip, *next;
 	int pipe = intel_crtc->pipe;
+	unsigned long flags;
+	LIST_HEAD(flips);
+
+	/*
+	 * If there are flips still waiting for the GPU, remove them
+	 * from the list, so that they won't be able to move over to
+	 * drm_flip_helpers' possession after we've called
+	 * drm_flip_helper_clear().
+	 */
+	spin_lock_irqsave(&dev_priv->flip.lock, flags);
+	list_cut_position(&flips, &dev_priv->flip.list, dev_priv->flip.list.prev);
+	spin_unlock_irqrestore(&dev_priv->flip.lock, flags);
 
 	drm_flip_helper_clear(&intel_crtc->flip_helper);
 
@@ -2481,4 +2495,26 @@ void intel_atomic_clear_flips(struct drm_crtc *crtc)
 		if (intel_plane->pipe == pipe)
 			drm_flip_helper_clear(&intel_plane->flip_helper);
 	}
+
+	/*
+	 * Drop all non-ready flips. Doing this after calling
+	 * drm_flip_helper_clear() maintaines the correct order
+	 * of completion events.
+	 */
+	list_for_each_entry_safe(intel_flip, next, &flips, base.list) {
+		struct intel_ring_buffer *ring = intel_flip->ring;
+
+		if (ring) {
+			intel_flip->ring = NULL;
+			ring->irq_put(ring);
+		}
+
+		intel_flip_complete(&intel_flip->base);
+		/*
+		 * FIXME drm_flip_helper calls the following functions
+		 * from a workqueue. Perhaps we should do the same here?
+		 */
+		intel_flip_finish(&intel_flip->base);
+		intel_flip_cleanup(&intel_flip->base);
+	}
 }
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 69/81] drm/i915: Refactor flip preaparation
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (67 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 68/81] drm/i915: Drop all flips waiting for the GPU when the CRTC is about to be disabled ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 70/81] drm/i915: Unstatic intel_modeset_commit_output_state() ville.syrjala
                   ` (13 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Most of the code for preparing the 'struct intel_flip' instances was
identical betwen the CRTC and plane codepaths. Refactor the common parts
into a single function.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_atomic.c |  122 +++++++++++++++--------------------
 1 files changed, 52 insertions(+), 70 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 36446d1..3717e89 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -2258,6 +2258,50 @@ void intel_atomic_wedged(struct drm_device *dev)
 	spin_unlock_irqrestore(&dev_priv->flip.lock, flags);
 }
 
+static void intel_atomic_flip_init(struct intel_flip *intel_flip,
+				   struct drm_device *dev,
+				   u32 flip_seq,
+				   struct drm_i915_file_private *file_priv,
+				   struct drm_pending_atomic_event *event,
+				   struct drm_framebuffer *fb,
+				   bool unpin_old_fb, struct drm_framebuffer *old_fb)
+{
+	intel_flip->flip_seq = flip_seq;
+
+	if (event) {
+		intel_flip->event = event;
+
+		/* need to keep track of it in case process exits */
+		spin_lock_irq(&dev->event_lock);
+		list_add_tail(&intel_flip->pending_head, &file_priv->pending_flips);
+		spin_unlock_irq(&dev->event_lock);
+	}
+
+	if (fb) {
+		struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj;
+
+		mutex_lock(&dev->struct_mutex);
+#ifdef USE_WRITE_SEQNO
+		intel_flip->seqno = obj->last_write_seqno;
+#else
+		intel_flip->seqno = obj->last_read_seqno;
+#endif
+		intel_flip->ring = obj->ring;
+		mutex_unlock(&dev->struct_mutex);
+	}
+
+	if (old_fb)
+		intel_flip->old_fb_id = old_fb->base.id;
+
+	if (unpin_old_fb && old_fb) {
+		intel_flip->old_bo = to_intel_framebuffer(old_fb)->obj;
+
+		mutex_lock(&dev->struct_mutex);
+		drm_gem_object_reference(&intel_flip->old_bo->base);
+		mutex_unlock(&dev->struct_mutex);
+	}
+}
+
 static void atomic_pipe_commit(struct drm_device *dev,
 			       struct intel_atomic_state *state,
 			       int pipe)
@@ -2290,33 +2334,13 @@ static void atomic_pipe_commit(struct drm_device *dev,
 
 		drm_flip_init(&intel_flip->base, &intel_crtc->flip_helper);
 
-		intel_flip->flip_seq = flip_seq;
-
-		if (st->event) {
-			intel_flip->event = st->event;
-			st->event = NULL;
-			/* need to keep track of it in case process exits */
-			spin_lock_irq(&dev->event_lock);
-			list_add_tail(&intel_flip->pending_head,
-				      &file_priv->pending_flips);
-			spin_unlock_irq(&dev->event_lock);
-		}
+		intel_atomic_flip_init(intel_flip, dev, flip_seq,
+				       file_priv, st->event, crtc->fb,
+				       st->fb_dirty, st->old.fb);
+		st->event = NULL;
 
 		intel_flip->crtc = crtc;
 
-		if (crtc->fb) {
-			struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc->fb)->obj;
-
-			mutex_lock(&dev->struct_mutex);
-#ifdef USE_WRITE_SEQNO
-			intel_flip->seqno = obj->last_write_seqno;
-#else
-			intel_flip->seqno = obj->last_read_seqno;
-#endif
-			intel_flip->ring = obj->ring;
-			mutex_unlock(&dev->struct_mutex);
-		}
-
 		/* update primary_disabled befoer calc_plane() */
 		intel_crtc->primary_disabled = st->primary_disabled;
 
@@ -2330,17 +2354,6 @@ static void atomic_pipe_commit(struct drm_device *dev,
 			intel_flip->old_cursor_bo = st->old.cursor_bo;
 		}
 
-		if (st->old.fb)
-			intel_flip->old_fb_id = st->old.fb->base.id;
-
-		if (st->fb_dirty && st->old.fb) {
-			intel_flip->old_bo = to_intel_framebuffer(st->old.fb)->obj;
-
-			mutex_lock(&dev->struct_mutex);
-			drm_gem_object_reference(&intel_flip->old_bo->base);
-			mutex_unlock(&dev->struct_mutex);
-		}
-
 		list_add_tail(&intel_flip->base.list, &flips);
 	}
 
@@ -2361,48 +2374,17 @@ static void atomic_pipe_commit(struct drm_device *dev,
 
 		drm_flip_init(&intel_flip->base, &intel_plane->flip_helper);
 
-		intel_flip->flip_seq = flip_seq;
-
-		if (st->event) {
-			intel_flip->event = st->event;
-			st->event = NULL;
-			/* need to keep track of it in case process exits */
-			spin_lock_irq(&dev->event_lock);
-			list_add_tail(&intel_flip->pending_head,
-				      &file_priv->pending_flips);
-			spin_unlock_irq(&dev->event_lock);
-		}
+		intel_atomic_flip_init(intel_flip, dev, flip_seq,
+				       file_priv, st->event, plane->fb,
+				       st->dirty, st->old.fb);
+		st->event = NULL;
 
 		intel_flip->crtc = intel_get_crtc_for_pipe(dev, pipe);
 		intel_flip->plane = plane;
 
-		if (plane->fb) {
-			struct drm_i915_gem_object *obj = to_intel_framebuffer(plane->fb)->obj;
-
-			mutex_lock(&dev->struct_mutex);
-#ifdef USE_WRITE_SEQNO
-			intel_flip->seqno = obj->last_write_seqno;
-#else
-			intel_flip->seqno = obj->last_read_seqno;
-#endif
-			intel_flip->ring = obj->ring;
-			mutex_unlock(&dev->struct_mutex);
-		}
-
 		intel_plane->calc(plane, plane->fb, &st->coords);
 		intel_flip->regs = intel_plane->regs;
 
-		if (st->old.fb)
-			intel_flip->old_fb_id = st->old.fb->base.id;
-
-		if (st->dirty && st->old.fb) {
-			intel_flip->old_bo = to_intel_framebuffer(st->old.fb)->obj;
-
-			mutex_lock(&dev->struct_mutex);
-			drm_gem_object_reference(&intel_flip->old_bo->base);
-			mutex_unlock(&dev->struct_mutex);
-		}
-
 		list_add_tail(&intel_flip->base.list, &flips);
 	}
 
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 70/81] drm/i915: Unstatic intel_modeset_commit_output_state()
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (68 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 69/81] drm/i915: Refactor flip preaparation ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 71/81] drm/i915: Eliminate swap_old_new() hack in the atomic code ville.syrjala
                   ` (12 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

The atomic code will want to call intel_modeset_commit_output_state()
too.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |    2 +-
 drivers/gpu/drm/i915/intel_drv.h     |    1 +
 2 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 2f518be..d950939 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -7449,7 +7449,7 @@ void intel_modeset_update_staged_output_state(struct drm_device *dev)
  *
  * This function copies the stage display pipe configuration to the real one.
  */
-static void intel_modeset_commit_output_state(struct drm_device *dev)
+void intel_modeset_commit_output_state(struct drm_device *dev)
 {
 	struct intel_encoder *encoder;
 	struct intel_connector *connector;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index e39a10b..d0666d8 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -740,5 +740,6 @@ extern void intel_crtc_attach_properties(struct drm_crtc *crtc);
 extern void intel_crtc_update_properties(struct drm_crtc *crtc);
 
 extern void intel_modeset_update_staged_output_state(struct drm_device *dev);
+extern void intel_modeset_commit_output_state(struct drm_device *dev);
 
 #endif /* __INTEL_DRV_H__ */
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 71/81] drm/i915: Eliminate swap_old_new() hack in the atomic code
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (69 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 70/81] drm/i915: Unstatic intel_modeset_commit_output_state() ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 72/81] drm: Drop old_crtc and old_encoder pointers ville.syrjala
                   ` (11 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Use the new_crtc and new_encoder pointes inside the intel_encoder and
intel_connector structures instead of swapping the crtc and encoder
pointers in the drm base structures around the disable calls.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_atomic.c |  115 ++++++++++++++--------------------
 1 files changed, 47 insertions(+), 68 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 3717e89..3f093d6 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -115,43 +115,57 @@ struct intel_atomic_state {
 	struct drm_encoder *saved_encoders;
 };
 
-static void update_connectors_bitmask(struct drm_crtc *crtc,
+static void update_connectors_bitmask(struct intel_crtc *intel_crtc,
 				      unsigned long *connectors_bitmask)
 {
-	struct drm_device *dev = crtc->dev;
-	struct drm_connector *connector;
+	struct drm_device *dev = intel_crtc->base.dev;
+	struct intel_connector *intel_connector;
 	unsigned int i = 0;
 
 	*connectors_bitmask = 0;
 
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		if (connector->encoder && connector->encoder->crtc == crtc)
+	list_for_each_entry(intel_connector, &dev->mode_config.connector_list, base.head) {
+		if (intel_connector->new_encoder &&
+		    intel_connector->new_encoder->new_crtc == intel_crtc)
 			__set_bit(i, connectors_bitmask);
 
 		i++;
 	}
 }
 
-static void update_encoders_bitmask(struct drm_crtc *crtc,
+static void update_encoders_bitmask(struct intel_crtc *intel_crtc,
 				    unsigned long *encoders_bitmask)
 {
-	struct drm_device *dev = crtc->dev;
-	struct drm_encoder *encoder;
+	struct drm_device *dev = intel_crtc->base.dev;
+	struct intel_encoder *intel_encoder;
 	unsigned int i = 0;
 
 	*encoders_bitmask = 0;
 
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-		if (encoder->crtc == crtc)
+	list_for_each_entry(intel_encoder, &dev->mode_config.encoder_list, base.head) {
+		if (intel_encoder->new_crtc == intel_crtc)
 			__set_bit(i, encoders_bitmask);
 
 		i++;
 	}
 }
 
+static bool intel_encoder_in_use(struct intel_encoder *intel_encoder)
+{
+	struct drm_device *dev = intel_encoder->base.dev;
+	struct intel_connector *intel_connector;
+
+	list_for_each_entry(intel_connector, &dev->mode_config.connector_list, base.head)
+		if (intel_connector->new_encoder == intel_encoder)
+			return true;
+
+	return false;
+}
+
 static int process_connectors(struct intel_crtc_state *s, const uint32_t *ids, int count_ids)
 {
 	struct drm_crtc *crtc = s->crtc;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct drm_device *dev = crtc->dev;
 	struct drm_connector *connectors[count_ids];
 	struct drm_connector *connector;
@@ -184,6 +198,9 @@ static int process_connectors(struct intel_crtc_state *s, const uint32_t *ids, i
 	}
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		struct intel_connector *intel_connector = to_intel_connector(connector);
+		struct intel_encoder *intel_encoder;
+
 		for (i = 0; i < count_ids; i++) {
 			if (connector == connectors[i])
 				break;
@@ -192,25 +209,28 @@ static int process_connectors(struct intel_crtc_state *s, const uint32_t *ids, i
 		/* this connector isn't in the set */
 		if (i == count_ids) {
 			/* remove the link to the encoder if this crtc was set to drive it */
-			if (connector->encoder && connector->encoder->crtc == crtc)
-				connector->encoder = NULL;
+			if (intel_connector->new_encoder &&
+			    intel_connector->new_encoder->new_crtc == intel_crtc)
+				intel_connector->new_encoder = NULL;
 			continue;
 		}
 
-		encoder = intel_best_encoder(connector);
+		intel_encoder = to_intel_encoder(intel_best_encoder(connector));
 
-		connector->encoder = encoder;
-		encoder->crtc = crtc;
+		intel_connector->new_encoder = intel_encoder;
+		intel_encoder->new_crtc = intel_crtc;
 	}
 
 	/* prune dangling encoder->crtc links pointing to this crtc  */
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-		if (encoder->crtc == crtc && !drm_helper_encoder_in_use(encoder))
-			encoder->crtc = NULL;
+		struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
+
+		if (intel_encoder->new_crtc == intel_crtc && !intel_encoder_in_use(intel_encoder))
+			intel_encoder->new_crtc = NULL;
 	}
 
-	update_connectors_bitmask(s->crtc, &s->connectors_bitmask);
-	update_encoders_bitmask(s->crtc, &s->encoders_bitmask);
+	update_connectors_bitmask(intel_crtc, &s->connectors_bitmask);
+	update_encoders_bitmask(intel_crtc, &s->encoders_bitmask);
 
 	return 0;
 }
@@ -232,19 +252,6 @@ static size_t intel_atomic_state_size(const struct drm_device *dev)
 		num_plane * sizeof state->saved_planes[0];
 }
 
-
-static void populate_old(struct drm_device *dev)
-{
-	struct drm_encoder *encoder;
-	struct drm_connector *connector;
-
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
-		encoder->old_crtc = encoder->crtc;
-
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
-		connector->old_encoder = connector->encoder;
-}
-
 static void *intel_atomic_begin(struct drm_device *dev, struct drm_file *file,
 				uint32_t flags, uint64_t user_data)
 {
@@ -275,8 +282,6 @@ static void *intel_atomic_begin(struct drm_device *dev, struct drm_file *file,
 	state->saved_crtcs = (struct intel_crtc *)(state->saved_encoders + num_encoder);
 	state->saved_planes = (struct drm_plane *)(state->saved_crtcs + num_crtc);
 
-	populate_old(dev);
-
 	i = 0;
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		struct intel_crtc_state *s = &state->crtc[i++];
@@ -297,8 +302,8 @@ static void *intel_atomic_begin(struct drm_device *dev, struct drm_file *file,
 		s->old.x = crtc->x;
 		s->old.y = crtc->y;
 
-		update_connectors_bitmask(crtc, &s->connectors_bitmask);
-		update_encoders_bitmask(crtc, &s->encoders_bitmask);
+		update_connectors_bitmask(intel_crtc, &s->connectors_bitmask);
+		update_encoders_bitmask(intel_crtc, &s->encoders_bitmask);
 
 		s->old.connectors_bitmask = s->connectors_bitmask;
 		s->old.encoders_bitmask = s->encoders_bitmask;
@@ -1045,39 +1050,11 @@ static void queue_remaining_events(struct drm_device *dev, struct intel_atomic_s
 	}
 }
 
-static void swap_old_new(struct drm_device *dev,
-			 struct intel_atomic_state *s)
-{
-	struct drm_encoder *encoder;
-	struct drm_connector *connector;
-	int i;
-
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
-		swap(encoder->crtc, encoder->old_crtc);
-
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
-		swap(connector->encoder, connector->old_encoder);
-
-	for (i = 0; i < dev->mode_config.num_crtc; i++) {
-		struct intel_crtc_state *st = &s->crtc[i];
-		struct drm_crtc *crtc = st->crtc;
-
-		swap(crtc->enabled, st->old.enabled);
-	}
-}
-
 static int apply_config(struct drm_device *dev,
 			struct intel_atomic_state *s)
 {
 	int i, ret;
 
-	/*
-	 * FIXME
-`	 * Hackish way to make crtc_disable() see the current
-	 * state (actually just some select pieces of it).
-	 */
-	swap_old_new(dev, s);
-
 	for (i = 0; i < dev->mode_config.num_crtc; i++) {
 		struct intel_crtc_state *st = &s->crtc[i];
 
@@ -1097,8 +1074,7 @@ static int apply_config(struct drm_device *dev,
 		crtc_prepare(st, st->crtc);
 	}
 
-	/* Undo the hack above. */
-	swap_old_new(dev, s);
+	intel_modeset_commit_output_state(dev);
 
 	for (i = 0; i < dev->mode_config.num_crtc; i++) {
 		struct intel_crtc_state *st = &s->crtc[i];
@@ -1204,6 +1180,9 @@ static void restore_state(struct drm_device *dev,
 	list_for_each_entry(plane, &dev->mode_config.plane_list, head)
 		*plane = s->saved_planes[i++];
 
+	/* must restore the new_crtc and new_encoder pointers as well */
+	intel_modeset_update_staged_output_state(dev);
+
 	/* FIXME props etc. */
 
 	/* was the hardware state clobbered? */
@@ -1318,8 +1297,9 @@ static int check_crtc(struct intel_crtc_state *s)
 
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 		const struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
+		struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
 
-		if (encoder->crtc != crtc)
+		if (intel_encoder->new_crtc != intel_crtc)
 			continue;
 
 		if (!encoder_funcs->mode_fixup(encoder, &crtc->mode, &crtc->hwmode))
@@ -1693,7 +1673,6 @@ static int intel_atomic_commit(struct drm_device *dev, void *state)
 
 	update_props(dev, s);
 
-	intel_modeset_update_staged_output_state(dev);
 
 	return 0;
 }
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 72/81] drm: Drop old_crtc and old_encoder pointers
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (70 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 71/81] drm/i915: Eliminate swap_old_new() hack in the atomic code ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 73/81] drm/i915: Use new_crtc when checking if CRTC is in use ville.syrjala
                   ` (10 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

These are not needed anymore.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 include/drm/drm_crtc.h |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index c8cea87..da9abb6 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -509,7 +509,6 @@ struct drm_encoder {
 	struct drm_crtc *crtc;
 	const struct drm_encoder_funcs *funcs;
 	void *helper_private;
-	struct drm_crtc *old_crtc;
 };
 
 enum drm_connector_force {
@@ -615,7 +614,6 @@ struct drm_connector {
 	int audio_latency[2];
 	int null_edid_counter; /* needed to workaround some HW bugs where we get all 0s */
 	unsigned bad_edid_counter;
-	struct drm_encoder *old_encoder;
 };
 
 /**
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 73/81] drm/i915: Use new_crtc when checking if CRTC is in use
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (71 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 72/81] drm: Drop old_crtc and old_encoder pointers ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 74/81] drm/i915: Add some TODO items to the atomic code ville.syrjala
                   ` (9 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

The atomic check() hook is interested in the staged new configuration,
so it must use the intel_encoder::new_crtc pointer when checking if
a CRTC is in use or not.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_atomic.c |   16 ++++++++++++++--
 1 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 3f093d6..ec79354 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -150,6 +150,18 @@ static void update_encoders_bitmask(struct intel_crtc *intel_crtc,
 	}
 }
 
+static bool intel_crtc_in_use(struct intel_crtc *intel_crtc)
+{
+	struct drm_device *dev = intel_crtc->base.dev;
+	struct intel_encoder *intel_encoder;
+
+	list_for_each_entry(intel_encoder, &dev->mode_config.encoder_list, base.head)
+		if (intel_encoder->new_crtc == intel_crtc)
+			return true;
+
+	return false;
+}
+
 static bool intel_encoder_in_use(struct intel_encoder *intel_encoder)
 {
 	struct drm_device *dev = intel_encoder->base.dev;
@@ -1246,12 +1258,12 @@ static int check_crtc(struct intel_crtc_state *s)
 	if (crtc->enabled) {
 		if (!fb)
 			return -EINVAL;
-		if (!drm_helper_crtc_in_use(crtc))
+		if (!intel_crtc_in_use(intel_crtc))
 			return -EINVAL;
 	} else {
 		if (fb)
 			return -EINVAL;
-		if (drm_helper_crtc_in_use(crtc))
+		if (intel_crtc_in_use(intel_crtc))
 			return -EINVAL;
 	}
 
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 74/81] drm/i915: Add some TODO items to the atomic code
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (72 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 73/81] drm/i915: Use new_crtc when checking if CRTC is in use ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 75/81] drm/i915: Drop some stale FIXMEs from " ville.syrjala
                   ` (8 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Add a comment that outlines some of the missign/incomplete parts of the
atomic code.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_atomic.c |   15 +++++++++++++++
 1 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index ec79354..415cd72 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -24,6 +24,21 @@
  * Ville Syrjälä <ville.syrjala@linux.intel.com>
  */
 
+/*
+ * TODO:
+ * - check crtc.enabled old vs. new state handling
+ * - generate a correct timestamp for override flips
+ * - send flip events at correct time when previous flip is pending,
+ *   and nothing changed in the later flip
+ * - flip_seq should be the same for all flips issued at the same time
+ * - make GPU reset handling robust
+ * - old style frame counter still has possible issues
+ * - move primary plane scanout handling into a drm_plane
+ * - cursor register handling needs work
+ * - should drm_plane be used for cursors too?
+ * - more refactoring and cleanups
+ */
+
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_flip.h>
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 75/81] drm/i915: Drop some stale FIXMEs from the atomic code
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (73 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 74/81] drm/i915: Add some TODO items to the atomic code ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 76/81] drm/i915: Add pin count trace point ville.syrjala
                   ` (7 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_atomic.c |    4 ----
 1 files changed, 0 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 415cd72..efdaff3 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -717,7 +717,6 @@ static void crtc_commit(struct drm_crtc *crtc)
 	dev_priv->display.crtc_enable(&intel_crtc->base);
 
 	/* FIXME need to check where this stuff is used really */
-	/* FIXME need to update DPMS state somewhere */
 	list_for_each_entry(intel_encoder, &dev->mode_config.encoder_list, base.head) {
 		if (intel_encoder->base.crtc == crtc)
 			intel_encoder->connectors_active = true;
@@ -1210,8 +1209,6 @@ static void restore_state(struct drm_device *dev,
 	/* must restore the new_crtc and new_encoder pointers as well */
 	intel_modeset_update_staged_output_state(dev);
 
-	/* FIXME props etc. */
-
 	/* was the hardware state clobbered? */
 	if (s->restore_hw)
 		apply_config(dev, s);
@@ -1523,7 +1520,6 @@ static void update_crtc(struct drm_device *dev,
 		struct intel_crtc_state *st = &s->crtc[i];
 		struct drm_crtc *crtc = st->crtc;
 
-		/* FIXME is this OK? */
 		if (st->fb_dirty && !st->mode_dirty) {
 			mutex_lock(&dev->struct_mutex);
 			intel_update_fbc(dev);
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 76/81] drm/i915: Add pin count trace point
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (74 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 75/81] drm/i915: Drop some stale FIXMEs from " ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 77/81] drm/i915: Add trace points for flip queue length ville.syrjala
                   ` (6 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

A new trace point for tracking changes to gem object pin count.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_gem.c   |    6 ++++++
 drivers/gpu/drm/i915/i915_trace.h |   19 +++++++++++++++++++
 2 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index f2f63ba..d4b76d9 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -3482,6 +3482,8 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj,
 	if (!obj->has_global_gtt_mapping && map_and_fenceable)
 		i915_gem_gtt_bind_object(obj, obj->cache_level);
 
+	trace_i915_gem_object_pin_count(obj, obj->pin_count, obj->pin_count + 1);
+
 	obj->pin_count++;
 	obj->pin_mappable |= map_and_fenceable;
 
@@ -3491,6 +3493,8 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj,
 void
 i915_gem_object_unpin(struct drm_i915_gem_object *obj)
 {
+	trace_i915_gem_object_pin_count(obj, obj->pin_count, obj->pin_count - 1);
+
 	BUG_ON(obj->pin_count == 0);
 	BUG_ON(obj->gtt_space == NULL);
 
@@ -3769,6 +3773,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
 	if (obj->phys_obj)
 		i915_gem_detach_phys_object(dev, obj);
 
+	trace_i915_gem_object_pin_count(obj, obj->pin_count, 0);
+
 	obj->pin_count = 0;
 	if (WARN_ON(i915_gem_object_unbind(obj) == -ERESTARTSYS)) {
 		bool was_interruptible;
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index 3db4a68..44f8d40 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -16,6 +16,25 @@
 
 /* object tracking */
 
+TRACE_EVENT(i915_gem_object_pin_count,
+	    TP_PROTO(struct drm_i915_gem_object *obj, u32 pin_count_pre, u32 pin_count_post),
+	    TP_ARGS(obj, pin_count_pre, pin_count_post),
+
+	    TP_STRUCT__entry(
+			     __field(struct drm_i915_gem_object *, obj)
+			     __field(u32, pin_count_pre)
+			     __field(u32, pin_count_post)
+			     ),
+
+	    TP_fast_assign(
+			   __entry->obj = obj;
+			   __entry->pin_count_pre = pin_count_pre;
+			   __entry->pin_count_post = pin_count_post;
+			   ),
+
+	    TP_printk("obj=%p, pin_count=%u->%u", __entry->obj, __entry->pin_count_pre, __entry->pin_count_post)
+);
+
 TRACE_EVENT(i915_gem_object_create,
 	    TP_PROTO(struct drm_i915_gem_object *obj),
 	    TP_ARGS(obj),
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 77/81] drm/i915: Add trace points for flip queue length
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (75 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 76/81] drm/i915: Add pin count trace point ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 78/81] HACK: drm/i915: Make non-blocking GPU synchronization optional ville.syrjala
                   ` (5 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h     |    1 +
 drivers/gpu/drm/i915/i915_trace.h   |   15 +++++++++++++++
 drivers/gpu/drm/i915/intel_atomic.c |    9 ++++++++-
 3 files changed, 24 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index d8e8a4f..53998f41 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -969,6 +969,7 @@ typedef struct drm_i915_private {
 		struct work_struct work;
 		struct workqueue_struct *wq;
 		unsigned int next_flip_seq;
+		unsigned int queue_len;
 	} flip;
 } drm_i915_private_t;
 
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index 44f8d40..f71e1b3 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -16,6 +16,21 @@
 
 /* object tracking */
 
+TRACE_EVENT(i915_flip_queue_len,
+	    TP_PROTO(unsigned int queue_len),
+	    TP_ARGS(queue_len),
+
+	    TP_STRUCT__entry(
+			     __field(u32, queue_len)
+			     ),
+
+	    TP_fast_assign(
+			   __entry->queue_len = queue_len;
+			   ),
+
+	    TP_printk("queue_len=%u", __entry->queue_len)
+);
+
 TRACE_EVENT(i915_gem_object_pin_count,
 	    TP_PROTO(struct drm_i915_gem_object *obj, u32 pin_count_pre, u32 pin_count_post),
 	    TP_ARGS(obj, pin_count_pre, pin_count_post),
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index efdaff3..ef5e352 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -2179,9 +2179,12 @@ static void intel_atomic_process_flips_work(struct work_struct *work)
 				if (intel_flip->flip_seq != flip_seq)
 					break;
 				list_move_tail(&intel_flip->base.list, &flips);
+				dev_priv->flip.queue_len--;
 			}
 		}
 
+		trace_i915_flip_queue_len(dev_priv->flip.queue_len);
+
 		spin_unlock_irqrestore(&dev_priv->flip.lock, flags);
 
 		if (list_empty(&flips))
@@ -2407,8 +2410,12 @@ static void atomic_pipe_commit(struct drm_device *dev,
 
 	spin_lock_irqsave(&dev_priv->flip.lock, flags);
 
-	list_for_each_entry_safe(intel_flip, next, &flips, base.list)
+	list_for_each_entry_safe(intel_flip, next, &flips, base.list) {
 		list_move_tail(&intel_flip->base.list, &dev_priv->flip.list);
+		dev_priv->flip.queue_len++;
+	}
+
+	trace_i915_flip_queue_len(dev_priv->flip.queue_len);
 
 	/* if no rings are involved, we can avoid checking seqnos */
 	if (rings_mask == 0)
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 78/81] HACK: drm/i915: Make non-blocking GPU synchronization optional
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (76 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 77/81] drm/i915: Add trace points for flip queue length ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 79/81] drm/i915: Add some timing debugs to atomic flips ville.syrjala
                   ` (4 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Add a module parameter that allows one to easily change between blocking
and non-blocking GPU synchronization with atomic page flips.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_stub.c          |    5 ++
 drivers/gpu/drm/i915/i915_trace.h   |   49 ++++++++++++++
 drivers/gpu/drm/i915/intel_atomic.c |  119 ++++++++++++++++++++++++++++++++++-
 3 files changed, 172 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index 200e104..b73fde8 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -52,6 +52,9 @@ EXPORT_SYMBOL(drm_timestamp_precision);
  */
 unsigned int drm_timestamp_monotonic = 1;
 
+unsigned int drm_async_gpu = 1;	/* 1 to enable async gpu wait */
+EXPORT_SYMBOL(drm_async_gpu);
+
 MODULE_AUTHOR(CORE_AUTHOR);
 MODULE_DESCRIPTION(CORE_DESC);
 MODULE_LICENSE("GPL and additional rights");
@@ -59,11 +62,13 @@ MODULE_PARM_DESC(debug, "Enable debug output");
 MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs]");
 MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]");
 MODULE_PARM_DESC(timestamp_monotonic, "Use monotonic timestamps");
+MODULE_PARM_DESC(async_gpu, "Async GPU wait");
 
 module_param_named(debug, drm_debug, int, 0600);
 module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600);
 module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600);
 module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600);
+module_param_named(async_gpu, drm_async_gpu, int, 0600);
 
 struct idr drm_minors_idr;
 
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index f71e1b3..754a204 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -16,6 +16,55 @@
 
 /* object tracking */
 
+TRACE_EVENT(i915_atomic_flip,
+	    TP_PROTO(bool sprite, int pipe, int action, u32 commit_surf, u32 commit_surflive, u32 surf, u32 surflive, u32 iir, u32 commit_dsl, u32 dsl, u32 flip_vbl_count, u32 vbl_count),
+	    TP_ARGS(sprite, pipe, action, commit_surf, commit_surflive, surf, surflive, iir, commit_dsl, dsl, flip_vbl_count, vbl_count),
+
+	    TP_STRUCT__entry(
+			     __field(bool, sprite)
+			     __field(int, pipe)
+			     __field(int, action)
+			     __field(u32, commit_surf)
+			     __field(u32, commit_surflive)
+			     __field(u32, surf)
+			     __field(u32, surflive)
+			     __field(u32, iir)
+			     __field(u32, commit_dsl)
+			     __field(u32, dsl)
+			     __field(u32, flip_vbl_count)
+			     __field(u32, vbl_count)
+			     ),
+
+	    TP_fast_assign(
+			   __entry->sprite = sprite;
+			   __entry->pipe = pipe;
+			   __entry->action = action;
+			   __entry->commit_surf = commit_surf;
+			   __entry->commit_surflive = commit_surflive;
+			   __entry->surf = surf;
+			   __entry->surflive = surflive;
+			   __entry->iir = iir;
+			   __entry->commit_dsl = commit_dsl;
+			   __entry->dsl = dsl;
+			   __entry->flip_vbl_count = flip_vbl_count;
+			   __entry->vbl_count = vbl_count;
+			   ),
+
+	    TP_printk(
+		      "%s/%d %s commit_surf=%x commit_surflive=%x surf=%x surflive=%x iir=%x commit_dsl=%u dsl=%u flip_vbl_count=%u vbl_count=%u",
+		      __entry->sprite ? "SPR" : "DSP", __entry->pipe,
+		      __entry->action == 0 ? "new" :
+		      __entry->action == 1 ? "flipped" :
+		      __entry->action == 2 ? "not flipped" :
+		      __entry->action == 3 ? "missed flipped" : "?",
+		      __entry->commit_surf, __entry->commit_surflive,
+		      __entry->surf, __entry->surflive,
+		      __entry->iir,
+		      __entry->commit_dsl, __entry->dsl,
+		      __entry->flip_vbl_count, __entry->vbl_count
+		      )
+);
+
 TRACE_EVENT(i915_flip_queue_len,
 	    TP_PROTO(unsigned int queue_len),
 	    TP_ARGS(queue_len),
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index ef5e352..c964b64a 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -47,6 +47,8 @@
 
 #define USE_WRITE_SEQNO
 
+//#define SURFLIVE_DEBUG
+
 struct intel_flip {
 	struct drm_flip base;
 	u32 vbl_count;
@@ -64,6 +66,11 @@ struct intel_flip {
 	unsigned int flip_seq;
 	/* FIXME need cursor regs too */
 	struct intel_plane_regs regs;
+#ifdef SURFLIVE_DEBUG
+	u32 commit_dsl;
+	u32 commit_surf;
+	u32 commit_surflive;
+#endif
 };
 
 struct intel_plane_state {
@@ -835,11 +842,13 @@ static void unpin_fbs(struct drm_device *dev,
 	}
 }
 
+extern unsigned int drm_async_gpu;
+
 static int pin_fbs(struct drm_device *dev,
 		   struct intel_atomic_state *s)
 {
 	int i, ret;
-	bool nonblock = s->flags & DRM_MODE_ATOMIC_NONBLOCK;
+	bool nonblock = drm_async_gpu && (s->flags & DRM_MODE_ATOMIC_NONBLOCK);
 
 	for (i = 0; i < dev->mode_config.num_crtc; i++) {
 		struct intel_crtc_state *st = &s->crtc[i];
@@ -1971,6 +1980,48 @@ static void intel_flip_prepare(struct drm_flip *flip)
 	}
 }
 
+#ifdef SURFLIVE_DEBUG
+enum flip_action {
+	_NEW,
+	_FLIPPED,
+	_NOT_FLIPPED,
+	_MISSED_FLIPPED,
+};
+
+static void trace_flip(struct intel_flip *intel_flip, enum flip_action action)
+{
+	struct drm_crtc *crtc = intel_flip->crtc;
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int pipe = to_intel_crtc(crtc)->pipe;
+	u32 surf;
+	u32 surflive;
+	u32 dsl;
+	u32 iir;
+	u32 vbl_count;
+
+	if (intel_flip->plane) {
+		surf = I915_READ(SPRSURF(pipe));
+		surflive = I915_READ(SPRSURFLIVE(pipe));
+	} else {
+		surf = I915_READ(DSPSURF(pipe));
+		surflive = I915_READ(DSPSURFLIVE(pipe));
+	}
+	dsl = I915_READ(PIPEDSL(pipe));
+	iir = I915_READ(DEIIR);
+	vbl_count = get_vbl_count(crtc);
+
+	trace_i915_atomic_flip(intel_flip->plane != NULL, pipe, action,
+			       intel_flip->commit_surf, intel_flip->commit_surflive,
+			       surf, surflive, iir, intel_flip->commit_dsl, dsl,
+			       intel_flip->vbl_count, vbl_count);
+}
+#endif
+
+#ifdef SURFLIVE_DEBUG
+static unsigned int missed_flips;
+#endif
+
 static bool intel_flip_flip(struct drm_flip *flip,
 			    struct drm_flip *pending_flip)
 {
@@ -1980,6 +2031,9 @@ static bool intel_flip_flip(struct drm_flip *flip,
 	struct drm_device *dev = crtc->dev;
 	int pipe = intel_crtc->pipe;
 	u32 vbl_count;
+#ifdef SURFLIVE_DEBUG
+	struct drm_i915_private *dev_priv = dev->dev_private;
+#endif
 
 	intel_flip->vblank_ref = drm_vblank_get(dev, pipe) == 0;
 
@@ -1991,10 +2045,26 @@ static bool intel_flip_flip(struct drm_flip *flip,
 		struct intel_plane *intel_plane = to_intel_plane(plane);
 
 		intel_plane->commit(plane, &intel_flip->regs);
+
+#ifdef SURFLIVE_DEBUG
+		intel_flip->commit_dsl = I915_READ(PIPEDSL(pipe));
+		intel_flip->commit_surf = I915_READ(SPRSURF(pipe));
+		intel_flip->commit_surflive = I915_READ(SPRSURFLIVE(pipe));
+		if (intel_flip->commit_surf != intel_flip->regs.surf)
+			pr_err("SPRITE SURF MISMATCH\n");
+#endif
 	} else {
 		struct drm_i915_private *dev_priv = dev->dev_private;
 
 		dev_priv->display.commit_plane(crtc, &intel_flip->regs);
+
+#ifdef SURFLIVE_DEBUG
+		intel_flip->commit_dsl = I915_READ(PIPEDSL(pipe));
+		intel_flip->commit_surf = I915_READ(DSPSURF(pipe));
+		intel_flip->commit_surflive = I915_READ(DSPSURFLIVE(pipe));
+		if (intel_flip->commit_surf != intel_flip->regs.surf)
+			pr_err("PRIMARY PLANE SURF MISMATCH\n");
+#endif
 	}
 
 	if (intel_flip->has_cursor)
@@ -2011,16 +2081,38 @@ static bool intel_flip_flip(struct drm_flip *flip,
 	else
 		intel_flip->vbl_count = (vbl_count + 1) & 0xffffff;
 
+#ifdef SURFLIVE_DEBUG
+	trace_flip(intel_flip, _NEW);
+#endif
+
 	if (pending_flip) {
 		struct intel_flip *old_intel_flip =
 			container_of(pending_flip, struct intel_flip, base);
 		bool flipped = intel_vbl_check(pending_flip, vbl_count);
 
 		if (!flipped) {
+#ifdef SURFLIVE_DEBUG
+			u32 surflive = I915_READ(old_intel_flip->plane ? SPRSURFLIVE(pipe) : DSPSURFLIVE(pipe));
+			if (old_intel_flip->commit_surflive != surflive)
+				trace_flip(old_intel_flip, _NOT_FLIPPED);
+#endif
 			swap(intel_flip->old_fb_id, old_intel_flip->old_fb_id);
 			swap(intel_flip->old_bo, old_intel_flip->old_bo);
 			swap(intel_flip->old_cursor_bo, old_intel_flip->old_cursor_bo);
 		}
+#ifdef SURFLIVE_DEBUG
+		else {
+			u32 surflive = I915_READ(old_intel_flip->plane ? SPRSURFLIVE(pipe) : DSPSURFLIVE(pipe));
+			if (old_intel_flip->commit_surf != surflive) {
+				trace_flip(old_intel_flip, _FLIPPED);
+				missed_flips++;
+				return false;
+			}
+			if (missed_flips)
+				trace_flip(old_intel_flip, _MISSED_FLIPPED);
+			missed_flips = 0;
+		}
+#endif
 
 		return flipped;
 	}
@@ -2034,7 +2126,26 @@ static bool intel_flip_vblank(struct drm_flip *pending_flip)
 		container_of(pending_flip, struct intel_flip, base);
 	u32 vbl_count = get_vbl_count(old_intel_flip->crtc);
 
+#ifdef SURFLIVE_DEBUG
+	struct drm_i915_private *dev_priv = old_intel_flip->crtc->dev->dev_private;
+	int pipe = to_intel_crtc(old_intel_flip->crtc)->pipe;
+	bool flipped;
+	flipped = intel_vbl_check(pending_flip, vbl_count);
+	if (flipped) {
+		u32 surflive = I915_READ(old_intel_flip->plane ? SPRSURFLIVE(pipe) : DSPSURFLIVE(pipe));
+		if (old_intel_flip->commit_surf != surflive) {
+			trace_flip(old_intel_flip, _FLIPPED);
+			missed_flips++;
+			return false;
+		}
+		if (missed_flips)
+			trace_flip(old_intel_flip, _MISSED_FLIPPED);
+		missed_flips = 0;
+	}
+	return flipped;
+#else
 	return intel_vbl_check(pending_flip, vbl_count);
+#endif
 }
 
 static const struct drm_flip_helper_funcs intel_flip_funcs = {
@@ -2396,6 +2507,12 @@ static void atomic_pipe_commit(struct drm_device *dev,
 	if (list_empty(&flips))
 		return;
 
+	if (!drm_async_gpu) {
+		struct intel_crtc *intel_crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe));
+		intel_atomic_schedule_flips(dev_priv, intel_crtc, &flips);
+		return;
+	}
+
 	mutex_lock(&dev->struct_mutex);
 
 	list_for_each_entry(intel_flip, &flips, base.list) {
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 79/81] drm/i915: Add some timing debugs to atomic flips
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (77 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 78/81] HACK: drm/i915: Make non-blocking GPU synchronization optional ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 80/81] drm/i915: Add post flush DSL readout for surflive debug ville.syrjala
                   ` (3 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

---
 drivers/gpu/drm/i915/intel_atomic.c |   15 +++++++++++++++
 1 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index c964b64a..43767c2 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -48,6 +48,7 @@
 #define USE_WRITE_SEQNO
 
 //#define SURFLIVE_DEBUG
+//#define FLIP_TIME_DEBUG
 
 struct intel_flip {
 	struct drm_flip base;
@@ -1842,6 +1843,10 @@ static void intel_flip_cleanup(struct drm_flip *flip)
 	kfree(intel_flip);
 }
 
+#ifdef FLIP_TIME_DEBUG
+static ktime_t tstart, tend, tdiff;
+#endif
+
 static void intel_flip_driver_flush(struct drm_flip_driver *driver)
 {
 	struct drm_i915_private *dev_priv =
@@ -1849,6 +1854,13 @@ static void intel_flip_driver_flush(struct drm_flip_driver *driver)
 
 	/* Flush posted writes */
 	I915_READ(PIPEDSL(PIPE_A));
+
+#ifdef FLIP_TIME_DEBUG
+	tend = ktime_get();
+	tdiff = ktime_sub(tend, tstart);
+	if (ktime_to_ns(tdiff) >= 10000ULL)
+		DRM_DEBUG_KMS("**** flip took %llu nsec ****\n", ktime_to_ns(tdiff));
+#endif
 }
 
 static bool intel_have_new_frmcount(struct drm_device *dev)
@@ -2242,6 +2254,9 @@ static void intel_atomic_schedule_flips(struct drm_i915_private *dev_priv,
 
 	intel_pipe_vblank_evade(&intel_crtc->base);
 
+#ifdef FLIP_TIME_DEBUG
+	tstart = ktime_get();
+#endif
 	drm_flip_driver_schedule_flips(&dev_priv->flip_driver, flips);
 
 	local_irq_enable();
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 80/81] drm/i915: Add post flush DSL readout for surflive debug
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (78 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 79/81] drm/i915: Add some timing debugs to atomic flips ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-12 16:16 ` [PATCH 81/81] drm/i915: Add trace point for atomic flip vblank evade ville.syrjala
                   ` (2 subsequent siblings)
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_trace.h   |   19 +++++++++++++++++++
 drivers/gpu/drm/i915/intel_atomic.c |    4 ++++
 2 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index 754a204..fb35edd 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -16,6 +16,25 @@
 
 /* object tracking */
 
+TRACE_EVENT(i915_atomic_flush,
+	    TP_PROTO(u32 dsl0, u32 dsl1, u32 dsl2),
+	    TP_ARGS(dsl0, dsl1, dsl2),
+
+	    TP_STRUCT__entry(
+			     __field(u32, dsl0)
+			     __field(u32, dsl1)
+			     __field(u32, dsl2)
+			     ),
+	    TP_fast_assign(
+			   __entry->dsl0 = dsl0;
+			   __entry->dsl1 = dsl1;
+			   __entry->dsl2 = dsl2;
+			   ),
+
+	    TP_printk("dsl(0)=%u dsl(1)=%u dsl(2)=%u", __entry->dsl0, __entry->dsl1, __entry->dsl2)
+);
+
+
 TRACE_EVENT(i915_atomic_flip,
 	    TP_PROTO(bool sprite, int pipe, int action, u32 commit_surf, u32 commit_surflive, u32 surf, u32 surflive, u32 iir, u32 commit_dsl, u32 dsl, u32 flip_vbl_count, u32 vbl_count),
 	    TP_ARGS(sprite, pipe, action, commit_surf, commit_surflive, surf, surflive, iir, commit_dsl, dsl, flip_vbl_count, vbl_count),
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 43767c2..0270d7e 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -1855,6 +1855,10 @@ static void intel_flip_driver_flush(struct drm_flip_driver *driver)
 	/* Flush posted writes */
 	I915_READ(PIPEDSL(PIPE_A));
 
+#ifdef SURFLIVE_DEBUG
+	trace_i915_atomic_flush(I915_READ(PIPEDSL(0)), I915_READ(PIPEDSL(1)), I915_READ(PIPEDSL(2)));
+#endif
+
 #ifdef FLIP_TIME_DEBUG
 	tend = ktime_get();
 	tdiff = ktime_sub(tend, tstart);
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [PATCH 81/81] drm/i915: Add trace point for atomic flip vblank evade
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (79 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 80/81] drm/i915: Add post flush DSL readout for surflive debug ville.syrjala
@ 2012-12-12 16:16 ` ville.syrjala
  2012-12-13 14:17 ` [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again Daniel Vetter
  2012-12-14 16:28 ` Ville Syrjälä
  82 siblings, 0 replies; 85+ messages in thread
From: ville.syrjala @ 2012-12-12 16:16 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_trace.h   |   18 ++++++++++++++++++
 drivers/gpu/drm/i915/intel_atomic.c |    2 ++
 2 files changed, 20 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index fb35edd..2b529f2 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -16,6 +16,24 @@
 
 /* object tracking */
 
+TRACE_EVENT(i915_atomic_evade,
+	    TP_PROTO(u32 dsl_min, u32 dsl_max, u32 dsl),
+	    TP_ARGS(dsl_min, dsl_max, dsl),
+
+	    TP_STRUCT__entry(
+			     __field(u32, dsl_min)
+			     __field(u32, dsl_max)
+			     __field(u32, dsl)
+			     ),
+	    TP_fast_assign(
+			   __entry->dsl_min = dsl_min;
+			   __entry->dsl_max = dsl_max;
+			   __entry->dsl = dsl;
+			   ),
+
+	    TP_printk("dsl_min=%u dsl_max=%u dsl=%u", __entry->dsl_min, __entry->dsl_max, __entry->dsl)
+);
+
 TRACE_EVENT(i915_atomic_flush,
 	    TP_PROTO(u32 dsl0, u32 dsl1, u32 dsl2),
 	    TP_ARGS(dsl0, dsl1, dsl2),
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 0270d7e..993a7dc 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -1950,6 +1950,8 @@ static void intel_pipe_vblank_evade(struct drm_crtc *crtc)
 		intel_crtc->vbl_received = false;
 
 		val = I915_READ(PIPEDSL(pipe));
+
+		trace_i915_atomic_evade(min, max, val);
 	}
 
 	if (vblank_ref)
-- 
1.7.8.6

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* Re: [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (80 preceding siblings ...)
  2012-12-12 16:16 ` [PATCH 81/81] drm/i915: Add trace point for atomic flip vblank evade ville.syrjala
@ 2012-12-13 14:17 ` Daniel Vetter
  2012-12-13 14:33   ` Ville Syrjälä
  2012-12-14 16:28 ` Ville Syrjälä
  82 siblings, 1 reply; 85+ messages in thread
From: Daniel Vetter @ 2012-12-13 14:17 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx, dri-devel

On Wed, Dec 12, 2012 at 06:15:27PM +0200, ville.syrjala@linux.intel.com wrote:
> Another month, another massive atomic patchset.
> 
> I managed to clean up warts left over from the modeset-rework rebase,
> but other than that I haven't really found the time to touch this too
> much since the last time I posted patches from this set.
> 
> Seeing as my schedule isn't getting any less busy in the forseeable
> future, it would be nice to get this monster merged sooner rather
> than never.
> 
> Ever since the code started to resemble something sane, I've tried
> to avoid squashing patches, just in case someone was actually trying
> to follow what's changed. But clearly some of the patches can
> be squashed, and that would probably allow some of the earlier ones
> to be dropped entirely.
> 
> What's clearly needed is a test tool that will stresss the mode
> setting side of the code more. My glplane test just changes the
> modes in the beginning, and then just does flips and other plane
> stuff. I'll try to get something done on that front before Christmas.
> 
> Repo is here:
> https://gitorious.org/vsyrjala/linux/commits/drm_atomic_23
> 
> The repo also contains 64bit get_user() implementation for x86-32,
> which I sent to lkml and x86 people for review. So this should now
> be testable even on a 32bit system.

Can you please upload your testcase somewhere so that I can play around
with this without too much hassle.

Thanks, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 85+ messages in thread

* Re: [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again
  2012-12-13 14:17 ` [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again Daniel Vetter
@ 2012-12-13 14:33   ` Ville Syrjälä
  0 siblings, 0 replies; 85+ messages in thread
From: Ville Syrjälä @ 2012-12-13 14:33 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx, dri-devel

On Thu, Dec 13, 2012 at 03:17:38PM +0100, Daniel Vetter wrote:
> On Wed, Dec 12, 2012 at 06:15:27PM +0200, ville.syrjala@linux.intel.com wrote:
> > Another month, another massive atomic patchset.
> > 
> > I managed to clean up warts left over from the modeset-rework rebase,
> > but other than that I haven't really found the time to touch this too
> > much since the last time I posted patches from this set.
> > 
> > Seeing as my schedule isn't getting any less busy in the forseeable
> > future, it would be nice to get this monster merged sooner rather
> > than never.
> > 
> > Ever since the code started to resemble something sane, I've tried
> > to avoid squashing patches, just in case someone was actually trying
> > to follow what's changed. But clearly some of the patches can
> > be squashed, and that would probably allow some of the earlier ones
> > to be dropped entirely.
> > 
> > What's clearly needed is a test tool that will stresss the mode
> > setting side of the code more. My glplane test just changes the
> > modes in the beginning, and then just does flips and other plane
> > stuff. I'll try to get something done on that front before Christmas.
> > 
> > Repo is here:
> > https://gitorious.org/vsyrjala/linux/commits/drm_atomic_23
> > 
> > The repo also contains 64bit get_user() implementation for x86-32,
> > which I sent to lkml and x86 people for review. So this should now
> > be testable even on a 32bit system.
> 
> Can you please upload your testcase somewhere so that I can play around
> with this without too much hassle.

It's here:
https://gitorious.org/vsyrjala/glplane

It responds to a bunch of keys in some way. Look near the end of main()
in plane.c to see which keys do what.

You'll need libdrm too:
https://gitorious.org/vsyrjala/drm/commits/drm_atomic_7

And there's an older test here, but I'm not sure it works anymore:
https://gitorious.org/vsyrjala/plane

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 85+ messages in thread

* Re: [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again
  2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
                   ` (81 preceding siblings ...)
  2012-12-13 14:17 ` [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again Daniel Vetter
@ 2012-12-14 16:28 ` Ville Syrjälä
  82 siblings, 0 replies; 85+ messages in thread
From: Ville Syrjälä @ 2012-12-14 16:28 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

On Wed, Dec 12, 2012 at 06:15:27PM +0200, ville.syrjala@linux.intel.com wrote:
...
> Ever since the code started to resemble something sane, I've tried
> to avoid squashing patches, just in case someone was actually trying
> to follow what's changed. But clearly some of the patches can
> be squashed, and that would probably allow some of the earlier ones
> to be dropped entirely.

FYI I now squashed this down to 56 patches, with 6 being pure
debug stuff, ~15 trivial unstatic/export stuff, and the rest
are of varying complexity. So we're down to ~35 patches with
substance.

Next week I can see about pulling some of the intel specific plane
stuff out and send that separately. Those would involve a few framework
type patches the core as well. By my quick calculation that could
bring the final count down by another 15 or so.

There are also some core drm patches that could be merged at any point,
but most of those wouldn't have any use until the atomic stuff starts
taking advantage or them (signed range props, resizeable blobs, etc.).

The current set is here:
https://gitorious.org/vsyrjala/linux/commits/drm_atomic_24

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 85+ messages in thread

end of thread, other threads:[~2012-12-14 16:28 UTC | newest]

Thread overview: 85+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-12-12 16:15 [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again ville.syrjala
2012-12-12 16:15 ` [PATCH 01/81] drm: Add struct drm_region and assorted utility functions ville.syrjala
2012-12-12 16:15 ` [PATCH 02/81] drm: Add drm_calc_{hscale, vscale}() " ville.syrjala
2012-12-12 16:15 ` [PATCH 03/81] drm: Keep a copy of last plane coordinates ville.syrjala
2012-12-12 16:15 ` [PATCH 04/81] drm: Add restore_fbdev_mode() hook to drm_fb_helper ville.syrjala
2012-12-12 16:15 ` [PATCH 05/81] drm: Export drm_property_create_blob() and drm_property_destroy_blob() ville.syrjala
2012-12-12 16:15 ` [PATCH 06/81] drm: Allow signed values for range properties ville.syrjala
2012-12-12 16:15 ` [PATCH 07/81] drm: Allow drm_mode_object_find() to look up an object of any type ville.syrjala
2012-12-12 16:15 ` [PATCH 08/81] drm: Export drm_encoder_crtc_ok ville.syrjala
2012-12-12 16:15 ` [PATCH 09/81] drm: Export drm_crtc_prepare_encoders() ville.syrjala
2012-12-12 16:15 ` [PATCH 10/81] drm: Refactor object property check code ville.syrjala
2012-12-12 16:15 ` [PATCH 11/81] drm: Export mode<->umode conversion functions ville.syrjala
2012-12-12 16:15 ` [PATCH 12/81] drm: Make blobs resizeable ville.syrjala
2012-12-12 16:15 ` [PATCH 13/81] drm: Add drm_flip helper ville.syrjala
2012-12-12 16:15 ` [PATCH 14/81] drm: Add mode_blob and connector_ids_blob to drm_crtc ville.syrjala
2012-12-12 16:15 ` [PATCH 15/81] drm: Add the atomic modeset ioctl ville.syrjala
2012-12-12 16:15 ` [PATCH 16/81] drm/i915: Use drm_format_plane_cpp() rather than bits_per_pixel/8 ville.syrjala
2012-12-12 16:15 ` [PATCH 17/81] drm/i915: Implement proper clipping for video sprites ville.syrjala
2012-12-12 16:15 ` [PATCH 18/81] drm/i915: Implement restore_fbdev_mode hook ville.syrjala
2012-12-12 16:15 ` [PATCH 19/81] drm/i915: Split clipping and checking from update_plane hook ville.syrjala
2012-12-12 16:15 ` [PATCH 20/81] drm/i915: Factor out i9xx_compute_clocks() like ironlake_compute_clocks() ville.syrjala
2012-12-12 16:15 ` [PATCH 21/81] drm/i915: Consitify adjusted_mode parameter ville.syrjala
2012-12-12 16:15 ` [PATCH 22/81] drm/i915: Add intel_check_clock() ville.syrjala
2012-12-12 16:15 ` [PATCH 23/81] drm/i915: store cursor_handle in struct intel_crtc ville.syrjala
2012-12-12 16:15 ` [PATCH 24/81] drm/i915: split cursor setting code into prepare/commit/unref parts ville.syrjala
2012-12-12 16:15 ` [PATCH 25/81] drm/i915: unstatic cursor functions for use with atomic modesetting ville.syrjala
2012-12-12 16:15 ` [PATCH 26/81] drm/i915: Unstatic intel_finish_fb() ville.syrjala
2012-12-12 16:15 ` [PATCH 27/81] drm/i915: Pull intel_pipe_set_base() out of the crtc_mode_set() functions ville.syrjala
2012-12-12 16:15 ` [PATCH 28/81] drm/i915: Unstatic intel_crtc_update_sarea() ville.syrjala
2012-12-12 16:15 ` [PATCH 29/81] drm/i915: Unstatic intel_crtc_update_sarea_pos() ville.syrjala
2012-12-12 16:15 ` [PATCH 30/81] drm/i915: Constify mode argument to intel_modeset_adjusted_mode() ville.syrjala
2012-12-12 16:15 ` [PATCH 31/81] drm/i915: Unstatic intel_crtc_mode_fixup() ville.syrjala
2012-12-12 16:15 ` [PATCH 32/81] drm/i915: Introduce intel_plane_regs ville.syrjala
2012-12-12 16:16 ` [PATCH 33/81] drm/i915: Split primary plane update_plane() into calc+commit phases ville.syrjala
2012-12-12 16:16 ` [PATCH 34/81] drm/i915: Split sprite " ville.syrjala
2012-12-12 16:16 ` [PATCH 35/81] drm/i915: Implement atomic modesetting ville.syrjala
2012-12-12 16:16 ` [PATCH 36/81] drm/i915: Add support for atomic modesetting completion events ville.syrjala
2012-12-12 16:16 ` [PATCH 37/81] drm/i915: Add atomic page flip support ville.syrjala
2012-12-12 16:16 ` [PATCH 38/81] drm/i915: Unstatic intel_enable_primary() and intel_disable_primary() ville.syrjala
2012-12-12 16:16 ` [PATCH 39/81] drm/i915: Respect primary_disabled in crtc_enable() ville.syrjala
2012-12-12 16:16 ` [PATCH 40/81] drm/i915: Enable/disable primary plane in calc_plane() ville.syrjala
2012-12-12 16:16 ` [PATCH 41/81] drm/i915: Add primary plane disable logic to atomic mode setting code ville.syrjala
2012-12-12 16:16 ` [PATCH 42/81] drm: Add missing EXPORT_SYMBOL()s for drm_flip ville.syrjala
2012-12-12 16:16 ` [PATCH 43/81] drm/i915: Clear flip helpers for sprites too ville.syrjala
2012-12-12 16:16 ` [PATCH 44/81] drm/i915: Refactor property handling in atomic code ville.syrjala
2012-12-12 16:16 ` [PATCH 45/81] drm/i915: Move standard properties under mode_config ville.syrjala
2012-12-12 16:16 ` [PATCH 46/81] drm_crtc_helper: Update standard crtc properties after modeset ville.syrjala
2012-12-12 16:16 ` [PATCH 47/81] drm: Update standard plane properties after update_plane/disable_plane ville.syrjala
2012-12-12 16:16 ` [PATCH 48/81] drm/i915: Update CRTC properties after modeset ville.syrjala
2012-12-12 16:16 ` [PATCH 49/81] drm: Move standard crtc/plane prop handling to drm_crtc.c ville.syrjala
2012-12-12 16:16 ` [PATCH 50/81] drm/i915: Use intel_best_encoder() directly ville.syrjala
2012-12-12 16:16 ` [PATCH 51/81] drm/i915: Unstatic intel_modeset_update_staged_output_state() ville.syrjala
2012-12-12 16:16 ` [PATCH 52/81] drm/i915: Update new_crtc and new_encoder fields after atomic modeset ville.syrjala
2012-12-12 16:16 ` [PATCH 53/81] drm/i915: Update connector DPMS state after an " ville.syrjala
2012-12-12 16:16 ` [PATCH 54/81] drm/i915: Kill the pending_flip counter manipulations ville.syrjala
2012-12-12 16:16 ` [PATCH 55/81] drm/i915: Don't mark cursor as pinned, when we don't have a cursor bo ville.syrjala
2012-12-12 16:16 ` [PATCH 56/81] drm/i915: Fix sprite_scaling_enabled for multiple sprites ville.syrjala
2012-12-12 16:16 ` [PATCH 57/81] drm/i915: Fix hiding the cursor with atomic ioctl ville.syrjala
2012-12-12 16:16 ` [PATCH 58/81] drm/i915: Fix plane src rectangle dirty check ville.syrjala
2012-12-12 16:16 ` [PATCH 59/81] drm/i915: Send atomic completion events even if nothing changed ville.syrjala
2012-12-12 16:16 ` [PATCH 60/81] drm/i915: Unpin old fbs only when appropriate ville.syrjala
2012-12-12 16:16 ` [PATCH 61/81] drm/i915: Remove stale prototypes form atomic code ville.syrjala
2012-12-12 16:16 ` [PATCH 62/81] drm/i915: Unstatic i915_gem_check_olr() ville.syrjala
2012-12-12 16:16 ` [PATCH 63/81] drm/i915: Refactor atomic flip code ville.syrjala
2012-12-12 16:16 ` [PATCH 64/81] drm/i915: Implement a non-blocking GPU synchronization mechanism for atomic page flips ville.syrjala
2012-12-12 16:16 ` [PATCH 65/81] drm/i915: Release all atomic flips when GPU hangs ville.syrjala
2012-12-12 16:16 ` [PATCH 66/81] drm/i915: Make a copy of the calculated plane regs ville.syrjala
2012-12-12 16:16 ` [PATCH 67/81] drm/i915: Clear pending flips in haswell_crtc_disable() ville.syrjala
2012-12-12 16:16 ` [PATCH 68/81] drm/i915: Drop all flips waiting for the GPU when the CRTC is about to be disabled ville.syrjala
2012-12-12 16:16 ` [PATCH 69/81] drm/i915: Refactor flip preaparation ville.syrjala
2012-12-12 16:16 ` [PATCH 70/81] drm/i915: Unstatic intel_modeset_commit_output_state() ville.syrjala
2012-12-12 16:16 ` [PATCH 71/81] drm/i915: Eliminate swap_old_new() hack in the atomic code ville.syrjala
2012-12-12 16:16 ` [PATCH 72/81] drm: Drop old_crtc and old_encoder pointers ville.syrjala
2012-12-12 16:16 ` [PATCH 73/81] drm/i915: Use new_crtc when checking if CRTC is in use ville.syrjala
2012-12-12 16:16 ` [PATCH 74/81] drm/i915: Add some TODO items to the atomic code ville.syrjala
2012-12-12 16:16 ` [PATCH 75/81] drm/i915: Drop some stale FIXMEs from " ville.syrjala
2012-12-12 16:16 ` [PATCH 76/81] drm/i915: Add pin count trace point ville.syrjala
2012-12-12 16:16 ` [PATCH 77/81] drm/i915: Add trace points for flip queue length ville.syrjala
2012-12-12 16:16 ` [PATCH 78/81] HACK: drm/i915: Make non-blocking GPU synchronization optional ville.syrjala
2012-12-12 16:16 ` [PATCH 79/81] drm/i915: Add some timing debugs to atomic flips ville.syrjala
2012-12-12 16:16 ` [PATCH 80/81] drm/i915: Add post flush DSL readout for surflive debug ville.syrjala
2012-12-12 16:16 ` [PATCH 81/81] drm/i915: Add trace point for atomic flip vblank evade ville.syrjala
2012-12-13 14:17 ` [PATCH 00/81] drm/i915: Atomic mode setting / page flip, yet again Daniel Vetter
2012-12-13 14:33   ` Ville Syrjälä
2012-12-14 16:28 ` Ville Syrjälä

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.