}
for (i = 0; i < state->num_private_objs; i++) {
- void *obj_state = state->private_objs[i].obj_state;
+ struct drm_private_obj *obj = state->private_objs[i].ptr;
- state->private_objs[i].funcs->destroy_state(obj_state);
- state->private_objs[i].obj = NULL;
- state->private_objs[i].obj_state = NULL;
- state->private_objs[i].funcs = NULL;
+ if (!obj)
+ continue;
+
+ obj->funcs->atomic_destroy_state(obj,
+ state->private_objs[i].state);
+ state->private_objs[i].ptr = NULL;
+ state->private_objs[i].state = NULL;
}
state->num_private_objs = 0;
}
/**
+ * drm_atomic_private_obj_init - initialize private object
+ * @obj: private object
+ * @state: initial private object state
+ * @funcs: pointer to the struct of function pointers that identify the object
+ * type
+ *
+ * Initialize the private object, which can be embedded into any
+ * driver private object that needs its own atomic state.
+ */
+void
+drm_atomic_private_obj_init(struct drm_private_obj *obj,
+ struct drm_private_state *state,
+ const struct drm_private_state_funcs *funcs)
+{
+ memset(obj, 0, sizeof(*obj));
+
+ obj->state = state;
+ obj->funcs = funcs;
+}
+EXPORT_SYMBOL(drm_atomic_private_obj_init);
+
+/**
+ * drm_atomic_private_obj_fini - finalize private object
+ * @obj: private object
+ *
+ * Finalize the private object.
+ */
+void
+drm_atomic_private_obj_fini(struct drm_private_obj *obj)
+{
+ obj->funcs->atomic_destroy_state(obj, obj->state);
+}
+EXPORT_SYMBOL(drm_atomic_private_obj_fini);
+
+/**
* drm_atomic_get_private_obj_state - get private object state
* @state: global atomic state
* @obj: private object to get the state for
- * @funcs: pointer to the struct of function pointers that identify the object
- * type
*
* This function returns the private object state for the given private object,
* allocating the state if needed. It does not grab any locks as the caller is
*
* Either the allocated state or the error code encoded into a pointer.
*/
-void *
-drm_atomic_get_private_obj_state(struct drm_atomic_state *state, void *obj,
- const struct drm_private_state_funcs *funcs)
+struct drm_private_state *
+drm_atomic_get_private_obj_state(struct drm_atomic_state *state,
+ struct drm_private_obj *obj)
{
int index, num_objs, i;
size_t size;
struct __drm_private_objs_state *arr;
+ struct drm_private_state *obj_state;
for (i = 0; i < state->num_private_objs; i++)
- if (obj == state->private_objs[i].obj &&
- state->private_objs[i].obj_state)
- return state->private_objs[i].obj_state;
+ if (obj == state->private_objs[i].ptr)
+ return state->private_objs[i].state;
num_objs = state->num_private_objs + 1;
size = sizeof(*state->private_objs) * num_objs;
index = state->num_private_objs;
memset(&state->private_objs[index], 0, sizeof(*state->private_objs));
- state->private_objs[index].obj_state = funcs->duplicate_state(state, obj);
- if (!state->private_objs[index].obj_state)
+ obj_state = obj->funcs->atomic_duplicate_state(obj);
+ if (!obj_state)
return ERR_PTR(-ENOMEM);
- state->private_objs[index].obj = obj;
- state->private_objs[index].funcs = funcs;
+ state->private_objs[index].state = obj_state;
+ state->private_objs[index].ptr = obj;
+
state->num_private_objs = num_objs;
- DRM_DEBUG_ATOMIC("Added new private object state %p to %p\n",
- state->private_objs[index].obj_state, state);
+ DRM_DEBUG_ATOMIC("Added new private object %p state %p to %p\n",
+ obj, obj_state, state);
- return state->private_objs[index].obj_state;
+ return obj_state;
}
EXPORT_SYMBOL(drm_atomic_get_private_obj_state);
struct drm_plane *plane;
struct drm_plane_state *plane_state;
struct drm_crtc_commit *commit;
- void *obj, *obj_state;
- const struct drm_private_state_funcs *funcs;
+ struct drm_private_obj *obj;
+ struct drm_private_state *obj_state;
if (stall) {
for_each_crtc_in_state(state, crtc, crtc_state, i) {
plane->state->state = NULL;
}
- __for_each_private_obj(state, obj, obj_state, i, funcs)
- funcs->swap_state(obj, &state->private_objs[i].obj_state);
+ for_each_private_obj(state, obj, obj_state, i) {
+ obj->state->state = state;
+ swap(state->private_objs[i].state, obj->state);
+ obj->state->state = NULL;
+ }
}
EXPORT_SYMBOL(drm_atomic_helper_swap_state);
goto retry;
}
EXPORT_SYMBOL(drm_atomic_helper_legacy_gamma_set);
+
+/**
+ * __drm_atomic_helper_private_duplicate_state - copy atomic private state
+ * @obj: CRTC object
+ * @state: new private object state
+ *
+ * Copies atomic state from a private objects's current state and resets inferred values.
+ * This is useful for drivers that subclass the private state.
+ */
+void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj,
+ struct drm_private_state *state)
+{
+ memcpy(state, obj->state, sizeof(*state));
+}
+EXPORT_SYMBOL(__drm_atomic_helper_private_obj_duplicate_state);
struct drm_connector_state *state;
};
+struct drm_private_obj;
+struct drm_private_state;
+
/**
* struct drm_private_state_funcs - atomic state functions for private objects
*
*/
struct drm_private_state_funcs {
/**
- * @duplicate_state:
+ * @atomic_duplicate_state:
*
* Duplicate the current state of the private object and return it. It
* is an error to call this before obj->state has been initialized.
* Duplicated atomic state or NULL when obj->state is not
* initialized or allocation failed.
*/
- void *(*duplicate_state)(struct drm_atomic_state *state, void *obj);
+ struct drm_private_state *(*atomic_duplicate_state)(struct drm_private_obj *obj);
/**
- * @swap_state:
+ * @atomic_destroy_state:
*
- * This function swaps the existing state of a private object @obj with
- * it's newly created state, the pointer to which is passed as
- * @obj_state_ptr.
+ * Frees the private object state created with @atomic_duplicate_state.
*/
- void (*swap_state)(void *obj, void **obj_state_ptr);
+ void (*atomic_destroy_state)(struct drm_private_obj *obj,
+ struct drm_private_state *state);
+};
- /**
- * @destroy_state:
- *
- * Frees the private object state created with @duplicate_state.
- */
- void (*destroy_state)(void *obj_state);
+struct drm_private_obj {
+ struct drm_private_state *state;
+
+ const struct drm_private_state_funcs *funcs;
+};
+
+struct drm_private_state {
+ struct drm_atomic_state *state;
};
struct __drm_private_objs_state {
- void *obj;
- void *obj_state;
- const struct drm_private_state_funcs *funcs;
+ struct drm_private_obj *ptr;
+ struct drm_private_state *state;
};
/**
struct drm_connector_state *state, struct drm_property *property,
uint64_t val);
-void * __must_check
+void drm_atomic_private_obj_init(struct drm_private_obj *obj,
+ struct drm_private_state *state,
+ const struct drm_private_state_funcs *funcs);
+void drm_atomic_private_obj_fini(struct drm_private_obj *obj);
+
+struct drm_private_state * __must_check
drm_atomic_get_private_obj_state(struct drm_atomic_state *state,
- void *obj,
- const struct drm_private_state_funcs *funcs);
+ struct drm_private_obj *obj);
/**
* drm_atomic_get_existing_crtc_state - get crtc state, if it exists
for_each_if (plane_state)
/**
- * __for_each_private_obj - iterate over all private objects
- * @__state: &struct drm_atomic_state pointer
- * @obj: private object iteration cursor
- * @obj_state: private object state iteration cursor
- * @__i: int iteration cursor, for macro-internal use
- * @__funcs: &struct drm_private_state_funcs iteration cursor
- *
- * This macro iterates over the array containing private object data in atomic
- * state
- */
-#define __for_each_private_obj(__state, obj, obj_state, __i, __funcs) \
- for ((__i) = 0; \
- (__i) < (__state)->num_private_objs && \
- ((obj) = (__state)->private_objs[__i].obj, \
- (__funcs) = (__state)->private_objs[__i].funcs, \
- (obj_state) = (__state)->private_objs[__i].obj_state, \
- 1); \
- (__i)++) \
-
-/**
* for_each_private_obj - iterate over a specify type of private object
* @__state: &struct drm_atomic_state pointer
- * @obj_funcs: &struct drm_private_state_funcs function table to filter
- * private objects
* @obj: private object iteration cursor
* @obj_state: private object state iteration cursor
* @__i: int iteration cursor, for macro-internal use
- * @__funcs: &struct drm_private_state_funcs iteration cursor
*
- * This macro iterates over the private objects state array while filtering the
- * objects based on the vfunc table that is passed as @obj_funcs. New macros
- * can be created by passing in the vfunc table associated with a specific
- * private object.
+ * This macro iterates over all private objects in an atomic update.
*/
-#define for_each_private_obj(__state, obj_funcs, obj, obj_state, __i, __funcs) \
- __for_each_private_obj(__state, obj, obj_state, __i, __funcs) \
- for_each_if (__funcs == obj_funcs)
+#define for_each_private_obj(__state, obj, obj_state, __i) \
+ for ((__i) = 0; \
+ (__i) < (__state)->num_private_objs && \
+ ((obj) = (__state)->private_objs[__i].ptr, \
+ (obj_state) = (__state)->private_objs[__i].state, 1); \
+ (__i)++) \
+ for_each_if (obj)
/**
* drm_atomic_crtc_needs_modeset - compute combined modeset need
#include <drm/drm_modeset_helper.h>
struct drm_atomic_state;
+struct drm_private_obj;
+struct drm_private_state;
int drm_atomic_helper_check_modeset(struct drm_device *dev,
struct drm_atomic_state *state);
int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
u16 *red, u16 *green, u16 *blue,
uint32_t size);
+void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj,
+ struct drm_private_state *state);
/**
* drm_atomic_crtc_for_each_plane - iterate over planes currently attached to CRTC