linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/5] Implement komeda DRM-Plane
@ 2019-01-22 11:05 james qian wang (Arm Technology China)
  2019-01-22 11:05 ` [PATCH v2 1/5] drm: Add drm_atomic_get_old/new_private_obj_state james qian wang (Arm Technology China)
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: james qian wang (Arm Technology China) @ 2019-01-22 11:05 UTC (permalink / raw)
  To: Liviu Dudau, airlied, Brian Starkey, maarten.lankhorst, sean
  Cc: Jonathan Chai (Arm Technology China),
	Julien Yin (Arm Technology China),
	thomas Sun (Arm Technology China),
	Lowry Li (Arm Technology China),
	Ayan Halder, Tiannan Zhu (Arm Technology China),
	Jin Gao (Arm Technology China), Yiqi Kang (Arm Technology China),
	nd, malidp, linux-kernel, dri-devel,
	james qian wang (Arm Technology China)

This is the 3rd patchset for the komeda driver.

This patchset implemented plane/plane_helper functions for DRM-Plane.
per the komeda driver design, A DRM-plane maps to komeda layer input
pipeline, so the plane->atomic_check will build a layer input pipeline
according to the plane_state. and with this build function the plane_state
will be covert to komeda private component states to represent the real
HW configuration.

Beside that also added some basic functions for operating the komeda
private object.

v2:
- Rebase
- Introduce struct komeda_data_flow_cfg
- Update code after applied commit:
  b962a12050a3 ("drm/atomic: integrate modeset lock with private objects")

james qian wang (Arm Technology China) (5):
  drm: Add drm_atomic_get_old/new_private_obj_state
  drm/komeda: Add komeda_pipeline/component_get_state_and_set_user
  drm/komeda: Initialize komeda component as drm private object
  drm/komeda: Add komeda_build_layer_data_flow
  drm/komeda: Add komeda_plane/plane_helper_funcs

 drivers/gpu/drm/arm/display/komeda/Makefile   |   1 +
 .../gpu/drm/arm/display/komeda/komeda_kms.c   |   3 +-
 .../gpu/drm/arm/display/komeda/komeda_kms.h   |   2 +-
 .../drm/arm/display/komeda/komeda_pipeline.h  |  24 ++
 .../display/komeda/komeda_pipeline_state.c    | 406 ++++++++++++++++++
 .../gpu/drm/arm/display/komeda/komeda_plane.c | 128 ++++++
 .../arm/display/komeda/komeda_private_obj.c   | 220 +++++++++-
 drivers/gpu/drm/drm_atomic.c                  |  45 +-
 include/drm/drm_atomic.h                      |   6 +
 9 files changed, 817 insertions(+), 18 deletions(-)
 create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c

-- 
2.17.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2 1/5] drm: Add drm_atomic_get_old/new_private_obj_state
  2019-01-22 11:05 [PATCH v2 0/5] Implement komeda DRM-Plane james qian wang (Arm Technology China)
@ 2019-01-22 11:05 ` james qian wang (Arm Technology China)
  2019-01-22 11:05 ` [PATCH v2 2/5] drm/komeda: Add komeda_pipeline/component_get_state_and_set_user james qian wang (Arm Technology China)
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: james qian wang (Arm Technology China) @ 2019-01-22 11:05 UTC (permalink / raw)
  To: Liviu Dudau, airlied, Brian Starkey, maarten.lankhorst, sean
  Cc: Jonathan Chai (Arm Technology China),
	Julien Yin (Arm Technology China),
	thomas Sun (Arm Technology China),
	Lowry Li (Arm Technology China),
	Ayan Halder, Tiannan Zhu (Arm Technology China),
	Jin Gao (Arm Technology China), Yiqi Kang (Arm Technology China),
	nd, malidp, linux-kernel, dri-devel,
	james qian wang (Arm Technology China)

From: "james qian wang (Arm Technology China)" <james.qian.wang@arm.com>

This pair of functions return the old/new private object state for the
given private_obj, or NULL if the private_obj is not part of the global
atomic state.

Reviewed-by: Alexandru Gheorghe <alexandru-cosmin.gheorghe@arm.com>
Signed-off-by: James Qian Wang (Arm Technology China) <james.qian.wang@arm.com>
---
 drivers/gpu/drm/drm_atomic.c | 45 +++++++++++++++++++++++++++++++++++-
 include/drm/drm_atomic.h     |  6 +++++
 2 files changed, 50 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 008224f376fe..900f9f9dedad 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -775,6 +775,50 @@ drm_atomic_get_private_obj_state(struct drm_atomic_state *state,
 }
 EXPORT_SYMBOL(drm_atomic_get_private_obj_state);
 
+/**
+ * drm_atomic_get_old_private_obj_state
+ * @state: global atomic state object
+ * @obj: private_obj to grab
+ *
+ * This function returns the old private object state for the given private_obj,
+ * or NULL if the private_obj is not part of the global atomic state.
+ */
+struct drm_private_state *
+drm_atomic_get_old_private_obj_state(struct drm_atomic_state *state,
+				     struct drm_private_obj *obj)
+{
+	int i;
+
+	for (i = 0; i < state->num_private_objs; i++)
+		if (obj == state->private_objs[i].ptr)
+			return state->private_objs[i].old_state;
+
+	return NULL;
+}
+EXPORT_SYMBOL(drm_atomic_get_old_private_obj_state);
+
+/**
+ * drm_atomic_get_new_private_obj_state
+ * @state: global atomic state object
+ * @obj: private_obj to grab
+ *
+ * This function returns the new private object state for the given private_obj,
+ * or NULL if the private_obj is not part of the global atomic state.
+ */
+struct drm_private_state *
+drm_atomic_get_new_private_obj_state(struct drm_atomic_state *state,
+				     struct drm_private_obj *obj)
+{
+	int i;
+
+	for (i = 0; i < state->num_private_objs; i++)
+		if (obj == state->private_objs[i].ptr)
+			return state->private_objs[i].new_state;
+
+	return NULL;
+}
+EXPORT_SYMBOL(drm_atomic_get_new_private_obj_state);
+
 /**
  * drm_atomic_get_connector_state - get connector state
  * @state: global atomic state object
@@ -1214,4 +1258,3 @@ int drm_atomic_debugfs_init(struct drm_minor *minor)
 			minor->debugfs_root, minor);
 }
 #endif
-
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index cac4a1b6b0e8..a4489b2fe740 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -443,6 +443,12 @@ 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,
 				 struct drm_private_obj *obj);
+struct drm_private_state *
+drm_atomic_get_old_private_obj_state(struct drm_atomic_state *state,
+				     struct drm_private_obj *obj);
+struct drm_private_state *
+drm_atomic_get_new_private_obj_state(struct drm_atomic_state *state,
+				     struct drm_private_obj *obj);
 
 /**
  * drm_atomic_get_existing_crtc_state - get crtc state, if it exists
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 2/5] drm/komeda: Add komeda_pipeline/component_get_state_and_set_user
  2019-01-22 11:05 [PATCH v2 0/5] Implement komeda DRM-Plane james qian wang (Arm Technology China)
  2019-01-22 11:05 ` [PATCH v2 1/5] drm: Add drm_atomic_get_old/new_private_obj_state james qian wang (Arm Technology China)
