From patchwork Thu Sep 13 03:49:55 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 11380 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id A1F9923E29 for ; Thu, 13 Sep 2012 03:52:00 +0000 (UTC) Received: from mail-iy0-f180.google.com (mail-iy0-f180.google.com [209.85.210.180]) by fiordland.canonical.com (Postfix) with ESMTP id AB3E334B8D01 for ; Thu, 13 Sep 2012 03:51:58 +0000 (UTC) Received: by mail-iy0-f180.google.com with SMTP id j25so1820584iaf.11 for ; Wed, 12 Sep 2012 20:51:58 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-forwarded-to:x-forwarded-for:delivered-to:received-spf :dkim-signature:sender:from:to:cc:subject:date:message-id:x-mailer :in-reply-to:references:x-gm-message-state; bh=QPzpnnpy21BR/a7wiKWk8QnrPXbqv2p6dkgdKA49u7E=; b=VxBK0SixebH1K7GO3sxjRG5YZ3tF27K2DuMJFUmkFzLbgkMPxcDz1zONabivX9hfrG ePqw5Aef9CuokM0oYxiRIb7c9MBX+jzMMII3rdSY6tq1aJ3qOY5L1rNYcGab4VG9K/l0 F9ZvYMl2YUNlE89DZZhmDpDj6oyWOpZOK0mWdnBqPuVV3wSDv0d2dO9FPZ0JxCN/MsVh zGDXOm4GIzjZrHOc4I8qNmtfx2Kgt1rbJMjjzohoc/6Nf/zHTC3trAEBlW0Lo07TEvnG A92Rk9r+gkIKJk4PVSQFuewoDr8mhLBx1ijN+enBWAKjnRlJ5Pu5YCYoISmz4zdlCTKe ohcQ== Received: by 10.50.237.41 with SMTP id uz9mr582895igc.43.1347508318469; Wed, 12 Sep 2012 20:51:58 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.50.184.232 with SMTP id ex8csp111110igc; Wed, 12 Sep 2012 20:51:58 -0700 (PDT) Received: by 10.182.187.98 with SMTP id fr2mr470863obc.73.1347508317849; Wed, 12 Sep 2012 20:51:57 -0700 (PDT) Received: from mail-ob0-f178.google.com (mail-ob0-f178.google.com [209.85.214.178]) by mx.google.com with ESMTPS id rp7si28188597obc.5.2012.09.12.20.51.57 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 12 Sep 2012 20:51:57 -0700 (PDT) Received-SPF: pass (google.com: domain of robdclark@gmail.com designates 209.85.214.178 as permitted sender) client-ip=209.85.214.178; Authentication-Results: mx.google.com; spf=pass (google.com: domain of robdclark@gmail.com designates 209.85.214.178 as permitted sender) smtp.mail=robdclark@gmail.com; dkim=pass header.i=@gmail.com Received: by mail-ob0-f178.google.com with SMTP id wd20so4595268obb.37 for ; Wed, 12 Sep 2012 20:51:57 -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=QPzpnnpy21BR/a7wiKWk8QnrPXbqv2p6dkgdKA49u7E=; b=zozHFlUFiGQVJNbie120aMJNf89xZDVkSiVjn+o4di1mWvbH5n2t/TIVD7E2dyTI/x kXMuy4dl+6f1o6JqqHI4CRJ7zsaNNszP1zEuZTekJcabSObcQZKMz0IoYG0U8OueZjoW 28Edq8VMGQn9m00h+lGfXCK3Z4Kzq8v0/9NDwnvWXGGSft8fCJtjYxRsyU3hW+Q53OfL uL/slPug5M3x9O7ZP6jY7XPX3HkRRUG6TIZdczhgBD+HB0SBFqWcELauyvsPWGdbvf/f M6tGLXUXyeQ1VjAIyI7ySlEGCyz/oYf7xlXRfqUIYzdz982QrBAY/LrwEqY4LP2mA8Xn GimA== Received: by 10.182.174.68 with SMTP id bq4mr486744obc.53.1347508317717; Wed, 12 Sep 2012 20:51:57 -0700 (PDT) Received: from localhost (ppp-70-129-131-42.dsl.rcsntx.swbell.net. [70.129.131.42]) by mx.google.com with ESMTPS id jd10sm22539157obb.13.2012.09.12.20.51.56 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 12 Sep 2012 20:51:57 -0700 (PDT) Sender: Rob Clark From: Rob Clark To: dri-devel@lists.freedesktop.org Cc: patches@linaro.org, ville.syrjala@linux.intel.com, jbarnes@virtuousgeek.org, daniel.vetter@ffwll.ch, Rob Clark Subject: [RFC 09/11] drm: add drm_crtc_state Date: Wed, 12 Sep 2012 22:49:55 -0500 Message-Id: <1347508195-14939-10-git-send-email-rob.clark@linaro.org> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1347508195-14939-1-git-send-email-rob.clark@linaro.org> References: <1347508195-14939-1-git-send-email-rob.clark@linaro.org> X-Gm-Message-State: ALoCoQnKFGd/WX760WwGpvHTficvgOYZcl9/NN+BmVTVH90QwqJxOFF6VwL+hmM+GDVCMlWfv3DE From: Rob Clark Start breaking out the mutable state of the CRTC into it's own structure. Plus add _check_state() and _set_property() helpers. This only moves the state that is related to scanout fb, which is needed for nuclear-pageflip. The rest of the mutable state should be moved from drm_crtc to drm_crtc_state as part of the atomic-modeset implementation. --- drivers/gpu/drm/drm_crtc.c | 88 ++++++++++++++++++++++++++++++------- drivers/gpu/drm/drm_crtc_helper.c | 51 ++++++++++----------- drivers/gpu/drm/drm_fb_helper.c | 11 ++--- include/drm/drm_crtc.h | 49 ++++++++++++++++----- 4 files changed, 143 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index f421fa6a..6d22c8c 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -396,7 +396,7 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb) /* remove from any CRTC */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - if (crtc->fb == fb) { + if (crtc->state->fb == fb) { /* should turn off the crtc */ drm_mode_crtc_set_obj_prop(crtc, state, config->prop_fb_id, 0); } @@ -446,7 +446,7 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, crtc->dev = dev; crtc->funcs = funcs; - crtc->invert_dimensions = false; + crtc->state->invert_dimensions = false; mutex_lock(&dev->mode_config.mutex); @@ -455,7 +455,7 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, goto out; crtc->base.properties = &crtc->properties; - crtc->base.propvals = &crtc->propvals; + crtc->base.propvals = &crtc->state->propvals; list_add_tail(&crtc->head, &dev->mode_config.crtc_list); dev->mode_config.num_crtc++; @@ -496,6 +496,67 @@ void drm_crtc_cleanup(struct drm_crtc *crtc) } EXPORT_SYMBOL(drm_crtc_cleanup); +int drm_crtc_check_state(struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + struct drm_framebuffer *fb = state->fb; + int hdisplay, vdisplay; + + /* disabling the crtc is allowed: */ + if (!fb) + return 0; + + hdisplay = crtc->mode.hdisplay; + vdisplay = crtc->mode.vdisplay; + + if (state->invert_dimensions) + swap(hdisplay, vdisplay); + + if (hdisplay > fb->width || + vdisplay > fb->height || + state->x > fb->width - hdisplay || + state->y > fb->height - vdisplay) { + DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n", + fb->width, fb->height, hdisplay, vdisplay, + state->x, state->y, + state->invert_dimensions ? " (inverted)" : ""); + return -ENOSPC; + } + + return 0; +} +EXPORT_SYMBOL(drm_crtc_check_state); + +void drm_crtc_commit_state(struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + crtc->state = state; + crtc->base.propvals = &state->propvals; +} +EXPORT_SYMBOL(drm_crtc_commit_state); + +int drm_crtc_set_property(struct drm_crtc *crtc, + struct drm_crtc_state *state, + struct drm_property *property, uint64_t value) +{ + struct drm_device *dev = crtc->dev; + struct drm_mode_config *config = &dev->mode_config; + + if (property == config->prop_fb_id) { + struct drm_mode_object *obj = drm_property_get_obj(property, value); + state->fb = obj ? obj_to_fb(obj) : NULL; + } else if (property == config->prop_crtc_x) { + state->x = *(int *)&value; + } else if (property == config->prop_crtc_y) { + state->y = *(int32_t *)&value; + } else { + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL(drm_crtc_set_property); + /** * drm_mode_probed_add - add a mode to a connector's probed mode list * @connector: connector the new mode @@ -1614,11 +1675,11 @@ int drm_mode_getcrtc(struct drm_device *dev, } crtc = obj_to_crtc(obj); - crtc_resp->x = crtc->x; - crtc_resp->y = crtc->y; + crtc_resp->x = crtc->state->x; + crtc_resp->y = crtc->state->y; crtc_resp->gamma_size = crtc->gamma_size; - if (crtc->fb) - crtc_resp->fb_id = crtc->fb->base.id; + if (crtc->state->fb) + crtc_resp->fb_id = crtc->state->fb->base.id; else crtc_resp->fb_id = 0; @@ -2072,12 +2133,12 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, /* If we have a mode we need a framebuffer. */ /* If we pass -1, set the mode with the currently bound fb */ if (crtc_req->fb_id == -1) { - if (!crtc->fb) { + if (!crtc->state->fb) { DRM_DEBUG_KMS("CRTC doesn't have current FB\n"); ret = -EINVAL; goto out; } - fb = crtc->fb; + fb = crtc->state->fb; } else { obj = drm_mode_object_find(dev, crtc_req->fb_id, DRM_MODE_OBJECT_FB); @@ -2107,7 +2168,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, hdisplay = mode->hdisplay; vdisplay = mode->vdisplay; - if (crtc->invert_dimensions) + if (crtc->state->invert_dimensions) swap(hdisplay, vdisplay); if (hdisplay > fb->width || @@ -2117,7 +2178,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n", fb->width, fb->height, hdisplay, vdisplay, crtc_req->x, crtc_req->y, - crtc->invert_dimensions ? " (inverted)" : ""); + crtc->state->invert_dimensions ? " (inverted)" : ""); ret = -ENOSPC; goto out; } @@ -3445,9 +3506,6 @@ int drm_mode_crtc_set_obj_prop(struct drm_crtc *crtc, if (crtc->funcs->set_property) ret = crtc->funcs->set_property(crtc, state, property, value); - if (!ret) - drm_object_property_set_value(&crtc->base, &crtc->propvals, - property, value); return ret; } @@ -3800,7 +3858,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, goto out_unlock; } - if (crtc->fb == NULL) { + if (crtc->state->fb == NULL) { /* The framebuffer is currently unbound, presumably * due to a hotplug event, that userspace has not * yet discovered. diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 3252e70..65ed229 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -266,7 +266,7 @@ void drm_helper_disable_unused_functions(struct drm_device *dev) (*crtc_funcs->disable)(crtc); else (*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF); - crtc->fb = NULL; + crtc->state->fb = NULL; } } } @@ -363,15 +363,15 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, saved_hwmode = crtc->hwmode; saved_mode = crtc->mode; - saved_x = crtc->x; - saved_y = crtc->y; + saved_x = crtc->state->x; + saved_y = crtc->state->y; /* Update crtc values up front so the driver can rely on them for mode * setting. */ crtc->mode = *mode; - crtc->x = x; - crtc->y = y; + crtc->state->x = x; + crtc->state->y = y; /* Pass our mode to the connectors and the CRTC to give them a chance to * adjust it according to limitations or connector properties, and also @@ -456,8 +456,8 @@ done: if (!ret) { crtc->hwmode = saved_hwmode; crtc->mode = saved_mode; - crtc->x = saved_x; - crtc->y = saved_y; + crtc->state->x = saved_x; + crtc->state->y = saved_y; } return ret; @@ -591,29 +591,29 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) save_set.crtc = set->crtc; save_set.mode = &set->crtc->mode; - save_set.x = set->crtc->x; - save_set.y = set->crtc->y; - save_set.fb = set->crtc->fb; + save_set.x = set->crtc->state->x; + save_set.y = set->crtc->state->y; + save_set.fb = set->crtc->state->fb; /* We should be able to check here if the fb has the same properties * and then just flip_or_move it */ - if (set->crtc->fb != set->fb) { + if (set->crtc->state->fb != set->fb) { /* If we have no fb then treat it as a full mode set */ - if (set->crtc->fb == NULL) { + if (set->crtc->state->fb == NULL) { DRM_DEBUG_KMS("crtc has no fb, full mode set\n"); mode_changed = true; } else if (set->fb == NULL) { mode_changed = true; - } else if (set->fb->depth != set->crtc->fb->depth) { + } else if (set->fb->depth != set->crtc->state->fb->depth) { mode_changed = true; } else if (set->fb->bits_per_pixel != - set->crtc->fb->bits_per_pixel) { + set->crtc->state->fb->bits_per_pixel) { mode_changed = true; } else fb_changed = true; } - if (set->x != set->crtc->x || set->y != set->crtc->y) + if (set->x != set->crtc->state->x || set->y != set->crtc->state->y) fb_changed = true; if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) { @@ -704,14 +704,14 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) DRM_DEBUG_KMS("attempting to set mode from" " userspace\n"); drm_mode_debug_printmodeline(set->mode); - old_fb = set->crtc->fb; - set->crtc->fb = set->fb; + old_fb = set->crtc->state->fb; + set->crtc->state->fb = set->fb; if (!drm_crtc_helper_set_mode(set->crtc, set->mode, set->x, set->y, old_fb)) { DRM_ERROR("failed to set mode on [CRTC:%d]\n", set->crtc->base.id); - set->crtc->fb = old_fb; + set->crtc->state->fb = old_fb; ret = -EINVAL; goto fail; } @@ -724,16 +724,16 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) } drm_helper_disable_unused_functions(dev); } else if (fb_changed) { - set->crtc->x = set->x; - set->crtc->y = set->y; + set->crtc->state->x = set->x; + set->crtc->state->y = set->y; - old_fb = set->crtc->fb; - if (set->crtc->fb != set->fb) - set->crtc->fb = set->fb; + old_fb = set->crtc->state->fb; + if (set->crtc->state->fb != set->fb) + set->crtc->state->fb = set->fb; ret = crtc_funcs->mode_set_base(set->crtc, set->x, set->y, old_fb); if (ret != 0) { - set->crtc->fb = old_fb; + set->crtc->state->fb = old_fb; goto fail; } } @@ -888,7 +888,8 @@ int drm_helper_resume_force_mode(struct drm_device *dev) continue; ret = drm_crtc_helper_set_mode(crtc, &crtc->mode, - crtc->x, crtc->y, crtc->fb); + crtc->state->x, crtc->state->y, + crtc->state->fb); if (ret == false) DRM_ERROR("failed to set mode on crtc %p\n", crtc); diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index f546d1e..d70b787 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -185,7 +185,7 @@ static struct drm_framebuffer *drm_mode_config_fb(struct drm_crtc *crtc) list_for_each_entry(c, &dev->mode_config.crtc_list, head) { if (crtc->base.id == c->base.id) - return c->fb; + return c->state->fb; } return NULL; @@ -214,8 +214,9 @@ int drm_fb_helper_debug_leave(struct fb_info *info) } drm_fb_helper_restore_lut_atomic(mode_set->crtc); - funcs->mode_set_base_atomic(mode_set->crtc, fb, crtc->x, - crtc->y, LEAVE_ATOMIC_MODE_SET); + funcs->mode_set_base_atomic(mode_set->crtc, fb, + crtc->state->x, crtc->state->y, + LEAVE_ATOMIC_MODE_SET); } return 0; @@ -1361,9 +1362,9 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) mutex_lock(&dev->mode_config.mutex); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - if (crtc->fb) + if (crtc->state->fb) crtcs_bound++; - if (crtc->fb == fb_helper->fb) + if (crtc->state->fb == fb_helper->fb) bound++; } diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 73a8a14..92e6bf8 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -363,18 +363,43 @@ struct drm_crtc_funcs { }; /** + * drm_crtc_state - mutable crtc state + * @fb: the framebuffer that the CRTC is currently bound to + * @invert_dimensions: for purposes of error checking crtc vs fb sizes, + * invert the width/height of the crtc. This is used if the driver + * is performing 90 or 270 degree rotated scanout + * @x: x position on screen + * @y: y position on screen + * @propvals: property values + */ +struct drm_crtc_state { + /* + * NOTE: more should move from 'struct drm_crtc' into here as + * part of the atomic-modeset support: + * + enabled + * + mode + * + hwmode + * + framedur_ns + * + linedur_ns + * + pixeldur_ns + * + * For now, I'm just moving what is needed for atomic-pageflip + */ + struct drm_framebuffer *fb; + bool invert_dimensions; + int x, y; + struct drm_object_property_values propvals; +}; + +/** * drm_crtc - central CRTC control structure * @dev: parent DRM device * @head: list management * @base: base KMS object for ID tracking etc. + * @state: the mutable state * @enabled: is this CRTC enabled? * @mode: current mode timings * @hwmode: mode timings as programmed to hw regs - * @invert_dimensions: for purposes of error checking crtc vs fb sizes, - * invert the width/height of the crtc. This is used if the driver - * is performing 90 or 270 degree rotated scanout - * @x: x position on screen - * @y: y position on screen * @funcs: CRTC control functions * @gamma_size: size of gamma ramp * @gamma_store: gamma ramp values @@ -393,8 +418,7 @@ struct drm_crtc { struct drm_mode_object base; - /* framebuffer the connector is currently bound to */ - struct drm_framebuffer *fb; + struct drm_crtc_state *state; bool enabled; @@ -406,9 +430,6 @@ struct drm_crtc { */ struct drm_display_mode hwmode; - bool invert_dimensions; - - int x, y; const struct drm_crtc_funcs *funcs; /* CRTC gamma size for reporting to userspace */ @@ -422,7 +443,6 @@ struct drm_crtc { void *helper_private; struct drm_object_properties properties; - struct drm_object_property_values propvals; }; @@ -882,6 +902,13 @@ extern int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, const struct drm_crtc_funcs *funcs); extern void drm_crtc_cleanup(struct drm_crtc *crtc); +extern int drm_crtc_check_state(struct drm_crtc *crtc, + struct drm_crtc_state *state); +extern void drm_crtc_commit_state(struct drm_crtc *crtc, + struct drm_crtc_state *state); +extern int drm_crtc_set_property(struct drm_crtc *crtc, + struct drm_crtc_state *state, + struct drm_property *property, uint64_t value); extern int drm_connector_init(struct drm_device *dev, struct drm_connector *connector,