1 // SPDX-License-Identifier: GPL-2.0
3 * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
4 * Author: James.Qian.Wang <james.qian.wang@arm.com>
8 #include <drm/drm_print.h>
10 #include "komeda_kms.h"
11 #include "malidp_io.h"
12 #include "komeda_framebuffer.h"
14 static void get_resources_id(u32 hw_id, u32 *pipe_id, u32 *comp_id)
16 u32 id = BLOCK_INFO_BLK_ID(hw_id);
19 switch (BLOCK_INFO_BLK_TYPE(hw_id)) {
20 case D71_BLK_TYPE_LPU_WB_LAYER:
21 id = KOMEDA_COMPONENT_WB_LAYER;
23 case D71_BLK_TYPE_CU_SPLITTER:
24 id = KOMEDA_COMPONENT_SPLITTER;
26 case D71_BLK_TYPE_CU_SCALER:
27 pipe = id / D71_PIPELINE_MAX_SCALERS;
28 id %= D71_PIPELINE_MAX_SCALERS;
29 id += KOMEDA_COMPONENT_SCALER0;
32 id += KOMEDA_COMPONENT_COMPIZ0;
34 case D71_BLK_TYPE_LPU_LAYER:
35 pipe = id / D71_PIPELINE_MAX_LAYERS;
36 id %= D71_PIPELINE_MAX_LAYERS;
37 id += KOMEDA_COMPONENT_LAYER0;
39 case D71_BLK_TYPE_DOU_IPS:
40 id += KOMEDA_COMPONENT_IPS0;
42 case D71_BLK_TYPE_CU_MERGER:
43 id = KOMEDA_COMPONENT_MERGER;
45 case D71_BLK_TYPE_DOU:
46 id = KOMEDA_COMPONENT_TIMING_CTRLR;
59 static u32 get_valid_inputs(struct block_header *blk)
61 u32 valid_inputs = 0, comp_id;
64 for (i = 0; i < PIPELINE_INFO_N_VALID_INPUTS(blk->pipeline_info); i++) {
65 get_resources_id(blk->input_ids[i], NULL, &comp_id);
66 if (comp_id == 0xFFFFFFFF)
68 valid_inputs |= BIT(comp_id);
74 static u32 to_rot_ctrl(u32 rot)
78 switch (rot & DRM_MODE_ROTATE_MASK) {
79 case DRM_MODE_ROTATE_0:
80 lr_ctrl |= L_ROT(L_ROT_R0);
82 case DRM_MODE_ROTATE_90:
83 lr_ctrl |= L_ROT(L_ROT_R90);
85 case DRM_MODE_ROTATE_180:
86 lr_ctrl |= L_ROT(L_ROT_R180);
88 case DRM_MODE_ROTATE_270:
89 lr_ctrl |= L_ROT(L_ROT_R270);
93 if (rot & DRM_MODE_REFLECT_X)
95 if (rot & DRM_MODE_REFLECT_Y)
101 static void d71_layer_disable(struct komeda_component *c)
103 malidp_write32_mask(c->reg, BLK_CONTROL, L_EN, 0);
106 static void d71_layer_update(struct komeda_component *c,
107 struct komeda_component_state *state)
109 struct komeda_layer_state *st = to_layer_st(state);
110 struct drm_plane_state *plane_st = state->plane->state;
111 struct drm_framebuffer *fb = plane_st->fb;
112 struct komeda_fb *kfb = to_kfb(fb);
113 u32 __iomem *reg = c->reg;
114 u32 ctrl_mask = L_EN | L_ROT(L_ROT_R270) | L_HFLIP | L_VFLIP | L_TBU_EN;
115 u32 ctrl = L_EN | to_rot_ctrl(st->rot);
118 for (i = 0; i < fb->format->num_planes; i++) {
120 BLK_P0_PTR_LOW + i * LAYER_PER_PLANE_REGS * 4,
121 lower_32_bits(st->addr[i]));
123 BLK_P0_PTR_HIGH + i * LAYER_PER_PLANE_REGS * 4,
124 upper_32_bits(st->addr[i]));
129 BLK_P0_STRIDE + i * LAYER_PER_PLANE_REGS * 4,
130 fb->pitches[i] & 0xFFFF);
133 malidp_write32(reg, LAYER_FMT, kfb->format_caps->hw_id);
134 malidp_write32(reg, BLK_IN_SIZE, HV_SIZE(st->hsize, st->vsize));
136 malidp_write32_mask(reg, BLK_CONTROL, ctrl_mask, ctrl);
139 static struct komeda_component_funcs d71_layer_funcs = {
140 .update = d71_layer_update,
141 .disable = d71_layer_disable,
144 static int d71_layer_init(struct d71_dev *d71,
145 struct block_header *blk, u32 __iomem *reg)
147 struct komeda_component *c;
148 struct komeda_layer *layer;
149 u32 pipe_id, layer_id, layer_info;
151 get_resources_id(blk->block_info, &pipe_id, &layer_id);
152 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*layer),
154 BLOCK_INFO_INPUT_ID(blk->block_info),
156 get_valid_inputs(blk),
157 1, reg, "LPU%d_LAYER%d", pipe_id, layer_id);
159 DRM_ERROR("Failed to add layer component\n");
164 layer_info = malidp_read32(reg, LAYER_INFO);
166 if (layer_info & L_INFO_RF)
167 layer->layer_type = KOMEDA_FMT_RICH_LAYER;
169 layer->layer_type = KOMEDA_FMT_SIMPLE_LAYER;
171 set_range(&layer->hsize_in, 4, d71->max_line_size);
172 set_range(&layer->vsize_in, 4, d71->max_vsize);
174 malidp_write32(reg, LAYER_PALPHA, D71_PALPHA_DEF_MAP);
176 layer->supported_rots = DRM_MODE_ROTATE_MASK | DRM_MODE_REFLECT_MASK;
181 static int d71_wb_layer_init(struct d71_dev *d71,
182 struct block_header *blk, u32 __iomem *reg)
184 DRM_DEBUG("Detect D71_Wb_Layer.\n");
189 static int d71_compiz_init(struct d71_dev *d71,
190 struct block_header *blk, u32 __iomem *reg)
192 DRM_DEBUG("Detect D71_compiz.\n");
197 static int d71_improc_init(struct d71_dev *d71,
198 struct block_header *blk, u32 __iomem *reg)
200 DRM_DEBUG("Detect D71_improc.\n");
205 static int d71_timing_ctrlr_init(struct d71_dev *d71,
206 struct block_header *blk, u32 __iomem *reg)
208 DRM_DEBUG("Detect D71_timing_ctrlr.\n");
213 int d71_probe_block(struct d71_dev *d71,
214 struct block_header *blk, u32 __iomem *reg)
216 struct d71_pipeline *pipe;
217 int blk_id = BLOCK_INFO_BLK_ID(blk->block_info);
221 switch (BLOCK_INFO_BLK_TYPE(blk->block_info)) {
222 case D71_BLK_TYPE_GCU:
225 case D71_BLK_TYPE_LPU:
226 pipe = d71->pipes[blk_id];
227 pipe->lpu_addr = reg;
230 case D71_BLK_TYPE_LPU_LAYER:
231 err = d71_layer_init(d71, blk, reg);
234 case D71_BLK_TYPE_LPU_WB_LAYER:
235 err = d71_wb_layer_init(d71, blk, reg);
238 case D71_BLK_TYPE_CU:
239 pipe = d71->pipes[blk_id];
241 err = d71_compiz_init(d71, blk, reg);
244 case D71_BLK_TYPE_CU_SPLITTER:
245 case D71_BLK_TYPE_CU_SCALER:
246 case D71_BLK_TYPE_CU_MERGER:
249 case D71_BLK_TYPE_DOU:
250 pipe = d71->pipes[blk_id];
251 pipe->dou_addr = reg;
254 case D71_BLK_TYPE_DOU_IPS:
255 err = d71_improc_init(d71, blk, reg);
258 case D71_BLK_TYPE_DOU_FT_COEFF:
259 pipe = d71->pipes[blk_id];
260 pipe->dou_ft_coeff_addr = reg;
263 case D71_BLK_TYPE_DOU_BS:
264 err = d71_timing_ctrlr_init(d71, blk, reg);
267 case D71_BLK_TYPE_GLB_LT_COEFF:
270 case D71_BLK_TYPE_GLB_SCL_COEFF:
271 d71->glb_scl_coeff_addr[blk_id] = reg;
275 DRM_ERROR("Unknown block (block_info: 0x%x) is found\n",