Active D77's Crossbar

Crossbar(CBU) is a new component added in D77, which is used for zorder
control.
At a time (per display frame) up to 5 inputs of the CBU can be enabled

Signed-off-by: Tiannan Zhu (Arm Technology China) <tiannan....@arm.com>
---
 .../arm/display/komeda/d71/d71_component.c    | 61 +++++++++++++++++++
 .../drm/arm/display/komeda/komeda_pipeline.c  | 10 +++
 .../drm/arm/display/komeda/komeda_pipeline.h  |  7 +++
 .../display/komeda/komeda_pipeline_state.c    | 36 +++++++++++
 .../arm/display/komeda/komeda_private_obj.c   | 49 +++++++++++++++
 5 files changed, 163 insertions(+)

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 ec96b69a5ade..3f2fee43867e 100644
--- a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
+++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
@@ -44,6 +44,9 @@ static void get_resources_id(u32 hw_id, u32 *pipe_id, u32 
*comp_id)
        case D71_BLK_TYPE_DOU:
                id = KOMEDA_COMPONENT_TIMING_CTRLR;
                break;
+       case D77_BLK_TYPE_CBU:
+               id += KOMEDA_COMPONENT_CROSSBAR0;
+               break;
        default:
                id = 0xFFFFFFFF;
        }
@@ -969,6 +972,63 @@ static int d71_splitter_init(struct d71_dev *d71,
        return 0;
 }
 
