@@ -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);
@@ -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
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@ffwll.ch> --- drivers/gpu/drm/drm_crtc.c | 5 ++ include/drm/drm_crtc.h | 149 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 154 insertions(+)