@ 2019-01-22 11:05 ` james qian wang (Arm Technology China)
  2019-01-22 11:06 ` [PATCH v2 3/5] drm/komeda: Initialize komeda component as drm private object james qian wang (Arm Technology China)
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: james qian wang (Arm Technology China) @ 2019-01-22 11:05 UTC (permalink / raw)
  To: Liviu Dudau, airlied, Brian Starkey, maarten.lankhorst, sean
  Cc: Jonathan Chai (Arm Technology China),
	Julien Yin (Arm Technology China),
	thomas Sun (Arm Technology China),
	Lowry Li (Arm Technology China),
	Ayan Halder, Tiannan Zhu (Arm Technology China),
	Jin Gao (Arm Technology China), Yiqi Kang (Arm Technology China),
	nd, malidp, linux-kernel, dri-devel,
	james qian wang (Arm Technology China)

From: "james qian wang (Arm Technology China)" <james.qian.wang@arm.com>

get_state_and_set_user packed get_state and set_user into one function,
which get pipeline/component state for a specific pipeline/component, if
success set the user to it.

v2:
- Rebase.
- Applied commit:
  b962a12050a3 ("drm/atomic: integrate modeset lock with private objects")
  And delete our private modeset lock for pipeline.

Signed-off-by: James Qian Wang (Arm Technology China) <james.qian.wang@arm.com>
---
 drivers/gpu/drm/arm/display/komeda/Makefile   |   1 +
 .../display/komeda/komeda_pipeline_state.c    | 142 ++++++++++++++++++
 2 files changed, 143 insertions(+)
 create mode 100644 drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c

diff --git a/drivers/gpu/drm/arm/display/komeda/Makefile b/drivers/gpu/drm/arm/display/komeda/Makefile
index d593125236ae..62bd1bff66a3 100644
--- a/drivers/gpu/drm/arm/display/komeda/Makefile
+++ b/drivers/gpu/drm/arm/display/komeda/Makefile
@@ -9,6 +9,7 @@ komeda-y := \
 	komeda_dev.o \
 	komeda_format_caps.o \
 	komeda_pipeline.o \
+	komeda_pipeline_state.o \
 	komeda_framebuffer.o \
 	komeda_kms.o \
 	komeda_crtc.o \
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
new file mode 100644
index 000000000000..7ebab4fae567
--- /dev/null
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
+ * Author: James.Qian.Wang <james.qian.wang@arm.com>
+ *
+ */
+#include <linux/clk.h>
+#include "komeda_dev.h"
+#include "komeda_kms.h"
+#include "komeda_pipeline.h"
+
+static inline bool is_switching_user(void *old, void *new)
+{
+	if (!old || !new)
+		return false;
+
+	return old != new;
+}
+
+struct komeda_pipeline_state *
+komeda_pipeline_get_state(struct komeda_pipeline *pipe,
+			  struct drm_atomic_state *state)
+{
+	struct drm_private_state *priv_st;
+
+	priv_st = drm_atomic_get_private_obj_state(state, &pipe->obj);
+	if (IS_ERR(priv_st))
+		return ERR_CAST(priv_st);
+
+	return priv_to_pipe_st(priv_st);
+}
+
+/* Assign pipeline for crtc */
+struct komeda_pipeline_state *
+komeda_pipeline_get_state_and_set_crtc(struct komeda_pipeline *pipe,
+				       struct drm_atomic_state *state,
+				       struct drm_crtc *crtc)
+{
+	struct komeda_pipeline_state *st;
+
+	st = komeda_pipeline_get_state(pipe, state);
+	if (IS_ERR(st))
+		return st;
+
+	if (is_switching_user(crtc, st->crtc)) {
+		DRM_DEBUG_ATOMIC("CRTC%d required pipeline%d is busy.\n",
+				 drm_crtc_index(crtc), pipe->id);
+		return ERR_PTR(-EBUSY);
+	}
+
+	/* pipeline only can be disabled when the it is free or unused */
+	if (!crtc && st->active_comps) {
+		DRM_DEBUG_ATOMIC("Disabling a busy pipeline:%d.\n", pipe->id);
+		return ERR_PTR(-EBUSY);
+	}
+
+	st->crtc = crtc;
+
+	if (crtc) {
+		struct komeda_crtc_state *kcrtc_st;
+
+		kcrtc_st = to_kcrtc_st(drm_atomic_get_new_crtc_state(state,
+								     crtc));
+
+		kcrtc_st->active_pipes |= BIT(pipe->id);
+		kcrtc_st->affected_pipes |= BIT(pipe->id);
+	}
+	return st;
+}
+
+static struct komeda_component_state *
+komeda_component_get_state(struct komeda_component *c,
+			   struct drm_atomic_state *state)
+{
+	struct drm_private_state *priv_st;
+
+	WARN_ON(!drm_modeset_is_locked(&c->pipeline->obj.lock));
+
+	priv_st = drm_atomic_get_private_obj_state(state, &c->obj);
+	if (IS_ERR(priv_st))
+		return ERR_CAST(priv_st);
+
+	return priv_to_comp_st(priv_st);
+}
+
+/**
+ * komeda_component_get_state_and_set_user()
+ *
+ * @c: component to get state and set user
+ * @state: global atomic state
+ * @user: direct user, the binding user
+ * @crtc: the CRTC user, the big boss :)
+ *
+ * This function accepts two users:
+ * -   The direct user: can be plane/crtc/wb_connector depends on component
+ * -   The big boss (CRTC)
+ * CRTC is the big boss (the final user), because all component resources
+ * eventually will be assigned to CRTC, like the layer will be binding to
+ * kms_plane, but kms plane will be binding to a CRTC eventually.
+ *
+ * The big boss (CRTC) is for pipeline assignment, since &komeda_component isn't
+ * independent and can be assigned to CRTC freely, but belongs to a specific
+ * pipeline, only pipeline can be shared between crtc, and pipeline as a whole
+ * (include all the internal components) assigned to a specific CRTC.
+ *
+ * So when set a user to komeda_component, need first to check the status of
+ * component->pipeline to see if the pipeline is available on this specific
+ * CRTC. if the pipeline is busy (assigned to another CRTC), even the required
+ * component is free, the component still cannot be assigned to the direct user.
+ */
+struct komeda_component_state *
+komeda_component_get_state_and_set_user(struct komeda_component *c,
+					struct drm_atomic_state *state,
+					void *user,
+					struct drm_crtc *crtc)
+{
+	struct komeda_pipeline_state *pipe_st;
+	struct komeda_component_state *st;
+
+	/* First check if the pipeline is available */
+	pipe_st = komeda_pipeline_get_state_and_set_crtc(c->pipeline,
+							 state, crtc);
+	if (IS_ERR(pipe_st))
+		return ERR_CAST(pipe_st);
+
+	st = komeda_component_get_state(c, state);
+	if (IS_ERR(st))
+		return st;
+
+	/* check if the component has been occupied */
+	if (is_switching_user(user, st->binding_user)) {
+		DRM_DEBUG_ATOMIC("required %s is busy.\n", c->name);
+		return ERR_PTR(-EBUSY);
+	}
+
+	st->binding_user = user;
+	/* mark the component as active if user is valid */
+	if (st->binding_user)
+		pipe_st->active_comps |= BIT(c->id);
+
+	return st;
+}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 3/5] drm/komeda: Initialize komeda component as drm private object
  2019-01-22 11:05 [PATCH v2 0/5] Implement komeda DRM-Plane james qian wang (Arm Technology China)
  2019-01-22 11:05 ` [PATCH v2 1/5] drm: Add drm_atomic_get_old/new_private_obj_state james qian wang (Arm Technology China)
  2019-01-22 11:05 ` [PATCH v2 2/5] drm/komeda: Add komeda_pipeline/component_get_state_and_set_user james qian wang (Arm Technology China)
