[media] v4l: vsp1: Rename video pipeline functions to use vsp1_video prefix
[deliverable/linux.git] / drivers / media / platform / vsp1 / vsp1_pipe.c
CommitLineData
dba4a180
LP
1/*
2 * vsp1_pipe.c -- R-Car VSP1 Pipeline
3 *
4 * Copyright (C) 2013-2015 Renesas Electronics Corporation
5 *
6 * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
7 *
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.
12 */
13
14#include <linux/list.h>
15#include <linux/sched.h>
16#include <linux/wait.h>
17
18#include <media/media-entity.h>
19#include <media/v4l2-subdev.h>
20
21#include "vsp1.h"
22#include "vsp1_bru.h"
23#include "vsp1_entity.h"
24#include "vsp1_pipe.h"
25#include "vsp1_rwpf.h"
26#include "vsp1_uds.h"
27
28/* -----------------------------------------------------------------------------
29 * Pipeline Management
30 */
31
32void vsp1_pipeline_reset(struct vsp1_pipeline *pipe)
33{
34 if (pipe->bru) {
35 struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
36 unsigned int i;
37
38 for (i = 0; i < ARRAY_SIZE(bru->inputs); ++i)
39 bru->inputs[i].rpf = NULL;
40 }
41
42 INIT_LIST_HEAD(&pipe->entities);
43 pipe->state = VSP1_PIPELINE_STOPPED;
44 pipe->buffers_ready = 0;
45 pipe->num_inputs = 0;
46 pipe->output = NULL;
47 pipe->bru = NULL;
48 pipe->lif = NULL;
49 pipe->uds = NULL;
50}
51
52void vsp1_pipeline_run(struct vsp1_pipeline *pipe)
53{
54 struct vsp1_device *vsp1 = pipe->output->entity.vsp1;
55
56 vsp1_write(vsp1, VI6_CMD(pipe->output->entity.index), VI6_CMD_STRCMD);
57 pipe->state = VSP1_PIPELINE_RUNNING;
58 pipe->buffers_ready = 0;
59}
60
61bool vsp1_pipeline_stopped(struct vsp1_pipeline *pipe)
62{
63 unsigned long flags;
64 bool stopped;
65
66 spin_lock_irqsave(&pipe->irqlock, flags);
67 stopped = pipe->state == VSP1_PIPELINE_STOPPED;
68 spin_unlock_irqrestore(&pipe->irqlock, flags);
69
70 return stopped;
71}
72
73int vsp1_pipeline_stop(struct vsp1_pipeline *pipe)
74{
75 struct vsp1_entity *entity;
76 unsigned long flags;
77 int ret;
78
79 spin_lock_irqsave(&pipe->irqlock, flags);
80 if (pipe->state == VSP1_PIPELINE_RUNNING)
81 pipe->state = VSP1_PIPELINE_STOPPING;
82 spin_unlock_irqrestore(&pipe->irqlock, flags);
83
84 ret = wait_event_timeout(pipe->wq, vsp1_pipeline_stopped(pipe),
85 msecs_to_jiffies(500));
86 ret = ret == 0 ? -ETIMEDOUT : 0;
87
88 list_for_each_entry(entity, &pipe->entities, list_pipe) {
89 if (entity->route && entity->route->reg)
90 vsp1_write(entity->vsp1, entity->route->reg,
91 VI6_DPR_NODE_UNUSED);
92
93 v4l2_subdev_call(&entity->subdev, video, s_stream, 0);
94 }
95
96 return ret;
97}
98
99bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe)
100{
101 unsigned int mask;
102
103 mask = ((1 << pipe->num_inputs) - 1) << 1;
104 if (!pipe->lif)
105 mask |= 1 << 0;
106
107 return pipe->buffers_ready == mask;
108}
109
110void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
111{
112 enum vsp1_pipeline_state state;
113 unsigned long flags;
114
115 if (pipe == NULL)
116 return;
117
118 /* Signal frame end to the pipeline handler. */
119 pipe->frame_end(pipe);
120
121 spin_lock_irqsave(&pipe->irqlock, flags);
122
123 state = pipe->state;
124 pipe->state = VSP1_PIPELINE_STOPPED;
125
126 /* If a stop has been requested, mark the pipeline as stopped and
127 * return.
128 */
129 if (state == VSP1_PIPELINE_STOPPING) {
130 wake_up(&pipe->wq);
131 goto done;
132 }
133
134 /* Restart the pipeline if ready. */
135 if (vsp1_pipeline_ready(pipe))
136 vsp1_pipeline_run(pipe);
137
138done:
139 spin_unlock_irqrestore(&pipe->irqlock, flags);
140}
141
142/*
143 * Propagate the alpha value through the pipeline.
144 *
145 * As the UDS has restricted scaling capabilities when the alpha component needs
146 * to be scaled, we disable alpha scaling when the UDS input has a fixed alpha
147 * value. The UDS then outputs a fixed alpha value which needs to be programmed
148 * from the input RPF alpha.
149 */
150void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
151 struct vsp1_entity *input,
152 unsigned int alpha)
153{
154 struct vsp1_entity *entity;
155 struct media_pad *pad;
156
157 pad = media_entity_remote_pad(&input->pads[RWPF_PAD_SOURCE]);
158
159 while (pad) {
160 if (!is_media_entity_v4l2_subdev(pad->entity))
161 break;
162
163 entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity));
164
165 /* The BRU background color has a fixed alpha value set to 255,
166 * the output alpha value is thus always equal to 255.
167 */
168 if (entity->type == VSP1_ENTITY_BRU)
169 alpha = 255;
170
171 if (entity->type == VSP1_ENTITY_UDS) {
172 struct vsp1_uds *uds = to_uds(&entity->subdev);
173
174 vsp1_uds_set_alpha(uds, alpha);
175 break;
176 }
177
178 pad = &entity->pads[entity->source_pad];
179 pad = media_entity_remote_pad(pad);
180 }
181}
182
183void vsp1_pipelines_suspend(struct vsp1_device *vsp1)
184{
185 unsigned long flags;
186 unsigned int i;
187 int ret;
188
189 /* To avoid increasing the system suspend time needlessly, loop over the
190 * pipelines twice, first to set them all to the stopping state, and
191 * then to wait for the stop to complete.
192 */
193 for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
194 struct vsp1_rwpf *wpf = vsp1->wpf[i];
195 struct vsp1_pipeline *pipe;
196
197 if (wpf == NULL)
198 continue;
199
200 pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity);
201 if (pipe == NULL)
202 continue;
203
204 spin_lock_irqsave(&pipe->irqlock, flags);
205 if (pipe->state == VSP1_PIPELINE_RUNNING)
206 pipe->state = VSP1_PIPELINE_STOPPING;
207 spin_unlock_irqrestore(&pipe->irqlock, flags);
208 }
209
210 for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
211 struct vsp1_rwpf *wpf = vsp1->wpf[i];
212 struct vsp1_pipeline *pipe;
213
214 if (wpf == NULL)
215 continue;
216
217 pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity);
218 if (pipe == NULL)
219 continue;
220
221 ret = wait_event_timeout(pipe->wq, vsp1_pipeline_stopped(pipe),
222 msecs_to_jiffies(500));
223 if (ret == 0)
224 dev_warn(vsp1->dev, "pipeline %u stop timeout\n",
225 wpf->entity.index);
226 }
227}
228
229void vsp1_pipelines_resume(struct vsp1_device *vsp1)
230{
231 unsigned int i;
232
233 /* Resume pipeline all running pipelines. */
234 for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
235 struct vsp1_rwpf *wpf = vsp1->wpf[i];
236 struct vsp1_pipeline *pipe;
237
238 if (wpf == NULL)
239 continue;
240
241 pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity);
242 if (pipe == NULL)
243 continue;
244
245 if (vsp1_pipeline_ready(pipe))
246 vsp1_pipeline_run(pipe);
247 }
248}
This page took 0.035301 seconds and 5 git commands to generate.