brintos

brintos / linux-shallow public Read only

0
0
Text · 9.3 KiB · 81e244f Raw
381 lines · c
1// SPDX-License-Identifier: GPL-2.02/*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, treat333 * 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}381