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_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 
64 static struct komeda_component **
65 komeda_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 
121 struct komeda_component *
122 komeda_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 
134 struct komeda_component *
135 komeda_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 
148 static struct komeda_component *
149 komeda_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 /** komeda_component_add - Add a component to &komeda_pipeline */
157 struct komeda_component *
158 komeda_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 
225 void komeda_component_destroy(struct komeda_dev *mdev,
226 			      struct komeda_component *c)
227 {
228 	devm_kfree(mdev->dev, c);
229 }
230 
231 static 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 
244 static 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 
260 static 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 
279 static struct komeda_layer *
280 komeda_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 
292 static 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 	/* calculate right layer for the layer split */
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 /* if pipeline_A accept another pipeline_B's component as input, treat
311  * pipeline_B as slave of pipeline_A.
312  */
313 struct komeda_pipeline *
314 komeda_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 
324 int 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 
339 void 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