@ 2019-01-22 11:06 ` james qian wang (Arm Technology China)
  2019-01-22 11:06 ` [PATCH v2 4/5] drm/komeda: Add komeda_build_layer_data_flow james qian wang (Arm Technology China)
  2019-01-22 11:06 ` [PATCH v2 5/5] drm/komeda: Add komeda_plane/plane_helper_funcs james qian wang (Arm Technology China)
  4 siblings, 0 replies; 6+ messages in thread
From: james qian wang (Arm Technology China) @ 2019-01-22 11:06 UTC (permalink / raw)
  To: Liviu Dudau, airlied, Brian Starkey, maarten.lankhorst, sean
  Cc: Jonathan Chai (Arm Technology China),
	Julien Yin (Arm Technology China),
	thomas Sun (Arm Technology China),
	Lowry Li (Arm Technology China),
	Ayan Halder, Tiannan Zhu (Arm Technology China),
	Jin Gao (Arm Technology China), Yiqi Kang (Arm Technology China),
	nd, malidp, linux-kernel, dri-devel,
	james qian wang (Arm Technology China)

From: "james qian wang (Arm Technology China)" <james.qian.wang@arm.com>

Initialize koemda_layer, komeda_compiz, komeda_improc and
komeda_timing_ctrlr as drm private object, then track komeda private
component state by drm_atomic_state.

v2:
- Update code after Applied commit:
  b962a12050a3 ("drm/atomic: integrate modeset lock with private objects")

Signed-off-by: James Qian Wang (Arm Technology China) <james.qian.wang@arm.com>
---
 .../gpu/drm/arm/display/komeda/komeda_kms.c   |   3 +-
 .../gpu/drm/arm/display/komeda/komeda_kms.h   |   2 +-
 .../arm/display/komeda/komeda_private_obj.c   | 220 ++++++++++++++++--
 3 files changed, 208 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
index 4adc6a3104c9..7d7fb5013464 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
@@ -179,6 +179,7 @@ struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev)
 	drm_irq_uninstall(drm);
 cleanup_mode_config:
 	drm_mode_config_cleanup(drm);
+	komeda_kms_cleanup_private_objs(kms);
 free_kms:
 	kfree(kms);
 	return ERR_PTR(err);
@@ -193,7 +194,7 @@ void komeda_kms_detach(struct komeda_kms_dev *kms)
 	drm_dev_unregister(drm);
 	drm_irq_uninstall(drm);
 	component_unbind_all(mdev->dev, drm);
-	komeda_kms_cleanup_private_objs(mdev);
+	komeda_kms_cleanup_private_objs(kms);
 	drm_mode_config_cleanup(drm);
 	drm->dev_private = NULL;
 	drm_dev_put(drm);
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.h b/drivers/gpu/drm/arm/display/komeda/komeda_kms.h
index 0faeeac2765a..06394716367b 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.h
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.h
@@ -107,7 +107,7 @@ int komeda_kms_add_crtcs(struct komeda_kms_dev *kms, struct komeda_dev *mdev);
 int komeda_kms_add_planes(struct komeda_kms_dev *kms, struct komeda_dev *mdev);
 int komeda_kms_add_private_objs(struct komeda_kms_dev *kms,
 				struct komeda_dev *mdev);
-void komeda_kms_cleanup_private_objs(struct komeda_dev *mdev);
+void komeda_kms_cleanup_private_objs(struct komeda_kms_dev *kms);
 
 void komeda_crtc_handle_event(struct komeda_crtc   *kcrtc,
 			      struct komeda_events *evts);
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_private_obj.c b/drivers/gpu/drm/arm/display/komeda/komeda_private_obj.c
index f1c9e3fefa86..a54878cbd6e4 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_private_obj.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_private_obj.c
@@ -7,6 +7,188 @@
 #include "komeda_dev.h"
 #include "komeda_kms.h"
 
+static void
+komeda_component_state_reset(struct komeda_component_state *st)
+{
+	st->binding_user = NULL;
+	st->affected_inputs = st->active_inputs;
+	st->active_inputs = 0;
+	st->changed_active_inputs = 0;
+}
+
+static struct drm_private_state *
+komeda_layer_atomic_duplicate_state(struct drm_private_obj *obj)
+{
+	struct komeda_layer_state *st;
+
+	st = kmemdup(obj->state, sizeof(*st), GFP_KERNEL);
+	if (!st)
+		return NULL;
+
+	komeda_component_state_reset(&st->base);
+	__drm_atomic_helper_private_obj_duplicate_state(obj, &st->base.obj);
+
+	return &st->base.obj;
+}
+
+static void
+komeda_layer_atomic_destroy_state(struct drm_private_obj *obj,
+				  struct drm_private_state *state)
+{
+	struct komeda_layer_state *st = to_layer_st(priv_to_comp_st(state));
+
+	kfree(st);
+}
+
+static const struct drm_private_state_funcs komeda_layer_obj_funcs = {
+	.atomic_duplicate_state	= komeda_layer_atomic_duplicate_state,
+	.atomic_destroy_state	= komeda_layer_atomic_destroy_state,
+};
+
+static int komeda_layer_obj_add(struct komeda_kms_dev *kms,
+				struct komeda_layer *layer)
+{
+	struct komeda_layer_state *st;
+
+	st = kzalloc(sizeof(*st), GFP_KERNEL);
+	if (!st)
+		return -ENOMEM;
+
+	st->base.component = &layer->base;
+	drm_atomic_private_obj_init(&kms->base, &layer->base.obj, &st->base.obj,
+				    &komeda_layer_obj_funcs);
+	return 0;
+}
+
+static struct drm_private_state *
+komeda_compiz_atomic_duplicate_state(struct drm_private_obj *obj)
+{
+	struct komeda_compiz_state *st;
+
+	st = kmemdup(obj->state, sizeof(*st), GFP_KERNEL);
+	if (!st)
+		return NULL;
+
+	komeda_component_state_reset(&st->base);
+	__drm_atomic_helper_private_obj_duplicate_state(obj, &st->base.obj);
+
+	return &st->base.obj;
+}
+
+static void
+komeda_compiz_atomic_destroy_state(struct drm_private_obj *obj,
+				   struct drm_private_state *state)
+{
+	kfree(to_compiz_st(priv_to_comp_st(state)));
+}
+
+static const struct drm_private_state_funcs komeda_compiz_obj_funcs = {
+	.atomic_duplicate_state	= komeda_compiz_atomic_duplicate_state,
+	.atomic_destroy_state	= komeda_compiz_atomic_destroy_state,
+};
+
+static int komeda_compiz_obj_add(struct komeda_kms_dev *kms,
+				 struct komeda_compiz *compiz)
+{
+	struct komeda_compiz_state *st;
+
+	st = kzalloc(sizeof(*st), GFP_KERNEL);
+	if (!st)
+		return -ENOMEM;
+
+	st->base.component = &compiz->base;
+	drm_atomic_private_obj_init(&kms->base, &compiz->base.obj, &st->base.obj,
+				    &komeda_compiz_obj_funcs);
+
+	return 0;
+}
+
+static struct drm_private_state *
+komeda_improc_atomic_duplicate_state(struct drm_private_obj *obj)
+{
+	struct komeda_improc_state *st;
+
+	st = kmemdup(obj->state, sizeof(*st), GFP_KERNEL);
+	if (!st)
+		return NULL;
+
+	komeda_component_state_reset(&st->base);
+	__drm_atomic_helper_private_obj_duplicate_state(obj, &st->base.obj);
+
+	return &st->base.obj;
+}
+
+static void
+komeda_improc_atomic_destroy_state(struct drm_private_obj *obj,
+				   struct drm_private_state *state)
+{
+	kfree(to_improc_st(priv_to_comp_st(state)));
+}
+
+static const struct drm_private_state_funcs komeda_improc_obj_funcs = {
+	.atomic_duplicate_state	= komeda_improc_atomic_duplicate_state,
+	.atomic_destroy_state	= komeda_improc_atomic_destroy_state,
+};
+
+static int komeda_improc_obj_add(struct komeda_kms_dev *kms,
+				 struct komeda_improc *improc)
+{
+	struct komeda_improc_state *st;
+
+	st = kzalloc(sizeof(*st), GFP_KERNEL);
+	if (!st)
+		return -ENOMEM;
+
+	st->base.component = &improc->base;
+	drm_atomic_private_obj_init(&kms->base, &improc->base.obj, &st->base.obj,
+				    &komeda_improc_obj_funcs);
+
+	return 0;
+}
+
+static struct drm_private_state *
+komeda_timing_ctrlr_atomic_duplicate_state(struct drm_private_obj *obj)
+{
+	struct komeda_timing_ctrlr_state *st;
+
+	st = kmemdup(obj->state, sizeof(*st), GFP_KERNEL);
+	if (!st)
+		return NULL;
+
+	komeda_component_state_reset(&st->base);
+	__drm_atomic_helper_private_obj_duplicate_state(obj, &st->base.obj);
+
+	return &st->base.obj;
+}
+
+static void
+komeda_timing_ctrlr_atomic_destroy_state(struct drm_private_obj *obj,
+					 struct drm_private_state *state)
+{
+	kfree(to_ctrlr_st(priv_to_comp_st(state)));
+}
+
+static const struct drm_private_state_funcs komeda_timing_ctrlr_obj_funcs = {
+	.atomic_duplicate_state	= komeda_timing_ctrlr_atomic_duplicate_state,
+	.atomic_destroy_state	= komeda_timing_ctrlr_atomic_destroy_state,
+};
+
+static int komeda_timing_ctrlr_obj_add(struct komeda_kms_dev *kms,
+				       struct komeda_timing_ctrlr *ctrlr)
+{
+	struct komeda_compiz_state *st;
+
+	st = kzalloc(sizeof(*st), GFP_KERNEL);
+	if (!st)
+		return -ENOMEM;
+
+	st->base.component = &ctrlr->base;
+	drm_atomic_private_obj_init(&kms->base, &ctrlr->base.obj, &st->base.obj,
+				    &komeda_timing_ctrlr_obj_funcs);
+
+	return 0;
+}
+
 static struct drm_private_state *
 komeda_pipeline_atomic_duplicate_state(struct drm_private_obj *obj)
 {
@@ -55,7 +237,7 @@ int komeda_kms_add_private_objs(struct komeda_kms_dev *kms,
 				struct komeda_dev *mdev)
 {
 	struct komeda_pipeline *pipe;
-	int i, err;
+	int i, j, err;
 
 	for (i = 0; i < mdev->n_pipelines; i++) {
 		pipe = mdev->pipelines[i];
@@ -64,25 +246,33 @@ int komeda_kms_add_private_objs(struct komeda_kms_dev *kms,
 		if (err)
 			return err;
 
-		/* Add component */
+		for (j = 0; j < pipe->n_layers; j++) {
+			err = komeda_layer_obj_add(kms, pipe->layers[j]);
+			if (err)
+				return err;
+		}
+
+		err = komeda_compiz_obj_add(kms, pipe->compiz);
+		if (err)
+			return err;
+
+		err = komeda_improc_obj_add(kms, pipe->improc);
+		if (err)
+			return err;
+
+		err = komeda_timing_ctrlr_obj_add(kms, pipe->ctrlr);
+		if (err)
+			return err;
 	}
 
 	return 0;
 }
 
-void komeda_kms_cleanup_private_objs(struct komeda_dev *mdev)
+void komeda_kms_cleanup_private_objs(struct komeda_kms_dev *kms)
 {
-	struct komeda_pipeline *pipe;
-	struct komeda_component *c;
-	int i, id;
+	struct drm_mode_config *config = &kms->base.mode_config;
+	struct drm_private_obj *obj, *next;
 
-	for (i = 0; i < mdev->n_pipelines; i++) {
-		pipe = mdev->pipelines[i];
-		dp_for_each_set_bit(id, pipe->avail_comps) {
-			c = komeda_pipeline_get_component(pipe, id);
-
-			drm_atomic_private_obj_fini(&c->obj);
-		}
-		drm_atomic_private_obj_fini(&pipe->obj);
-	}
+	list_for_each_entry_safe(obj, next, &config->privobj_list, head)
+		drm_atomic_private_obj_fini(obj);
 }
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 4/5] drm/komeda: Add komeda_build_layer_data_flow
  2019-01-22 11:05 [PATCH v2 0/5] Implement komeda DRM-Plane james qian wang (Arm Technology China)
                   ` (2 preceding siblings ...)
  2019-01-22 11:06 ` [PATCH v2 3/5] drm/komeda: Initialize komeda component as drm private object james qian wang (Arm Technology China)
@ 2019-01-22 11:06 ` james qian wang (Arm Technology China)
  2019-01-22 11:06 ` [PATCH v2 5/5] drm/komeda: Add komeda_plane/plane_helper_funcs james qian wang (Arm Technology China)
  4 siblings, 0 replies; 6+ messages in thread
From: james qian wang (Arm Technology China) @ 2019-01-22 11:06 UTC (permalink / raw)
  To: Liviu Dudau, airlied, Brian Starkey, maarten.lankhorst, sean
  Cc: Jonathan Chai (Arm Technology China),
	Julien Yin (Arm Technology China),
	thomas Sun (Arm Technology China),
	Lowry Li (Arm Technology China),
	Ayan Halder, Tiannan Zhu (Arm Technology China),
	Jin Gao (Arm Technology China), Yiqi Kang (Arm Technology China),
	nd, malidp, linux-kernel, dri-devel,
	james qian wang (Arm Technology China)

From: "james qian wang (Arm Technology China)" <james.qian.wang@arm.com>

build_layer_data_flow builds a input pipeline according to plane_state.
and in this initial stage only added this simplest pipeline usage:
  Layer -> compiz
The scaler and layer_split will be added in the future.

v2:
- Rebase.
- Introduce struct komeda_data_flow_cfg
- Add a function komeda_component_validate_private to replace the MACRO
  component_validate_private

Signed-off-by: James Qian Wang (Arm Technology China) <james.qian.wang@arm.com>
---
 .../drm/arm/display/komeda/komeda_pipeline.h  |  24 ++
 .../display/komeda/komeda_pipeline_state.c    | 266 +++++++++++++++++-
 2 files changed, 289 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
index c30a790d0712..16d7ae891e81 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
@@ -278,6 +278,22 @@ struct komeda_timing_ctrlr_state {
 	struct komeda_component_state base;
 };
 
+/* Why define A separated structure but not use plane_state directly ?
+ * 1. Komeda supports layer_split which means a plane_state can be split and
+ *    handled by two layers, one layer only handle half of plane image.
+ * 2. Fix up the user properties according to HW's capabilities, like user
+ *    set rotation to R180, but HW only supports REFLECT_X+Y. the rot here is
+ *    after drm_rotation_simplify()
+ */
+struct komeda_data_flow_cfg {
+	struct komeda_component_output input;
+	u16 in_x, in_y, in_w, in_h;
+	u32 out_x, out_y, out_w, out_h;
+	u32 rot;
+	int blending_zorder;
+	u8 pixel_blend_mode, layer_alpha;
+};
+
 /** struct komeda_pipeline_funcs */
 struct komeda_pipeline_funcs {
 	/* dump_register: Optional, dump registers to seq_file */
@@ -382,4 +398,12 @@ komeda_component_add(struct komeda_pipeline *pipe,
 void komeda_component_destroy(struct komeda_dev *mdev,
 			      struct komeda_component *c);
 
+struct komeda_plane_state;
+struct komeda_crtc_state;
+
+int komeda_build_layer_data_flow(struct komeda_layer *layer,
+				 struct komeda_plane_state *kplane_st,
+				 struct komeda_crtc_state *kcrtc_st,
+				 struct komeda_data_flow_cfg *dflow);
+
 #endif /* _KOMEDA_PIPELINE_H_*/
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
index 7ebab4fae567..74d25e542103 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
@@ -8,6 +8,7 @@
 #include "komeda_dev.h"
 #include "komeda_kms.h"
 #include "komeda_pipeline.h"
+#include "komeda_framebuffer.h"
 
 static inline bool is_switching_user(void *old, void *new)
 {
@@ -83,6 +84,18 @@ komeda_component_get_state(struct komeda_component *c,
 	return priv_to_comp_st(priv_st);
 }
 
+static struct komeda_component_state *
+komeda_component_get_old_state(struct komeda_component *c,
+			       struct drm_atomic_state *state)
+{
+	struct drm_private_state *priv_st;
+
+	priv_st = drm_atomic_get_old_private_obj_state(state, &c->obj);
+	if (priv_st)
+		return priv_to_comp_st(priv_st);
+	return NULL;
+}
+
 /**
  * komeda_component_get_state_and_set_user()
  *
@@ -108,7 +121,7 @@ komeda_component_get_state(struct komeda_component *c,
  * CRTC. if the pipeline is busy (assigned to another CRTC), even the required
  * component is free, the component still cannot be assigned to the direct user.
  */
-struct komeda_component_state *
+static struct komeda_component_state *
 komeda_component_get_state_and_set_user(struct komeda_component *c,
 					struct drm_atomic_state *state,
 					void *user,
@@ -140,3 +153,254 @@ komeda_component_get_state_and_set_user(struct komeda_component *c,
 
 	return st;
 }
+
+static void
+komeda_component_add_input(struct komeda_component_state *state,
+			   struct komeda_component_output *input,
+			   int idx)
+{
+	struct komeda_component *c = state->component;
+
+	WARN_ON((idx < 0 || idx >= c->max_active_inputs));
+
+	/* since the inputs[i] is only valid when it is active. So if a input[i]
+	 * is a newly enabled input which switches from disable to enable, then
+	 * the old inputs[i] is undefined (NOT zeroed), we can not rely on
+	 * memcmp, but directly mark it changed
+	 */
+	if (!has_bit(idx, state->affected_inputs) ||
+	    memcmp(&state->inputs[idx], input, sizeof(*input))) {
+		memcpy(&state->inputs[idx], input, sizeof(*input));
+		state->changed_active_inputs |= BIT(idx);
+	}
+	state->active_inputs |= BIT(idx);
+	state->affected_inputs |= BIT(idx);
+}
+
+static int
+komeda_component_check_input(struct komeda_component_state *state,
+			     struct komeda_component_output *input,
+			     int idx)
+{
+	struct komeda_component *c = state->component;
+
+	if ((idx < 0) || (idx >= c->max_active_inputs)) {
+		DRM_DEBUG_ATOMIC("%s invalid input id: %d.\n", c->name, idx);
+		return -EINVAL;
+	}
+
+	if (has_bit(idx, state->active_inputs)) {
+		DRM_DEBUG_ATOMIC("%s required input_id: %d has been occupied already.\n",
+				 c->name, idx);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void
+komeda_component_set_output(struct komeda_component_output *output,
+			    struct komeda_component *comp,
+			    u8 output_port)
+{
+	output->component = comp;
+	output->output_port = output_port;
+}
+
+static int
+komeda_component_validate_private(struct komeda_component *c,
+				  struct komeda_component_state *st)
+{
+	int err;
+
+	if (!c->funcs->validate)
+		return 0;
+
+	err = c->funcs->validate(c, st);
+	if (err)
+		DRM_DEBUG_ATOMIC("%s validate private failed.\n", c->name);
+
+	return err;
+}
+
+static int
+komeda_layer_check_cfg(struct komeda_layer *layer,
+		       struct komeda_plane_state *kplane_st,
+		       struct komeda_data_flow_cfg *dflow)
+{
+	if (!in_range(&layer->hsize_in, dflow->in_w)) {
+		DRM_DEBUG_ATOMIC("src_w: %d is out of range.\n", dflow->in_w);
+		return -EINVAL;
+	}
+
+	if (!in_range(&layer->vsize_in, dflow->in_h)) {
+		DRM_DEBUG_ATOMIC("src_h: %d is out of range.\n", dflow->in_h);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+komeda_layer_validate(struct komeda_layer *layer,
+		      struct komeda_plane_state *kplane_st,
+		      struct komeda_data_flow_cfg *dflow)
+{
+	struct drm_plane_state *plane_st = &kplane_st->base;
+	struct drm_framebuffer *fb = plane_st->fb;
+	struct komeda_fb *kfb = to_kfb(fb);
+	struct komeda_component_state *c_st;
+	struct komeda_layer_state *st;
+	int i, err;
+
+	err = komeda_layer_check_cfg(layer, kplane_st, dflow);
+	if (err)
+		return err;
+
+	c_st = komeda_component_get_state_and_set_user(&layer->base,
+			plane_st->state, plane_st->plane, plane_st->crtc);
+	if (IS_ERR(c_st))
+		return PTR_ERR(c_st);
+
+	st = to_layer_st(c_st);
+
+	st->rot = dflow->rot;
+	st->hsize = kfb->aligned_w;
+	st->vsize = kfb->aligned_h;
+
+	for (i = 0; i < fb->format->num_planes; i++)
+		st->addr[i] = komeda_fb_get_pixel_addr(kfb, dflow->in_x,
+						       dflow->in_y, i);
+
+	err = komeda_component_validate_private(&layer->base, c_st);
+	if (err)
+		return err;
+
+	/* update the data flow for the next stage */
+	komeda_component_set_output(&dflow->input, &layer->base, 0);
+
+	return 0;
+}
+
+static void pipeline_composition_size(struct komeda_crtc_state *kcrtc_st,
+				      u16 *hsize, u16 *vsize)
+{
+	struct drm_display_mode *m = &kcrtc_st->base.adjusted_mode;
+
+	if (hsize)
+		*hsize = m->hdisplay;
+	if (vsize)
+		*vsize = m->vdisplay;
+}
+
+static int
+komeda_compiz_set_input(struct komeda_compiz *compiz,
+			struct komeda_crtc_state *kcrtc_st,
+			struct komeda_data_flow_cfg *dflow)
+{
+	struct drm_atomic_state *drm_st = kcrtc_st->base.state;
+	struct komeda_component_state *c_st, *old_st;
+	struct komeda_compiz_input_cfg *cin;
+	u16 compiz_w, compiz_h;
+	int idx = dflow->blending_zorder;
+
+	pipeline_composition_size(kcrtc_st, &compiz_w, &compiz_h);
+	/* check display rect */
+	if ((dflow->out_x + dflow->out_w > compiz_w) ||
+	    (dflow->out_y + dflow->out_h > compiz_h) ||
+	     dflow->out_w == 0 || dflow->out_h == 0) {
+		DRM_DEBUG_ATOMIC("invalid disp rect [x=%d, y=%d, w=%d, h=%d]\n",
+				 dflow->out_x, dflow->out_y,
+				 dflow->out_w, dflow->out_h);
+		return -EINVAL;
+	}
+
+	c_st = komeda_component_get_state_and_set_user(&compiz->base, drm_st,
+			kcrtc_st->base.crtc, kcrtc_st->base.crtc);
+	if (IS_ERR(c_st))
+		return PTR_ERR(c_st);
+
+	if (komeda_component_check_input(c_st, &dflow->input, idx))
+		return -EINVAL;
+
+	cin = &(to_compiz_st(c_st)->cins[idx]);
+
+	cin->hsize   = dflow->out_w;
+	cin->vsize   = dflow->out_h;
+	cin->hoffset = dflow->out_x;
+	cin->voffset = dflow->out_y;
+	cin->pixel_blend_mode = dflow->pixel_blend_mode;
+	cin->layer_alpha = dflow->layer_alpha;
+
+	old_st = komeda_component_get_old_state(&compiz->base, drm_st);
+	WARN_ON(!old_st);
+
+	/* compare with old to check if this input has been changed */
+	if (memcmp(&(to_compiz_st(old_st)->cins[idx]), cin, sizeof(*cin)))
+		c_st->changed_active_inputs |= BIT(idx);
+
+	komeda_component_add_input(c_st, &dflow->input, idx);
+
+	return 0;
+}
+
+int
+komeda_compiz_validate(struct komeda_compiz *compiz,
+		       struct komeda_crtc_state *state,
+		       struct komeda_data_flow_cfg *dflow)
+{
+	struct komeda_component_state *c_st;
+	struct komeda_compiz_state *st;
+
+	c_st = komeda_component_get_state_and_set_user(&compiz->base,
+			state->base.state, state->base.crtc, state->base.crtc);
+	if (IS_ERR(c_st))
+		return PTR_ERR(c_st);
+
+	st = to_compiz_st(c_st);
+
+	pipeline_composition_size(state, &st->hsize, &st->vsize);
+
+	komeda_component_set_output(&dflow->input, &compiz->base, 0);
+
+	/* compiz output dflow will be fed to the next pipeline stage, prepare
+	 * the data flow configuration for the next stage
+	 */
+	if (dflow) {
+		dflow->in_w = st->hsize;
+		dflow->in_h = st->vsize;
+		dflow->out_w = dflow->in_w;
+		dflow->out_h = dflow->in_h;
+		/* the output data of compiz doesn't have alpha, it only can be
+		 * used as bottom layer when blend it with master layers
+		 */
+		dflow->pixel_blend_mode = DRM_MODE_BLEND_PIXEL_NONE;
+		dflow->layer_alpha = 0xFF;
+		dflow->blending_zorder = 0;
+	}
+
+	return 0;
+}
+
+int komeda_build_layer_data_flow(struct komeda_layer *layer,
+				 struct komeda_plane_state *kplane_st,
+				 struct komeda_crtc_state *kcrtc_st,
+				 struct komeda_data_flow_cfg *dflow)
+{
+	struct drm_plane *plane = kplane_st->base.plane;
+	struct komeda_pipeline *pipe = layer->base.pipeline;
+	int err;
+
+	DRM_DEBUG_ATOMIC("%s handling [PLANE:%d:%s]: src[x/y:%d/%d, w/h:%d/%d] disp[x/y:%d/%d, w/h:%d/%d]",
+			 layer->base.name, plane->base.id, plane->name,
+			 dflow->in_x, dflow->in_y, dflow->in_w, dflow->in_h,
+			 dflow->out_x, dflow->out_y, dflow->out_w, dflow->out_h);
+
+	err = komeda_layer_validate(layer, kplane_st, dflow);
+	if (err)
+		return err;
+
+	err = komeda_compiz_set_input(pipe->compiz, kcrtc_st, dflow);
+
+	return err;
+}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 5/5] drm/komeda: Add komeda_plane/plane_helper_funcs
  2019-01-22 11:05 [PATCH v2 0/5] Implement komeda DRM-Plane james qian wang (Arm Technology China)
                   ` (3 preceding siblings ...)
  2019-01-22 11:06 ` [PATCH v2 4/5] drm/komeda: Add komeda_build_layer_data_flow james qian wang (Arm Technology China)
@ 2019-01-22 11:06 ` james qian wang (Arm Technology China)
  4 siblings, 0 replies; 6+ messages in thread
