File Index
Files and directories
Sign in
FILE

komeda_pipeline.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c C
  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 */
 17struct komeda_pipeline *
 18komeda_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
 48void 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
 70static struct komeda_component **
 71komeda_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
127struct komeda_component *
128komeda_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
140struct komeda_component *
141komeda_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
155static struct komeda_component *
156komeda_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 */
164struct komeda_component *
165komeda_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
232void komeda_component_destroy(struct komeda_dev *mdev,
233			      struct komeda_component *c)
234{
235	devm_kfree(mdev->dev, c);
236}
237
238static 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
251void 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
274static 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
294static struct komeda_layer *
295komeda_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
307static 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 */
335struct komeda_pipeline *
336komeda_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
346int 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
360void 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}
~/ Read-only file preview.