From: Rob Clark <r...@ti.com>

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        |   70 +++++++++++++++++++++++++++++++------
 drivers/gpu/drm/drm_crtc_helper.c |   51 ++++++++++++++-------------
 drivers/gpu/drm/drm_fb_helper.c   |   11 +++---
 include/drm/drm_crtc.h            |   44 +++++++++++++++++------
 4 files changed, 125 insertions(+), 51 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 8be57e4..0ddd43e 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -397,7 +397,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_crtc_id, 0);
                }
@@ -447,7 +447,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);
 
@@ -496,6 +496,54 @@ 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;
+
+       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);
+
+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) {
+               state->fb = U642VOID(value);
+       } 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
@@ -1593,11 +1641,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;
 
@@ -2042,12 +2090,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);
@@ -2077,7 +2125,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 ||
@@ -2087,7 +2135,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;
                }
@@ -3773,7 +3821,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
                goto out;
        crtc = obj_to_crtc(obj);
 
-       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 a0bec04..9417aaa 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -352,18 +352,41 @@ 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
+ */
+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 nuclear-pageflip
+        */
+       struct drm_framebuffer *fb;
+       bool invert_dimensions;
+       int x, y;
+};
+
+/**
  * 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
@@ -382,8 +405,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;
 
@@ -395,9 +417,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 */
@@ -858,6 +877,11 @@ 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 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,
-- 
1.7.9.5

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

Reply via email to