]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c
ca85e12312a388c5dd42765cca51ed2d450e4161
[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 <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                     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         clk_put(pipe->aclk);
57
58         of_node_put(pipe->of_output_dev);
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 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_IPS0:
96         case KOMEDA_COMPONENT_IPS1:
97                 temp = mdev->pipelines[id - KOMEDA_COMPONENT_IPS0];
98                 if (!temp) {
99                         DRM_ERROR("ips-%d doesn't exist.\n", id);
100                         return NULL;
101                 }
102                 pos = to_cpos(temp->improc);
103                 break;
104         case KOMEDA_COMPONENT_TIMING_CTRLR:
105                 pos = to_cpos(pipe->ctrlr);
106                 break;
107         default:
108                 pos = NULL;
109                 DRM_ERROR("Unknown pipeline resource ID: %d.\n", id);
110                 break;
111         }
112
113         return pos;
114 }
115
116 struct komeda_component *
117 komeda_pipeline_get_component(struct komeda_pipeline *pipe, int id)
118 {
119         struct komeda_component **pos = NULL;
120         struct komeda_component *c = NULL;
121
122         pos = komeda_pipeline_get_component_pos(pipe, id);
123         if (pos)
124                 c = *pos;
125
126         return c;
127 }
128
129 /** komeda_component_add - Add a component to &komeda_pipeline */
130 struct komeda_component *
131 komeda_component_add(struct komeda_pipeline *pipe,
132                      size_t comp_sz, u32 id, u32 hw_id,
133                      struct komeda_component_funcs *funcs,
134                      u8 max_active_inputs, u32 supported_inputs,
135                      u8 max_active_outputs, u32 __iomem *reg,
136                      const char *name_fmt, ...)
137 {
138         struct komeda_component **pos;
139         struct komeda_component *c;
140         int idx, *num = NULL;
141
142         if (max_active_inputs > KOMEDA_COMPONENT_N_INPUTS) {
143                 WARN(1, "please large KOMEDA_COMPONENT_N_INPUTS to %d.\n",
144                      max_active_inputs);
145                 return ERR_PTR(-ENOSPC);
146         }
147
148         pos = komeda_pipeline_get_component_pos(pipe, id);
149         if (!pos || (*pos))
150                 return ERR_PTR(-EINVAL);
151
152         if (has_bit(id, KOMEDA_PIPELINE_LAYERS)) {
153                 idx = id - KOMEDA_COMPONENT_LAYER0;
154                 num = &pipe->n_layers;
155                 if (idx != pipe->n_layers) {
156                         DRM_ERROR("please add Layer by id sequence.\n");
157                         return ERR_PTR(-EINVAL);
158                 }
159         } else if (has_bit(id,  KOMEDA_PIPELINE_SCALERS)) {
160                 idx = id - KOMEDA_COMPONENT_SCALER0;
161                 num = &pipe->n_scalers;
162                 if (idx != pipe->n_scalers) {
163                         DRM_ERROR("please add Scaler by id sequence.\n");
164                         return ERR_PTR(-EINVAL);
165                 }
166         }
167
168         c = devm_kzalloc(pipe->mdev->dev, comp_sz, GFP_KERNEL);
169         if (!c)
170                 return ERR_PTR(-ENOMEM);
171
172         c->id = id;
173         c->hw_id = hw_id;
174         c->reg = reg;
175         c->pipeline = pipe;
176         c->max_active_inputs = max_active_inputs;
177         c->max_active_outputs = max_active_outputs;
178         c->supported_inputs = supported_inputs;
179         c->funcs = funcs;
180
181         if (name_fmt) {
182                 va_list args;
183
184                 va_start(args, name_fmt);
185                 vsnprintf(c->name, sizeof(c->name), name_fmt, args);
186                 va_end(args);
187         }
188
189         if (num)
190                 *num = *num + 1;
191
192         pipe->avail_comps |= BIT(c->id);
193         *pos = c;
194
195         return c;
196 }
197
198 void komeda_component_destroy(struct komeda_dev *mdev,
199                               struct komeda_component *c)
200 {
201         devm_kfree(mdev->dev, c);
202 }
203
204 static void komeda_component_dump(struct komeda_component *c)
205 {
206         if (!c)
207                 return;
208
209         DRM_DEBUG("     %s: ID %d-0x%08lx.\n",
210                   c->name, c->id, BIT(c->id));
211         DRM_DEBUG("             max_active_inputs:%d, supported_inputs: 0x%08x.\n",
212                   c->max_active_inputs, c->supported_inputs);
213         DRM_DEBUG("             max_active_outputs:%d, supported_outputs: 0x%08x.\n",
214                   c->max_active_outputs, c->supported_outputs);
215 }
216
217 static void komeda_pipeline_dump(struct komeda_pipeline *pipe)
218 {
219         struct komeda_component *c;
220         int id;
221
222         DRM_INFO("Pipeline-%d: n_layers: %d, n_scalers: %d, output: %s\n",
223                  pipe->id, pipe->n_layers, pipe->n_scalers,
224                  pipe->of_output_dev ? pipe->of_output_dev->full_name : "none");
225
226         dp_for_each_set_bit(id, pipe->avail_comps) {
227                 c = komeda_pipeline_get_component(pipe, id);
228
229                 komeda_component_dump(c);
230         }
231 }
232
233 static void komeda_component_verify_inputs(struct komeda_component *c)
234 {
235         struct komeda_pipeline *pipe = c->pipeline;
236         struct komeda_component *input;
237         int id;
238
239         dp_for_each_set_bit(id, c->supported_inputs) {
240                 input = komeda_pipeline_get_component(pipe, id);
241                 if (!input) {
242                         c->supported_inputs &= ~(BIT(id));
243                         DRM_WARN("Can not find input(ID-%d) for component: %s.\n",
244                                  id, c->name);
245                         continue;
246                 }
247
248                 input->supported_outputs |= BIT(c->id);
249         }
250 }
251
252 static void komeda_pipeline_assemble(struct komeda_pipeline *pipe)
253 {
254         struct komeda_component *c;
255         int id;
256
257         dp_for_each_set_bit(id, pipe->avail_comps) {
258                 c = komeda_pipeline_get_component(pipe, id);
259
260                 komeda_component_verify_inputs(c);
261         }
262 }
263
264 int komeda_assemble_pipelines(struct komeda_dev *mdev)
265 {
266         struct komeda_pipeline *pipe;
267         int i;
268
269         for (i = 0; i < mdev->n_pipelines; i++) {
270                 pipe = mdev->pipelines[i];
271
272                 komeda_pipeline_assemble(pipe);
273                 komeda_pipeline_dump(pipe);
274         }
275
276         return 0;
277 }