From: james qian wang (Arm Technology China) @ 2019-01-22 11:06 UTC (permalink / raw)
  To: Liviu Dudau, airlied, Brian Starkey, maarten.lankhorst, sean
  Cc: Jonathan Chai (Arm Technology China),
	Julien Yin (Arm Technology China),
	thomas Sun (Arm Technology China),
	Lowry Li (Arm Technology China),
	Ayan Halder, Tiannan Zhu (Arm Technology China),
	Jin Gao (Arm Technology China), Yiqi Kang (Arm Technology China),
	nd, malidp, linux-kernel, dri-devel,
	james qian wang (Arm Technology China)

From: "james qian wang (Arm Technology China)" <james.qian.wang@arm.com>

Per komeda design KMS-plane maps to komeda layer input pipeline.
komeda_plane_atomic_check is for building a komeda layer input pipeline.

And KMS-plane is only a user of komeda resources. so there is no real HW
update for plane, but all HW update will be handled in crtc->flush.

v2: Rebase

Signed-off-by: James Qian Wang (Arm Technology China) <james.qian.wang@arm.com>
---
 .../gpu/drm/arm/display/komeda/komeda_plane.c | 128 ++++++++++++++++++
 1 file changed, 128 insertions(+)

diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
index 0a4953a9a909..af51f0cc9c16 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
@@ -10,7 +10,82 @@
 #include "komeda_dev.h"
 #include "komeda_kms.h"
 
