drm/msm: subclass drm_atomic_state
authorRob Clark <robdclark@gmail.com>
Fri, 4 Nov 2016 17:51:42 +0000 (13:51 -0400)
committerRob Clark <robdclark@gmail.com>
Sun, 27 Nov 2016 16:32:27 +0000 (11:32 -0500)
This will give the kms backends a slot to stash their own hw specific
global state.

Signed-off-by: Rob Clark <robdclark@gmail.com>
drivers/gpu/drm/msm/msm_atomic.c
drivers/gpu/drm/msm/msm_drv.c
drivers/gpu/drm/msm/msm_drv.h
drivers/gpu/drm/msm/msm_kms.h

index 4e21e1d7237855563a6cd4b404fa9c32882c85e0..30b5d23e53b45179473ff4a495584e419a137abb 100644 (file)
@@ -241,6 +241,10 @@ int msm_atomic_commit(struct drm_device *dev,
 
        drm_atomic_helper_swap_state(state, true);
 
+       /* swap driver private state while still holding state_lock */
+       if (to_kms_state(state)->state)
+               priv->kms->funcs->swap_state(priv->kms, state);
+
        /*
         * Everything below can be run asynchronously without the need to grab
         * any modeset locks at all under one conditions: It must be guaranteed
@@ -271,3 +275,30 @@ error:
        drm_atomic_helper_cleanup_planes(dev, state);
        return ret;
 }
+
+struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device *dev)
+{
+       struct msm_kms_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
+
+       if (!state || drm_atomic_state_init(dev, &state->base) < 0) {
+               kfree(state);
+               return NULL;
+       }
+
+       return &state->base;
+}
+
+void msm_atomic_state_clear(struct drm_atomic_state *s)
+{
+       struct msm_kms_state *state = to_kms_state(s);
+       drm_atomic_state_default_clear(&state->base);
+       kfree(state->state);
+       state->state = NULL;
+}
+
+void msm_atomic_state_free(struct drm_atomic_state *state)
+{
+       kfree(to_kms_state(state)->state);
+       drm_atomic_state_default_release(state);
+       kfree(state);
+}
index c740eaf9272b3ff6f78acf0a6d0468f7a7ce324b..aa41d8dd623b6dd2880129dc2d82c18497c8b9ac 100644 (file)
@@ -46,6 +46,9 @@ static const struct drm_mode_config_funcs mode_config_funcs = {
        .output_poll_changed = msm_fb_output_poll_changed,
        .atomic_check = msm_atomic_check,
        .atomic_commit = msm_atomic_commit,
+       .atomic_state_alloc = msm_atomic_state_alloc,
+       .atomic_state_clear = msm_atomic_state_clear,
+       .atomic_state_free = msm_atomic_state_free,
 };
 
 int msm_register_address_space(struct drm_device *dev,
index 03ce6a18ac40e27093534ed0a1ee8593a1eb005e..175b2bfae5e1ad298a87948709457d935bd0214d 100644 (file)
@@ -179,6 +179,9 @@ int msm_atomic_check(struct drm_device *dev,
                     struct drm_atomic_state *state);
 int msm_atomic_commit(struct drm_device *dev,
                struct drm_atomic_state *state, bool nonblock);
+struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device *dev);
+void msm_atomic_state_clear(struct drm_atomic_state *state);
+void msm_atomic_state_free(struct drm_atomic_state *state);
 
 int msm_register_address_space(struct drm_device *dev,
                struct msm_gem_address_space *aspace);
index 40e41e5cdbc6fad17d970cb1b645ba90cf0cbe75..cb9758bcadfd2681a103694ba5fd486b9264f0db 100644 (file)
@@ -40,6 +40,8 @@ struct msm_kms_funcs {
        irqreturn_t (*irq)(struct msm_kms *kms);
        int (*enable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc);
        void (*disable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc);
+       /* swap global atomic state: */
+       void (*swap_state)(struct msm_kms *kms, struct drm_atomic_state *state);
        /* modeset, bracketing atomic_commit(): */
        void (*prepare_commit)(struct msm_kms *kms, struct drm_atomic_state *state);
        void (*complete_commit)(struct msm_kms *kms, struct drm_atomic_state *state);
@@ -65,6 +67,18 @@ struct msm_kms {
        int irq;
 };
 
+/**
+ * Subclass of drm_atomic_state, to allow kms backend to have driver
+ * private global state.  The kms backend can do whatever it wants
+ * with the ->state ptr.  On ->atomic_state_clear() the ->state ptr
+ * is kfree'd and set back to NULL.
+ */
+struct msm_kms_state {
+       struct drm_atomic_state base;
+       void *state;
+};
+#define to_kms_state(x) container_of(x, struct msm_kms_state, base)
+
 static inline void msm_kms_init(struct msm_kms *kms,
                const struct msm_kms_funcs *funcs)
 {