Heavily based upon Rob Clark's atomic series.
- Dropped the connctor state from the crtc state, instead opting for a
  full-blown connector state. The only thing it has is the desired
  crtc, but drivers which have connector properties have now a
  data-structure to subclass.

- Rename create_state to duplicate_state. Especially for legacy ioctls
  we want updates on top of existing state, so we need a way to get at
  the current state. We need to be careful to clear the backpointers
  correctly though. We need to be careful though with the ->state
  backpointer we need while constructing the atomic state.

- Drop property values. Drivers with properties simply need to
  subclass the datastructures and track the decoded values in there. I
  also think that common properties (like rotation) should be decoded
  and stored in the core structures.

- Create a new set of ->atomic_set_prop functions, for smoother
  transitions from legacy to atomic operations.

- Pass the ->atomic_set_prop ioctl the right structure to avoid
  chasing pointers in drivers.

- Drop temporary boolean state for now until we resurrect them with
  the helper functions.

- Drop invert_dimensions. For now we don't need any checking since
  that's done by the higher-level legacy ioctls. But even then we
  should also add rotation/flip tracking to the core drm_crtc_state,
  not just whether the dimensions are inverted.

- Track crtc state with an enable/disable. That's equivalent to
  mode_valid, but a bit clearer that it means the entire crtc.

The global interface will follow in subsequent patches.

v2: We need to allow drivers to somehow set up the initial state and
clear it on resume. So add a plane->reset callback for that. Helpers
will be provided with default behaviour for all these.

