From patchwork Sat Oct 13 00:49:09 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 1588601 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork2.kernel.org (Postfix) with ESMTP id BD2B3DFFEE for ; Sat, 13 Oct 2012 00:56:36 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 903D09EB0F for ; Fri, 12 Oct 2012 17:56:36 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-ob0-f177.google.com (mail-ob0-f177.google.com [209.85.214.177]) by gabe.freedesktop.org (Postfix) with ESMTP id CE2BA9E964 for ; Fri, 12 Oct 2012 17:49:38 -0700 (PDT) Received: by mail-ob0-f177.google.com with SMTP id wd20so3566441obb.36 for ; Fri, 12 Oct 2012 17:49:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=8/WkUeN53giq8W3oGA95e2ZsMnbSahS228JOL4o28r8=; b=yKOx5P/UQBcF2XB+7rxzdlknBI4ziRX/0qz5OHhtb/RiEsQh2qv5ag9Or0VeeeyYJQ hjxmbiUljTc9goCgLQaArxY80Xa4j47H02liZ/5Er2B5xjtP3qzuPplz9RSI3O1VSEo+ iA2Ea2em5QvP/LsB+ZzdHHi2jvqn4uEBZaHg2Kg0igIpT3f9xi/fHIX/Qoh1yGLDFt/c hswU8PypJ4B32d1lSqrITs9sNiipblmR3lVKFEc50NEetHYlw2Ii6Qc/hLs4unLCkkWM 3V4/ndoypI4Lq28xAFtRvLN8v5qCn3/6swqcL3QBxIqJrtMp5wo9XP3sW6nQWwtt1FEI Tl2Q== Received: by 10.60.32.19 with SMTP id e19mr4981813oei.9.1350089378713; Fri, 12 Oct 2012 17:49:38 -0700 (PDT) Received: from localhost (ppp-70-129-143-201.dsl.rcsntx.swbell.net. [70.129.143.201]) by mx.google.com with ESMTPS id h2sm8244793obn.11.2012.10.12.17.49.36 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 12 Oct 2012 17:49:37 -0700 (PDT) From: Rob Clark To: dri-devel@lists.freedesktop.org Subject: [RFC 08/11] drm: convert page_flip to properties Date: Fri, 12 Oct 2012 19:49:09 -0500 Message-Id: <1350089352-18162-9-git-send-email-rob.clark@linaro.org> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1350089352-18162-1-git-send-email-rob.clark@linaro.org> References: <1350089352-18162-1-git-send-email-rob.clark@linaro.org> Cc: patches@linaro.org, daniel.vetter@ffwll.ch, Rob Clark X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Errors-To: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org From: Rob Clark Use atomic properties mechanism for CRTC page_flip. 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 | 167 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 130 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 63365f0..bcdd6be 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -441,9 +441,7 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb) 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); @@ -460,12 +458,7 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb) 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); + drm_mode_crtc_set_obj_prop(crtc, state, config->prop_fb_id, 0); } } @@ -508,6 +501,7 @@ EXPORT_SYMBOL(drm_framebuffer_remove); int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, const struct drm_crtc_funcs *funcs) { + struct drm_mode_config *config = &dev->mode_config; int ret; crtc->dev = dev; @@ -526,6 +520,13 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, list_add_tail(&crtc->head, &dev->mode_config.crtc_list); dev->mode_config.num_crtc++; + if (!dev_supports_atomic(dev)) + goto out; + + drm_object_attach_property(&crtc->base, config->prop_fb_id, 0); + drm_object_attach_property(&crtc->base, config->prop_crtc_x, 0); + drm_object_attach_property(&crtc->base, config->prop_crtc_y, 0); + out: mutex_unlock(&dev->mode_config.mutex); @@ -3960,7 +3961,53 @@ out: return ret; } -int drm_mode_page_flip_ioctl(struct drm_device *dev, +static struct drm_pending_vblank_event *create_vblank_event( + struct drm_device *dev, struct drm_file *file_priv, uint64_t user_data) +{ + struct drm_pending_vblank_event *e = NULL; + 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); + 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); + goto out; + } + + e->event.base.type = DRM_EVENT_FLIP_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; + +out: + return e; +} + +static void destroy_vblank_event(struct drm_device *dev, + struct drm_file *file_priv, struct drm_pending_vblank_event *e) +{ + unsigned long flags; + + spin_lock_irqsave(&dev->event_lock, flags); + file_priv->event_space += sizeof e->event; + spin_unlock_irqrestore(&dev->event_lock, flags); + kfree(e); +} + +/* Legacy version.. remove when all drivers converted to 'atomic' API */ +static int drm_mode_page_flip_ioctl_legacy(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_crtc_page_flip *page_flip = data; @@ -3968,7 +4015,6 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, struct drm_crtc *crtc; struct drm_framebuffer *fb; struct drm_pending_vblank_event *e = NULL; - unsigned long flags; int hdisplay, vdisplay; int ret = -EINVAL; @@ -4017,43 +4063,90 @@ 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); + e = create_vblank_event(dev, file_priv, page_flip->user_data); + if (!e) { + ret = -ENOMEM; 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); - goto out; - } + ret = crtc->funcs->page_flip(crtc, fb, e); + if (ret && e) + destroy_vblank_event(dev, file_priv, e); + +out: + mutex_unlock(&dev->mode_config.mutex); + return ret; +} + +int drm_mode_page_flip_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_crtc_page_flip *page_flip = data; + struct drm_mode_config *config = &dev->mode_config; + struct drm_mode_object *obj; + struct drm_crtc *crtc; + struct drm_pending_vblank_event *e = NULL; + void *state; + int ret = -EINVAL; + + if (!dev_supports_atomic(dev)) + return drm_mode_page_flip_ioctl_legacy(dev, data, file_priv); + + if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS || + page_flip->reserved != 0) + return -EINVAL; - 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; + mutex_lock(&dev->mode_config.mutex); + + obj = drm_mode_object_find(dev, page_flip->crtc_id, + DRM_MODE_OBJECT_CRTC); + if (!obj) { + DRM_DEBUG_KMS("Unknown CRTC ID %d\n", page_flip->crtc_id); + ret = -ENOENT; + goto out_unlock; } + crtc = obj_to_crtc(obj); - ret = crtc->funcs->page_flip(crtc, fb, e); - 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); + state = dev->driver->atomic_begin(dev, crtc); + if (IS_ERR(state)) { + ret = PTR_ERR(state); + goto out_unlock; + } + + if (crtc->fb == NULL) { + /* The framebuffer is currently unbound, presumably + * due to a hotplug event, that userspace has not + * yet discovered. + */ + ret = -EBUSY; + goto out; + } + + if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { + e = create_vblank_event(dev, file_priv, page_flip->user_data); + if (!e) { + ret = -ENOMEM; + goto out; } } + ret = drm_mode_set_obj_prop(obj, state, + config->prop_fb_id, page_flip->fb_id); + if (ret) + goto out; + + ret = dev->driver->atomic_check(dev, state); + if (ret) + goto out; + + ret = dev->driver->atomic_commit(dev, state, e); + if (ret && e) + destroy_vblank_event(dev, file_priv, e); + out: + dev->driver->atomic_end(dev, state); +out_unlock: mutex_unlock(&dev->mode_config.mutex); return ret; }