Merge tag 'topic/drm-misc-2016-02-08' of git://anongit.freedesktop.org/drm-intel...
[cascardo/linux.git] / drivers / gpu / drm / drm_crtc.c
index 32dd134..6e6514e 100644 (file)
@@ -649,6 +649,18 @@ EXPORT_SYMBOL(drm_framebuffer_remove);
 
 DEFINE_WW_CLASS(crtc_ww_class);
 
+static unsigned int drm_num_crtcs(struct drm_device *dev)
+{
+       unsigned int num = 0;
+       struct drm_crtc *tmp;
+
+       drm_for_each_crtc(tmp, dev) {
+               num++;
+       }
+
+       return num;
+}
+
 /**
  * drm_crtc_init_with_planes - Initialise a new CRTC object with
  *    specified primary and cursor planes.
@@ -657,6 +669,7 @@ DEFINE_WW_CLASS(crtc_ww_class);
  * @primary: Primary plane for CRTC
  * @cursor: Cursor plane for CRTC
  * @funcs: callbacks for the new CRTC
+ * @name: printf style format string for the CRTC name, or NULL for default name
  *
  * Inits a new object created as base part of a driver crtc object.
  *
@@ -666,7 +679,8 @@ DEFINE_WW_CLASS(crtc_ww_class);
 int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
                              struct drm_plane *primary,
                              struct drm_plane *cursor,
-                             const struct drm_crtc_funcs *funcs)
+                             const struct drm_crtc_funcs *funcs,
+                             const char *name, ...)
 {
        struct drm_mode_config *config = &dev->mode_config;
        int ret;
@@ -682,6 +696,21 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
        if (ret)
                return ret;
 
+       if (name) {
+               va_list ap;
+
+               va_start(ap, name);
+               crtc->name = kvasprintf(GFP_KERNEL, name, ap);
+               va_end(ap);
+       } else {
+               crtc->name = kasprintf(GFP_KERNEL, "crtc-%d",
+                                      drm_num_crtcs(dev));
+       }
+       if (!crtc->name) {
+               drm_mode_object_put(dev, &crtc->base);
+               return -ENOMEM;
+       }
+
        crtc->base.properties = &crtc->properties;
 
        list_add_tail(&crtc->head, &config->crtc_list);
@@ -728,6 +757,8 @@ void drm_crtc_cleanup(struct drm_crtc *crtc)
        if (crtc->state && crtc->funcs->atomic_destroy_state)
                crtc->funcs->atomic_destroy_state(crtc, crtc->state);
 
+       kfree(crtc->name);
+
        memset(crtc, 0, sizeof(*crtc));
 }
 EXPORT_SYMBOL(drm_crtc_cleanup);
@@ -1075,6 +1106,7 @@ EXPORT_SYMBOL(drm_connector_unplug_all);
  * @encoder: the encoder to init
  * @funcs: callbacks for this encoder
  * @encoder_type: user visible type of the encoder
+ * @name: printf style format string for the encoder name, or NULL for default name
  *
  * Initialises a preallocated encoder. Encoder should be
  * subclassed as part of driver encoder objects.
@@ -1085,7 +1117,7 @@ EXPORT_SYMBOL(drm_connector_unplug_all);
 int drm_encoder_init(struct drm_device *dev,
                      struct drm_encoder *encoder,
                      const struct drm_encoder_funcs *funcs,
-                     int encoder_type)
+                     int encoder_type, const char *name, ...)
 {
        int ret;
 
@@ -1098,9 +1130,17 @@ int drm_encoder_init(struct drm_device *dev,
        encoder->dev = dev;
        encoder->encoder_type = encoder_type;
        encoder->funcs = funcs;
-       encoder->name = kasprintf(GFP_KERNEL, "%s-%d",
-                                 drm_encoder_enum_list[encoder_type].name,
-                                 encoder->base.id);
+       if (name) {
+               va_list ap;
+
+               va_start(ap, name);
+               encoder->name = kvasprintf(GFP_KERNEL, name, ap);
+               va_end(ap);
+       } else {
+               encoder->name = kasprintf(GFP_KERNEL, "%s-%d",
+                                         drm_encoder_enum_list[encoder_type].name,
+                                         encoder->base.id);
+       }
        if (!encoder->name) {
                ret = -ENOMEM;
                goto out_put;
@@ -1141,6 +1181,18 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
 }
 EXPORT_SYMBOL(drm_encoder_cleanup);
 
+static unsigned int drm_num_planes(struct drm_device *dev)
+{
+       unsigned int num = 0;
+       struct drm_plane *tmp;
+
+       drm_for_each_plane(tmp, dev) {
+               num++;
+       }
+
+       return num;
+}
+
 /**
  * drm_universal_plane_init - Initialize a new universal plane object
  * @dev: DRM device
@@ -1150,6 +1202,7 @@ EXPORT_SYMBOL(drm_encoder_cleanup);
  * @formats: array of supported formats (%DRM_FORMAT_*)
  * @format_count: number of elements in @formats
  * @type: type of plane (overlay, primary, cursor)
+ * @name: printf style format string for the plane name, or NULL for default name
  *
  * Initializes a plane object of type @type.
  *
@@ -1160,7 +1213,8 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
                             unsigned long possible_crtcs,
                             const struct drm_plane_funcs *funcs,
                             const uint32_t *formats, unsigned int format_count,
-                            enum drm_plane_type type)
+                            enum drm_plane_type type,
+                            const char *name, ...)
 {
        struct drm_mode_config *config = &dev->mode_config;
        int ret;
@@ -1182,6 +1236,22 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
                return -ENOMEM;
        }
 
+       if (name) {
+               va_list ap;
+
+               va_start(ap, name);
+               plane->name = kvasprintf(GFP_KERNEL, name, ap);
+               va_end(ap);
+       } else {
+               plane->name = kasprintf(GFP_KERNEL, "plane-%d",
+                                       drm_num_planes(dev));
+       }
+       if (!plane->name) {
+               kfree(plane->format_types);
+               drm_mode_object_put(dev, &plane->base);
+               return -ENOMEM;
+       }
+
        memcpy(plane->format_types, formats, format_count * sizeof(uint32_t));
        plane->format_count = format_count;
        plane->possible_crtcs = possible_crtcs;
@@ -1240,7 +1310,7 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
 
        type = is_primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
        return drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
-                                       formats, format_count, type);
+                                       formats, format_count, type, NULL);
 }
 EXPORT_SYMBOL(drm_plane_init);
 
@@ -1272,6 +1342,8 @@ void drm_plane_cleanup(struct drm_plane *plane)
        if (plane->state && plane->funcs->atomic_destroy_state)
                plane->funcs->atomic_destroy_state(plane, plane->state);
 
+       kfree(plane->name);
+
        memset(plane, 0, sizeof(*plane));
 }
 EXPORT_SYMBOL(drm_plane_cleanup);
@@ -1801,7 +1873,8 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
                copied = 0;
                crtc_id = (uint32_t __user *)(unsigned long)card_res->crtc_id_ptr;
                drm_for_each_crtc(crtc, dev) {
-                       DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
+                       DRM_DEBUG_KMS("[CRTC:%d:%s]\n",
+                                     crtc->base.id, crtc->name);
                        if (put_user(crtc->base.id, crtc_id + copied)) {
                                ret = -EFAULT;
                                goto out;
@@ -2646,7 +2719,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
                ret = -ENOENT;
                goto out;
        }
-       DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
+       DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
 
        if (crtc_req->mode_valid) {
                /* If we have a mode we need a framebuffer. */
