xref: /linux/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c (revision 4fd18fc38757217c746aa063ba9e4729814dc737)
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 }
372