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 inline u32 to_d71_input_id(struct komeda_component_output *output)
103 struct komeda_component *comp = output->component;
105 return comp ? (comp->hw_id + output->output_port) : 0;
108 static void d71_layer_disable(struct komeda_component *c)
110 malidp_write32_mask(c->reg, BLK_CONTROL, L_EN, 0);
113 static void d71_layer_update(struct komeda_component *c,
114 struct komeda_component_state *state)
116 struct komeda_layer_state *st = to_layer_st(state);
117 struct drm_plane_state *plane_st = state->plane->state;
118 struct drm_framebuffer *fb = plane_st->fb;
119 struct komeda_fb *kfb = to_kfb(fb);
120 u32 __iomem *reg = c->reg;
121 u32 ctrl_mask = L_EN | L_ROT(L_ROT_R270) | L_HFLIP | L_VFLIP | L_TBU_EN;
122 u32 ctrl = L_EN | to_rot_ctrl(st->rot);
125 for (i = 0; i < fb->format->num_planes; i++) {
127 BLK_P0_PTR_LOW + i * LAYER_PER_PLANE_REGS * 4,
128 lower_32_bits(st->addr[i]));
130 BLK_P0_PTR_HIGH + i * LAYER_PER_PLANE_REGS * 4,
131 upper_32_bits(st->addr[i]));
136 BLK_P0_STRIDE + i * LAYER_PER_PLANE_REGS * 4,
137 fb->pitches[i] & 0xFFFF);
140 malidp_write32(reg, LAYER_FMT, kfb->format_caps->hw_id);
141 malidp_write32(reg, BLK_IN_SIZE, HV_SIZE(st->hsize, st->vsize));
143 malidp_write32_mask(reg, BLK_CONTROL, ctrl_mask, ctrl);
146 static struct komeda_component_funcs d71_layer_funcs = {
147 .update = d71_layer_update,
148 .disable = d71_layer_disable,
151 static int d71_layer_init(struct d71_dev *d71,
152 struct block_header *blk, u32 __iomem *reg)
154 struct komeda_component *c;
155 struct komeda_layer *layer;
156 u32 pipe_id, layer_id, layer_info;
158 get_resources_id(blk->block_info, &pipe_id, &layer_id);
159 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*layer),
161 BLOCK_INFO_INPUT_ID(blk->block_info),
163 get_valid_inputs(blk),
164 1, reg, "LPU%d_LAYER%d", pipe_id, layer_id);
166 DRM_ERROR("Failed to add layer component\n");
171 layer_info = malidp_read32(reg, LAYER_INFO);
173 if (layer_info & L_INFO_RF)
174 layer->layer_type = KOMEDA_FMT_RICH_LAYER;
176 layer->layer_type = KOMEDA_FMT_SIMPLE_LAYER;
178 set_range(&layer->hsize_in, 4, d71->max_line_size);
179 set_range(&layer->vsize_in, 4, d71->max_vsize);
181 malidp_write32(reg, LAYER_PALPHA, D71_PALPHA_DEF_MAP);
183 layer->supported_rots = DRM_MODE_ROTATE_MASK | DRM_MODE_REFLECT_MASK;
188 static int d71_wb_layer_init(struct d71_dev *d71,
189 struct block_header *blk, u32 __iomem *reg)
191 DRM_DEBUG("Detect D71_Wb_Layer.\n");
196 static void d71_component_disable(struct komeda_component *c)
198 u32 __iomem *reg = c->reg;
201 malidp_write32(reg, BLK_CONTROL, 0);
203 for (i = 0; i < c->max_active_inputs; i++)
204 malidp_write32(reg, BLK_INPUT_ID0 + (i << 2), 0);
207 static void compiz_enable_input(u32 __iomem *id_reg,
208 u32 __iomem *cfg_reg,
210 struct komeda_compiz_input_cfg *cin)
212 u32 ctrl = CU_INPUT_CTRL_EN;
213 u8 blend = cin->pixel_blend_mode;
215 if (blend == DRM_MODE_BLEND_PIXEL_NONE)
216 ctrl |= CU_INPUT_CTRL_PAD;
217 else if (blend == DRM_MODE_BLEND_PREMULTI)
218 ctrl |= CU_INPUT_CTRL_PMUL;
220 ctrl |= CU_INPUT_CTRL_ALPHA(cin->layer_alpha);
222 malidp_write32(id_reg, BLK_INPUT_ID0, input_hw_id);
224 malidp_write32(cfg_reg, CU_INPUT0_SIZE,
225 HV_SIZE(cin->hsize, cin->vsize));
226 malidp_write32(cfg_reg, CU_INPUT0_OFFSET,
227 HV_OFFSET(cin->hoffset, cin->voffset));
228 malidp_write32(cfg_reg, CU_INPUT0_CONTROL, ctrl);
231 static void d71_compiz_update(struct komeda_component *c,
232 struct komeda_component_state *state)
234 struct komeda_compiz_state *st = to_compiz_st(state);
235 u32 __iomem *reg = c->reg;
236 u32 __iomem *id_reg, *cfg_reg;
237 u32 index, input_hw_id;
239 for_each_changed_input(state, index) {
240 id_reg = reg + index;
241 cfg_reg = reg + index * CU_PER_INPUT_REGS;
242 input_hw_id = to_d71_input_id(&state->inputs[index]);
243 if (state->active_inputs & BIT(index)) {
244 compiz_enable_input(id_reg, cfg_reg,
245 input_hw_id, &st->cins[index]);
247 malidp_write32(id_reg, BLK_INPUT_ID0, 0);
248 malidp_write32(cfg_reg, CU_INPUT0_CONTROL, 0);
252 malidp_write32(reg, BLK_SIZE, HV_SIZE(st->hsize, st->vsize));
255 struct komeda_component_funcs d71_compiz_funcs = {
256 .update = d71_compiz_update,
257 .disable = d71_component_disable,
260 static int d71_compiz_init(struct d71_dev *d71,
261 struct block_header *blk, u32 __iomem *reg)
263 struct komeda_component *c;
264 struct komeda_compiz *compiz;
265 u32 pipe_id, comp_id;
267 get_resources_id(blk->block_info, &pipe_id, &comp_id);
269 c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*compiz),
271 BLOCK_INFO_INPUT_ID(blk->block_info),
273 CU_NUM_INPUT_IDS, get_valid_inputs(blk),
274 CU_NUM_OUTPUT_IDS, reg,
279 compiz = to_compiz(c);
281 set_range(&compiz->hsize, D71_MIN_LINE_SIZE, d71->max_line_size);
282 set_range(&compiz->vsize, D71_MIN_VERTICAL_SIZE, d71->max_vsize);
287 static int d71_improc_init(struct d71_dev *d71,
288 struct block_header *blk, u32 __iomem *reg)
290 DRM_DEBUG("Detect D71_improc.\n");
295 static int d71_timing_ctrlr_init(struct d71_dev *d71,
296 struct block_header *blk, u32 __iomem *reg)
298 DRM_DEBUG("Detect D71_timing_ctrlr.\n");
303 int d71_probe_block(struct d71_dev *d71,
304 struct block_header *blk, u32 __iomem *reg)
306 struct d71_pipeline *pipe;
307 int blk_id = BLOCK_INFO_BLK_ID(blk->block_info);
311 switch (BLOCK_INFO_BLK_TYPE(blk->block_info)) {
312 case D71_BLK_TYPE_GCU:
315 case D71_BLK_TYPE_LPU:
316 pipe = d71->pipes[blk_id];
317 pipe->lpu_addr = reg;
320 case D71_BLK_TYPE_LPU_LAYER:
321 err = d71_layer_init(d71, blk, reg);
324 case D71_BLK_TYPE_LPU_WB_LAYER:
325 err = d71_wb_layer_init(d71, blk, reg);
328 case D71_BLK_TYPE_CU:
329 pipe = d71->pipes[blk_id];
331 err = d71_compiz_init(d71, blk, reg);
334 case D71_BLK_TYPE_CU_SPLITTER:
335 case D71_BLK_TYPE_CU_SCALER:
336 case D71_BLK_TYPE_CU_MERGER:
339 case D71_BLK_TYPE_DOU:
340 pipe = d71->pipes[blk_id];
341 pipe->dou_addr = reg;
344 case D71_BLK_TYPE_DOU_IPS:
345 err = d71_improc_init(d71, blk, reg);
348 case D71_BLK_TYPE_DOU_FT_COEFF:
349 pipe = d71->pipes[blk_id];
350 pipe->dou_ft_coeff_addr = reg;
353 case D71_BLK_TYPE_DOU_BS:
354 err = d71_timing_ctrlr_init(d71, blk, reg);
357 case D71_BLK_TYPE_GLB_LT_COEFF:
360 case D71_BLK_TYPE_GLB_SCL_COEFF:
361 d71->glb_scl_coeff_addr[blk_id] = reg;
365 DRM_ERROR("Unknown block (block_info: 0x%x) is found\n",