Path: blob/master/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c
26519 views
// SPDX-License-Identifier: GPL-2.01/*2* (C) COPYRIGHT 2018 ARM Limited. All rights reserved.3* Author: James.Qian.Wang <[email protected]>4*5*/6#include <linux/of.h>7#include <linux/seq_file.h>89#include <drm/drm_print.h>1011#include "komeda_dev.h"12#include "komeda_kms.h"13#include "komeda_pipeline.h"1415/** komeda_pipeline_add - Add a pipeline to &komeda_dev */16struct komeda_pipeline *17komeda_pipeline_add(struct komeda_dev *mdev, size_t size,18const struct komeda_pipeline_funcs *funcs)19{20struct komeda_pipeline *pipe;2122if (mdev->n_pipelines + 1 > KOMEDA_MAX_PIPELINES) {23DRM_ERROR("Exceed max support %d pipelines.\n",24KOMEDA_MAX_PIPELINES);25return ERR_PTR(-ENOSPC);26}2728if (size < sizeof(*pipe)) {29DRM_ERROR("Request pipeline size too small.\n");30return ERR_PTR(-EINVAL);31}3233pipe = devm_kzalloc(mdev->dev, size, GFP_KERNEL);34if (!pipe)35return ERR_PTR(-ENOMEM);3637pipe->mdev = mdev;38pipe->id = mdev->n_pipelines;39pipe->funcs = funcs;4041mdev->pipelines[mdev->n_pipelines] = pipe;42mdev->n_pipelines++;4344return pipe;45}4647void komeda_pipeline_destroy(struct komeda_dev *mdev,48struct komeda_pipeline *pipe)49{50struct komeda_component *c;51int i;52unsigned long avail_comps = pipe->avail_comps;5354for_each_set_bit(i, &avail_comps, 32) {55c = komeda_pipeline_get_component(pipe, i);56komeda_component_destroy(mdev, c);57}5859clk_put(pipe->pxlclk);6061of_node_put(pipe->of_output_links[0]);62of_node_put(pipe->of_output_links[1]);63of_node_put(pipe->of_output_port);64of_node_put(pipe->of_node);6566devm_kfree(mdev->dev, pipe);67}6869static struct komeda_component **70komeda_pipeline_get_component_pos(struct komeda_pipeline *pipe, int id)71{72struct komeda_dev *mdev = pipe->mdev;73struct komeda_pipeline *temp = NULL;74struct komeda_component **pos = NULL;7576switch (id) {77case KOMEDA_COMPONENT_LAYER0:78case KOMEDA_COMPONENT_LAYER1:79case KOMEDA_COMPONENT_LAYER2:80case KOMEDA_COMPONENT_LAYER3:81pos = to_cpos(pipe->layers[id - KOMEDA_COMPONENT_LAYER0]);82break;83case KOMEDA_COMPONENT_WB_LAYER:84pos = to_cpos(pipe->wb_layer);85break;86case KOMEDA_COMPONENT_COMPIZ0:87case KOMEDA_COMPONENT_COMPIZ1:88temp = mdev->pipelines[id - KOMEDA_COMPONENT_COMPIZ0];89if (!temp) {90DRM_ERROR("compiz-%d doesn't exist.\n", id);91return NULL;92}93pos = to_cpos(temp->compiz);94break;95case KOMEDA_COMPONENT_SCALER0:96case KOMEDA_COMPONENT_SCALER1:97pos = to_cpos(pipe->scalers[id - KOMEDA_COMPONENT_SCALER0]);98break;99case KOMEDA_COMPONENT_SPLITTER:100pos = to_cpos(pipe->splitter);101break;102case KOMEDA_COMPONENT_MERGER:103pos = to_cpos(pipe->merger);104break;105case KOMEDA_COMPONENT_IPS0:106case KOMEDA_COMPONENT_IPS1:107temp = mdev->pipelines[id - KOMEDA_COMPONENT_IPS0];108if (!temp) {109DRM_ERROR("ips-%d doesn't exist.\n", id);110return NULL;111}112pos = to_cpos(temp->improc);113break;114case KOMEDA_COMPONENT_TIMING_CTRLR:115pos = to_cpos(pipe->ctrlr);116break;117default:118pos = NULL;119DRM_ERROR("Unknown pipeline resource ID: %d.\n", id);120break;121}122123return pos;124}125126struct komeda_component *127komeda_pipeline_get_component(struct komeda_pipeline *pipe, int id)128{129struct komeda_component **pos = NULL;130struct komeda_component *c = NULL;131132pos = komeda_pipeline_get_component_pos(pipe, id);133if (pos)134c = *pos;135136return c;137}138139struct komeda_component *140komeda_pipeline_get_first_component(struct komeda_pipeline *pipe,141u32 comp_mask)142{143struct komeda_component *c = NULL;144unsigned long comp_mask_local = (unsigned long)comp_mask;145int id;146147id = find_first_bit(&comp_mask_local, 32);148if (id < 32)149c = komeda_pipeline_get_component(pipe, id);150151return c;152}153154static struct komeda_component *155komeda_component_pickup_input(struct komeda_component *c, u32 avail_comps)156{157u32 avail_inputs = c->supported_inputs & (avail_comps);158159return komeda_pipeline_get_first_component(c->pipeline, avail_inputs);160}161162/** komeda_component_add - Add a component to &komeda_pipeline */163struct komeda_component *164komeda_component_add(struct komeda_pipeline *pipe,165size_t comp_sz, u32 id, u32 hw_id,166const struct komeda_component_funcs *funcs,167u8 max_active_inputs, u32 supported_inputs,168u8 max_active_outputs, u32 __iomem *reg,169const char *name_fmt, ...)170{171struct komeda_component **pos;172struct komeda_component *c;173int idx, *num = NULL;174175if (max_active_inputs > KOMEDA_COMPONENT_N_INPUTS) {176WARN(1, "please large KOMEDA_COMPONENT_N_INPUTS to %d.\n",177max_active_inputs);178return ERR_PTR(-ENOSPC);179}180181pos = komeda_pipeline_get_component_pos(pipe, id);182if (!pos || (*pos))183return ERR_PTR(-EINVAL);184185if (has_bit(id, KOMEDA_PIPELINE_LAYERS)) {186idx = id - KOMEDA_COMPONENT_LAYER0;187num = &pipe->n_layers;188if (idx != pipe->n_layers) {189DRM_ERROR("please add Layer by id sequence.\n");190return ERR_PTR(-EINVAL);191}192} else if (has_bit(id, KOMEDA_PIPELINE_SCALERS)) {193idx = id - KOMEDA_COMPONENT_SCALER0;194num = &pipe->n_scalers;195if (idx != pipe->n_scalers) {196DRM_ERROR("please add Scaler by id sequence.\n");197return ERR_PTR(-EINVAL);198}199}200201c = devm_kzalloc(pipe->mdev->dev, comp_sz, GFP_KERNEL);202if (!c)203return ERR_PTR(-ENOMEM);204205c->id = id;206c->hw_id = hw_id;207c->reg = reg;208c->pipeline = pipe;209c->max_active_inputs = max_active_inputs;210c->max_active_outputs = max_active_outputs;211c->supported_inputs = supported_inputs;212c->funcs = funcs;213214if (name_fmt) {215va_list args;216217va_start(args, name_fmt);218vsnprintf(c->name, sizeof(c->name), name_fmt, args);219va_end(args);220}221222if (num)223*num = *num + 1;224225pipe->avail_comps |= BIT(c->id);226*pos = c;227228return c;229}230231void komeda_component_destroy(struct komeda_dev *mdev,232struct komeda_component *c)233{234devm_kfree(mdev->dev, c);235}236237static void komeda_component_dump(struct komeda_component *c)238{239if (!c)240return;241242DRM_DEBUG(" %s: ID %d-0x%08lx.\n",243c->name, c->id, BIT(c->id));244DRM_DEBUG(" max_active_inputs:%d, supported_inputs: 0x%08x.\n",245c->max_active_inputs, c->supported_inputs);246DRM_DEBUG(" max_active_outputs:%d, supported_outputs: 0x%08x.\n",247c->max_active_outputs, c->supported_outputs);248}249250void komeda_pipeline_dump(struct komeda_pipeline *pipe)251{252struct komeda_component *c;253int id;254unsigned long avail_comps = pipe->avail_comps;255256DRM_INFO("Pipeline-%d: n_layers: %d, n_scalers: %d, output: %s.\n",257pipe->id, pipe->n_layers, pipe->n_scalers,258pipe->dual_link ? "dual-link" : "single-link");259DRM_INFO(" output_link[0]: %s.\n",260pipe->of_output_links[0] ?261pipe->of_output_links[0]->full_name : "none");262DRM_INFO(" output_link[1]: %s.\n",263pipe->of_output_links[1] ?264pipe->of_output_links[1]->full_name : "none");265266for_each_set_bit(id, &avail_comps, 32) {267c = komeda_pipeline_get_component(pipe, id);268269komeda_component_dump(c);270}271}272273static void komeda_component_verify_inputs(struct komeda_component *c)274{275struct komeda_pipeline *pipe = c->pipeline;276struct komeda_component *input;277int id;278unsigned long supported_inputs = c->supported_inputs;279280for_each_set_bit(id, &supported_inputs, 32) {281input = komeda_pipeline_get_component(pipe, id);282if (!input) {283c->supported_inputs &= ~(BIT(id));284DRM_WARN("Can not find input(ID-%d) for component: %s.\n",285id, c->name);286continue;287}288289input->supported_outputs |= BIT(c->id);290}291}292293static struct komeda_layer *294komeda_get_layer_split_right_layer(struct komeda_pipeline *pipe,295struct komeda_layer *left)296{297int index = left->base.id - KOMEDA_COMPONENT_LAYER0;298int i;299300for (i = index + 1; i < pipe->n_layers; i++)301if (left->layer_type == pipe->layers[i]->layer_type)302return pipe->layers[i];303return NULL;304}305306static void komeda_pipeline_assemble(struct komeda_pipeline *pipe)307{308struct komeda_component *c;309struct komeda_layer *layer;310int i, id;311unsigned long avail_comps = pipe->avail_comps;312313for_each_set_bit(id, &avail_comps, 32) {314c = komeda_pipeline_get_component(pipe, id);315komeda_component_verify_inputs(c);316}317/* calculate right layer for the layer split */318for (i = 0; i < pipe->n_layers; i++) {319layer = pipe->layers[i];320321layer->right = komeda_get_layer_split_right_layer(pipe, layer);322}323324if (pipe->dual_link && !pipe->ctrlr->supports_dual_link) {325pipe->dual_link = false;326DRM_WARN("PIPE-%d doesn't support dual-link, ignore DT dual-link configuration.\n",327pipe->id);328}329}330331/* if pipeline_A accept another pipeline_B's component as input, treat332* pipeline_B as slave of pipeline_A.333*/334struct komeda_pipeline *335komeda_pipeline_get_slave(struct komeda_pipeline *master)336{337struct komeda_component *slave;338339slave = komeda_component_pickup_input(&master->compiz->base,340KOMEDA_PIPELINE_COMPIZS);341342return slave ? slave->pipeline : NULL;343}344345int komeda_assemble_pipelines(struct komeda_dev *mdev)346{347struct komeda_pipeline *pipe;348int i;349350for (i = 0; i < mdev->n_pipelines; i++) {351pipe = mdev->pipelines[i];352353komeda_pipeline_assemble(pipe);354}355356return 0;357}358359void komeda_pipeline_dump_register(struct komeda_pipeline *pipe,360struct seq_file *sf)361{362struct komeda_component *c;363u32 id;364unsigned long avail_comps;365366seq_printf(sf, "\n======== Pipeline-%d ==========\n", pipe->id);367368if (pipe->funcs && pipe->funcs->dump_register)369pipe->funcs->dump_register(pipe, sf);370371avail_comps = pipe->avail_comps;372for_each_set_bit(id, &avail_comps, 32) {373c = komeda_pipeline_get_component(pipe, id);374375seq_printf(sf, "\n------%s------\n", c->name);376if (c->funcs->dump_register)377c->funcs->dump_register(c, sf);378}379}380381382