[PATCH 2/2] drm/komeda: add Crossbar support
Tiannan Zhu (Arm Technology China)
Tiannan.Zhu at arm.com
Wed Dec 11 10:30:13 UTC 2019
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.zhu at 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
More information about the dri-devel
mailing list