+static void d77_crossbar_update(struct komeda_component *c,
+                               struct komeda_component_state *state)
+{
+       u32 __iomem *reg;
+       u32 index, input_hw_id;
+
+       for_each_changed_input(state, index) {
+               reg = c->reg + index;
+               input_hw_id = to_d71_input_id(state, index);
+               if (state->active_inputs & BIT(index)) {
+                       malidp_write32(reg, BLK_INPUT_ID0, input_hw_id);
+                       malidp_write32(reg, BLK_CONTROL, CBU_INPUT_CTRL_EN);
+               } else {
+                       malidp_write32(reg, BLK_INPUT_ID0, 0);
+                       malidp_write32(reg, BLK_CONTROL, 0);
+               }
+       }
+}
+
+static void d77_crossbar_disable(struct komeda_component *c)
+{
+       u32 __iomem *reg = c->reg;
+       u32 i;
+
+       for (i = 0; i < c->max_active_inputs; i++) {
+               malidp_write32(reg, BLK_CONTROL + (i << 2), 0);
+               malidp_write32(reg, BLK_INPUT_ID0 + (i << 2), 0);
+       }
+}
+
+static struct komeda_component_funcs d77_crossbar_funcs = {
+       .update         = d77_crossbar_update,
+       .disable        = d77_crossbar_disable,
+};
+
+static int d77_crossbar_init(struct d71_dev *d71,
+                            struct block_header *blk, u32 __iomem *reg)
+{
+       struct komeda_component *c;
+       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(*c),
+                                comp_id,
+                                BLOCK_INFO_INPUT_ID(blk->block_info),
+                                &d77_crossbar_funcs,
+                                CBU_NUM_INPUT_IDS, get_valid_inputs(blk),
+                                CBU_NUM_OUTPUT_IDS, reg,
+                                "CBU%d", pipe_id);
+       if (IS_ERR(c)) {
+               DRM_ERROR("Failed to add crossbar component\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 static void d71_merger_update(struct komeda_component *c,
                              struct komeda_component_state *state)
 {
@@ -1351,6 +1411,7 @@ int d71_probe_block(struct d71_dev *d71,
                break;
 
        case D77_BLK_TYPE_CBU:
+               err = d77_crossbar_init(d71, blk, reg);
                break;
 
        case D77_BLK_TYPE_ATU:
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c 
b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c
index 104e27cc1dc3..fdb17a7c6fb6 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c
@@ -76,6 +76,16 @@ komeda_pipeline_get_component_pos(struct komeda_pipeline 
*pipe, int id)
        case KOMEDA_COMPONENT_LAYER3:
                pos = to_cpos(pipe->layers[id - KOMEDA_COMPONENT_LAYER0]);
                break;
+       case KOMEDA_COMPONENT_CROSSBAR0:
+       case KOMEDA_COMPONENT_CROSSBAR1:
+               temp = mdev->pipelines[id - KOMEDA_COMPONENT_CROSSBAR0];
+               if (!temp) {
+                       DRM_ERROR("crossbar-%d's pipeline doesn't exist.\n",
+                                 id);
+                       return NULL;
+               }
+               pos = to_cpos(temp->cbar);
+               break;
        case KOMEDA_COMPONENT_WB_LAYER:
                pos = to_cpos(pipe->wb_layer);
                break;
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h 
b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
index 76621a972803..b15649d08c3a 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
@@ -34,6 +34,8 @@ enum {
        KOMEDA_COMPONENT_IPS0           = 20, /* post image processor */
        KOMEDA_COMPONENT_IPS1           = 21,
        KOMEDA_COMPONENT_TIMING_CTRLR   = 22, /* timing controller */
+       KOMEDA_COMPONENT_CROSSBAR0      = 24,
+       KOMEDA_COMPONENT_CROSSBAR1      = 25,
 };
 
 #define KOMEDA_PIPELINE_LAYERS         (BIT(KOMEDA_COMPONENT_LAYER0) |\
@@ -41,6 +43,9 @@ enum {
                                         BIT(KOMEDA_COMPONENT_LAYER2) |\
                                         BIT(KOMEDA_COMPONENT_LAYER3))
 
+#define KOMEDA_PIPELINE_CROSSBARS      (BIT(KOMEDA_COMPONENT_CROSSBAR0) |\
+                                        BIT(KOMEDA_COMPONENT_CROSSBAR1))
+
 #define KOMEDA_PIPELINE_SCALERS                (BIT(KOMEDA_COMPONENT_SCALER0) 
|\
                                         BIT(KOMEDA_COMPONENT_SCALER1))
 
@@ -412,6 +417,8 @@ struct komeda_pipeline {
        int n_layers;
        /** @layers: the pipeline layers */
        struct komeda_layer *layers[KOMEDA_PIPELINE_MAX_LAYERS];
+       /** @cbar: the pipeline crossbar */
+       struct komeda_component *cbar;
        /** @n_scalers: the number of scaler on @scalers */
        int n_scalers;
        /** @scalers: the pipeline scalers */
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 79f7e7b6526f..82f21e9b5c73 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
@@ -665,6 +665,32 @@ void pipeline_composition_size(struct komeda_crtc_state 
*kcrtc_st,
                *vsize = m->vdisplay;
 }
 
+static int
+komeda_crossbar_set_input(struct komeda_component *cbar,
+                         struct komeda_crtc_state *kcrtc_st,
+                         struct komeda_data_flow_cfg *dflow)
+{
+       struct drm_atomic_state *drm_st = kcrtc_st->base.state;
+       struct drm_crtc *crtc = kcrtc_st->base.crtc;
+       struct komeda_component_state *st;
+       u32 idx = dflow->blending_zorder;
+
+       if (!cbar)
+               return 0;
+
+       st = komeda_component_get_state_and_set_user(cbar, drm_st, crtc, crtc);
+       if (IS_ERR(st))
+               return PTR_ERR(st);
+
+       if (komeda_component_check_input(st, &dflow->input, idx))
+               return -EINVAL;
+
+       komeda_component_add_input(st, &dflow->input, idx);
+       komeda_component_set_output(&dflow->input, cbar, idx);
+
+       return 0;
+}
+
 static int
 komeda_compiz_set_input(struct komeda_compiz *compiz,
                        struct komeda_crtc_state *kcrtc_st,
@@ -905,6 +931,10 @@ int komeda_build_layer_data_flow(struct komeda_layer 
*layer,
        if (err)
                return err;
 
+       err = komeda_crossbar_set_input(pipe->cbar, kcrtc_st, dflow);
+       if (err)
+               return err;
+
        err = komeda_scaler_validate(plane, kcrtc_st, dflow);
        if (err)
                return err;
@@ -1452,6 +1482,12 @@ int komeda_build_display_data_flow(struct komeda_crtc 
*kcrtc,
                if (err)
                        return err;
 
+               /* if master has crossbar, connect s_dflow to crossbar */
+               err = komeda_crossbar_set_input(master->cbar, kcrtc_st,
+                                               &s_dflow);
+               if (err)
+                       return err;
+
                /* merge the slave dflow into master pipeline */
                err = komeda_compiz_set_input(master->compiz, kcrtc_st,
                                              &s_dflow);
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 914400c4af73..4cc8ccf224f1 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_private_obj.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_private_obj.c
@@ -103,6 +103,49 @@ static int komeda_scaler_obj_add(struct komeda_kms_dev 
*kms,
        return 0;
 }
 
+static struct drm_private_state *
+komeda_crossbar_atomic_duplicate_state(struct drm_private_obj *obj)
+{
+       struct komeda_component_state *st;
+
+       st = kmemdup(obj->state, sizeof(*st), GFP_KERNEL);
+       if (!st)
+               return NULL;
+
+       komeda_component_state_reset(st);
+       __drm_atomic_helper_private_obj_duplicate_state(obj, &st->obj);
+
+       return &st->obj;
+}
+
+static void
+komeda_crossbar_atomic_destroy_state(struct drm_private_obj *obj,
+                                    struct drm_private_state *state)
+{
+       kfree(priv_to_comp_st(state));
+}
+
+static const struct drm_private_state_funcs komeda_crossbar_obj_funcs = {
+       .atomic_duplicate_state = komeda_crossbar_atomic_duplicate_state,
+       .atomic_destroy_state   = komeda_crossbar_atomic_destroy_state,
+};
+
+static int komeda_crossbar_obj_add(struct komeda_kms_dev *kms,
+                                  struct komeda_component *cbar)
+{
+       struct komeda_component_state *st;
+       struct drm_device *dev = &kms->base;
+
+       st = kzalloc(sizeof(*st), GFP_KERNEL);
+       if (!st)
+               return -ENOMEM;
+       st->component = cbar;
+
+       drm_atomic_private_obj_init(dev, &cbar->obj, &st->obj,
+                                   &komeda_crossbar_obj_funcs);
+       return 0;
+}
+
 static struct drm_private_state *
 komeda_compiz_atomic_duplicate_state(struct drm_private_obj *obj)
 {
@@ -388,6 +431,12 @@ int komeda_kms_add_private_objs(struct komeda_kms_dev *kms,
                                return err;
                }
 
+               if (pipe->cbar) {
+                       err = komeda_crossbar_obj_add(kms, pipe->cbar);
+                       if (err)
+                               return err;
+               }
+
                for (j = 0; j < pipe->n_scalers; j++) {
                        err = komeda_scaler_obj_add(kms, pipe->scalers[j]);
                        if (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