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