Skip to content

Commit

Permalink
drm/komeda: Add new component komeda_splitter
Browse files Browse the repository at this point in the history
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.

v2: Rebase

Signed-off-by: James Qian Wang (Arm Technology China) <james.qian.wang@arm.com>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
  • Loading branch information
james qian wang (Arm Technology China) authored and Liviu Dudau committed Jun 19, 2019
1 parent f461d65 commit 4b9baf7
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 2 deletions.
63 changes: 63 additions & 0 deletions drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
Original file line number Diff line number Diff line change
Expand Up @@ -808,6 +808,68 @@ static int d71_downscaling_clk_check(struct komeda_pipeline *pipe,
0 : -EINVAL;
}

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)
{
Expand Down Expand Up @@ -1102,6 +1164,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:
Expand Down
3 changes: 3 additions & 0 deletions drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,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;
Expand Down
19 changes: 17 additions & 2 deletions drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,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*/
Expand Down Expand Up @@ -388,6 +399,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 */
Expand Down Expand Up @@ -432,14 +445,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)

Expand Down
50 changes: 50 additions & 0 deletions drivers/gpu/drm/arm/display/komeda/komeda_private_obj.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 4b9baf7

Please sign in to comment.