Signed-off-by: Daniel Vetter <daniel.vetter at ffwll.ch>
---
 drivers/gpu/drm/drm_crtc.c |   5 ++
 include/drm/drm_crtc.h     | 149 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 154 insertions(+)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 805240b11229..0f934a58702d 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -4623,9 +4623,14 @@ out:
 void drm_mode_config_reset(struct drm_device *dev)
 {
        struct drm_crtc *crtc;
+       struct drm_crtc *plane;
        struct drm_encoder *encoder;
        struct drm_connector *connector;

+       list_for_each_entry(plane, &dev->mode_config.plane_list, head)
+               if (plane->funcs->reset)
+                       plane->funcs->reset(plane);
+
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
                if (crtc->funcs->reset)
                        crtc->funcs->reset(crtc);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index f1105d0da059..a1a8c694e765 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -228,6 +228,25 @@ struct drm_encoder;
 struct drm_pending_vblank_event;
 struct drm_plane;
 struct drm_bridge;
+struct drm_atomic_state;
+
+/**
+ * drm_crtc_state - mutable crtc state
+ * @mode_valid: a valid mode has been set
+ * @set_config: needs modeset (crtc->set_config())
+ * @connectors_change: the connector-ids array has changed
+ * @mode: current mode timings
+ * @event: pending pageflip event
+ */
+struct drm_crtc_state {
+       bool enable        : 1;
+
+       struct drm_display_mode mode;
+
+       struct drm_pending_vblank_event *event;
+
+       struct drm_atomic_state *state;
+};

 /**
  * drm_crtc_funcs - control CRTCs for a given device
@@ -291,6 +310,15 @@ struct drm_crtc_funcs {

        int (*set_property)(struct drm_crtc *crtc,
                            struct drm_property *property, uint64_t val);
+
+       /* atomic update handling */
+       struct drm_crtc_state *(*atomic_duplicate_state)(struct drm_crtc *crtc);
+       void (*atomic_destroy_state)(struct drm_crtc *crtc,
+                                    struct drm_crtc_state *cstate);
+       int (*atomic_set_property)(struct drm_crtc *crtc,
+                                  struct drm_crtc_state *state,
+                                  struct drm_property *property,
+                                  uint64_t val);
 };

 /**
@@ -375,8 +403,38 @@ struct drm_crtc {
        void *helper_private;

        struct drm_object_properties properties;
+
+       struct drm_crtc_state *state;
 };

+static inline struct drm_crtc_state *
+drm_crtc_duplicate_state(struct drm_crtc *crtc)
+{
+       if (crtc->funcs->atomic_duplicate_state)
+               return crtc->funcs->atomic_duplicate_state(crtc);
+       return kmemdup(crtc->state, sizeof(struct drm_crtc_state), GFP_KERNEL);
+}
+
+static inline void
+drm_crtc_destroy_state(struct drm_crtc *crtc,
+                      struct drm_crtc_state *cstate)
+{
+       if (crtc->funcs->atomic_destroy_state)
+               crtc->funcs->atomic_destroy_state(crtc, cstate);
+       else
+               kfree(cstate);
+}
+
+
+/**
+ * drm_connector_state - mutable connector state
+ * @crtc: crtc to connect connector to, NULL if disabled
+ */
+struct drm_connector_state {
+       struct drm_crtc *crtc;
+
+       struct drm_atomic_state *state;
+};

 /**
  * drm_connector_funcs - control connectors on a given device
@@ -413,6 +471,15 @@ struct drm_connector_funcs {
                             uint64_t val);
        void (*destroy)(struct drm_connector *connector);
        void (*force)(struct drm_connector *connector);
+
+       /* atomic update handling */
+       struct drm_connector_state *(*atomic_duplicate_state)(struct 
drm_connector *connector);
+       void (*atomic_destroy_state)(struct drm_connector *connector,
+                                    struct drm_connector_state *cstate);
+       int (*atomic_set_property)(struct drm_connector *connector,
+                                  struct drm_connector_state *state,
+                                  struct drm_property *property,
+                                  uint64_t val);
 };

 /**
@@ -564,8 +631,59 @@ struct drm_connector {
        unsigned bad_edid_counter;

        struct dentry *debugfs_entry;
+
+       struct drm_connector_state *state;
 };

+static inline struct drm_connector_state *
+drm_connector_duplicate_state(struct drm_connector *connector)
+{
+       if (connector->funcs->atomic_duplicate_state)
+               return connector->funcs->atomic_duplicate_state(connector);
+       return kmemdup(connector->state,
+                      sizeof(struct drm_connector_state), GFP_KERNEL);
+}
+
+static inline void
+drm_connector_destroy_state(struct drm_connector *connector,
+                           struct drm_connector_state *cstate)
+{
+       if (connector->funcs->atomic_destroy_state)
+               connector->funcs->atomic_destroy_state(connector, cstate);
+       else
+               kfree(cstate);
+}
+
+/**
+ * drm_plane_state - mutable plane state
+ * @crtc: currently bound CRTC
+ * @fb: currently bound fb
+ * @crtc_x: left position of visible portion of plane on crtc
+ * @crtc_y: upper position of visible portion of plane on crtc
+ * @crtc_w: width of visible portion of plane on crtc
+ * @crtc_h: height of visible portion of plane on crtc
+ * @src_x: left position of visible portion of plane within
+ *     plane (in 16.16)
+ * @src_y: upper position of visible portion of plane within
+ *     plane (in 16.16)
+ * @src_w: width of visible portion of plane (in 16.16)
+ * @src_h: height of visible portion of plane (in 16.16)
+ */
+struct drm_plane_state {
+       struct drm_crtc *crtc;
+       struct drm_framebuffer *fb;
+
+       /* Signed dest location allows it to be partially off screen */
+       int32_t crtc_x, crtc_y;
+       uint32_t crtc_w, crtc_h;
+
+       /* Source values are 16.16 fixed point */
+       uint32_t src_x, src_y;
+       uint32_t src_h, src_w;
+       struct drm_atomic_state *state;
+};
+
+
 /**
  * drm_plane_funcs - driver plane control functions
  * @update_plane: update the plane configuration
@@ -582,9 +700,19 @@ struct drm_plane_funcs {
                            uint32_t src_w, uint32_t src_h);
        int (*disable_plane)(struct drm_plane *plane);
        void (*destroy)(struct drm_plane *plane);
+       void (*reset)(struct drm_plane *plane);

        int (*set_property)(struct drm_plane *plane,
                            struct drm_property *property, uint64_t val);
+
+       /* atomic update handling */
+       struct drm_plane_state *(*atomic_duplicate_state)(struct drm_plane 
*plane);
+       void (*atomic_destroy_state)(struct drm_plane *plane,
+                                    struct drm_plane_state *cstate);
+       int (*atomic_set_property)(struct drm_plane *plane,
+                                  struct drm_plane_state *state,
+                                  struct drm_property *property,
+                                  uint64_t val);
 };

 enum drm_plane_type {
@@ -625,8 +753,29 @@ struct drm_plane {
        struct drm_object_properties properties;

        enum drm_plane_type type;
+
+       struct drm_plane_state *state;
 };

+static inline struct drm_plane_state *
+drm_plane_duplicate_state(struct drm_plane *plane)
+{
+       if (plane->funcs->atomic_duplicate_state)
+               return plane->funcs->atomic_duplicate_state(plane);
+       return kmemdup(plane->state, sizeof(struct drm_plane_state), 
GFP_KERNEL);
+}
+
+static inline void
+drm_plane_destroy_state(struct drm_plane *plane,
+                       struct drm_plane_state *cstate)
+{
+       if (plane->funcs->atomic_destroy_state)
+               plane->funcs->atomic_destroy_state(plane, cstate);
+       else
+               kfree(cstate);
+}
+
+
 /**
  * drm_bridge_funcs - drm_bridge control functions
  * @mode_fixup: Try to fixup (or reject entirely) proposed mode for this bridge
-- 
2.0.1

Reply via email to