1 // SPDX-License-Identifier: GPL-2.0
3 * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
4 * Author: James.Qian.Wang <james.qian.wang@arm.com>
7 #include <drm/drm_print.h>
9 #include "komeda_dev.h"
10 #include "komeda_pipeline.h"
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)
17 struct komeda_pipeline *pipe;
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);
25 if (size < sizeof(*pipe)) {
26 DRM_ERROR("Request pipeline size too small.\n");
27 return ERR_PTR(-EINVAL);
30 pipe = devm_kzalloc(mdev->dev, size, GFP_KERNEL);
32 return ERR_PTR(-ENOMEM);
35 pipe->id = mdev->n_pipelines;
38 mdev->pipelines[mdev->n_pipelines] = pipe;
44 void komeda_pipeline_destroy(struct komeda_dev *mdev,
45 struct komeda_pipeline *pipe)
47 struct komeda_component *c;
50 dp_for_each_set_bit(i, pipe->avail_comps) {
51 c = komeda_pipeline_get_component(pipe, i);
52 komeda_component_destroy(mdev, c);
55 clk_put(pipe->pxlclk);
58 of_node_put(pipe->of_output_dev);
59 of_node_put(pipe->of_output_port);
60 of_node_put(pipe->of_node);
62 devm_kfree(mdev->dev, pipe);
65 struct komeda_component **
66 komeda_pipeline_get_component_pos(struct komeda_pipeline *pipe, int id)
68 struct komeda_dev *mdev = pipe->mdev;
69 struct komeda_pipeline *temp = NULL;
70 struct komeda_component **pos = NULL;
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]);
79 case KOMEDA_COMPONENT_WB_LAYER:
80 pos = to_cpos(pipe->wb_layer);
82 case KOMEDA_COMPONENT_COMPIZ0:
83 case KOMEDA_COMPONENT_COMPIZ1:
84 temp = mdev->pipelines[id - KOMEDA_COMPONENT_COMPIZ0];
86 DRM_ERROR("compiz-%d doesn't exist.\n", id);
89 pos = to_cpos(temp->compiz);
91 case KOMEDA_COMPONENT_SCALER0:
92 case KOMEDA_COMPONENT_SCALER1:
93 pos = to_cpos(pipe->scalers[id - KOMEDA_COMPONENT_SCALER0]);
95 case KOMEDA_COMPONENT_IPS0:
96 case KOMEDA_COMPONENT_IPS1:
97 temp = mdev->pipelines[id - KOMEDA_COMPONENT_IPS0];
99 DRM_ERROR("ips-%d doesn't exist.\n", id);
102 pos = to_cpos(temp->improc);
104 case KOMEDA_COMPONENT_TIMING_CTRLR:
105 pos = to_cpos(pipe->ctrlr);
109 DRM_ERROR("Unknown pipeline resource ID: %d.\n", id);
116 struct komeda_component *
117 komeda_pipeline_get_component(struct komeda_pipeline *pipe, int id)
119 struct komeda_component **pos = NULL;
120 struct komeda_component *c = NULL;
122 pos = komeda_pipeline_get_component_pos(pipe, id);
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, ...)
138 struct komeda_component **pos;
139 struct komeda_component *c;
140 int idx, *num = NULL;
142 if (max_active_inputs > KOMEDA_COMPONENT_N_INPUTS) {
143 WARN(1, "please large KOMEDA_COMPONENT_N_INPUTS to %d.\n",
145 return ERR_PTR(-ENOSPC);
148 pos = komeda_pipeline_get_component_pos(pipe, id);
150 return ERR_PTR(-EINVAL);
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);
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);
168 c = devm_kzalloc(pipe->mdev->dev, comp_sz, GFP_KERNEL);
170 return ERR_PTR(-ENOMEM);
176 c->max_active_inputs = max_active_inputs;
177 c->max_active_outputs = max_active_outputs;
178 c->supported_inputs = supported_inputs;
184 va_start(args, name_fmt);
185 vsnprintf(c->name, sizeof(c->name), name_fmt, args);
192 pipe->avail_comps |= BIT(c->id);
198 void komeda_component_destroy(struct komeda_dev *mdev,
199 struct komeda_component *c)
201 devm_kfree(mdev->dev, c);
204 static void komeda_component_dump(struct komeda_component *c)
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);
217 static void komeda_pipeline_dump(struct komeda_pipeline *pipe)
219 struct komeda_component *c;
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");
226 dp_for_each_set_bit(id, pipe->avail_comps) {
227 c = komeda_pipeline_get_component(pipe, id);
229 komeda_component_dump(c);
233 static void komeda_component_verify_inputs(struct komeda_component *c)
235 struct komeda_pipeline *pipe = c->pipeline;
236 struct komeda_component *input;
239 dp_for_each_set_bit(id, c->supported_inputs) {
240 input = komeda_pipeline_get_component(pipe, id);
242 c->supported_inputs &= ~(BIT(id));
243 DRM_WARN("Can not find input(ID-%d) for component: %s.\n",
248 input->supported_outputs |= BIT(c->id);
252 static void komeda_pipeline_assemble(struct komeda_pipeline *pipe)
254 struct komeda_component *c;
257 dp_for_each_set_bit(id, pipe->avail_comps) {
258 c = komeda_pipeline_get_component(pipe, id);
260 komeda_component_verify_inputs(c);
264 int komeda_assemble_pipelines(struct komeda_dev *mdev)
266 struct komeda_pipeline *pipe;
269 for (i = 0; i < mdev->n_pipelines; i++) {
270 pipe = mdev->pipelines[i];
272 komeda_pipeline_assemble(pipe);
273 komeda_pipeline_dump(pipe);