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@xxxxxxx> --- .../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@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel