Merge tag 'drm-next-2020-12-24' of git://anongit.freedesktop.org/drm/drm
[linux-2.6-microblaze.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 <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 *
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
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_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);
61
62         devm_kfree(mdev->dev, pipe);
63 }
64
65 static struct komeda_component **
66 komeda_pipeline_get_component_pos(struct komeda_pipeline *pipe, int id)
67 {
68         struct komeda_dev *mdev = pipe->mdev;
69         struct komeda_pipeline *temp = NULL;
70         struct komeda_component **pos = NULL;
71
72         switch (id) {
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]);
78                 break;
79         case KOMEDA_COMPONENT_WB_LAYER:
80                 pos = to_cpos(pipe->wb_layer);
81                 break;
82         case KOMEDA_COMPONENT_COMPIZ0:
83         case KOMEDA_COMPONENT_COMPIZ1:
84                 temp = mdev->pipelines[id - KOMEDA_COMPONENT_COMPIZ0];
85                 if (!temp) {
86                         DRM_ERROR("compiz-%d doesn't exist.\n", id);
87                         return NULL;
88                 }
89                 pos = to_cpos(temp->compiz);
90                 break;
91         case KOMEDA_COMPONENT_SCALER0:
92         case KOMEDA_COMPONENT_SCALER1:
93                 pos = to_cpos(pipe->scalers[id - KOMEDA_COMPONENT_SCALER0]);
94                 break;
95         case KOMEDA_COMPONENT_SPLITTER:
96                 pos = to_cpos(pipe->splitter);
97                 break;
98         case KOMEDA_COMPONENT_MERGER:
99                 pos = to_cpos(pipe->merger);
100                 break;
101         case KOMEDA_COMPONENT_IPS0:
102         case KOMEDA_COMPONENT_IPS1:
103                 temp = mdev->pipelines[id - KOMEDA_COMPONENT_IPS0];
104                 if (!temp) {
105                         DRM_ERROR("ips-%d doesn't exist.\n", id);
106                         return NULL;
107                 }
108                 pos = to_cpos(temp->improc);
109                 break;
110         case KOMEDA_COMPONENT_TIMING_CTRLR:
111                 pos = to_cpos(pipe->ctrlr);
112                 break;
113         default:
114                 pos = NULL;
115                 DRM_ERROR("Unknown pipeline resource ID: %d.\n", id);
116                 break;
117         }
118
119         return pos;
120 }
121
122 struct komeda_component *
123 komeda_pipeline_get_component(struct komeda_pipeline *pipe, int id)
124 {
125         struct komeda_component **pos = NULL;
126         struct komeda_component *c = NULL;
127
128         pos = komeda_pipeline_get_component_pos(pipe, id);
129         if (pos)
130                 c = *pos;
131
132         return c;
133 }
134
135 struct komeda_component *
136 komeda_pipeline_get_first_component(struct komeda_pipeline *pipe,
137                                     u32 comp_mask)
138 {
139         struct komeda_component *c = NULL;
140         unsigned long comp_mask_local = (unsigned long)comp_mask;
141         int id;
142
143         id = find_first_bit(&comp_mask_local, 32);
144         if (id < 32)
145                 c = komeda_pipeline_get_component(pipe, id);
146
147         return c;
148 }
149
150 static struct komeda_component *
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 *
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
227 void komeda_component_destroy(struct komeda_dev *mdev,
228                               struct komeda_component *c)
229 {
230         devm_kfree(mdev->dev, c);
231 }
232
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
246 static void komeda_pipeline_dump(struct komeda_pipeline *pipe)
247 {
248         struct komeda_component *c;
249         int id;
250
251         DRM_INFO("Pipeline-%d: n_layers: %d, n_scalers: %d, output: %s.\n",
252                  pipe->id, pipe->n_layers, pipe->n_scalers,
253                  pipe->dual_link ? "dual-link" : "single-link");
254         DRM_INFO("      output_link[0]: %s.\n",
255                  pipe->of_output_links[0] ?
256                  pipe->of_output_links[0]->full_name : "none");
257         DRM_INFO("      output_link[1]: %s.\n",
258                  pipe->of_output_links[1] ?
259                  pipe->of_output_links[1]->full_name : "none");
260
261         dp_for_each_set_bit(id, pipe->avail_comps) {
262                 c = komeda_pipeline_get_component(pipe, id);
263
264                 komeda_component_dump(c);
265         }
266 }
267
268 static void komeda_component_verify_inputs(struct komeda_component *c)
269 {
270         struct komeda_pipeline *pipe = c->pipeline;
271         struct komeda_component *input;
272         int id;
273
274         dp_for_each_set_bit(id, c->supported_inputs) {
275                 input = komeda_pipeline_get_component(pipe, id);
276                 if (!input) {
277                         c->supported_inputs &= ~(BIT(id));
278                         DRM_WARN("Can not find input(ID-%d) for component: %s.\n",
279                                  id, c->name);
280                         continue;
281                 }
282
283                 input->supported_outputs |= BIT(c->id);
284         }
285 }
286
287 static struct komeda_layer *
288 komeda_get_layer_split_right_layer(struct komeda_pipeline *pipe,
289                                    struct komeda_layer *left)
290 {
291         int index = left->base.id - KOMEDA_COMPONENT_LAYER0;
292         int i;
293
294         for (i = index + 1; i < pipe->n_layers; i++)
295                 if (left->layer_type == pipe->layers[i]->layer_type)
296                         return pipe->layers[i];
297         return NULL;
298 }
299
300 static void komeda_pipeline_assemble(struct komeda_pipeline *pipe)
301 {
302         struct komeda_component *c;
303         struct komeda_layer *layer;
304         int i, id;
305
306         dp_for_each_set_bit(id, pipe->avail_comps) {
307                 c = komeda_pipeline_get_component(pipe, id);
308                 komeda_component_verify_inputs(c);
309         }
310         /* calculate right layer for the layer split */
311         for (i = 0; i < pipe->n_layers; i++) {
312                 layer = pipe->layers[i];
313
314                 layer->right = komeda_get_layer_split_right_layer(pipe, layer);
315         }
316
317         if (pipe->dual_link && !pipe->ctrlr->supports_dual_link) {
318                 pipe->dual_link = false;
319                 DRM_WARN("PIPE-%d doesn't support dual-link, ignore DT dual-link configuration.\n",
320                          pipe->id);
321         }
322 }
323
324 /* if pipeline_A accept another pipeline_B's component as input, treat
325  * pipeline_B as slave of pipeline_A.
326  */
327 struct komeda_pipeline *
328 komeda_pipeline_get_slave(struct komeda_pipeline *master)
329 {
330         struct komeda_component *slave;
331
332         slave = komeda_component_pickup_input(&master->compiz->base,
333                                               KOMEDA_PIPELINE_COMPIZS);
334
335         return slave ? slave->pipeline : NULL;
336 }
337
338 int komeda_assemble_pipelines(struct komeda_dev *mdev)
339 {
340         struct komeda_pipeline *pipe;
341         int i;
342
343         for (i = 0; i < mdev->n_pipelines; i++) {
344                 pipe = mdev->pipelines[i];
345
346                 komeda_pipeline_assemble(pipe);
347                 komeda_pipeline_dump(pipe);
348         }
349
350         return 0;
351 }
352
353 void komeda_pipeline_dump_register(struct komeda_pipeline *pipe,
354                                    struct seq_file *sf)
355 {
356         struct komeda_component *c;
357         u32 id;
358
359         seq_printf(sf, "\n======== Pipeline-%d ==========\n", pipe->id);
360
361         if (pipe->funcs && pipe->funcs->dump_register)
362                 pipe->funcs->dump_register(pipe, sf);
363
364         dp_for_each_set_bit(id, pipe->avail_comps) {
365                 c = komeda_pipeline_get_component(pipe, id);
366
367                 seq_printf(sf, "\n------%s------\n", c->name);
368                 if (c->funcs->dump_register)
369                         c->funcs->dump_register(c, sf);
370         }
371 }