Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c
26519 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
4
* Author: James.Qian.Wang <[email protected]>
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 */
17
struct komeda_pipeline *
18
komeda_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
48
void 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
70
static struct komeda_component **
71
komeda_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
127
struct komeda_component *
128
komeda_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
140
struct komeda_component *
141
komeda_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
155
static struct komeda_component *
156
komeda_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 */
164
struct komeda_component *
165
komeda_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
232
void komeda_component_destroy(struct komeda_dev *mdev,
233
struct komeda_component *c)
234
{
235
devm_kfree(mdev->dev, c);
236
}
237
238
static 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
251
void 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
274
static 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
294
static struct komeda_layer *
295
komeda_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
307
static 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
*/
335
struct komeda_pipeline *
336
komeda_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
346
int 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
360
void 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
382