drm/komeda: Add d71 layer
authorjames qian wang (Arm Technology China) <james.qian.wang@arm.com>
Tue, 22 Jan 2019 09:23:49 +0000 (09:23 +0000)
committerLiviu Dudau <Liviu.Dudau@arm.com>
Mon, 1 Apr 2019 17:07:43 +0000 (18:07 +0100)
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>
drivers/gpu/drm/arm/display/include/malidp_utils.h
drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h

index 9096e40facfa770e541073273c903c8c5ab95c0f..8cfd91196e1540ce9c193ee47e804463d4049226 100644 (file)
        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_ */
index c30a440e7b578aae4a9a4cf5040ea55f68d0ab01..22324ac0881f8e5405a0e7ebd855e79278e3f5fc 100644 (file)
 #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;
 }
index 8c950bc8ae964f6394c4f044448c339fc6fc012c..03525330efe83d3cfc7c8d7dfe9a37063b03c818 100644 (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 {