+static int
+komeda_plane_init_data_flow(struct drm_plane_state *st,
+			    struct komeda_data_flow_cfg *dflow)
+{
+	struct drm_framebuffer *fb = st->fb;
+
+	memset(dflow, 0, sizeof(*dflow));
+
+	dflow->blending_zorder = st->zpos;
+
+	/* if format doesn't have alpha, fix blend mode to PIXEL_NONE */
+	dflow->pixel_blend_mode = fb->format->has_alpha ?
+		st->pixel_blend_mode : DRM_MODE_BLEND_PIXEL_NONE;
+	dflow->layer_alpha = st->alpha >> 8;
+
+	dflow->out_x = st->crtc_x;
+	dflow->out_y = st->crtc_y;
+	dflow->out_w = st->crtc_w;
+	dflow->out_h = st->crtc_h;
+
+	dflow->in_x = st->src_x >> 16;
+	dflow->in_y = st->src_y >> 16;
+	dflow->in_w = st->src_w >> 16;
+	dflow->in_h = st->src_h >> 16;
+
+	return 0;
+}
+
+int komeda_plane_atomic_check(struct drm_plane *plane,
+			      struct drm_plane_state *state)
+{
+	struct komeda_plane *kplane = to_kplane(plane);
+	struct komeda_plane_state *kplane_st = to_kplane_st(state);
+	struct komeda_layer *layer = kplane->layer;
+	struct drm_crtc_state *crtc_st;
+	struct komeda_crtc *kcrtc;
+	struct komeda_crtc_state *kcrtc_st;
+	struct komeda_data_flow_cfg dflow;
+	int err;
+
+	if (!state->crtc || !state->fb)
+		return 0;
+
+	crtc_st = drm_atomic_get_crtc_state(state->state, state->crtc);
+	if (!crtc_st->enable) {
+		DRM_DEBUG_ATOMIC("Cannot update plane on a disabled CRTC.\n");
+		return -EINVAL;
+	}
+
+	/* crtc is inactive, skip the resource assignment */
+	if (!crtc_st->active)
+		return 0;
+
+	kcrtc = to_kcrtc(state->crtc);
+	kcrtc_st = to_kcrtc_st(crtc_st);
+
+	err = komeda_plane_init_data_flow(state, &dflow);
+	if (err)
+		return err;
+
+	err = komeda_build_layer_data_flow(layer, kplane_st, kcrtc_st, &dflow);
+
+	return err;
+}
+
+/* plane doesn't represent a real HW, so there is no HW update for plane.
+ * komeda handles all the HW update in crtc->atomic_flush
+ */
+void komeda_plane_atomic_update(struct drm_plane *plane,
+				struct drm_plane_state *old_state)
+{
+}
+
 static const struct drm_plane_helper_funcs komeda_plane_helper_funcs = {
+	.atomic_check	= komeda_plane_atomic_check,
+	.atomic_update	= komeda_plane_atomic_update,
 };
 
 static void komeda_plane_destroy(struct drm_plane *plane)
