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