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