1
0
Fork 0

drm/komeda: Add d71 layer

1. Add detailed layer/layer_state definitions
2. Add d71_layer_init to report layer features and capabilities according
   to D71 layer block.
3. Add d71_layer_updat/disable

v2: Rebase.

Signed-off-by: James Qian Wang (Arm Technology China) <james.qian.wang@arm.com>
[removed d71_layer_dump() from this commit]
Signed-off-by: Liviu Dudau <liviu.dudau@arm.com>
hifive-unleashed-5.2
james qian wang (Arm Technology China) 2019-01-22 09:23:49 +00:00 committed by Liviu Dudau
parent 1f2367a39f
commit 71c420b7bf
3 changed files with 185 additions and 4 deletions

View File

@ -27,4 +27,21 @@
num_tries; \
})
/* the restriction of range is [start, end] */
struct malidp_range {
u32 start;
u32 end;
};
static inline void set_range(struct malidp_range *rg, u32 start, u32 end)
{
rg->start = start;
rg->end = end;
}
static inline bool in_range(struct malidp_range *rg, u32 v)
{
return (v >= rg->start) && (v <= rg->end);
}
#endif /* _MALIDP_UTILS_ */

View File

@ -9,11 +9,171 @@
#include "d71_dev.h"
#include "komeda_kms.h"
#include "malidp_io.h"
#include "komeda_framebuffer.h"
static void get_resources_id(u32 hw_id, u32 *pipe_id, u32 *comp_id)
{
u32 id = BLOCK_INFO_BLK_ID(hw_id);
u32 pipe = id;
switch (BLOCK_INFO_BLK_TYPE(hw_id)) {
case D71_BLK_TYPE_LPU_WB_LAYER:
id = KOMEDA_COMPONENT_WB_LAYER;
break;
case D71_BLK_TYPE_CU_SPLITTER:
id = KOMEDA_COMPONENT_SPLITTER;
break;
case D71_BLK_TYPE_CU_SCALER:
pipe = id / D71_PIPELINE_MAX_SCALERS;
id %= D71_PIPELINE_MAX_SCALERS;
id += KOMEDA_COMPONENT_SCALER0;
break;
case D71_BLK_TYPE_CU:
id += KOMEDA_COMPONENT_COMPIZ0;
break;
case D71_BLK_TYPE_LPU_LAYER:
pipe = id / D71_PIPELINE_MAX_LAYERS;
id %= D71_PIPELINE_MAX_LAYERS;
id += KOMEDA_COMPONENT_LAYER0;
break;
case D71_BLK_TYPE_DOU_IPS:
id += KOMEDA_COMPONENT_IPS0;
break;
case D71_BLK_TYPE_CU_MERGER:
id = KOMEDA_COMPONENT_MERGER;
break;
case D71_BLK_TYPE_DOU:
id = KOMEDA_COMPONENT_TIMING_CTRLR;
break;
default:
id = 0xFFFFFFFF;
}
if (comp_id)
*comp_id = id;
if (pipe_id)
*pipe_id = pipe;
}
static u32 get_valid_inputs(struct block_header *blk)
{
u32 valid_inputs = 0, comp_id;
int i;
for (i = 0; i < PIPELINE_INFO_N_VALID_INPUTS(blk->pipeline_info); i++) {
get_resources_id(blk->input_ids[i], NULL, &comp_id);
if (comp_id == 0xFFFFFFFF)
continue;
valid_inputs |= BIT(comp_id);
}
return valid_inputs;
}
static u32 to_rot_ctrl(u32 rot)
{
u32 lr_ctrl = 0;
switch (rot & DRM_MODE_ROTATE_MASK) {
case DRM_MODE_ROTATE_0:
lr_ctrl |= L_ROT(L_ROT_R0);
break;
case DRM_MODE_ROTATE_90:
lr_ctrl |= L_ROT(L_ROT_R90);
break;
case DRM_MODE_ROTATE_180:
lr_ctrl |= L_ROT(L_ROT_R180);
break;
case DRM_MODE_ROTATE_270:
lr_ctrl |= L_ROT(L_ROT_R270);
break;
}
if (rot & DRM_MODE_REFLECT_X)
lr_ctrl |= L_HFLIP;
if (rot & DRM_MODE_REFLECT_Y)
lr_ctrl |= L_VFLIP;
return lr_ctrl;
}
static void d71_layer_disable(struct komeda_component *c)
{
malidp_write32_mask(c->reg, BLK_CONTROL, L_EN, 0);
}
static void d71_layer_update(struct komeda_component *c,
struct komeda_component_state *state)
{
struct komeda_layer_state *st = to_layer_st(state);
struct drm_plane_state *plane_st = state->plane->state;
struct drm_framebuffer *fb = plane_st->fb;
struct komeda_fb *kfb = to_kfb(fb);
u32 __iomem *reg = c->reg;
u32 ctrl_mask = L_EN | L_ROT(L_ROT_R270) | L_HFLIP | L_VFLIP | L_TBU_EN;
u32 ctrl = L_EN | to_rot_ctrl(st->rot);
int i;
for (i = 0; i < fb->format->num_planes; i++) {
malidp_write32(reg,
BLK_P0_PTR_LOW + i * LAYER_PER_PLANE_REGS * 4,
lower_32_bits(st->addr[i]));
malidp_write32(reg,
BLK_P0_PTR_HIGH + i * LAYER_PER_PLANE_REGS * 4,
upper_32_bits(st->addr[i]));
if (i >= 2)
break;
malidp_write32(reg,
BLK_P0_STRIDE + i * LAYER_PER_PLANE_REGS * 4,
fb->pitches[i] & 0xFFFF);
}
malidp_write32(reg, LAYER_FMT, kfb->format_caps->hw_id);
malidp_write32(reg, BLK_IN_SIZE, HV_SIZE(st->hsize, st->vsize));
malidp_write32_mask(reg, BLK_CONTROL, ctrl_mask, ctrl);
}
static struct komeda_component_funcs d71_layer_funcs = {
.update = d71_layer_update,
.disable = d71_layer_disable,
};
static int d71_layer_init(struct d71_dev *d71,
struct block_header *blk, u32 __iomem *reg)
{
DRM_DEBUG("Detect D71_Layer.\n");
struct komeda_component *c;
struct komeda_layer *layer;
u32 pipe_id, layer_id, layer_info;
get_resources_id(blk->block_info, &pipe_id, &layer_id);
c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*layer),
layer_id,
BLOCK_INFO_INPUT_ID(blk->block_info),
&d71_layer_funcs, 0,
get_valid_inputs(blk),
1, reg, "LPU%d_LAYER%d", pipe_id, layer_id);
if (IS_ERR(c)) {
DRM_ERROR("Failed to add layer component\n");
return PTR_ERR(c);
}
layer = to_layer(c);
layer_info = malidp_read32(reg, LAYER_INFO);
if (layer_info & L_INFO_RF)
layer->layer_type = KOMEDA_FMT_RICH_LAYER;
else
layer->layer_type = KOMEDA_FMT_SIMPLE_LAYER;
set_range(&layer->hsize_in, 4, d71->max_line_size);
set_range(&layer->vsize_in, 4, d71->max_vsize);
malidp_write32(reg, LAYER_PALPHA, D71_PALPHA_DEF_MAP);
layer->supported_rots = DRM_MODE_ROTATE_MASK | DRM_MODE_REFLECT_MASK;
return 0;
}

View File

@ -207,16 +207,20 @@ static inline u16 component_changed_inputs(struct komeda_component_state *st)
#define to_comp(__c) (((__c) == NULL) ? NULL : &((__c)->base))
#define to_cpos(__c) ((struct komeda_component **)&(__c))
/* these structures are going to be filled in in uture patches */
struct komeda_layer {
struct komeda_component base;
/* layer specific features and caps */
int layer_type; /* RICH, SIMPLE or WB */
/* accepted h/v input range before rotation */
struct malidp_range hsize_in, vsize_in;
u32 layer_type; /* RICH, SIMPLE or WB */
u32 supported_rots;
};
struct komeda_layer_state {
struct komeda_component_state base;
/* layer specific configuration state */
u16 hsize, vsize;
u32 rot;
dma_addr_t addr[3];
};
struct komeda_compiz {