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>
7 #include <drm/drm_print.h>
9 #include "komeda_dev.h"
10 #include "komeda_pipeline.h"
12 /** komeda_pipeline_add - Add a pipeline to &komeda_dev */
13 struct komeda_pipeline
*
14 komeda_pipeline_add(struct komeda_dev
*mdev
, size_t size
,
15 const struct komeda_pipeline_funcs
*funcs
)
17 struct komeda_pipeline
*pipe
;
19 if (mdev
->n_pipelines
+ 1 > KOMEDA_MAX_PIPELINES
) {
20 DRM_ERROR("Exceed max support %d pipelines.\n",
21 KOMEDA_MAX_PIPELINES
);
22 return ERR_PTR(-ENOSPC
);
25 if (size
< sizeof(*pipe
)) {
26 DRM_ERROR("Request pipeline size too small.\n");
27 return ERR_PTR(-EINVAL
);
30 pipe
= devm_kzalloc(mdev
->dev
, size
, GFP_KERNEL
);
32 return ERR_PTR(-ENOMEM
);
35 pipe
->id
= mdev
->n_pipelines
;
38 mdev
->pipelines
[mdev
->n_pipelines
] = pipe
;
44 void komeda_pipeline_destroy(struct komeda_dev
*mdev
,
45 struct komeda_pipeline
*pipe
)
47 struct komeda_component
*c
;
50 dp_for_each_set_bit(i
, pipe
->avail_comps
) {
51 c
= komeda_pipeline_get_component(pipe
, i
);
52 komeda_component_destroy(mdev
, c
);
55 clk_put(pipe
->pxlclk
);
57 of_node_put(pipe
->of_output_links
[0]);
58 of_node_put(pipe
->of_output_links
[1]);
59 of_node_put(pipe
->of_output_port
);
60 of_node_put(pipe
->of_node
);
62 devm_kfree(mdev
->dev
, pipe
);
65 static struct komeda_component
**
66 komeda_pipeline_get_component_pos(struct komeda_pipeline
*pipe
, int id
)
68 struct komeda_dev
*mdev
= pipe
->mdev
;
69 struct komeda_pipeline
*temp
= NULL
;
70 struct komeda_component
**pos
= NULL
;
73 case KOMEDA_COMPONENT_LAYER0
:
74 case KOMEDA_COMPONENT_LAYER1
:
75 case KOMEDA_COMPONENT_LAYER2
:
76 case KOMEDA_COMPONENT_LAYER3
:
77 pos
= to_cpos(pipe
->layers
[id
- KOMEDA_COMPONENT_LAYER0
]);
79 case KOMEDA_COMPONENT_WB_LAYER
:
80 pos
= to_cpos(pipe
->wb_layer
);
82 case KOMEDA_COMPONENT_COMPIZ0
:
83 case KOMEDA_COMPONENT_COMPIZ1
:
84 temp
= mdev
->pipelines
[id
- KOMEDA_COMPONENT_COMPIZ0
];
86 DRM_ERROR("compiz-%d doesn't exist.\n", id
);
89 pos
= to_cpos(temp
->compiz
);
91 case KOMEDA_COMPONENT_SCALER0
:
92 case KOMEDA_COMPONENT_SCALER1
:
93 pos
= to_cpos(pipe
->scalers
[id
- KOMEDA_COMPONENT_SCALER0
]);
95 case KOMEDA_COMPONENT_SPLITTER
:
96 pos
= to_cpos(pipe
->splitter
);
98 case KOMEDA_COMPONENT_MERGER
:
99 pos
= to_cpos(pipe
->merger
);
101 case KOMEDA_COMPONENT_IPS0
:
102 case KOMEDA_COMPONENT_IPS1
:
103 temp
= mdev
->pipelines
[id
- KOMEDA_COMPONENT_IPS0
];
105 DRM_ERROR("ips-%d doesn't exist.\n", id
);
108 pos
= to_cpos(temp
->improc
);
110 case KOMEDA_COMPONENT_TIMING_CTRLR
:
111 pos
= to_cpos(pipe
->ctrlr
);
115 DRM_ERROR("Unknown pipeline resource ID: %d.\n", id
);
122 struct komeda_component
*
123 komeda_pipeline_get_component(struct komeda_pipeline
*pipe
, int id
)
125 struct komeda_component
**pos
= NULL
;
126 struct komeda_component
*c
= NULL
;
128 pos
= komeda_pipeline_get_component_pos(pipe
, id
);
135 struct komeda_component
*
136 komeda_pipeline_get_first_component(struct komeda_pipeline
*pipe
,
139 struct komeda_component
*c
= NULL
;
142 id
= find_first_bit((unsigned long *)&comp_mask
, 32);
144 c
= komeda_pipeline_get_component(pipe
, id
);
149 static struct komeda_component
*
150 komeda_component_pickup_input(struct komeda_component
*c
, u32 avail_comps
)
152 u32 avail_inputs
= c
->supported_inputs
& (avail_comps
);
154 return komeda_pipeline_get_first_component(c
->pipeline
, avail_inputs
);
157 /** komeda_component_add - Add a component to &komeda_pipeline */
158 struct komeda_component
*
159 komeda_component_add(struct komeda_pipeline
*pipe
,
160 size_t comp_sz
, u32 id
, u32 hw_id
,
161 const struct komeda_component_funcs
*funcs
,
162 u8 max_active_inputs
, u32 supported_inputs
,
163 u8 max_active_outputs
, u32 __iomem
*reg
,
164 const char *name_fmt
, ...)
166 struct komeda_component
**pos
;
167 struct komeda_component
*c
;
168 int idx
, *num
= NULL
;
170 if (max_active_inputs
> KOMEDA_COMPONENT_N_INPUTS
) {
171 WARN(1, "please large KOMEDA_COMPONENT_N_INPUTS to %d.\n",
173 return ERR_PTR(-ENOSPC
);
176 pos
= komeda_pipeline_get_component_pos(pipe
, id
);
178 return ERR_PTR(-EINVAL
);
180 if (has_bit(id
, KOMEDA_PIPELINE_LAYERS
)) {
181 idx
= id
- KOMEDA_COMPONENT_LAYER0
;
182 num
= &pipe
->n_layers
;
183 if (idx
!= pipe
->n_layers
) {
184 DRM_ERROR("please add Layer by id sequence.\n");
185 return ERR_PTR(-EINVAL
);
187 } else if (has_bit(id
, KOMEDA_PIPELINE_SCALERS
)) {
188 idx
= id
- KOMEDA_COMPONENT_SCALER0
;
189 num
= &pipe
->n_scalers
;
190 if (idx
!= pipe
->n_scalers
) {
191 DRM_ERROR("please add Scaler by id sequence.\n");
192 return ERR_PTR(-EINVAL
);
196 c
= devm_kzalloc(pipe
->mdev
->dev
, comp_sz
, GFP_KERNEL
);
198 return ERR_PTR(-ENOMEM
);
204 c
->max_active_inputs
= max_active_inputs
;
205 c
->max_active_outputs
= max_active_outputs
;
206 c
->supported_inputs
= supported_inputs
;
212 va_start(args
, name_fmt
);
213 vsnprintf(c
->name
, sizeof(c
->name
), name_fmt
, args
);
220 pipe
->avail_comps
|= BIT(c
->id
);
226 void komeda_component_destroy(struct komeda_dev
*mdev
,
227 struct komeda_component
*c
)
229 devm_kfree(mdev
->dev
, c
);
232 static void komeda_component_dump(struct komeda_component
*c
)
237 DRM_DEBUG(" %s: ID %d-0x%08lx.\n",
238 c
->name
, c
->id
, BIT(c
->id
));
239 DRM_DEBUG(" max_active_inputs:%d, supported_inputs: 0x%08x.\n",
240 c
->max_active_inputs
, c
->supported_inputs
);
241 DRM_DEBUG(" max_active_outputs:%d, supported_outputs: 0x%08x.\n",
242 c
->max_active_outputs
, c
->supported_outputs
);
245 static void komeda_pipeline_dump(struct komeda_pipeline
*pipe
)
247 struct komeda_component
*c
;
250 DRM_INFO("Pipeline-%d: n_layers: %d, n_scalers: %d, output: %s.\n",
251 pipe
->id
, pipe
->n_layers
, pipe
->n_scalers
,
252 pipe
->dual_link
? "dual-link" : "single-link");
253 DRM_INFO(" output_link[0]: %s.\n",
254 pipe
->of_output_links
[0] ?
255 pipe
->of_output_links
[0]->full_name
: "none");
256 DRM_INFO(" output_link[1]: %s.\n",
257 pipe
->of_output_links
[1] ?
258 pipe
->of_output_links
[1]->full_name
: "none");
260 dp_for_each_set_bit(id
, pipe
->avail_comps
) {
261 c
= komeda_pipeline_get_component(pipe
, id
);
263 komeda_component_dump(c
);
267 static void komeda_component_verify_inputs(struct komeda_component
*c
)
269 struct komeda_pipeline
*pipe
= c
->pipeline
;
270 struct komeda_component
*input
;
273 dp_for_each_set_bit(id
, c
->supported_inputs
) {
274 input
= komeda_pipeline_get_component(pipe
, id
);
276 c
->supported_inputs
&= ~(BIT(id
));
277 DRM_WARN("Can not find input(ID-%d) for component: %s.\n",
282 input
->supported_outputs
|= BIT(c
->id
);
286 static struct komeda_layer
*
287 komeda_get_layer_split_right_layer(struct komeda_pipeline
*pipe
,
288 struct komeda_layer
*left
)
290 int index
= left
->base
.id
- KOMEDA_COMPONENT_LAYER0
;
293 for (i
= index
+ 1; i
< pipe
->n_layers
; i
++)
294 if (left
->layer_type
== pipe
->layers
[i
]->layer_type
)
295 return pipe
->layers
[i
];
299 static void komeda_pipeline_assemble(struct komeda_pipeline
*pipe
)
301 struct komeda_component
*c
;
302 struct komeda_layer
*layer
;
305 dp_for_each_set_bit(id
, pipe
->avail_comps
) {
306 c
= komeda_pipeline_get_component(pipe
, id
);
307 komeda_component_verify_inputs(c
);
309 /* calculate right layer for the layer split */
310 for (i
= 0; i
< pipe
->n_layers
; i
++) {
311 layer
= pipe
->layers
[i
];
313 layer
->right
= komeda_get_layer_split_right_layer(pipe
, layer
);
316 if (pipe
->dual_link
&& !pipe
->ctrlr
->supports_dual_link
) {
317 pipe
->dual_link
= false;
318 DRM_WARN("PIPE-%d doesn't support dual-link, ignore DT dual-link configuration.\n",
323 /* if pipeline_A accept another pipeline_B's component as input, treat
324 * pipeline_B as slave of pipeline_A.
326 struct komeda_pipeline
*
327 komeda_pipeline_get_slave(struct komeda_pipeline
*master
)
329 struct komeda_component
*slave
;
331 slave
= komeda_component_pickup_input(&master
->compiz
->base
,
332 KOMEDA_PIPELINE_COMPIZS
);
334 return slave
? slave
->pipeline
: NULL
;
337 int komeda_assemble_pipelines(struct komeda_dev
*mdev
)
339 struct komeda_pipeline
*pipe
;
342 for (i
= 0; i
< mdev
->n_pipelines
; i
++) {
343 pipe
= mdev
->pipelines
[i
];
345 komeda_pipeline_assemble(pipe
);
346 komeda_pipeline_dump(pipe
);
352 void komeda_pipeline_dump_register(struct komeda_pipeline
*pipe
,
355 struct komeda_component
*c
;
358 seq_printf(sf
, "\n======== Pipeline-%d ==========\n", pipe
->id
);
360 if (pipe
->funcs
&& pipe
->funcs
->dump_register
)
361 pipe
->funcs
->dump_register(pipe
, sf
);
363 dp_for_each_set_bit(id
, pipe
->avail_comps
) {
364 c
= komeda_pipeline_get_component(pipe
, id
);
366 seq_printf(sf
, "\n------%s------\n", c
->name
);
367 if (c
->funcs
->dump_register
)
368 c
->funcs
->dump_register(c
, sf
);