[RFC 06/11] drm: convert plane to properties

2012-10-12 Thread Rob Clark
From: Rob Clark 

Use atomic properties mechanism to set plane attributes.  This by
itself doesn't accomplish anything, but it avoids having multiple
code paths to do the same thing when nuclear-pageflip and atomic-
modeset are introduced.
---
 drivers/gpu/drm/drm_crtc.c |  278 +---
 include/drm/drm_crtc.h |   25 +++-
 2 files changed, 289 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index b1ccfea..da29732 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -38,6 +38,14 @@
 #include "drm_edid.h"
 #include "drm_fourcc.h"

+static int drm_mode_set_obj_prop(struct drm_mode_object *obj,
+   void *state, struct drm_property *property, uint64_t value);
+
+static inline bool dev_supports_atomic(struct drm_device *dev)
+{
+   return !!dev->driver->atomic_begin;
+}
+
 /* Avoid boilerplate.  I'm tired of typing. */
 #define DRM_ENUM_NAME_FN(fnname, list) \
char *fnname(int val)   \
@@ -376,8 +384,10 @@ EXPORT_SYMBOL(drm_framebuffer_cleanup);
  *
  * Scans all the CRTCs and planes in @dev's mode_config.  If they're
  * using @fb, removes it, setting it to NULL.
+ *
+ * Legacy version.. remove when all drivers converted to 'atomic' API
  */
-void drm_framebuffer_remove(struct drm_framebuffer *fb)
+static void drm_framebuffer_remove_legacy(struct drm_framebuffer *fb)
 {
struct drm_device *dev = fb->dev;
struct drm_crtc *crtc;
@@ -414,6 +424,71 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)

drm_framebuffer_unreference(fb);
 }
