cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vsp1_pipe.c (15788B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * vsp1_pipe.c  --  R-Car VSP1 Pipeline
      4 *
      5 * Copyright (C) 2013-2015 Renesas Electronics Corporation
      6 *
      7 * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
      8 */
      9
     10#include <linux/delay.h>
     11#include <linux/list.h>
     12#include <linux/sched.h>
     13#include <linux/wait.h>
     14
     15#include <media/media-entity.h>
     16#include <media/v4l2-subdev.h>
     17
     18#include "vsp1.h"
     19#include "vsp1_brx.h"
     20#include "vsp1_dl.h"
     21#include "vsp1_entity.h"
     22#include "vsp1_hgo.h"
     23#include "vsp1_hgt.h"
     24#include "vsp1_pipe.h"
     25#include "vsp1_rwpf.h"
     26#include "vsp1_uds.h"
     27
     28/* -----------------------------------------------------------------------------
     29 * Helper Functions
     30 */
     31
     32static const struct vsp1_format_info vsp1_video_formats[] = {
     33	{ V4L2_PIX_FMT_RGB332, MEDIA_BUS_FMT_ARGB8888_1X32,
     34	  VI6_FMT_RGB_332, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
     35	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
     36	  1, { 8, 0, 0 }, false, false, 1, 1, false },
     37	{ V4L2_PIX_FMT_ARGB444, MEDIA_BUS_FMT_ARGB8888_1X32,
     38	  VI6_FMT_ARGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
     39	  VI6_RPF_DSWAP_P_WDS,
     40	  1, { 16, 0, 0 }, false, false, 1, 1, true },
     41	{ V4L2_PIX_FMT_XRGB444, MEDIA_BUS_FMT_ARGB8888_1X32,
     42	  VI6_FMT_XRGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
     43	  VI6_RPF_DSWAP_P_WDS,
     44	  1, { 16, 0, 0 }, false, false, 1, 1, false },
     45	{ V4L2_PIX_FMT_RGBA444, MEDIA_BUS_FMT_ARGB8888_1X32,
     46	  VI6_FMT_RGBA_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
     47	  VI6_RPF_DSWAP_P_WDS,
     48	  1, { 16, 0, 0 }, false, false, 1, 1, true },
     49	{ V4L2_PIX_FMT_RGBX444, MEDIA_BUS_FMT_ARGB8888_1X32,
     50	  VI6_FMT_RGBX_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
     51	  VI6_RPF_DSWAP_P_WDS,
     52	  1, { 16, 0, 0 }, false, false, 1, 1, false },
     53	{ V4L2_PIX_FMT_ABGR444, MEDIA_BUS_FMT_ARGB8888_1X32,
     54	  VI6_FMT_ABGR_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
     55	  VI6_RPF_DSWAP_P_WDS,
     56	  1, { 16, 0, 0 }, false, false, 1, 1, true },
     57	{ V4L2_PIX_FMT_XBGR444, MEDIA_BUS_FMT_ARGB8888_1X32,
     58	  VI6_FMT_ABGR_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
     59	  VI6_RPF_DSWAP_P_WDS,
     60	  1, { 16, 0, 0 }, false, false, 1, 1, false },
     61	{ V4L2_PIX_FMT_BGRA444, MEDIA_BUS_FMT_ARGB8888_1X32,
     62	  VI6_FMT_BGRA_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
     63	  VI6_RPF_DSWAP_P_WDS,
     64	  1, { 16, 0, 0 }, false, false, 1, 1, true },
     65	{ V4L2_PIX_FMT_BGRX444, MEDIA_BUS_FMT_ARGB8888_1X32,
     66	  VI6_FMT_BGRA_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
     67	  VI6_RPF_DSWAP_P_WDS,
     68	  1, { 16, 0, 0 }, false, false, 1, 1, false },
     69	{ V4L2_PIX_FMT_ARGB555, MEDIA_BUS_FMT_ARGB8888_1X32,
     70	  VI6_FMT_ARGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
     71	  VI6_RPF_DSWAP_P_WDS,
     72	  1, { 16, 0, 0 }, false, false, 1, 1, true },
     73	{ V4L2_PIX_FMT_XRGB555, MEDIA_BUS_FMT_ARGB8888_1X32,
     74	  VI6_FMT_XRGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
     75	  VI6_RPF_DSWAP_P_WDS,
     76	  1, { 16, 0, 0 }, false, false, 1, 1, false },
     77	{ V4L2_PIX_FMT_RGBA555, MEDIA_BUS_FMT_ARGB8888_1X32,
     78	  VI6_FMT_RGBA_5551, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
     79	  VI6_RPF_DSWAP_P_WDS,
     80	  1, { 16, 0, 0 }, false, false, 1, 1, true },
     81	{ V4L2_PIX_FMT_RGBX555, MEDIA_BUS_FMT_ARGB8888_1X32,
     82	  VI6_FMT_RGBX_5551, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
     83	  VI6_RPF_DSWAP_P_WDS,
     84	  1, { 16, 0, 0 }, false, false, 1, 1, false },
     85	{ V4L2_PIX_FMT_ABGR555, MEDIA_BUS_FMT_ARGB8888_1X32,
     86	  VI6_FMT_ABGR_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
     87	  VI6_RPF_DSWAP_P_WDS,
     88	  1, { 16, 0, 0 }, false, false, 1, 1, true },
     89	{ V4L2_PIX_FMT_XBGR555, MEDIA_BUS_FMT_ARGB8888_1X32,
     90	  VI6_FMT_ABGR_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
     91	  VI6_RPF_DSWAP_P_WDS,
     92	  1, { 16, 0, 0 }, false, false, 1, 1, false },
     93	{ V4L2_PIX_FMT_BGRA555, MEDIA_BUS_FMT_ARGB8888_1X32,
     94	  VI6_FMT_BGRA_5551, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
     95	  VI6_RPF_DSWAP_P_WDS,
     96	  1, { 16, 0, 0 }, false, false, 1, 1, true },
     97	{ V4L2_PIX_FMT_BGRX555, MEDIA_BUS_FMT_ARGB8888_1X32,
     98	  VI6_FMT_BGRA_5551, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
     99	  VI6_RPF_DSWAP_P_WDS,
    100	  1, { 16, 0, 0 }, false, false, 1, 1, false },
    101	{ V4L2_PIX_FMT_RGB565, MEDIA_BUS_FMT_ARGB8888_1X32,
    102	  VI6_FMT_RGB_565, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
    103	  VI6_RPF_DSWAP_P_WDS,
    104	  1, { 16, 0, 0 }, false, false, 1, 1, false },
    105	{ V4L2_PIX_FMT_BGR24, MEDIA_BUS_FMT_ARGB8888_1X32,
    106	  VI6_FMT_BGR_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
    107	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
    108	  1, { 24, 0, 0 }, false, false, 1, 1, false },
    109	{ V4L2_PIX_FMT_RGB24, MEDIA_BUS_FMT_ARGB8888_1X32,
    110	  VI6_FMT_RGB_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
    111	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
    112	  1, { 24, 0, 0 }, false, false, 1, 1, false },
    113	{ V4L2_PIX_FMT_ABGR32, MEDIA_BUS_FMT_ARGB8888_1X32,
    114	  VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS,
    115	  1, { 32, 0, 0 }, false, false, 1, 1, true },
    116	{ V4L2_PIX_FMT_XBGR32, MEDIA_BUS_FMT_ARGB8888_1X32,
    117	  VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS,
    118	  1, { 32, 0, 0 }, false, false, 1, 1, false },
    119	{ V4L2_PIX_FMT_BGRA32, MEDIA_BUS_FMT_ARGB8888_1X32,
    120	  VI6_FMT_RGBA_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS,
    121	  1, { 32, 0, 0 }, false, false, 1, 1, true },
    122	{ V4L2_PIX_FMT_BGRX32, MEDIA_BUS_FMT_ARGB8888_1X32,
    123	  VI6_FMT_RGBA_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS,
    124	  1, { 32, 0, 0 }, false, false, 1, 1, false },
    125	{ V4L2_PIX_FMT_RGBA32, MEDIA_BUS_FMT_ARGB8888_1X32,
    126	  VI6_FMT_RGBA_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
    127	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
    128	  1, { 32, 0, 0 }, false, false, 1, 1, true },
    129	{ V4L2_PIX_FMT_RGBX32, MEDIA_BUS_FMT_ARGB8888_1X32,
    130	  VI6_FMT_RGBA_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
    131	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
    132	  1, { 32, 0, 0 }, false, false, 1, 1, false },
    133	{ V4L2_PIX_FMT_ARGB32, MEDIA_BUS_FMT_ARGB8888_1X32,
    134	  VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
    135	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
    136	  1, { 32, 0, 0 }, false, false, 1, 1, true },
    137	{ V4L2_PIX_FMT_XRGB32, MEDIA_BUS_FMT_ARGB8888_1X32,
    138	  VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
    139	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
    140	  1, { 32, 0, 0 }, false, false, 1, 1, false },
    141	{ V4L2_PIX_FMT_HSV24, MEDIA_BUS_FMT_AHSV8888_1X32,
    142	  VI6_FMT_RGB_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
    143	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
    144	  1, { 24, 0, 0 }, false, false, 1, 1, false },
    145	{ V4L2_PIX_FMT_HSV32, MEDIA_BUS_FMT_AHSV8888_1X32,
    146	  VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
    147	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
    148	  1, { 32, 0, 0 }, false, false, 1, 1, false },
    149	{ V4L2_PIX_FMT_UYVY, MEDIA_BUS_FMT_AYUV8_1X32,
    150	  VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
    151	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
    152	  1, { 16, 0, 0 }, false, false, 2, 1, false },
    153	{ V4L2_PIX_FMT_VYUY, MEDIA_BUS_FMT_AYUV8_1X32,
    154	  VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
    155	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
    156	  1, { 16, 0, 0 }, false, true, 2, 1, false },
    157	{ V4L2_PIX_FMT_YUYV, MEDIA_BUS_FMT_AYUV8_1X32,
    158	  VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
    159	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
    160	  1, { 16, 0, 0 }, true, false, 2, 1, false },
    161	{ V4L2_PIX_FMT_YVYU, MEDIA_BUS_FMT_AYUV8_1X32,
    162	  VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
    163	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
    164	  1, { 16, 0, 0 }, true, true, 2, 1, false },
    165	{ V4L2_PIX_FMT_NV12M, MEDIA_BUS_FMT_AYUV8_1X32,
    166	  VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
    167	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
    168	  2, { 8, 16, 0 }, false, false, 2, 2, false },
    169	{ V4L2_PIX_FMT_NV21M, MEDIA_BUS_FMT_AYUV8_1X32,
    170	  VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
    171	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
    172	  2, { 8, 16, 0 }, false, true, 2, 2, false },
    173	{ V4L2_PIX_FMT_NV16M, MEDIA_BUS_FMT_AYUV8_1X32,
    174	  VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
    175	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
    176	  2, { 8, 16, 0 }, false, false, 2, 1, false },
    177	{ V4L2_PIX_FMT_NV61M, MEDIA_BUS_FMT_AYUV8_1X32,
    178	  VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
    179	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
    180	  2, { 8, 16, 0 }, false, true, 2, 1, false },
    181	{ V4L2_PIX_FMT_YUV420M, MEDIA_BUS_FMT_AYUV8_1X32,
    182	  VI6_FMT_Y_U_V_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
    183	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
    184	  3, { 8, 8, 8 }, false, false, 2, 2, false },
    185	{ V4L2_PIX_FMT_YVU420M, MEDIA_BUS_FMT_AYUV8_1X32,
    186	  VI6_FMT_Y_U_V_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
    187	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
    188	  3, { 8, 8, 8 }, false, true, 2, 2, false },
    189	{ V4L2_PIX_FMT_YUV422M, MEDIA_BUS_FMT_AYUV8_1X32,
    190	  VI6_FMT_Y_U_V_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
    191	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
    192	  3, { 8, 8, 8 }, false, false, 2, 1, false },
    193	{ V4L2_PIX_FMT_YVU422M, MEDIA_BUS_FMT_AYUV8_1X32,
    194	  VI6_FMT_Y_U_V_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
    195	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
    196	  3, { 8, 8, 8 }, false, true, 2, 1, false },
    197	{ V4L2_PIX_FMT_YUV444M, MEDIA_BUS_FMT_AYUV8_1X32,
    198	  VI6_FMT_Y_U_V_444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
    199	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
    200	  3, { 8, 8, 8 }, false, false, 1, 1, false },
    201	{ V4L2_PIX_FMT_YVU444M, MEDIA_BUS_FMT_AYUV8_1X32,
    202	  VI6_FMT_Y_U_V_444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
    203	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
    204	  3, { 8, 8, 8 }, false, true, 1, 1, false },
    205};
    206
    207/**
    208 * vsp1_get_format_info - Retrieve format information for a 4CC
    209 * @vsp1: the VSP1 device
    210 * @fourcc: the format 4CC
    211 *
    212 * Return a pointer to the format information structure corresponding to the
    213 * given V4L2 format 4CC, or NULL if no corresponding format can be found.
    214 */
    215const struct vsp1_format_info *vsp1_get_format_info(struct vsp1_device *vsp1,
    216						    u32 fourcc)
    217{
    218	unsigned int i;
    219
    220	/* Special case, the VYUY and HSV formats are supported on Gen2 only. */
    221	if (vsp1->info->gen != 2) {
    222		switch (fourcc) {
    223		case V4L2_PIX_FMT_VYUY:
    224		case V4L2_PIX_FMT_HSV24:
    225		case V4L2_PIX_FMT_HSV32:
    226			return NULL;
    227		}
    228	}
    229
    230	for (i = 0; i < ARRAY_SIZE(vsp1_video_formats); ++i) {
    231		const struct vsp1_format_info *info = &vsp1_video_formats[i];
    232
    233		if (info->fourcc == fourcc)
    234			return info;
    235	}
    236
    237	return NULL;
    238}
    239
    240/* -----------------------------------------------------------------------------
    241 * Pipeline Management
    242 */
    243
    244void vsp1_pipeline_reset(struct vsp1_pipeline *pipe)
    245{
    246	struct vsp1_entity *entity;
    247	unsigned int i;
    248
    249	if (pipe->brx) {
    250		struct vsp1_brx *brx = to_brx(&pipe->brx->subdev);
    251
    252		for (i = 0; i < ARRAY_SIZE(brx->inputs); ++i)
    253			brx->inputs[i].rpf = NULL;
    254	}
    255
    256	for (i = 0; i < ARRAY_SIZE(pipe->inputs); ++i)
    257		pipe->inputs[i] = NULL;
    258
    259	pipe->output = NULL;
    260
    261	list_for_each_entry(entity, &pipe->entities, list_pipe)
    262		entity->pipe = NULL;
    263
    264	INIT_LIST_HEAD(&pipe->entities);
    265	pipe->state = VSP1_PIPELINE_STOPPED;
    266	pipe->buffers_ready = 0;
    267	pipe->num_inputs = 0;
    268	pipe->brx = NULL;
    269	pipe->hgo = NULL;
    270	pipe->hgt = NULL;
    271	pipe->lif = NULL;
    272	pipe->uds = NULL;
    273}
    274
    275void vsp1_pipeline_init(struct vsp1_pipeline *pipe)
    276{
    277	mutex_init(&pipe->lock);
    278	spin_lock_init(&pipe->irqlock);
    279	init_waitqueue_head(&pipe->wq);
    280	kref_init(&pipe->kref);
    281
    282	INIT_LIST_HEAD(&pipe->entities);
    283	pipe->state = VSP1_PIPELINE_STOPPED;
    284}
    285
    286/* Must be called with the pipe irqlock held. */
    287void vsp1_pipeline_run(struct vsp1_pipeline *pipe)
    288{
    289	struct vsp1_device *vsp1 = pipe->output->entity.vsp1;
    290
    291	if (pipe->state == VSP1_PIPELINE_STOPPED) {
    292		vsp1_write(vsp1, VI6_CMD(pipe->output->entity.index),
    293			   VI6_CMD_STRCMD);
    294		pipe->state = VSP1_PIPELINE_RUNNING;
    295	}
    296
    297	pipe->buffers_ready = 0;
    298}
    299
    300bool vsp1_pipeline_stopped(struct vsp1_pipeline *pipe)
    301{
    302	unsigned long flags;
    303	bool stopped;
    304
    305	spin_lock_irqsave(&pipe->irqlock, flags);
    306	stopped = pipe->state == VSP1_PIPELINE_STOPPED;
    307	spin_unlock_irqrestore(&pipe->irqlock, flags);
    308
    309	return stopped;
    310}
    311
    312int vsp1_pipeline_stop(struct vsp1_pipeline *pipe)
    313{
    314	struct vsp1_device *vsp1 = pipe->output->entity.vsp1;
    315	struct vsp1_entity *entity;
    316	unsigned long flags;
    317	int ret;
    318
    319	if (pipe->lif) {
    320		/*
    321		 * When using display lists in continuous frame mode the only
    322		 * way to stop the pipeline is to reset the hardware.
    323		 */
    324		ret = vsp1_reset_wpf(vsp1, pipe->output->entity.index);
    325		if (ret == 0) {
    326			spin_lock_irqsave(&pipe->irqlock, flags);
    327			pipe->state = VSP1_PIPELINE_STOPPED;
    328			spin_unlock_irqrestore(&pipe->irqlock, flags);
    329		}
    330	} else {
    331		/* Otherwise just request a stop and wait. */
    332		spin_lock_irqsave(&pipe->irqlock, flags);
    333		if (pipe->state == VSP1_PIPELINE_RUNNING)
    334			pipe->state = VSP1_PIPELINE_STOPPING;
    335		spin_unlock_irqrestore(&pipe->irqlock, flags);
    336
    337		ret = wait_event_timeout(pipe->wq, vsp1_pipeline_stopped(pipe),
    338					 msecs_to_jiffies(500));
    339		ret = ret == 0 ? -ETIMEDOUT : 0;
    340	}
    341
    342	list_for_each_entry(entity, &pipe->entities, list_pipe) {
    343		if (entity->route && entity->route->reg)
    344			vsp1_write(vsp1, entity->route->reg,
    345				   VI6_DPR_NODE_UNUSED);
    346	}
    347
    348	if (pipe->hgo)
    349		vsp1_write(vsp1, VI6_DPR_HGO_SMPPT,
    350			   (7 << VI6_DPR_SMPPT_TGW_SHIFT) |
    351			   (VI6_DPR_NODE_UNUSED << VI6_DPR_SMPPT_PT_SHIFT));
    352
    353	if (pipe->hgt)
    354		vsp1_write(vsp1, VI6_DPR_HGT_SMPPT,
    355			   (7 << VI6_DPR_SMPPT_TGW_SHIFT) |
    356			   (VI6_DPR_NODE_UNUSED << VI6_DPR_SMPPT_PT_SHIFT));
    357
    358	v4l2_subdev_call(&pipe->output->entity.subdev, video, s_stream, 0);
    359
    360	return ret;
    361}
    362
    363bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe)
    364{
    365	unsigned int mask;
    366
    367	mask = ((1 << pipe->num_inputs) - 1) << 1;
    368	if (!pipe->lif)
    369		mask |= 1 << 0;
    370
    371	return pipe->buffers_ready == mask;
    372}
    373
    374void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
    375{
    376	unsigned int flags;
    377
    378	if (pipe == NULL)
    379		return;
    380
    381	/*
    382	 * If the DL commit raced with the frame end interrupt, the commit ends
    383	 * up being postponed by one frame. The returned flags tell whether the
    384	 * active frame was finished or postponed.
    385	 */
    386	flags = vsp1_dlm_irq_frame_end(pipe->output->dlm);
    387
    388	if (pipe->hgo)
    389		vsp1_hgo_frame_end(pipe->hgo);
    390
    391	if (pipe->hgt)
    392		vsp1_hgt_frame_end(pipe->hgt);
    393
    394	/*
    395	 * Regardless of frame completion we still need to notify the pipe
    396	 * frame_end to account for vblank events.
    397	 */
    398	if (pipe->frame_end)
    399		pipe->frame_end(pipe, flags);
    400
    401	pipe->sequence++;
    402}
    403
    404/*
    405 * Propagate the alpha value through the pipeline.
    406 *
    407 * As the UDS has restricted scaling capabilities when the alpha component needs
    408 * to be scaled, we disable alpha scaling when the UDS input has a fixed alpha
    409 * value. The UDS then outputs a fixed alpha value which needs to be programmed
    410 * from the input RPF alpha.
    411 */
    412void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
    413				   struct vsp1_dl_body *dlb, unsigned int alpha)
    414{
    415	if (!pipe->uds)
    416		return;
    417
    418	/*
    419	 * The BRU and BRS background color has a fixed alpha value set to 255,
    420	 * the output alpha value is thus always equal to 255.
    421	 */
    422	if (pipe->uds_input->type == VSP1_ENTITY_BRU ||
    423	    pipe->uds_input->type == VSP1_ENTITY_BRS)
    424		alpha = 255;
    425
    426	vsp1_uds_set_alpha(pipe->uds, dlb, alpha);
    427}
    428
    429/*
    430 * Propagate the partition calculations through the pipeline
    431 *
    432 * Work backwards through the pipe, allowing each entity to update the partition
    433 * parameters based on its configuration, and the entity connected to its
    434 * source. Each entity must produce the partition required for the previous
    435 * entity in the pipeline.
    436 */
    437void vsp1_pipeline_propagate_partition(struct vsp1_pipeline *pipe,
    438				       struct vsp1_partition *partition,
    439				       unsigned int index,
    440				       struct vsp1_partition_window *window)
    441{
    442	struct vsp1_entity *entity;
    443
    444	list_for_each_entry_reverse(entity, &pipe->entities, list_pipe) {
    445		if (entity->ops->partition)
    446			entity->ops->partition(entity, pipe, partition, index,
    447					       window);
    448	}
    449}
    450