diff mbox series

[1/2] drm/komeda: Add new component komeda_splitter

Message ID 20190530104335.2395-2-james.qian.wang@arm.com (mailing list archive)
State New, archived
Headers show
Series drm/komeda: Add writeback downscaling split support | expand

Commit Message

James Qian Wang May 30, 2019, 10:44 a.m. UTC
Similar to Layer Split, but Splitter is used for writeback, which splits
the compiz result to two half parts and then feed them to two scalers.

Signed-off-by: James Qian Wang (Arm Technology China) <james.qian.wang@arm.com>
---
 .../arm/display/komeda/d71/d71_component.c    | 63 +++++++++++++++++++
 .../drm/arm/display/komeda/komeda_pipeline.c  |  3 +
 .../drm/arm/display/komeda/komeda_pipeline.h  | 19 +++++-
 .../arm/display/komeda/komeda_private_obj.c   | 50 +++++++++++++++
 4 files changed, 133 insertions(+), 2 deletions(-)

--
2.17.1
diff mbox series

Patch

diff --git a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
index 240f82cb9fa0..769f5a2da030 100644
--- a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
+++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
@@ -767,6 +767,68 @@  static int d71_scaler_init(struct d71_dev *d71,
 	return 0;
 }

+static void d71_splitter_update(struct komeda_component *c,
+				struct komeda_component_state *state)
+{
+	struct komeda_splitter_state *st = to_splitter_st(state);
+	u32 __iomem *reg = c->reg;
+
+	malidp_write32(reg, BLK_INPUT_ID0, to_d71_input_id(state, 0));
+	malidp_write32(reg, BLK_SIZE, HV_SIZE(st->hsize, st->vsize));
+	malidp_write32(reg, SP_OVERLAP_SIZE, st->overlap & 0x1FFF);
+	malidp_write32(reg, BLK_CONTROL, BLK_CTRL_EN);
+}
+
+static void d71_splitter_dump(struct komeda_component *c, struct seq_file *sf)
+{
+	u32 v[3];
+
+	dump_block_header(sf, c->reg);
+
+	get_values_from_reg(c->reg, BLK_INPUT_ID0, 1, v);
+	seq_printf(sf, "SP_INPUT_ID0:\t\t0x%X\n", v[0]);
+
+	get_values_from_reg(c->reg, BLK_CONTROL, 3, v);
+	seq_printf(sf, "SP_CONTROL:\t\t0x%X\n", v[0]);
+	seq_printf(sf, "SP_SIZE:\t\t0x%X\n", v[1]);
+	seq_printf(sf, "SP_OVERLAP_SIZE:\t0x%X\n", v[2]);
+}
+
+static const struct komeda_component_funcs d71_splitter_funcs = {
+	.update		= d71_splitter_update,
+	.disable	= d71_component_disable,
+	.dump_register	= d71_splitter_dump,
+};
+
+static int d71_splitter_init(struct d71_dev *d71,
+			     struct block_header *blk, u32 __iomem *reg)
+{
+	struct komeda_component *c;
+	struct komeda_splitter *splitter;
+	u32 pipe_id, comp_id;
+
+	get_resources_id(blk->block_info, &pipe_id, &comp_id);
+
+	c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*splitter),
+				 comp_id,
+				 BLOCK_INFO_INPUT_ID(blk->block_info),
+				 &d71_splitter_funcs,
+				 1, get_valid_inputs(blk), 2, reg,
+				 "CU%d_SPLITTER", pipe_id);
+
+	if (IS_ERR(c)) {
+		DRM_ERROR("Failed to initialize splitter");
+		return -1;
+	}
+
+	splitter = to_splitter(c);
+
+	set_range(&splitter->hsize, 4, d71->max_line_size);
+	set_range(&splitter->vsize, 4, d71->max_vsize);
+
+	return 0;
+}
+
 static void d71_merger_update(struct komeda_component *c,
 			      struct komeda_component_state *state)
 {
@@ -1126,6 +1188,7 @@  int d71_probe_block(struct d71_dev *d71,
 		break;

 	case D71_BLK_TYPE_CU_SPLITTER:
+		err = d71_splitter_init(d71, blk, reg);
 		break;

 	case D71_BLK_TYPE_CU_MERGER:
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c
index c7c3caad13bd..0b76e2acd38c 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c
@@ -92,6 +92,9 @@  komeda_pipeline_get_component_pos(struct komeda_pipeline *pipe, int id)
 	case KOMEDA_COMPONENT_SCALER1:
 		pos = to_cpos(pipe->scalers[id - KOMEDA_COMPONENT_SCALER0]);
 		break;
+	case KOMEDA_COMPONENT_SPLITTER:
+		pos = to_cpos(pipe->splitter);
+		break;
 	case KOMEDA_COMPONENT_MERGER:
 		pos = to_cpos(pipe->merger);
 		break;
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
index 989408b53091..4632fc5ec71f 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
@@ -302,6 +302,17 @@  struct komeda_merger_state {
 	u16 vsize_merged;
 };

+struct komeda_splitter {
+	struct komeda_component base;
+	struct malidp_range hsize, vsize;
+};
+
+struct komeda_splitter_state {
+	struct komeda_component_state base;
+	u16 hsize, vsize;
+	u16 overlap;
+};
+
 struct komeda_improc {
 	struct komeda_component base;
 	u32 supported_color_formats;  /* DRM_RGB/YUV444/YUV420*/
@@ -393,6 +404,8 @@  struct komeda_pipeline {
 	struct komeda_scaler *scalers[KOMEDA_PIPELINE_MAX_SCALERS];
 	/** @compiz: compositor */
 	struct komeda_compiz *compiz;
+	/** @splitter: for split the compiz output to two half data flows */
+	struct komeda_splitter *splitter;
 	/** @merger: merger */
 	struct komeda_merger *merger;
 	/** @wb_layer: writeback layer */
@@ -437,14 +450,16 @@  struct komeda_pipeline_state {
 #define to_layer(c)	container_of(c, struct komeda_layer, base)
 #define to_compiz(c)	container_of(c, struct komeda_compiz, base)
 #define to_scaler(c)	container_of(c, struct komeda_scaler, base)
+#define to_splitter(c)	container_of(c, struct komeda_splitter, base)
 #define to_merger(c)	container_of(c, struct komeda_merger, base)
 #define to_improc(c)	container_of(c, struct komeda_improc, base)
 #define to_ctrlr(c)	container_of(c, struct komeda_timing_ctrlr, base)

 #define to_layer_st(c)	container_of(c, struct komeda_layer_state, base)
 #define to_compiz_st(c)	container_of(c, struct komeda_compiz_state, base)
-#define to_scaler_st(c) container_of(c, struct komeda_scaler_state, base)
-#define to_merger_st(c) container_of(c, struct komeda_merger_state, base)
+#define to_scaler_st(c)	container_of(c, struct komeda_scaler_state, base)
+#define to_splitter_st(c) container_of(c, struct komeda_splitter_state, base)
+#define to_merger_st(c)	container_of(c, struct komeda_merger_state, base)
 #define to_improc_st(c)	container_of(c, struct komeda_improc_state, base)
 #define to_ctrlr_st(c)	container_of(c, struct komeda_timing_ctrlr_state, base)

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 0f4e1f601ce0..914400c4af73 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_private_obj.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_private_obj.c
@@ -146,6 +146,50 @@  static int komeda_compiz_obj_add(struct komeda_kms_dev *kms,
 	return 0;
 }

+static struct drm_private_state *
+komeda_splitter_atomic_duplicate_state(struct drm_private_obj *obj)
+{
+	struct komeda_splitter_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_splitter_atomic_destroy_state(struct drm_private_obj *obj,
+				     struct drm_private_state *state)
+{
+	kfree(to_splitter_st(priv_to_comp_st(state)));
+}
+
+static const struct drm_private_state_funcs komeda_splitter_obj_funcs = {
+	.atomic_duplicate_state	= komeda_splitter_atomic_duplicate_state,
+	.atomic_destroy_state	= komeda_splitter_atomic_destroy_state,
+};
+
+static int komeda_splitter_obj_add(struct komeda_kms_dev *kms,
+				   struct komeda_splitter *splitter)
+{
+	struct komeda_splitter_state *st;
+
+	st = kzalloc(sizeof(*st), GFP_KERNEL);
+	if (!st)
+		return -ENOMEM;
+
+	st->base.component = &splitter->base;
+	drm_atomic_private_obj_init(&kms->base,
+				    &splitter->base.obj, &st->base.obj,
+				    &komeda_splitter_obj_funcs);
+
+	return 0;
+}
+
 static struct drm_private_state *
 komeda_merger_atomic_duplicate_state(struct drm_private_obj *obj)
 {
@@ -354,6 +398,12 @@  int komeda_kms_add_private_objs(struct komeda_kms_dev *kms,
 		if (err)
 			return err;

+		if (pipe->splitter) {
+			err = komeda_splitter_obj_add(kms, pipe->splitter);
+			if (err)
+				return err;
+		}
+
 		if (pipe->merger) {
 			err = komeda_merger_obj_add(kms, pipe->merger);
 			if (err)