2 * vsp1_drm.c -- R-Car VSP1 DRM API
4 * Copyright (C) 2015 Renesas Electronics Corporation
6 * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
14 #include <linux/device.h>
15 #include <linux/dma-mapping.h>
16 #include <linux/slab.h>
18 #include <media/media-entity.h>
19 #include <media/v4l2-subdev.h>
20 #include <media/vsp1.h>
27 #include "vsp1_pipe.h"
28 #include "vsp1_rwpf.h"
31 /* -----------------------------------------------------------------------------
35 static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline
*pipe
,
38 struct vsp1_drm_pipeline
*drm_pipe
= to_vsp1_drm_pipeline(pipe
);
40 if (drm_pipe
->du_complete
)
41 drm_pipe
->du_complete(drm_pipe
->du_private
, completed
);
44 /* -----------------------------------------------------------------------------
48 int vsp1_du_init(struct device
*dev
)
50 struct vsp1_device
*vsp1
= dev_get_drvdata(dev
);
57 EXPORT_SYMBOL_GPL(vsp1_du_init
);
60 * vsp1_du_setup_lif - Setup the output part of the VSP pipeline
61 * @dev: the VSP device
62 * @pipe_index: the DRM pipeline index
63 * @cfg: the LIF configuration
65 * Configure the output part of VSP DRM pipeline for the given frame @cfg.width
66 * and @cfg.height. This sets up formats on the blend unit (BRU or BRS) source
67 * pad, the WPF sink and source pads, and the LIF sink pad.
69 * The @pipe_index argument selects which DRM pipeline to setup. The number of
70 * available pipelines depend on the VSP instance.
72 * As the media bus code on the blend unit source pad is conditioned by the
73 * configuration of its sink 0 pad, we also set up the formats on all blend unit
74 * sinks, even if the configuration will be overwritten later by
75 * vsp1_du_setup_rpf(). This ensures that the blend unit configuration is set to
76 * a well defined state.
78 * Return 0 on success or a negative error code on failure.
80 int vsp1_du_setup_lif(struct device
*dev
, unsigned int pipe_index
,
81 const struct vsp1_du_lif_config
*cfg
)
83 struct vsp1_device
*vsp1
= dev_get_drvdata(dev
);
84 struct vsp1_drm_pipeline
*drm_pipe
;
85 struct vsp1_pipeline
*pipe
;
87 struct vsp1_entity
*entity
;
88 struct vsp1_entity
*next
;
89 struct vsp1_dl_list
*dl
;
90 struct v4l2_subdev_format format
;
96 if (pipe_index
>= vsp1
->info
->lif_count
)
99 drm_pipe
= &vsp1
->drm
->pipe
[pipe_index
];
100 pipe
= &drm_pipe
->pipe
;
101 bru
= to_bru(&pipe
->bru
->subdev
);
102 bru_name
= pipe
->bru
->type
== VSP1_ENTITY_BRU
? "BRU" : "BRS";
106 * NULL configuration means the CRTC is being disabled, stop
107 * the pipeline and turn the light off.
109 ret
= vsp1_pipeline_stop(pipe
);
110 if (ret
== -ETIMEDOUT
)
111 dev_err(vsp1
->dev
, "DRM pipeline stop timeout\n");
113 media_pipeline_stop(&pipe
->output
->entity
.subdev
.entity
);
115 for (i
= 0; i
< ARRAY_SIZE(pipe
->inputs
); ++i
) {
116 struct vsp1_rwpf
*rpf
= pipe
->inputs
[i
];
122 * Remove the RPF from the pipe and the list of BRU
125 WARN_ON(list_empty(&rpf
->entity
.list_pipe
));
126 list_del_init(&rpf
->entity
.list_pipe
);
127 pipe
->inputs
[i
] = NULL
;
129 bru
->inputs
[rpf
->bru_input
].rpf
= NULL
;
132 drm_pipe
->du_complete
= NULL
;
133 pipe
->num_inputs
= 0;
135 vsp1_dlm_reset(pipe
->output
->dlm
);
136 vsp1_device_put(vsp1
);
138 dev_dbg(vsp1
->dev
, "%s: pipeline disabled\n", __func__
);
143 dev_dbg(vsp1
->dev
, "%s: configuring LIF%u with format %ux%u\n",
144 __func__
, pipe_index
, cfg
->width
, cfg
->height
);
147 * Configure the format at the BRU sinks and propagate it through the
150 memset(&format
, 0, sizeof(format
));
151 format
.which
= V4L2_SUBDEV_FORMAT_ACTIVE
;
153 for (i
= 0; i
< pipe
->bru
->source_pad
; ++i
) {
156 format
.format
.width
= cfg
->width
;
157 format
.format
.height
= cfg
->height
;
158 format
.format
.code
= MEDIA_BUS_FMT_ARGB8888_1X32
;
159 format
.format
.field
= V4L2_FIELD_NONE
;
161 ret
= v4l2_subdev_call(&pipe
->bru
->subdev
, pad
,
162 set_fmt
, NULL
, &format
);
166 dev_dbg(vsp1
->dev
, "%s: set format %ux%u (%x) on %s pad %u\n",
167 __func__
, format
.format
.width
, format
.format
.height
,
168 format
.format
.code
, bru_name
, i
);
171 format
.pad
= pipe
->bru
->source_pad
;
172 format
.format
.width
= cfg
->width
;
173 format
.format
.height
= cfg
->height
;
174 format
.format
.code
= MEDIA_BUS_FMT_ARGB8888_1X32
;
175 format
.format
.field
= V4L2_FIELD_NONE
;
177 ret
= v4l2_subdev_call(&pipe
->bru
->subdev
, pad
, set_fmt
, NULL
,
182 dev_dbg(vsp1
->dev
, "%s: set format %ux%u (%x) on %s pad %u\n",
183 __func__
, format
.format
.width
, format
.format
.height
,
184 format
.format
.code
, bru_name
, i
);
186 format
.pad
= RWPF_PAD_SINK
;
187 ret
= v4l2_subdev_call(&pipe
->output
->entity
.subdev
, pad
, set_fmt
, NULL
,
192 dev_dbg(vsp1
->dev
, "%s: set format %ux%u (%x) on WPF%u sink\n",
193 __func__
, format
.format
.width
, format
.format
.height
,
194 format
.format
.code
, pipe
->output
->entity
.index
);
196 format
.pad
= RWPF_PAD_SOURCE
;
197 ret
= v4l2_subdev_call(&pipe
->output
->entity
.subdev
, pad
, get_fmt
, NULL
,
202 dev_dbg(vsp1
->dev
, "%s: got format %ux%u (%x) on WPF%u source\n",
203 __func__
, format
.format
.width
, format
.format
.height
,
204 format
.format
.code
, pipe
->output
->entity
.index
);
206 format
.pad
= LIF_PAD_SINK
;
207 ret
= v4l2_subdev_call(&pipe
->lif
->subdev
, pad
, set_fmt
, NULL
,
212 dev_dbg(vsp1
->dev
, "%s: set format %ux%u (%x) on LIF%u sink\n",
213 __func__
, format
.format
.width
, format
.format
.height
,
214 format
.format
.code
, pipe_index
);
217 * Verify that the format at the output of the pipeline matches the
218 * requested frame size and media bus code.
220 if (format
.format
.width
!= cfg
->width
||
221 format
.format
.height
!= cfg
->height
||
222 format
.format
.code
!= MEDIA_BUS_FMT_ARGB8888_1X32
) {
223 dev_dbg(vsp1
->dev
, "%s: format mismatch\n", __func__
);
228 * Mark the pipeline as streaming and enable the VSP1. This will store
229 * the pipeline pointer in all entities, which the s_stream handlers
230 * will need. We don't start the entities themselves right at this point
231 * as there's no plane configured yet, so we can't start processing
234 ret
= vsp1_device_get(vsp1
);
239 * Register a callback to allow us to notify the DRM driver of frame
242 drm_pipe
->du_complete
= cfg
->callback
;
243 drm_pipe
->du_private
= cfg
->callback_data
;
245 ret
= media_pipeline_start(&pipe
->output
->entity
.subdev
.entity
,
248 dev_dbg(vsp1
->dev
, "%s: pipeline start failed\n", __func__
);
249 vsp1_device_put(vsp1
);
253 /* Disable the display interrupts. */
254 vsp1_write(vsp1
, VI6_DISP_IRQ_STA
, 0);
255 vsp1_write(vsp1
, VI6_DISP_IRQ_ENB
, 0);
257 /* Configure all entities in the pipeline. */
258 dl
= vsp1_dl_list_get(pipe
->output
->dlm
);
260 list_for_each_entry_safe(entity
, next
, &pipe
->entities
, list_pipe
) {
261 vsp1_entity_route_setup(entity
, pipe
, dl
);
263 if (entity
->ops
->configure
) {
264 entity
->ops
->configure(entity
, pipe
, dl
,
265 VSP1_ENTITY_PARAMS_INIT
);
266 entity
->ops
->configure(entity
, pipe
, dl
,
267 VSP1_ENTITY_PARAMS_RUNTIME
);
268 entity
->ops
->configure(entity
, pipe
, dl
,
269 VSP1_ENTITY_PARAMS_PARTITION
);
273 vsp1_dl_list_commit(dl
);
275 /* Start the pipeline. */
276 spin_lock_irqsave(&pipe
->irqlock
, flags
);
277 vsp1_pipeline_run(pipe
);
278 spin_unlock_irqrestore(&pipe
->irqlock
, flags
);
280 dev_dbg(vsp1
->dev
, "%s: pipeline enabled\n", __func__
);
284 EXPORT_SYMBOL_GPL(vsp1_du_setup_lif
);
287 * vsp1_du_atomic_begin - Prepare for an atomic update
288 * @dev: the VSP device
289 * @pipe_index: the DRM pipeline index
291 void vsp1_du_atomic_begin(struct device
*dev
, unsigned int pipe_index
)
293 struct vsp1_device
*vsp1
= dev_get_drvdata(dev
);
294 struct vsp1_drm_pipeline
*drm_pipe
= &vsp1
->drm
->pipe
[pipe_index
];
296 drm_pipe
->enabled
= drm_pipe
->pipe
.num_inputs
!= 0;
298 EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin
);
301 * vsp1_du_atomic_update - Setup one RPF input of the VSP pipeline
302 * @dev: the VSP device
303 * @pipe_index: the DRM pipeline index
304 * @rpf_index: index of the RPF to setup (0-based)
305 * @cfg: the RPF configuration
307 * Configure the VSP to perform image composition through RPF @rpf_index as
308 * described by the @cfg configuration. The image to compose is referenced by
309 * @cfg.mem and composed using the @cfg.src crop rectangle and the @cfg.dst
310 * composition rectangle. The Z-order is configurable with higher @zpos values
313 * If the @cfg configuration is NULL, the RPF will be disabled. Calling the
314 * function on a disabled RPF is allowed.
316 * Image format as stored in memory is expressed as a V4L2 @cfg.pixelformat
317 * value. The memory pitch is configurable to allow for padding at end of lines,
318 * or simply for images that extend beyond the crop rectangle boundaries. The
319 * @cfg.pitch value is expressed in bytes and applies to all planes for
320 * multiplanar formats.
322 * The source memory buffer is referenced by the DMA address of its planes in
323 * the @cfg.mem array. Up to two planes are supported. The second plane DMA
324 * address is ignored for formats using a single plane.
326 * This function isn't reentrant, the caller needs to serialize calls.
328 * Return 0 on success or a negative error code on failure.
330 int vsp1_du_atomic_update(struct device
*dev
, unsigned int pipe_index
,
331 unsigned int rpf_index
,
332 const struct vsp1_du_atomic_config
*cfg
)
334 struct vsp1_device
*vsp1
= dev_get_drvdata(dev
);
335 struct vsp1_drm_pipeline
*drm_pipe
= &vsp1
->drm
->pipe
[pipe_index
];
336 const struct vsp1_format_info
*fmtinfo
;
337 struct vsp1_rwpf
*rpf
;
339 if (rpf_index
>= vsp1
->info
->rpf_count
)
342 rpf
= vsp1
->rpf
[rpf_index
];
345 dev_dbg(vsp1
->dev
, "%s: RPF%u: disable requested\n", __func__
,
349 * Remove the RPF from the pipe's inputs. The atomic flush
350 * handler will disable the input and remove the entity from the
351 * pipe's entities list.
353 drm_pipe
->pipe
.inputs
[rpf_index
] = NULL
;
358 "%s: RPF%u: (%u,%u)/%ux%u -> (%u,%u)/%ux%u (%08x), pitch %u dma { %pad, %pad, %pad } zpos %u\n",
360 cfg
->src
.left
, cfg
->src
.top
, cfg
->src
.width
, cfg
->src
.height
,
361 cfg
->dst
.left
, cfg
->dst
.top
, cfg
->dst
.width
, cfg
->dst
.height
,
362 cfg
->pixelformat
, cfg
->pitch
, &cfg
->mem
[0], &cfg
->mem
[1],
363 &cfg
->mem
[2], cfg
->zpos
);
366 * Store the format, stride, memory buffer address, crop and compose
367 * rectangles and Z-order position and for the input.
369 fmtinfo
= vsp1_get_format_info(vsp1
, cfg
->pixelformat
);
371 dev_dbg(vsp1
->dev
, "Unsupport pixel format %08x for RPF\n",
376 rpf
->fmtinfo
= fmtinfo
;
377 rpf
->format
.num_planes
= fmtinfo
->planes
;
378 rpf
->format
.plane_fmt
[0].bytesperline
= cfg
->pitch
;
379 rpf
->format
.plane_fmt
[1].bytesperline
= cfg
->pitch
;
380 rpf
->alpha
= cfg
->alpha
;
382 rpf
->mem
.addr
[0] = cfg
->mem
[0];
383 rpf
->mem
.addr
[1] = cfg
->mem
[1];
384 rpf
->mem
.addr
[2] = cfg
->mem
[2];
386 vsp1
->drm
->inputs
[rpf_index
].crop
= cfg
->src
;
387 vsp1
->drm
->inputs
[rpf_index
].compose
= cfg
->dst
;
388 vsp1
->drm
->inputs
[rpf_index
].zpos
= cfg
->zpos
;
390 drm_pipe
->pipe
.inputs
[rpf_index
] = rpf
;
394 EXPORT_SYMBOL_GPL(vsp1_du_atomic_update
);
396 static int vsp1_du_setup_rpf_pipe(struct vsp1_device
*vsp1
,
397 struct vsp1_pipeline
*pipe
,
398 struct vsp1_rwpf
*rpf
, unsigned int bru_input
)
400 struct v4l2_subdev_selection sel
;
401 struct v4l2_subdev_format format
;
402 const struct v4l2_rect
*crop
;
406 * Configure the format on the RPF sink pad and propagate it up to the
409 crop
= &vsp1
->drm
->inputs
[rpf
->entity
.index
].crop
;
411 memset(&format
, 0, sizeof(format
));
412 format
.which
= V4L2_SUBDEV_FORMAT_ACTIVE
;
413 format
.pad
= RWPF_PAD_SINK
;
414 format
.format
.width
= crop
->width
+ crop
->left
;
415 format
.format
.height
= crop
->height
+ crop
->top
;
416 format
.format
.code
= rpf
->fmtinfo
->mbus
;
417 format
.format
.field
= V4L2_FIELD_NONE
;
419 ret
= v4l2_subdev_call(&rpf
->entity
.subdev
, pad
, set_fmt
, NULL
,
425 "%s: set format %ux%u (%x) on RPF%u sink\n",
426 __func__
, format
.format
.width
, format
.format
.height
,
427 format
.format
.code
, rpf
->entity
.index
);
429 memset(&sel
, 0, sizeof(sel
));
430 sel
.which
= V4L2_SUBDEV_FORMAT_ACTIVE
;
431 sel
.pad
= RWPF_PAD_SINK
;
432 sel
.target
= V4L2_SEL_TGT_CROP
;
435 ret
= v4l2_subdev_call(&rpf
->entity
.subdev
, pad
, set_selection
, NULL
,
441 "%s: set selection (%u,%u)/%ux%u on RPF%u sink\n",
442 __func__
, sel
.r
.left
, sel
.r
.top
, sel
.r
.width
, sel
.r
.height
,
446 * RPF source, hardcode the format to ARGB8888 to turn on format
447 * conversion if needed.
449 format
.pad
= RWPF_PAD_SOURCE
;
451 ret
= v4l2_subdev_call(&rpf
->entity
.subdev
, pad
, get_fmt
, NULL
,
457 "%s: got format %ux%u (%x) on RPF%u source\n",
458 __func__
, format
.format
.width
, format
.format
.height
,
459 format
.format
.code
, rpf
->entity
.index
);
461 format
.format
.code
= MEDIA_BUS_FMT_ARGB8888_1X32
;
463 ret
= v4l2_subdev_call(&rpf
->entity
.subdev
, pad
, set_fmt
, NULL
,
468 /* BRU sink, propagate the format from the RPF source. */
469 format
.pad
= bru_input
;
471 ret
= v4l2_subdev_call(&pipe
->bru
->subdev
, pad
, set_fmt
, NULL
,
476 dev_dbg(vsp1
->dev
, "%s: set format %ux%u (%x) on BRU pad %u\n",
477 __func__
, format
.format
.width
, format
.format
.height
,
478 format
.format
.code
, format
.pad
);
481 sel
.target
= V4L2_SEL_TGT_COMPOSE
;
482 sel
.r
= vsp1
->drm
->inputs
[rpf
->entity
.index
].compose
;
484 ret
= v4l2_subdev_call(&pipe
->bru
->subdev
, pad
, set_selection
, NULL
,
490 "%s: set selection (%u,%u)/%ux%u on BRU pad %u\n",
491 __func__
, sel
.r
.left
, sel
.r
.top
, sel
.r
.width
, sel
.r
.height
,
497 static unsigned int rpf_zpos(struct vsp1_device
*vsp1
, struct vsp1_rwpf
*rpf
)
499 return vsp1
->drm
->inputs
[rpf
->entity
.index
].zpos
;
503 * vsp1_du_atomic_flush - Commit an atomic update
504 * @dev: the VSP device
505 * @pipe_index: the DRM pipeline index
507 void vsp1_du_atomic_flush(struct device
*dev
, unsigned int pipe_index
)
509 struct vsp1_device
*vsp1
= dev_get_drvdata(dev
);
510 struct vsp1_drm_pipeline
*drm_pipe
= &vsp1
->drm
->pipe
[pipe_index
];
511 struct vsp1_pipeline
*pipe
= &drm_pipe
->pipe
;
512 struct vsp1_rwpf
*inputs
[VSP1_MAX_RPF
] = { NULL
, };
513 struct vsp1_bru
*bru
= to_bru(&pipe
->bru
->subdev
);
514 struct vsp1_entity
*entity
;
515 struct vsp1_entity
*next
;
516 struct vsp1_dl_list
*dl
;
517 const char *bru_name
;
521 bru_name
= pipe
->bru
->type
== VSP1_ENTITY_BRU
? "BRU" : "BRS";
523 /* Prepare the display list. */
524 dl
= vsp1_dl_list_get(pipe
->output
->dlm
);
526 /* Count the number of enabled inputs and sort them by Z-order. */
527 pipe
->num_inputs
= 0;
529 for (i
= 0; i
< vsp1
->info
->rpf_count
; ++i
) {
530 struct vsp1_rwpf
*rpf
= vsp1
->rpf
[i
];
533 if (!pipe
->inputs
[i
])
536 /* Insert the RPF in the sorted RPFs array. */
537 for (j
= pipe
->num_inputs
++; j
> 0; --j
) {
538 if (rpf_zpos(vsp1
, inputs
[j
-1]) <= rpf_zpos(vsp1
, rpf
))
540 inputs
[j
] = inputs
[j
-1];
546 /* Setup the RPF input pipeline for every enabled input. */
547 for (i
= 0; i
< pipe
->bru
->source_pad
; ++i
) {
548 struct vsp1_rwpf
*rpf
= inputs
[i
];
551 bru
->inputs
[i
].rpf
= NULL
;
555 if (list_empty(&rpf
->entity
.list_pipe
))
556 list_add_tail(&rpf
->entity
.list_pipe
, &pipe
->entities
);
558 bru
->inputs
[i
].rpf
= rpf
;
560 rpf
->entity
.sink
= pipe
->bru
;
561 rpf
->entity
.sink_pad
= i
;
563 dev_dbg(vsp1
->dev
, "%s: connecting RPF.%u to %s:%u\n",
564 __func__
, rpf
->entity
.index
, bru_name
, i
);
566 ret
= vsp1_du_setup_rpf_pipe(vsp1
, pipe
, rpf
, i
);
569 "%s: failed to setup RPF.%u\n",
570 __func__
, rpf
->entity
.index
);
573 /* Configure all entities in the pipeline. */
574 list_for_each_entry_safe(entity
, next
, &pipe
->entities
, list_pipe
) {
575 /* Disconnect unused RPFs from the pipeline. */
576 if (entity
->type
== VSP1_ENTITY_RPF
&&
577 !pipe
->inputs
[entity
->index
]) {
578 vsp1_dl_list_write(dl
, entity
->route
->reg
,
579 VI6_DPR_NODE_UNUSED
);
581 list_del_init(&entity
->list_pipe
);
586 vsp1_entity_route_setup(entity
, pipe
, dl
);
588 if (entity
->ops
->configure
) {
589 entity
->ops
->configure(entity
, pipe
, dl
,
590 VSP1_ENTITY_PARAMS_INIT
);
591 entity
->ops
->configure(entity
, pipe
, dl
,
592 VSP1_ENTITY_PARAMS_RUNTIME
);
593 entity
->ops
->configure(entity
, pipe
, dl
,
594 VSP1_ENTITY_PARAMS_PARTITION
);
598 vsp1_dl_list_commit(dl
);
600 EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush
);
602 int vsp1_du_map_sg(struct device
*dev
, struct sg_table
*sgt
)
604 struct vsp1_device
*vsp1
= dev_get_drvdata(dev
);
607 * As all the buffers allocated by the DU driver are coherent, we can
608 * skip cache sync. This will need to be revisited when support for
609 * non-coherent buffers will be added to the DU driver.
611 return dma_map_sg_attrs(vsp1
->bus_master
, sgt
->sgl
, sgt
->nents
,
612 DMA_TO_DEVICE
, DMA_ATTR_SKIP_CPU_SYNC
);
614 EXPORT_SYMBOL_GPL(vsp1_du_map_sg
);
616 void vsp1_du_unmap_sg(struct device
*dev
, struct sg_table
*sgt
)
618 struct vsp1_device
*vsp1
= dev_get_drvdata(dev
);
620 dma_unmap_sg_attrs(vsp1
->bus_master
, sgt
->sgl
, sgt
->nents
,
621 DMA_TO_DEVICE
, DMA_ATTR_SKIP_CPU_SYNC
);
623 EXPORT_SYMBOL_GPL(vsp1_du_unmap_sg
);
625 /* -----------------------------------------------------------------------------
629 int vsp1_drm_init(struct vsp1_device
*vsp1
)
633 vsp1
->drm
= devm_kzalloc(vsp1
->dev
, sizeof(*vsp1
->drm
), GFP_KERNEL
);
637 /* Create one DRM pipeline per LIF. */
638 for (i
= 0; i
< vsp1
->info
->lif_count
; ++i
) {
639 struct vsp1_drm_pipeline
*drm_pipe
= &vsp1
->drm
->pipe
[i
];
640 struct vsp1_pipeline
*pipe
= &drm_pipe
->pipe
;
642 vsp1_pipeline_init(pipe
);
645 * The DRM pipeline is static, add entities manually. The first
646 * pipeline uses the BRU and the second pipeline the BRS.
648 pipe
->bru
= i
== 0 ? &vsp1
->bru
->entity
: &vsp1
->brs
->entity
;
649 pipe
->lif
= &vsp1
->lif
[i
]->entity
;
650 pipe
->output
= vsp1
->wpf
[i
];
651 pipe
->output
->pipe
= pipe
;
652 pipe
->frame_end
= vsp1_du_pipeline_frame_end
;
654 pipe
->bru
->sink
= &pipe
->output
->entity
;
655 pipe
->bru
->sink_pad
= 0;
656 pipe
->output
->entity
.sink
= pipe
->lif
;
657 pipe
->output
->entity
.sink_pad
= 0;
659 list_add_tail(&pipe
->bru
->list_pipe
, &pipe
->entities
);
660 list_add_tail(&pipe
->lif
->list_pipe
, &pipe
->entities
);
661 list_add_tail(&pipe
->output
->entity
.list_pipe
, &pipe
->entities
);
664 /* Disable all RPFs initially. */
665 for (i
= 0; i
< vsp1
->info
->rpf_count
; ++i
) {
666 struct vsp1_rwpf
*input
= vsp1
->rpf
[i
];
668 INIT_LIST_HEAD(&input
->entity
.list_pipe
);
674 void vsp1_drm_cleanup(struct vsp1_device
*vsp1
)