+
+/**
+ * drm_framebuffer_remove - remove and unreference a framebuffer object
+ * @fb: framebuffer to remove
+ *
+ * LOCKING:
+ * Caller must hold mode config lock.
+ *
+ * Scans all the CRTCs and planes in @dev's mode_config.  If they're
+ * using @fb, removes it, setting it to NULL.
+ */
+void drm_framebuffer_remove(struct drm_framebuffer *fb)
+{
+   struct drm_device *dev = fb->dev;
+   struct drm_mode_config *config = >mode_config;
+   struct drm_crtc *crtc;
+   struct drm_plane *plane;
+   struct drm_mode_set set;
+   void *state;
+   int ret;
+
+   if (!dev_supports_atomic(dev)) {
+   drm_framebuffer_remove_legacy(fb);
+   return;
+   }
+
+   state = dev->driver->atomic_begin(dev, NULL);
+   if (IS_ERR(state)) {
+   DRM_ERROR("failed to disable crtc and/or plane when fb was 
deleted\n");
+   return;
+   }
+
+   /* remove from any CRTC */
+   list_for_each_entry(crtc, >mode_config.crtc_list, head) {
+   if (crtc->fb == fb) {
+   /* should turn off the crtc */
+   memset(, 0, sizeof(struct drm_mode_set));
+   set.crtc = crtc;
+   set.fb = NULL;
+   ret = crtc->funcs->set_config();
+   if (ret)
+   DRM_ERROR("failed to reset crtc %p when fb was 
deleted\n", crtc);
+   }
+   }
+
+   list_for_each_entry(plane, >mode_config.plane_list, head) {
+   if (plane->fb == fb) {
+   /* should turn off the crtc */
+   drm_mode_plane_set_obj_prop(plane, state, 
config->prop_crtc_id, 0);
+   drm_mode_plane_set_obj_prop(plane, state, 
config->prop_fb_id, 0);
+   }
+   }
+
+   /* just disabling stuff shouldn't fail, hopefully: */
+   if(dev->driver->atomic_check(dev, state))
+   DRM_ERROR("failed to disable crtc and/or plane when fb was 
deleted\n");
+   else
+   dev->driver->atomic_commit(dev, state, NULL);
+
+   dev->driver->atomic_end(dev, state);
+
+   list_del(>filp_head);
+
+   drm_framebuffer_unreference(fb);
+}
 EXPORT_SYMBOL(drm_framebuffer_remove);

 /**
@@ -663,6 +738,7 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane 
*plane,
   const uint32_t *formats, uint32_t format_count,
   bool priv)
 {
+   struct drm_mode_config *config = >mode_config;
int ret;

mutex_lock(>mode_config.mutex);
@@ -699,6 +775,20 @@ int drm_plane_init(struct drm_device *dev, struct 
drm_plane *plane,
INIT_LIST_HEAD(>head);
}

+   if (!dev_supports_atomic(dev))
+   goto out;
+
+   drm_object_attach_property(>base, config->prop_fb_id, 0);
+   drm_object_attach_property(>base, config->prop_crtc_id, 0);
+   drm_object_attach_property(>base, config->prop_crtc_x, 0);
+   drm_object_attach_property(>base, config->prop_crtc_y, 0);
+   drm_object_attach_property(>base, config->prop_crtc_w, 0);
+   drm_object_attach_property(>base, config->prop_crtc_h, 0);
+   drm_object_attach_property(>base, config->prop_src_x, 0);
+   

[RFC 06/11] drm: convert plane to properties

2012-10-12 Thread Rob Clark
From: Rob Clark r...@ti.com

Use atomic properties mechanism to set plane attributes.  This by
itself doesn't accomplish anything, but it avoids having multiple
code paths to do the same thing when nuclear-pageflip and atomic-
modeset are introduced.
---
 drivers/gpu/drm/drm_crtc.c |  278 +---
 include/drm/drm_crtc.h |   25 +++-
 2 files changed, 289 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index b1ccfea..da29732 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -38,6 +38,14 @@
 #include drm_edid.h
 #include drm_fourcc.h
 
+static int drm_mode_set_obj_prop(struct drm_mode_object *obj,
+   void *state, struct drm_property *property, uint64_t value);
+
+static inline bool dev_supports_atomic(struct drm_device *dev)
+{
+   return !!dev-driver-atomic_begin;
+}
+
 /* Avoid boilerplate.  I'm tired of typing. */
 #define DRM_ENUM_NAME_FN(fnname, list) \
char *fnname(int val)   \
@@ -376,8 +384,10 @@ EXPORT_SYMBOL(drm_framebuffer_cleanup);
  *
  * Scans all the CRTCs and planes in @dev's mode_config.  If they're
  * using @fb, removes it, setting it to NULL.
+ *
+ * Legacy version.. remove when all drivers converted to 'atomic' API
  */
-void drm_framebuffer_remove(struct drm_framebuffer *fb)
+static void drm_framebuffer_remove_legacy(struct drm_framebuffer *fb)
 {
struct drm_device *dev = fb-dev;
struct drm_crtc *crtc;
@@ -414,6 +424,71 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
 
drm_framebuffer_unreference(fb);
 }
+
+/**
+ * drm_framebuffer_remove - remove and unreference a framebuffer object
+ * @fb: framebuffer to remove
+ *
+ * LOCKING:
+ * Caller must hold mode config lock.
+ *
+ * Scans all the CRTCs and planes in @dev's mode_config.  If they're
+ * using @fb, removes it, setting it to NULL.
+ */
+void drm_framebuffer_remove(struct drm_framebuffer *fb)
+{
+   struct drm_device *dev = fb-dev;
+   struct drm_mode_config *config = dev-mode_config;
+   struct drm_crtc *crtc;
+   struct drm_plane *plane;
+   struct drm_mode_set set;
+   void *state;
+   int ret;
+
+   if (!dev_supports_atomic(dev)) {
+   drm_framebuffer_remove_legacy(fb);
+   return;
+   }
+
+   state = dev-driver-atomic_begin(dev, NULL);
+   if (IS_ERR(state)) {
+   DRM_ERROR(failed to disable crtc and/or plane when fb was 
deleted\n);
+   return;
+   }
+
+   /* remove from any CRTC */
+   list_for_each_entry(crtc, dev-mode_config.crtc_list, head) {
+   if (crtc-fb == fb) {
+   /* should turn off the crtc */
+   memset(set, 0, sizeof(struct drm_mode_set));
+   set.crtc = crtc;
+   set.fb = NULL;
+   ret = crtc-funcs-set_config(set);
+   if (ret)
+   DRM_ERROR(failed to reset crtc %p when fb was 
deleted\n, crtc);
+   }
+   }
+
+   list_for_each_entry(plane, dev-mode_config.plane_list, head) {
+   if (plane-fb == fb) {
+   /* should turn off the crtc */
+   drm_mode_plane_set_obj_prop(plane, state, 
config-prop_crtc_id, 0);
+   drm_mode_plane_set_obj_prop(plane, state, 
config-prop_fb_id, 0);
+   }
+   }
+
+   /* just disabling stuff shouldn't fail, hopefully: */
+   if(dev-driver-atomic_check(dev, state))
+   DRM_ERROR(failed to disable crtc and/or plane when fb was 
deleted\n);
+   else
+   dev-driver-atomic_commit(dev, state, NULL);
+
+   dev-driver-atomic_end(dev, state);
+
+   list_del(fb-filp_head);
+
+   drm_framebuffer_unreference(fb);
+}
 EXPORT_SYMBOL(drm_framebuffer_remove);
 
 /**
@@ -663,6 +738,7 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane 
*plane,
   const uint32_t *formats, uint32_t format_count,
   bool priv)
 {
+   struct drm_mode_config *config = dev-mode_config;
int ret;
 
mutex_lock(dev-mode_config.mutex);
@@ -699,6 +775,20 @@ int drm_plane_init(struct drm_device *dev, struct 
drm_plane *plane,
INIT_LIST_HEAD(plane-head);
}
 
+   if (!dev_supports_atomic(dev))
+   goto out;
+
+   drm_object_attach_property(plane-base, config-prop_fb_id, 0);
+   drm_object_attach_property(plane-base, config-prop_crtc_id, 0);
+   drm_object_attach_property(plane-base, config-prop_crtc_x, 0);
+   drm_object_attach_property(plane-base, config-prop_crtc_y, 0);
+   drm_object_attach_property(plane-base, config-prop_crtc_w, 0);
+   drm_object_attach_property(plane-base, config-prop_crtc_h, 0);
+   drm_object_attach_property(plane-base, config-prop_src_x, 

[RFC 06/11] drm: convert plane to properties

2012-09-13 Thread Rob Clark
From: Rob Clark r...@ti.com

Use atomic properties mechanism to set plane attributes.  This by
itself doesn't accomplish anything, but it avoids having multiple
code paths to do the same thing when nuclear-pageflip and atomic-
modeset are introduced.
---
 drivers/gpu/drm/drm_crtc.c |  257 ++--
 include/drm/drm_crtc.h |   32 --
 2 files changed, 179 insertions(+), 110 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 245c462..81a63fe 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -38,6 +38,9 @@
 #include drm_edid.h
 #include drm_fourcc.h
 
+static int drm_mode_set_obj_prop(struct drm_mode_object *obj,
+   void *state, struct drm_property *property, uint64_t value);
+
 /* Avoid boilerplate.  I'm tired of typing. */
 #define DRM_ENUM_NAME_FN(fnname, list) \
char *fnname(int val)   \
@@ -380,11 +383,19 @@ EXPORT_SYMBOL(drm_framebuffer_cleanup);
 void drm_framebuffer_remove(struct drm_framebuffer *fb)
 {
struct drm_device *dev = fb-dev;
+   struct drm_mode_config *config = dev-mode_config;
struct drm_crtc *crtc;
struct drm_plane *plane;
struct drm_mode_set set;
+   void *state;
int ret;
 
+   state = dev-driver-atomic_begin(dev, NULL);
+   if (IS_ERR(state)) {
+   DRM_ERROR(failed to disable crtc and/or plane when fb was 
deleted\n);
+   return;
+   }
+
/* remove from any CRTC */
list_for_each_entry(crtc, dev-mode_config.crtc_list, head) {
if (crtc-fb == fb) {
@@ -401,15 +412,19 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
list_for_each_entry(plane, dev-mode_config.plane_list, head) {
if (plane-fb == fb) {
/* should turn off the crtc */
-   ret = plane-funcs-disable_plane(plane);
-   if (ret)
-   DRM_ERROR(failed to disable plane with busy 
fb\n);
-   /* disconnect the plane from the fb and crtc: */
-   plane-fb = NULL;
-   plane-crtc = NULL;
+   drm_mode_plane_set_obj_prop(plane, state, 
config-prop_crtc_id, 0);
+   drm_mode_plane_set_obj_prop(plane, state, 
config-prop_fb_id, 0);
}
}
 
+   /* just disabling stuff shouldn't fail, hopefully: */
+   if(dev-driver-atomic_check(dev, state))
+   DRM_ERROR(failed to disable crtc and/or plane when fb was 
deleted\n);
+   else
+   dev-driver-atomic_commit(dev, state, NULL);
+
+   dev-driver-atomic_end(dev, state);
+
list_del(fb-filp_head);
 
drm_framebuffer_unreference(fb);
@@ -663,6 +678,7 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane 
*plane,
   const uint32_t *formats, uint32_t format_count,
   bool priv)
 {
+   struct drm_mode_config *config = dev-mode_config;
int ret;
 
mutex_lock(dev-mode_config.mutex);
@@ -699,6 +715,17 @@ int drm_plane_init(struct drm_device *dev, struct 
drm_plane *plane,
INIT_LIST_HEAD(plane-head);
}
 
+   drm_object_attach_property(plane-base, config-prop_fb_id, 0);
+   drm_object_attach_property(plane-base, config-prop_crtc_id, 0);
+   drm_object_attach_property(plane-base, config-prop_crtc_x, 0);
+   drm_object_attach_property(plane-base, config-prop_crtc_y, 0);
+   drm_object_attach_property(plane-base, config-prop_crtc_w, 0);
+   drm_object_attach_property(plane-base, config-prop_crtc_h, 0);
+   drm_object_attach_property(plane-base, config-prop_src_x, 0);
+   drm_object_attach_property(plane-base, config-prop_src_y, 0);
+   drm_object_attach_property(plane-base, config-prop_src_w, 0);
+   drm_object_attach_property(plane-base, config-prop_src_h, 0);
+
  out:
mutex_unlock(dev-mode_config.mutex);
 
@@ -772,23 +799,91 @@ void drm_mode_destroy(struct drm_device *dev, struct 
drm_display_mode *mode)
 }
 EXPORT_SYMBOL(drm_mode_destroy);
 
-static int drm_mode_create_standard_connector_properties(struct drm_device 
*dev)
+static int drm_mode_create_standard_properties(struct drm_device *dev)
 {
-   struct drm_property *edid;
-   struct drm_property *dpms;
+   struct drm_property *prop;
 
/*
 * Standard properties (apply to all connectors)
 */
-   edid = drm_property_create(dev, DRM_MODE_PROP_BLOB |
+   prop = drm_property_create(dev, DRM_MODE_PROP_BLOB |
   DRM_MODE_PROP_IMMUTABLE,
   EDID, 0);
-   dev-mode_config.edid_property = edid;
+   if (!prop)
+   return -ENOMEM;
+   dev-mode_config.edid_property = prop;
 
-   dpms = drm_property_create_enum(dev, 0,
+   

[RFC 06/11] drm: convert plane to properties

2012-09-12 Thread Rob Clark
From: Rob Clark 

Use atomic properties mechanism to set plane attributes.  This by
itself doesn't accomplish anything, but it avoids having multiple
code paths to do the same thing when nuclear-pageflip and atomic-
modeset are introduced.
---
 drivers/gpu/drm/drm_crtc.c |  257 ++--
 include/drm/drm_crtc.h |   32 --
 2 files changed, 179 insertions(+), 110 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 245c462..81a63fe 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -38,6 +38,9 @@
 #include "drm_edid.h"
 #include "drm_fourcc.h"

+static int drm_mode_set_obj_prop(struct drm_mode_object *obj,
+   void *state, struct drm_property *property, uint64_t value);
+
 /* Avoid boilerplate.  I'm tired of typing. */
 #define DRM_ENUM_NAME_FN(fnname, list) \
char *fnname(int val)   \
@@ -380,11 +383,19 @@ EXPORT_SYMBOL(drm_framebuffer_cleanup);
 void drm_framebuffer_remove(struct drm_framebuffer *fb)
 {
struct drm_device *dev = fb->dev;
+   struct drm_mode_config *config = >mode_config;
struct drm_crtc *crtc;
struct drm_plane *plane;
struct drm_mode_set set;
+   void *state;
int ret;

+   state = dev->driver->atomic_begin(dev, NULL);
+   if (IS_ERR(state)) {
+   DRM_ERROR("failed to disable crtc and/or plane when fb was 
deleted\n");
+   return;
+   }
+
/* remove from any CRTC */
list_for_each_entry(crtc, >mode_config.crtc_list, head) {
if (crtc->fb == fb) {
@@ -401,15 +412,19 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
list_for_each_entry(plane, >mode_config.plane_list, head) {
if (plane->fb == fb) {
/* should turn off the crtc */
-   ret = plane->funcs->disable_plane(plane);
-   if (ret)
-   DRM_ERROR("failed to disable plane with busy 
fb\n");
-   /* disconnect the plane from the fb and crtc: */
-   plane->fb = NULL;
-   plane->crtc = NULL;
+   drm_mode_plane_set_obj_prop(plane, state, 
config->prop_crtc_id, 0);
+   drm_mode_plane_set_obj_prop(plane, state, 
config->prop_fb_id, 0);
}
}

+   /* just disabling stuff shouldn't fail, hopefully: */
+   if(dev->driver->atomic_check(dev, state))
+   DRM_ERROR("failed to disable crtc and/or plane when fb was 
deleted\n");
+   else
+   dev->driver->atomic_commit(dev, state, NULL);
+
+   dev->driver->atomic_end(dev, state);
+
list_del(>filp_head);

drm_framebuffer_unreference(fb);
@@ -663,6 +678,7 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane 
*plane,
   const uint32_t *formats, uint32_t format_count,
   bool priv)
 {
+   struct drm_mode_config *config = >mode_config;
int ret;

mutex_lock(>mode_config.mutex);
@@ -699,6 +715,17 @@ int drm_plane_init(struct drm_device *dev, struct 
drm_plane *plane,
INIT_LIST_HEAD(>head);
}

+   drm_object_attach_property(>base, config->prop_fb_id, 0);
+   drm_object_attach_property(>base, config->prop_crtc_id, 0);
+   drm_object_attach_property(>base, config->prop_crtc_x, 0);
+   drm_object_attach_property(>base, config->prop_crtc_y, 0);
+   drm_object_attach_property(>base, config->prop_crtc_w, 0);
+   drm_object_attach_property(>base, config->prop_crtc_h, 0);
+   drm_object_attach_property(>base, config->prop_src_x, 0);
+   drm_object_attach_property(>base, config->prop_src_y, 0);
+   drm_object_attach_property(>base, config->prop_src_w, 0);
+   drm_object_attach_property(>base, config->prop_src_h, 0);
+
  out:
mutex_unlock(>mode_config.mutex);

@@ -772,23 +799,91 @@ void drm_mode_destroy(struct drm_device *dev, struct 
drm_display_mode *mode)
 }
 EXPORT_SYMBOL(drm_mode_destroy);

-static int drm_mode_create_standard_connector_properties(struct drm_device 
*dev)
+static int drm_mode_create_standard_properties(struct drm_device *dev)
 {
-   struct drm_property *edid;
-   struct drm_property *dpms;
+   struct drm_property *prop;

/*
 * Standard properties (apply to all connectors)
 */
-   edid = drm_property_create(dev, DRM_MODE_PROP_BLOB |
+   prop = drm_property_create(dev, DRM_MODE_PROP_BLOB |
   DRM_MODE_PROP_IMMUTABLE,
   "EDID", 0);
-   dev->mode_config.edid_property = edid;
+   if (!prop)
+   return -ENOMEM;
+   dev->mode_config.edid_property = prop;

-   dpms = drm_property_create_enum(dev, 0,
+   prop = drm_property_create_enum(dev, 0,