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 		    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 	clk_put(pipe->aclk);
57 
58 	of_node_put(pipe->of_output_dev);
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_IPS0:
96 	case KOMEDA_COMPONENT_IPS1:
97 		temp = mdev->pipelines[id - KOMEDA_COMPONENT_IPS0];
98 		if (!temp) {
99 			DRM_ERROR("ips-%d doesn't exist.\n", id);
100 			return NULL;
101 		}
102 		pos = to_cpos(temp->improc);
103 		break;
104 	case KOMEDA_COMPONENT_TIMING_CTRLR:
105 		pos = to_cpos(pipe->ctrlr);
106 		break;
107 	default:
108 		pos = NULL;
109 		DRM_ERROR("Unknown pipeline resource ID: %d.\n", id);
110 		break;
111 	}
112 
113 	return pos;
114 }
115 
116 struct komeda_component *
117 komeda_pipeline_get_component(struct komeda_pipeline *pipe, int id)
118 {
119 	struct komeda_component **pos = NULL;
120 	struct komeda_component *c = NULL;
121 
122 	pos = komeda_pipeline_get_component_pos(pipe, id);
123 	if (pos)
124 		c = *pos;
125 
126 	return c;
127 }
128 
129 /** komeda_component_add - Add a component to &komeda_pipeline */
130 struct komeda_component *
131 komeda_component_add(struct komeda_pipeline *pipe,
132 		     size_t comp_sz, u32 id, u32 hw_id,
133 		     struct komeda_component_funcs *funcs,
134 		     u8 max_active_inputs, u32 supported_inputs,
135 		     u8 max_active_outputs, u32 __iomem *reg,
136 		     const char *name_fmt, ...)
137 {
138 	struct komeda_component **pos;
139 	struct komeda_component *c;
140 	int idx, *num = NULL;
141 
142 	if (max_active_inputs > KOMEDA_COMPONENT_N_INPUTS) {
143 		WARN(1, "please large KOMEDA_COMPONENT_N_INPUTS to %d.\n",
144 		     max_active_inputs);
145 		return ERR_PTR(-ENOSPC);
146 	}
147 
148 	pos = komeda_pipeline_get_component_pos(pipe, id);
149 	if (!pos || (*pos))
150 		return ERR_PTR(-EINVAL);
151 
152 	if (has_bit(id, KOMEDA_PIPELINE_LAYERS)) {
153 		idx = id - KOMEDA_COMPONENT_LAYER0;
154 		num = &pipe->n_layers;
155 		if (idx != pipe->n_layers) {
156 			DRM_ERROR("please add Layer by id sequence.\n");
157 			return ERR_PTR(-EINVAL);
158 		}
159 	} else if (has_bit(id,  KOMEDA_PIPELINE_SCALERS)) {
160 		idx = id - KOMEDA_COMPONENT_SCALER0;
161 		num = &pipe->n_scalers;
162 		if (idx != pipe->n_scalers) {
163 			DRM_ERROR("please add Scaler by id sequence.\n");
164 			return ERR_PTR(-EINVAL);
165 		}
166 	}
167 
168 	c = devm_kzalloc(pipe->mdev->dev, comp_sz, GFP_KERNEL);
169 	if (!c)
170 		return ERR_PTR(-ENOMEM);
171 
172 	c->id = id;
173 	c->hw_id = hw_id;
174 	c->reg = reg;
175 	c->pipeline = pipe;
176 	c->max_active_inputs = max_active_inputs;
177 	c->max_active_outputs = max_active_outputs;
178 	c->supported_inputs = supported_inputs;
179 	c->funcs = funcs;
180 
181 	if (name_fmt) {
182 		va_list args;
183 
184 		va_start(args, name_fmt);
185 		vsnprintf(c->name, sizeof(c->name), name_fmt, args);
186 		va_end(args);
187 	}
188 
189 	if (num)
190 		*num = *num + 1;
191 
192 	pipe->avail_comps |= BIT(c->id);
193 	*pos = c;
194 
195 	return c;
196 }
197 
198 void komeda_component_destroy(struct komeda_dev *mdev,
199 			      struct komeda_component *c)
200 {
201 	devm_kfree(mdev->dev, c);
202 }
203 
204 static void komeda_component_dump(struct komeda_component *c)
205 {
206 	if (!c)
207 		return;
208 
209 	DRM_DEBUG("	%s: ID %d-0x%08lx.\n",
210 		  c->name, c->id, BIT(c->id));
211 	DRM_DEBUG("		max_active_inputs:%d, supported_inputs: 0x%08x.\n",
212 		  c->max_active_inputs, c->supported_inputs);
213 	DRM_DEBUG("		max_active_outputs:%d, supported_outputs: 0x%08x.\n",
214 		  c->max_active_outputs, c->supported_outputs);
215 }
216 
217 static void komeda_pipeline_dump(struct komeda_pipeline *pipe)
218 {
219 	struct komeda_component *c;
220 	int id;
221 
222 	DRM_INFO("Pipeline-%d: n_layers: %d, n_scalers: %d, output: %s\n",
223 		 pipe->id, pipe->n_layers, pipe->n_scalers,
224 		 pipe->of_output_dev ? pipe->of_output_dev->full_name : "none");
225 
226 	dp_for_each_set_bit(id, pipe->avail_comps) {
227 		c = komeda_pipeline_get_component(pipe, id);
228 
229 		komeda_component_dump(c);
230 	}
231 }
232 
233 static void komeda_component_verify_inputs(struct komeda_component *c)
234 {
235 	struct komeda_pipeline *pipe = c->pipeline;
236 	struct komeda_component *input;
237 	int id;
238 
239 	dp_for_each_set_bit(id, c->supported_inputs) {
240 		input = komeda_pipeline_get_component(pipe, id);
241 		if (!input) {
242 			c->supported_inputs &= ~(BIT(id));
243 			DRM_WARN("Can not find input(ID-%d) for component: %s.\n",
244 				 id, c->name);
245 			continue;
246 		}
247 
248 		input->supported_outputs |= BIT(c->id);
249 	}
250 }
251 
252 static void komeda_pipeline_assemble(struct komeda_pipeline *pipe)
253 {
254 	struct komeda_component *c;
255 	int id;
256 
257 	dp_for_each_set_bit(id, pipe->avail_comps) {
258 		c = komeda_pipeline_get_component(pipe, id);
259 
260 		komeda_component_verify_inputs(c);
261 	}
262 }
263 
264 int komeda_assemble_pipelines(struct komeda_dev *mdev)
265 {
266 	struct komeda_pipeline *pipe;
267 	int i;
268 
269 	for (i = 0; i < mdev->n_pipelines; i++) {
270 		pipe = mdev->pipelines[i];
271 
272 		komeda_pipeline_assemble(pipe);
273 		komeda_pipeline_dump(pipe);
274 	}
275 
276 	return 0;
277 }
278 
279 void komeda_pipeline_dump_register(struct komeda_pipeline *pipe,
280 				   struct seq_file *sf)
281 {
282 	struct komeda_component *c;
283 	u32 id;
284 
285 	seq_printf(sf, "\n======== Pipeline-%d ==========\n", pipe->id);
286 
287 	if (pipe->funcs && pipe->funcs->dump_register)
288 		pipe->funcs->dump_register(pipe, sf);
289 
290 	dp_for_each_set_bit(id, pipe->avail_comps) {
291 		c = komeda_pipeline_get_component(pipe, id);
292 
293 		seq_printf(sf, "\n------%s------\n", c->name);
294 		if (c->funcs->dump_register)
295 			c->funcs->dump_register(c, sf);
296 	}
297 }
298