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