@@ -4785,9 +4858,7 @@ static int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
 
        /* Do DPMS ourselves */
        if (property == connector->dev->mode_config.dpms_property) {
-               ret = 0;
-               if (connector->funcs->dpms)
-                       ret = (*connector->funcs->dpms)(connector, (int)value);
+               ret = (*connector->funcs->dpms)(connector, (int)value);
        } else if (connector->funcs->set_property)
                ret = connector->funcs->set_property(connector, property, value);
 
@@ -4983,6 +5054,20 @@ int drm_mode_connector_attach_encoder(struct drm_connector *connector,
 {
        int i;
 
+       /*
+        * In the past, drivers have attempted to model the static association
+        * of connector to encoder in simple connector/encoder devices using a
+        * direct assignment of connector->encoder = encoder. This connection
+        * is a logical one and the responsibility of the core, so drivers are
+        * expected not to mess with this.
+        *
+        * Note that the error return should've been enough here, but a large
+        * majority of drivers ignores the return value, so add in a big WARN
+        * to get people's attention.
+        */
+       if (WARN_ON(connector->encoder))
+               return -EINVAL;
+
        for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
                if (connector->encoder_ids[i] == 0) {
                        connector->encoder_ids[i] = encoder->base.id;
@@ -5180,7 +5265,6 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
        struct drm_crtc *crtc;
        struct drm_framebuffer *fb = NULL;
        struct drm_pending_vblank_event *e = NULL;
-       unsigned long flags;
        int ret = -EINVAL;
 
        if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
@@ -5231,41 +5315,26 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
        }
 
        if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
-               ret = -ENOMEM;
-               spin_lock_irqsave(&dev->event_lock, flags);
-               if (file_priv->event_space < sizeof(e->event)) {
-                       spin_unlock_irqrestore(&dev->event_lock, flags);
-                       goto out;
-               }
-               file_priv->event_space -= sizeof(e->event);
-               spin_unlock_irqrestore(&dev->event_lock, flags);
-
-               e = kzalloc(sizeof(*e), GFP_KERNEL);
-               if (e == NULL) {
-                       spin_lock_irqsave(&dev->event_lock, flags);
-                       file_priv->event_space += sizeof(e->event);
-                       spin_unlock_irqrestore(&dev->event_lock, flags);
+               e = kzalloc(sizeof *e, GFP_KERNEL);
+               if (!e) {
+                       ret = -ENOMEM;
                        goto out;
                }
-
                e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
                e->event.base.length = sizeof(e->event);
                e->event.user_data = page_flip->user_data;
-               e->base.event = &e->event.base;
-               e->base.file_priv = file_priv;
-               e->base.destroy =
-                       (void (*) (struct drm_pending_event *)) kfree;
+               ret = drm_event_reserve_init(dev, file_priv, &e->base, &e->event.base);
+               if (ret) {
+                       kfree(e);
+                       goto out;
+               }
        }
 
        crtc->primary->old_fb = crtc->primary->fb;
        ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags);
        if (ret) {
-               if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
-                       spin_lock_irqsave(&dev->event_lock, flags);
-                       file_priv->event_space += sizeof(e->event);
-                       spin_unlock_irqrestore(&dev->event_lock, flags);
-                       kfree(e);
-               }
+               if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT)
+                       drm_event_cancel_free(dev, &e->base);
                /* Keep the old fb, don't unref it. */
                crtc->primary->old_fb = NULL;
        } else {