@@ -20,7 +95,60 @@ static void komeda_plane_destroy(struct drm_plane *plane)
 	kfree(to_kplane(plane));
 }
 
+static void komeda_plane_reset(struct drm_plane *plane)
+{
+	struct komeda_plane_state *state;
+	struct komeda_plane *kplane = to_kplane(plane);
+
+	if (plane->state)
+		__drm_atomic_helper_plane_destroy_state(plane->state);
+
+	kfree(plane->state);
+	plane->state = NULL;
+
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+	if (state) {
+		state->base.rotation = DRM_MODE_ROTATE_0;
+		state->base.pixel_blend_mode = DRM_MODE_BLEND_PREMULTI;
+		state->base.alpha = DRM_BLEND_ALPHA_OPAQUE;
+		state->base.zpos = kplane->layer->base.id;
+		plane->state = &state->base;
+		plane->state->plane = plane;
+	}
+}
+
+static struct drm_plane_state *
+komeda_plane_atomic_duplicate_state(struct drm_plane *plane)
+{
+	struct komeda_plane_state *new;
+
+	if (WARN_ON(!plane->state))
+		return NULL;
+
+	new = kzalloc(sizeof(*new), GFP_KERNEL);
+	if (!new)
+		return NULL;
+
+	__drm_atomic_helper_plane_duplicate_state(plane, &new->base);
+
+	return &new->base;
+}
+
+static void
+komeda_plane_atomic_destroy_state(struct drm_plane *plane,
+				  struct drm_plane_state *state)
+{
+	__drm_atomic_helper_plane_destroy_state(state);
+	kfree(to_kplane_st(state));
+}
+
 static const struct drm_plane_funcs komeda_plane_funcs = {
+	.update_plane		= drm_atomic_helper_update_plane,
+	.disable_plane		= drm_atomic_helper_disable_plane,
+	.destroy		= komeda_plane_destroy,
+	.reset			= komeda_plane_reset,
+	.atomic_duplicate_state	= komeda_plane_atomic_duplicate_state,
+	.atomic_destroy_state	= komeda_plane_atomic_destroy_state,
 };
 
 /* for komeda, which is pipeline can be share between crtcs */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2019-01-22 11:06 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-22 11:05 [PATCH v2 0/5] Implement komeda DRM-Plane james qian wang (Arm Technology China)
2019-01-22 11:05 ` [PATCH v2 1/5] drm: Add drm_atomic_get_old/new_private_obj_state james qian wang (Arm Technology China)
2019-01-22 11:05 ` [PATCH v2 2/5] drm/komeda: Add komeda_pipeline/component_get_state_and_set_user james qian wang (Arm Technology China)
2019-01-22 11:06 ` [PATCH v2 3/5] drm/komeda: Initialize komeda component as drm private object james qian wang (Arm Technology China)
2019-01-22 11:06 ` [PATCH v2 4/5] drm/komeda: Add komeda_build_layer_data_flow james qian wang (Arm Technology China)
2019-01-22 11:06 ` [PATCH v2 5/5] drm/komeda: Add komeda_plane/plane_helper_funcs james qian wang (Arm Technology China)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).