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