]> Git Repo - linux.git/blob - drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c
Merge remote-tracking branch 'spi/for-5.14' into spi-linus
[linux.git] / drivers / gpu / drm / arm / display / komeda / komeda_pipeline.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
4  * Author: James.Qian.Wang <[email protected]>
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 *
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
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 **
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 *
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 *
137 komeda_pipeline_get_first_component(struct komeda_pipeline *pipe,
138                                     u32 comp_mask)
139 {
140         struct komeda_component *c = NULL;
141         unsigned long comp_mask_local = (unsigned long)comp_mask;
142         int id;
143
144         id = find_first_bit(&comp_mask_local, 32);
145         if (id < 32)
146                 c = komeda_pipeline_get_component(pipe, id);
147
148         return c;
149 }
150
151 static struct komeda_component *
152 komeda_component_pickup_input(struct komeda_component *c, u32 avail_comps)
153 {
154         u32 avail_inputs = c->supported_inputs & (avail_comps);
155
156         return komeda_pipeline_get_first_component(c->pipeline, avail_inputs);
157 }
158
159 /** komeda_component_add - Add a component to &komeda_pipeline */
160 struct komeda_component *
161 komeda_component_add(struct komeda_pipeline *pipe,
162                      size_t comp_sz, u32 id, u32 hw_id,
163                      const struct komeda_component_funcs *funcs,
164                      u8 max_active_inputs, u32 supported_inputs,
165                      u8 max_active_outputs, u32 __iomem *reg,
166                      const char *name_fmt, ...)
167 {
168         struct komeda_component **pos;
169         struct komeda_component *c;
170         int idx, *num = NULL;
171
172         if (max_active_inputs > KOMEDA_COMPONENT_N_INPUTS) {
173                 WARN(1, "please large KOMEDA_COMPONENT_N_INPUTS to %d.\n",
174                      max_active_inputs);
175                 return ERR_PTR(-ENOSPC);
176         }
177
178         pos = komeda_pipeline_get_component_pos(pipe, id);
179         if (!pos || (*pos))
180                 return ERR_PTR(-EINVAL);
181
182         if (has_bit(id, KOMEDA_PIPELINE_LAYERS)) {
183                 idx = id - KOMEDA_COMPONENT_LAYER0;
184                 num = &pipe->n_layers;
185                 if (idx != pipe->n_layers) {
186                         DRM_ERROR("please add Layer by id sequence.\n");
187                         return ERR_PTR(-EINVAL);
188                 }
189         } else if (has_bit(id,  KOMEDA_PIPELINE_SCALERS)) {
190                 idx = id - KOMEDA_COMPONENT_SCALER0;
191                 num = &pipe->n_scalers;
192                 if (idx != pipe->n_scalers) {
193                         DRM_ERROR("please add Scaler by id sequence.\n");
194                         return ERR_PTR(-EINVAL);
195                 }
196         }
197
198         c = devm_kzalloc(pipe->mdev->dev, comp_sz, GFP_KERNEL);
199         if (!c)
200                 return ERR_PTR(-ENOMEM);
201
202         c->id = id;
203         c->hw_id = hw_id;
204         c->reg = reg;
205         c->pipeline = pipe;
206         c->max_active_inputs = max_active_inputs;
207         c->max_active_outputs = max_active_outputs;
208         c->supported_inputs = supported_inputs;
209         c->funcs = funcs;
210
211         if (name_fmt) {
212                 va_list args;
213
214                 va_start(args, name_fmt);
215                 vsnprintf(c->name, sizeof(c->name), name_fmt, args);
216                 va_end(args);
217         }
218
219         if (num)
220                 *num = *num + 1;
221
222         pipe->avail_comps |= BIT(c->id);
223         *pos = c;
224
225         return c;
226 }
227
228 void komeda_component_destroy(struct komeda_dev *mdev,
229                               struct komeda_component *c)
230 {
231         devm_kfree(mdev->dev, c);
232 }
233
234 static void komeda_component_dump(struct komeda_component *c)
235 {
236         if (!c)
237                 return;
238
239         DRM_DEBUG("     %s: ID %d-0x%08lx.\n",
240                   c->name, c->id, BIT(c->id));
241         DRM_DEBUG("             max_active_inputs:%d, supported_inputs: 0x%08x.\n",
242                   c->max_active_inputs, c->supported_inputs);
243         DRM_DEBUG("             max_active_outputs:%d, supported_outputs: 0x%08x.\n",
244                   c->max_active_outputs, c->supported_outputs);
245 }
246
247 static void komeda_pipeline_dump(struct komeda_pipeline *pipe)
248 {
249         struct komeda_component *c;
250         int id;
251         unsigned long avail_comps = pipe->avail_comps;
252
253         DRM_INFO("Pipeline-%d: n_layers: %d, n_scalers: %d, output: %s.\n",
254                  pipe->id, pipe->n_layers, pipe->n_scalers,
255                  pipe->dual_link ? "dual-link" : "single-link");
256         DRM_INFO("      output_link[0]: %s.\n",
257                  pipe->of_output_links[0] ?
258                  pipe->of_output_links[0]->full_name : "none");
259         DRM_INFO("      output_link[1]: %s.\n",
260                  pipe->of_output_links[1] ?
261                  pipe->of_output_links[1]->full_name : "none");
262
263         for_each_set_bit(id, &avail_comps, 32) {
264                 c = komeda_pipeline_get_component(pipe, id);
265
266                 komeda_component_dump(c);
267         }
268 }
269
270 static void komeda_component_verify_inputs(struct komeda_component *c)
271 {
272         struct komeda_pipeline *pipe = c->pipeline;
273         struct komeda_component *input;
274         int id;
275         unsigned long supported_inputs = c->supported_inputs;
276
277         for_each_set_bit(id, &supported_inputs, 32) {
278                 input = komeda_pipeline_get_component(pipe, id);
279                 if (!input) {
280                         c->supported_inputs &= ~(BIT(id));
281                         DRM_WARN("Can not find input(ID-%d) for component: %s.\n",
282                                  id, c->name);
283                         continue;
284                 }
285
286                 input->supported_outputs |= BIT(c->id);
287         }
288 }
289
290 static struct komeda_layer *
291 komeda_get_layer_split_right_layer(struct komeda_pipeline *pipe,
292                                    struct komeda_layer *left)
293 {
294         int index = left->base.id - KOMEDA_COMPONENT_LAYER0;
295         int i;
296
297         for (i = index + 1; i < pipe->n_layers; i++)
298                 if (left->layer_type == pipe->layers[i]->layer_type)
299                         return pipe->layers[i];
300         return NULL;
301 }
302
303 static void komeda_pipeline_assemble(struct komeda_pipeline *pipe)
304 {
305         struct komeda_component *c;
306         struct komeda_layer *layer;
307         int i, id;
308         unsigned long avail_comps = pipe->avail_comps;
309
310         for_each_set_bit(id, &avail_comps, 32) {
311                 c = komeda_pipeline_get_component(pipe, id);
312                 komeda_component_verify_inputs(c);
313         }
314         /* calculate right layer for the layer split */
315         for (i = 0; i < pipe->n_layers; i++) {
316                 layer = pipe->layers[i];
317
318                 layer->right = komeda_get_layer_split_right_layer(pipe, layer);
319         }
320
321         if (pipe->dual_link && !pipe->ctrlr->supports_dual_link) {
322                 pipe->dual_link = false;
323                 DRM_WARN("PIPE-%d doesn't support dual-link, ignore DT dual-link configuration.\n",
324                          pipe->id);
325         }
326 }
327
328 /* if pipeline_A accept another pipeline_B's component as input, treat
329  * pipeline_B as slave of pipeline_A.
330  */
331 struct komeda_pipeline *
332 komeda_pipeline_get_slave(struct komeda_pipeline *master)
333 {
334         struct komeda_component *slave;
335
336         slave = komeda_component_pickup_input(&master->compiz->base,
337                                               KOMEDA_PIPELINE_COMPIZS);
338
339         return slave ? slave->pipeline : NULL;
340 }
341
342 int komeda_assemble_pipelines(struct komeda_dev *mdev)
343 {
344         struct komeda_pipeline *pipe;
345         int i;
346
347         for (i = 0; i < mdev->n_pipelines; i++) {
348                 pipe = mdev->pipelines[i];
349
350                 komeda_pipeline_assemble(pipe);
351                 komeda_pipeline_dump(pipe);
352         }
353
354         return 0;
355 }
356
357 void komeda_pipeline_dump_register(struct komeda_pipeline *pipe,
358                                    struct seq_file *sf)
359 {
360         struct komeda_component *c;
361         u32 id;
362         unsigned long avail_comps;
363
364         seq_printf(sf, "\n======== Pipeline-%d ==========\n", pipe->id);
365
366         if (pipe->funcs && pipe->funcs->dump_register)
367                 pipe->funcs->dump_register(pipe, sf);
368
369         avail_comps = pipe->avail_comps;
370         for_each_set_bit(id, &avail_comps, 32) {
371                 c = komeda_pipeline_get_component(pipe, id);
372
373                 seq_printf(sf, "\n------%s------\n", c->name);
374                 if (c->funcs->dump_register)
375                         c->funcs->dump_register(c, sf);
376         }
377 }
This page took 0.057528 seconds and 4 git commands to generate.