1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
4 * Author: James.Qian.Wang <james.qian.wang@arm.com>
5 *
6 */
7 #include <drm/drm_print.h>
8
9 #include "komeda_dev.h"
10 #include "komeda_pipeline.h"
11
12 /** komeda_pipeline_add - Add a pipeline to &komeda_dev */
13 struct komeda_pipeline *
komeda_pipeline_add(struct komeda_dev * mdev,size_t size,const struct komeda_pipeline_funcs * funcs)14 komeda_pipeline_add(struct komeda_dev *mdev, size_t size,
15 const struct komeda_pipeline_funcs *funcs)
16 {
17 struct komeda_pipeline *pipe;
18
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);
23 }
24
25 if (size < sizeof(*pipe)) {
26 DRM_ERROR("Request pipeline size too small.\n");
27 return ERR_PTR(-EINVAL);
28 }
29
30 pipe = devm_kzalloc(mdev->dev, size, GFP_KERNEL);
31 if (!pipe)
32 return ERR_PTR(-ENOMEM);
33
34 pipe->mdev = mdev;
35 pipe->id = mdev->n_pipelines;
36 pipe->funcs = funcs;
37
38 mdev->pipelines[mdev->n_pipelines] = pipe;
39 mdev->n_pipelines++;
40
41 return pipe;
42 }
43
komeda_pipeline_destroy(struct komeda_dev * mdev,struct komeda_pipeline * pipe)44 void komeda_pipeline_destroy(struct komeda_dev *mdev,
45 struct komeda_pipeline *pipe)
46 {
47 struct komeda_component *c;
48 int i;
49 unsigned long avail_comps = pipe->avail_comps;
50
51 for_each_set_bit(i, &avail_comps, 32) {
52 c = komeda_pipeline_get_component(pipe, i);
53 komeda_component_destroy(mdev, c);
54 }
55
56 clk_put(pipe->pxlclk);
57
58 of_node_put(pipe->of_output_links[0]);
59 of_node_put(pipe->of_output_links[1]);
60 of_node_put(pipe->of_output_port);
61 of_node_put(pipe->of_node);
62
63 devm_kfree(mdev->dev, pipe);
64 }
65
66 static struct komeda_component **
komeda_pipeline_get_component_pos(struct komeda_pipeline * pipe,int id)67 komeda_pipeline_get_component_pos(struct komeda_pipeline *pipe, int id)
68 {
69 struct komeda_dev *mdev = pipe->mdev;
70 struct komeda_pipeline *temp = NULL;
71 struct komeda_component **pos = NULL;
72
73 switch (id) {
74 case KOMEDA_COMPONENT_LAYER0:
75 case KOMEDA_COMPONENT_LAYER1:
76 case KOMEDA_COMPONENT_LAYER2:
77 case KOMEDA_COMPONENT_LAYER3:
78 pos = to_cpos(pipe->layers[id - KOMEDA_COMPONENT_LAYER0]);
79 break;
80 case KOMEDA_COMPONENT_WB_LAYER:
81 pos = to_cpos(pipe->wb_layer);
82 break;
83 case KOMEDA_COMPONENT_COMPIZ0:
84 case KOMEDA_COMPONENT_COMPIZ1:
85 temp = mdev->pipelines[id - KOMEDA_COMPONENT_COMPIZ0];
86 if (!temp) {
87 DRM_ERROR("compiz-%d doesn't exist.\n", id);
88 return NULL;
89 }
90 pos = to_cpos(temp->compiz);
91 break;
92 case KOMEDA_COMPONENT_SCALER0:
93 case KOMEDA_COMPONENT_SCALER1:
94 pos = to_cpos(pipe->scalers[id - KOMEDA_COMPONENT_SCALER0]);
95 break;
96 case KOMEDA_COMPONENT_SPLITTER:
97 pos = to_cpos(pipe->splitter);
98 break;
99 case KOMEDA_COMPONENT_MERGER:
100 pos = to_cpos(pipe->merger);
101 break;
102 case KOMEDA_COMPONENT_IPS0:
103 case KOMEDA_COMPONENT_IPS1:
104 temp = mdev->pipelines[id - KOMEDA_COMPONENT_IPS0];
105 if (!temp) {
106 DRM_ERROR("ips-%d doesn't exist.\n", id);
107 return NULL;
108 }
109 pos = to_cpos(temp->improc);
110 break;
111 case KOMEDA_COMPONENT_TIMING_CTRLR:
112 pos = to_cpos(pipe->ctrlr);
113 break;
114 default:
115 pos = NULL;
116 DRM_ERROR("Unknown pipeline resource ID: %d.\n", id);
117 break;
118 }
119
120 return pos;
121 }
122
123 struct komeda_component *
komeda_pipeline_get_component(struct komeda_pipeline * pipe,int id)124 komeda_pipeline_get_component(struct komeda_pipeline *pipe, int id)
125 {
126 struct komeda_component **pos = NULL;
127 struct komeda_component *c = NULL;
128
129 pos = komeda_pipeline_get_component_pos(pipe, id);
130 if (pos)
131 c = *pos;
132
133 return c;
134 }
135
136 struct komeda_component *
komeda_pipeline_get_first_component(struct komeda_pipeline * pipe,u32 comp_mask)137 komeda_pipeline_get_first_component(struct komeda_pipeline *pipe,
138 u32 comp_mask)
139 {
140 struct komeda_component *c = NULL;
141 int id;
142
143 id = find_first_bit((unsigned long *)&comp_mask, 32);
144 if (id < 32)
145 c = komeda_pipeline_get_component(pipe, id);
146
147 return c;
148 }
149
150 static struct komeda_component *
komeda_component_pickup_input(struct komeda_component * c,u32 avail_comps)151 komeda_component_pickup_input(struct komeda_component *c, u32 avail_comps)
152 {
153 u32 avail_inputs = c->supported_inputs & (avail_comps);
154
155 return komeda_pipeline_get_first_component(c->pipeline, avail_inputs);
156 }
157
158 /** komeda_component_add - Add a component to &komeda_pipeline */
159 struct komeda_component *
komeda_component_add(struct komeda_pipeline * pipe,size_t comp_sz,u32 id,u32 hw_id,const struct komeda_component_funcs * funcs,u8 max_active_inputs,u32 supported_inputs,u8 max_active_outputs,u32 __iomem * reg,const char * name_fmt,...)160 komeda_component_add(struct komeda_pipeline *pipe,
161 size_t comp_sz, u32 id, u32 hw_id,
162 const struct komeda_component_funcs *funcs,
163 u8 max_active_inputs, u32 supported_inputs,
164 u8 max_active_outputs, u32 __iomem *reg,
165 const char *name_fmt, ...)
166 {
167 struct komeda_component **pos;
168 struct komeda_component *c;
169 int idx, *num = NULL;
170
171 if (max_active_inputs > KOMEDA_COMPONENT_N_INPUTS) {
172 WARN(1, "please large KOMEDA_COMPONENT_N_INPUTS to %d.\n",
173 max_active_inputs);
174 return ERR_PTR(-ENOSPC);
175 }
176
177 pos = komeda_pipeline_get_component_pos(pipe, id);
178 if (!pos || (*pos))
179 return ERR_PTR(-EINVAL);
180
181 if (has_bit(id, KOMEDA_PIPELINE_LAYERS)) {
182 idx = id - KOMEDA_COMPONENT_LAYER0;
183 num = &pipe->n_layers;
184 if (idx != pipe->n_layers) {
185 DRM_ERROR("please add Layer by id sequence.\n");
186 return ERR_PTR(-EINVAL);
187 }
188 } else if (has_bit(id, KOMEDA_PIPELINE_SCALERS)) {
189 idx = id - KOMEDA_COMPONENT_SCALER0;
190 num = &pipe->n_scalers;
191 if (idx != pipe->n_scalers) {
192 DRM_ERROR("please add Scaler by id sequence.\n");
193 return ERR_PTR(-EINVAL);
194 }
195 }
196
197 c = devm_kzalloc(pipe->mdev->dev, comp_sz, GFP_KERNEL);
198 if (!c)
199 return ERR_PTR(-ENOMEM);
200
201 c->id = id;
202 c->hw_id = hw_id;
203 c->reg = reg;
204 c->pipeline = pipe;
205 c->max_active_inputs = max_active_inputs;
206 c->max_active_outputs = max_active_outputs;
207 c->supported_inputs = supported_inputs;
208 c->funcs = funcs;
209
210 if (name_fmt) {
211 va_list args;
212
213 va_start(args, name_fmt);
214 vsnprintf(c->name, sizeof(c->name), name_fmt, args);
215 va_end(args);
216 }
217
218 if (num)
219 *num = *num + 1;
220
221 pipe->avail_comps |= BIT(c->id);
222 *pos = c;
223
224 return c;
225 }
226
komeda_component_destroy(struct komeda_dev * mdev,struct komeda_component * c)227 void komeda_component_destroy(struct komeda_dev *mdev,
228 struct komeda_component *c)
229 {
230 devm_kfree(mdev->dev, c);
231 }
232
komeda_component_dump(struct komeda_component * c)233 static void komeda_component_dump(struct komeda_component *c)
234 {
235 if (!c)
236 return;
237
238 DRM_DEBUG(" %s: ID %d-0x%08lx.\n",
239 c->name, c->id, BIT(c->id));
240 DRM_DEBUG(" max_active_inputs:%d, supported_inputs: 0x%08x.\n",
241 c->max_active_inputs, c->supported_inputs);
242 DRM_DEBUG(" max_active_outputs:%d, supported_outputs: 0x%08x.\n",
243 c->max_active_outputs, c->supported_outputs);
244 }
245
komeda_pipeline_dump(struct komeda_pipeline * pipe)246 static void komeda_pipeline_dump(struct komeda_pipeline *pipe)
247 {
248 struct komeda_component *c;
249 int id;
250 unsigned long avail_comps = pipe->avail_comps;
251
252 DRM_INFO("Pipeline-%d: n_layers: %d, n_scalers: %d, output: %s.\n",
253 pipe->id, pipe->n_layers, pipe->n_scalers,
254 pipe->dual_link ? "dual-link" : "single-link");
255 DRM_INFO(" output_link[0]: %s.\n",
256 pipe->of_output_links[0] ?
257 pipe->of_output_links[0]->full_name : "none");
258 DRM_INFO(" output_link[1]: %s.\n",
259 pipe->of_output_links[1] ?
260 pipe->of_output_links[1]->full_name : "none");
261
262 for_each_set_bit(id, &avail_comps, 32) {
263 c = komeda_pipeline_get_component(pipe, id);
264
265 komeda_component_dump(c);
266 }
267 }
268
komeda_component_verify_inputs(struct komeda_component * c)269 static void komeda_component_verify_inputs(struct komeda_component *c)
270 {
271 struct komeda_pipeline *pipe = c->pipeline;
272 struct komeda_component *input;
273 int id;
274 unsigned long supported_inputs = c->supported_inputs;
275
276 for_each_set_bit(id, &supported_inputs, 32) {
277 input = komeda_pipeline_get_component(pipe, id);
278 if (!input) {
279 c->supported_inputs &= ~(BIT(id));
280 DRM_WARN("Can not find input(ID-%d) for component: %s.\n",
281 id, c->name);
282 continue;
283 }
284
285 input->supported_outputs |= BIT(c->id);
286 }
287 }
288
289 static struct komeda_layer *
komeda_get_layer_split_right_layer(struct komeda_pipeline * pipe,struct komeda_layer * left)290 komeda_get_layer_split_right_layer(struct komeda_pipeline *pipe,
291 struct komeda_layer *left)
292 {
293 int index = left->base.id - KOMEDA_COMPONENT_LAYER0;
294 int i;
295
296 for (i = index + 1; i < pipe->n_layers; i++)
297 if (left->layer_type == pipe->layers[i]->layer_type)
298 return pipe->layers[i];
299 return NULL;
300 }
301
komeda_pipeline_assemble(struct komeda_pipeline * pipe)302 static void komeda_pipeline_assemble(struct komeda_pipeline *pipe)
303 {
304 struct komeda_component *c;
305 struct komeda_layer *layer;
306 int i, id;
307 unsigned long avail_comps = pipe->avail_comps;
308
309 for_each_set_bit(id, &avail_comps, 32) {
310 c = komeda_pipeline_get_component(pipe, id);
311 komeda_component_verify_inputs(c);
312 }
313 /* calculate right layer for the layer split */
314 for (i = 0; i < pipe->n_layers; i++) {
315 layer = pipe->layers[i];
316
317 layer->right = komeda_get_layer_split_right_layer(pipe, layer);
318 }
319
320 if (pipe->dual_link && !pipe->ctrlr->supports_dual_link) {
321 pipe->dual_link = false;
322 DRM_WARN("PIPE-%d doesn't support dual-link, ignore DT dual-link configuration.\n",
323 pipe->id);
324 }
325 }
326
327 /* if pipeline_A accept another pipeline_B's component as input, treat
328 * pipeline_B as slave of pipeline_A.
329 */
330 struct komeda_pipeline *
komeda_pipeline_get_slave(struct komeda_pipeline * master)331 komeda_pipeline_get_slave(struct komeda_pipeline *master)
332 {
333 struct komeda_component *slave;
334
335 slave = komeda_component_pickup_input(&master->compiz->base,
336 KOMEDA_PIPELINE_COMPIZS);
337
338 return slave ? slave->pipeline : NULL;
339 }
340
komeda_assemble_pipelines(struct komeda_dev * mdev)341 int komeda_assemble_pipelines(struct komeda_dev *mdev)
342 {
343 struct komeda_pipeline *pipe;
344 int i;
345
346 for (i = 0; i < mdev->n_pipelines; i++) {
347 pipe = mdev->pipelines[i];
348
349 komeda_pipeline_assemble(pipe);
350 komeda_pipeline_dump(pipe);
351 }
352
353 return 0;
354 }
355
komeda_pipeline_dump_register(struct komeda_pipeline * pipe,struct seq_file * sf)356 void komeda_pipeline_dump_register(struct komeda_pipeline *pipe,
357 struct seq_file *sf)
358 {
359 struct komeda_component *c;
360 u32 id;
361 unsigned long avail_comps;
362
363 seq_printf(sf, "\n======== Pipeline-%d ==========\n", pipe->id);
364
365 if (pipe->funcs && pipe->funcs->dump_register)
366 pipe->funcs->dump_register(pipe, sf);
367
368 avail_comps = pipe->avail_comps;
369 for_each_set_bit(id, &avail_comps, 32) {
370 c = komeda_pipeline_get_component(pipe, id);
371
372 seq_printf(sf, "\n------%s------\n", c->name);
373 if (c->funcs->dump_register)
374 c->funcs->dump_register(c, sf);
375 }
376 }
377