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