Introduce a new component komeda_merger, because D71 HW supports to split
a whole image to two half parts and does the scaling independently. Merger
merges two separate results to one, and output it to compositor or wb_layer
For this patch:
- Add the definition of komeda_merger/merger_state
- Report and initialize komeda_merger according to the D71 HW.

Signed-off-by: James Qian Wang (Arm Technology China) <james.qian.w...@arm.com>
---
 .../arm/display/komeda/d71/d71_component.c    | 74 +++++++++++++++++++
 .../drm/arm/display/komeda/komeda_pipeline.c  |  3 +
 .../drm/arm/display/komeda/komeda_pipeline.h  | 18 ++++-
 .../arm/display/komeda/komeda_private_obj.c   | 49 ++++++++++++
 4 files changed, 143 insertions(+), 1 deletion(-)

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 ca4b2f7a8106..3266bd54c936 100644
--- a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
+++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
@@ -726,6 +726,77 @@ static int d71_scaler_init(struct d71_dev *d71,
        return 0;
 }
 
+static void d71_merger_update(struct komeda_component *c,
+                             struct komeda_component_state *state)
+{
+       struct komeda_merger_state *st = to_merger_st(state);
+       u32 __iomem *reg = c->reg;
+       u32 index;
+
+       for_each_changed_input(state, index)
+               malidp_write32(reg, MG_INPUT_ID0 + index * 4,
+                              to_d71_input_id(&state->inputs[index]));
+
+       malidp_write32(reg, MG_SIZE, HV_SIZE(st->hsize_merged,
+                                            st->vsize_merged));
+       malidp_write32(reg, BLK_CONTROL, BLK_CTRL_EN);
+}
+
+static void d71_merger_dump(struct komeda_component *c, struct seq_file *sf)
+{
+       u32 v;
+
+       dump_block_header(sf, c->reg);
+
+       get_values_from_reg(c->reg, MG_INPUT_ID0, 1, &v);
+       seq_printf(sf, "MG_INPUT_ID0:\t\t0x%X\n", v);
+
+       get_values_from_reg(c->reg, MG_INPUT_ID1, 1, &v);
+       seq_printf(sf, "MG_INPUT_ID1:\t\t0x%X\n", v);
+
+       get_values_from_reg(c->reg, BLK_CONTROL, 1, &v);
+       seq_printf(sf, "MG_CONTROL:\t\t0x%X\n", v);
+
+       get_values_from_reg(c->reg, MG_SIZE, 1, &v);
+       seq_printf(sf, "MG_SIZE:\t\t0x%X\n", v);
+}
+
+static const struct komeda_component_funcs d71_merger_funcs = {
+       .update         = d71_merger_update,
+       .disable        = d71_component_disable,
+       .dump_register  = d71_merger_dump,
+};
+
+static int d71_merger_init(struct d71_dev *d71,
+                          struct block_header *blk, u32 __iomem *reg)
+{
+       struct komeda_component *c;
+       struct komeda_merger *merger;
+       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(*merger),
+                                comp_id,
+                                BLOCK_INFO_INPUT_ID(blk->block_info),
+                                &d71_merger_funcs,
+                                MG_NUM_INPUTS_IDS, get_valid_inputs(blk),
+                                MG_NUM_OUTPUTS_IDS, reg,
+                                "CU%d_MERGER", pipe_id);
+
+       if (!c) {
+               DRM_ERROR("Failed to initialize merger.\n");
+               return -1;
+       }
+
+       merger = to_merger(c);
+
+       set_range(&merger->hsize_merged, 4, 4032);
+       set_range(&merger->vsize_merged, 4, 4096);
+
+       return 0;
+}
+
 static void d71_improc_update(struct komeda_component *c,
                              struct komeda_component_state *state)
 {
@@ -951,7 +1022,10 @@ int d71_probe_block(struct d71_dev *d71,
                break;
 
        case D71_BLK_TYPE_CU_SPLITTER:
+               break;
+
        case D71_BLK_TYPE_CU_MERGER:
+               err = d71_merger_init(d71, blk, reg);
                break;
 
        case D71_BLK_TYPE_DOU:
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c 
b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c
index 96248586b4e8..f434cb526dbe 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_MERGER:
+               pos = to_cpos(pipe->merger);
+               break;
        case KOMEDA_COMPONENT_IPS0:
        case KOMEDA_COMPONENT_IPS1:
                temp = mdev->pipelines[id - KOMEDA_COMPONENT_IPS0];
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h 
b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
index 2c7e3f97a6f3..c92733736799 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
@@ -276,6 +276,18 @@ struct komeda_compiz_state {
        struct komeda_compiz_input_cfg cins[KOMEDA_COMPONENT_N_INPUTS];
 };
 
+struct komeda_merger {
+       struct komeda_component base;
+       struct malidp_range hsize_merged;
+       struct malidp_range vsize_merged;
+};
+
+struct komeda_merger_state {
+       struct komeda_component_state base;
+       u16 hsize_merged;
+       u16 vsize_merged;
+};
+
 struct komeda_improc {
        struct komeda_component base;
        u32 supported_color_formats;  /* DRM_RGB/YUV444/YUV420*/
@@ -353,6 +365,8 @@ struct komeda_pipeline {
        struct komeda_scaler *scalers[KOMEDA_PIPELINE_MAX_SCALERS];
        /** @compiz: compositor */
        struct komeda_compiz *compiz;
+       /** @merger: merger */
+       struct komeda_merger *merger;
        /** @wb_layer: writeback layer */
        struct komeda_layer  *wb_layer;
        /** @improc: post image processor */
@@ -395,17 +409,19 @@ 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_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_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)
 
 #define priv_to_comp_st(o) container_of(o, struct komeda_component_state, obj)
-#define priv_to_pipe_st(o)  container_of(o, struct komeda_pipeline_state, obj)
+#define priv_to_pipe_st(o) container_of(o, struct komeda_pipeline_state, obj)
 
 /* pipeline APIs */
 struct komeda_pipeline *
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 bac90ab8fdc9..0f4e1f601ce0 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,49 @@ static int komeda_compiz_obj_add(struct komeda_kms_dev 
*kms,
        return 0;
 }
 
+static struct drm_private_state *
+komeda_merger_atomic_duplicate_state(struct drm_private_obj *obj)
+{
+       struct komeda_merger_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_merger_atomic_destroy_state(struct drm_private_obj *obj,
+                                              struct drm_private_state *state)
+{
+       kfree(to_merger_st(priv_to_comp_st(state)));
+}
+
+static const struct drm_private_state_funcs komeda_merger_obj_funcs = {
+       .atomic_duplicate_state = komeda_merger_atomic_duplicate_state,
+       .atomic_destroy_state   = komeda_merger_atomic_destroy_state,
+};
+
+static int komeda_merger_obj_add(struct komeda_kms_dev *kms,
+                                struct komeda_merger *merger)
+{
+       struct komeda_merger_state *st;
+
+       st = kzalloc(sizeof(*st), GFP_KERNEL);
+       if (!st)
+               return -ENOMEM;
+
+       st->base.component = &merger->base;
+       drm_atomic_private_obj_init(&kms->base,
+                                   &merger->base.obj, &st->base.obj,
+                                   &komeda_merger_obj_funcs);
+
+       return 0;
+}
+
 static struct drm_private_state *
 komeda_improc_atomic_duplicate_state(struct drm_private_obj *obj)
 {
@@ -311,6 +354,12 @@ int komeda_kms_add_private_objs(struct komeda_kms_dev *kms,
                if (err)
                        return err;
 
+               if (pipe->merger) {
+                       err = komeda_merger_obj_add(kms, pipe->merger);
+                       if (err)
+                               return err;
+               }
+
                err = komeda_improc_obj_add(kms, pipe->improc);
                if (err)
                        return err;
-- 
2.17.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to