b79bdb8412ba9b8f432cb86bb385a5a88a12bf2f
[openwrt/staging/ldir.git] /
1 From adab474d1f91594d6d96d44054586ba36d7f26d4 Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.org>
3 Date: Mon, 24 Sep 2018 18:15:38 +0100
4 Subject: [PATCH] staging: mmal-vchiq: Add support for event callbacks.
5
6 (Preparation for the codec driver).
7 The codec uses the event mechanism to report things such as
8 resolution changes. It is signalled by the cmd field of the buffer
9 being non-zero.
10
11 Add support for passing this information out to the client.
12
13 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
14 ---
15 .../vc04_services/vchiq-mmal/mmal-common.h | 1 +
16 .../vc04_services/vchiq-mmal/mmal-msg.h | 35 ++++
17 .../vc04_services/vchiq-mmal/mmal-vchiq.c | 170 ++++++++++++++++--
18 .../vc04_services/vchiq-mmal/mmal-vchiq.h | 4 +
19 4 files changed, 196 insertions(+), 14 deletions(-)
20
21 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
22 +++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
23 @@ -51,6 +51,7 @@ struct mmal_buffer {
24
25 struct mmal_msg_context *msg_context;
26
27 + u32 cmd; /* MMAL command. 0=data. */
28 unsigned long length;
29 u32 mmal_flags;
30 s64 dts;
31 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h
32 +++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h
33 @@ -346,6 +346,41 @@ struct mmal_msg_port_parameter_get_reply
34 /* event messages */
35 #define MMAL_WORKER_EVENT_SPACE 256
36
37 +/* Four CC's for events */
38 +#define MMAL_FOURCC(a, b, c, d) ((a) | (b << 8) | (c << 16) | (d << 24))
39 +
40 +#define MMAL_EVENT_ERROR MMAL_FOURCC('E', 'R', 'R', 'O')
41 +#define MMAL_EVENT_EOS MMAL_FOURCC('E', 'E', 'O', 'S')
42 +#define MMAL_EVENT_FORMAT_CHANGED MMAL_FOURCC('E', 'F', 'C', 'H')
43 +#define MMAL_EVENT_PARAMETER_CHANGED MMAL_FOURCC('E', 'P', 'C', 'H')
44 +
45 +/* Structs for each of the event message payloads */
46 +struct mmal_msg_event_eos {
47 + u32 port_type; /**< Type of port that received the end of stream */
48 + u32 port_index; /**< Index of port that received the end of stream */
49 +};
50 +
51 +/** Format changed event data. */
52 +struct mmal_msg_event_format_changed {
53 + /* Minimum size of buffers the port requires */
54 + u32 buffer_size_min;
55 + /* Minimum number of buffers the port requires */
56 + u32 buffer_num_min;
57 + /* Size of buffers the port recommends for optimal performance.
58 + * A value of zero means no special recommendation.
59 + */
60 + u32 buffer_size_recommended;
61 + /* Number of buffers the port recommends for optimal
62 + * performance. A value of zero means no special recommendation.
63 + */
64 + u32 buffer_num_recommended;
65 +
66 + u32 es_ptr;
67 + struct mmal_es_format format;
68 + union mmal_es_specific_format es;
69 + u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE];
70 +};
71 +
72 struct mmal_msg_event_to_host {
73 u32 client_component; /* component context */
74
75 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
76 +++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
77 @@ -151,6 +151,8 @@ struct mmal_msg_context {
78 /* Presentation and Decode timestamps */
79 s64 pts;
80 s64 dts;
81 + /* MMAL buffer command flag */
82 + u32 cmd;
83
84 int status; /* context status */
85
86 @@ -238,18 +240,6 @@ release_msg_context(struct mmal_msg_cont
87 kfree(msg_context);
88 }
89
90 -/* deals with receipt of event to host message */
91 -static void event_to_host_cb(struct vchiq_mmal_instance *instance,
92 - struct mmal_msg *msg, u32 msg_len)
93 -{
94 - pr_debug("unhandled event\n");
95 - pr_debug("component:%u port type:%d num:%d cmd:0x%x length:%d\n",
96 - msg->u.event_to_host.client_component,
97 - msg->u.event_to_host.port_type,
98 - msg->u.event_to_host.port_num,
99 - msg->u.event_to_host.cmd, msg->u.event_to_host.length);
100 -}
101 -
102 /* workqueue scheduled callback
103 *
104 * we do this because it is important we do not call any other vchiq
105 @@ -271,13 +261,18 @@ static void buffer_work_cb(struct work_s
106 buffer->mmal_flags = msg_context->u.bulk.mmal_flags;
107 buffer->dts = msg_context->u.bulk.dts;
108 buffer->pts = msg_context->u.bulk.pts;
109 + buffer->cmd = msg_context->u.bulk.cmd;
110
111 - atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu);
112 + if (!buffer->cmd)
113 + atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu);
114
115 msg_context->u.bulk.port->buffer_cb(msg_context->u.bulk.instance,
116 msg_context->u.bulk.port,
117 msg_context->u.bulk.status,
118 msg_context->u.bulk.buffer);
119 +
120 + if (buffer->cmd)
121 + mutex_unlock(&msg_context->u.bulk.port->event_context_mutex);
122 }
123
124 /* workqueue scheduled callback to handle receiving buffers
125 @@ -356,6 +351,7 @@ static int bulk_receive(struct vchiq_mma
126 msg_context->u.bulk.buffer_used = rd_len;
127 msg_context->u.bulk.dts = msg->u.buffer_from_host.buffer_header.dts;
128 msg_context->u.bulk.pts = msg->u.buffer_from_host.buffer_header.pts;
129 + msg_context->u.bulk.cmd = msg->u.buffer_from_host.buffer_header.cmd;
130
131 queue_work(msg_context->instance->bulk_wq,
132 &msg_context->u.bulk.buffer_to_host_work);
133 @@ -457,6 +453,103 @@ buffer_from_host(struct vchiq_mmal_insta
134 return ret;
135 }
136
137 +/* deals with receipt of event to host message */
138 +static void event_to_host_cb(struct vchiq_mmal_instance *instance,
139 + struct mmal_msg *msg, u32 msg_len)
140 +{
141 + /* FIXME: Not going to work on 64 bit */
142 + struct vchiq_mmal_component *component =
143 + (struct vchiq_mmal_component *)msg->u.event_to_host.client_component;
144 + struct vchiq_mmal_port *port = NULL;
145 + struct mmal_msg_context *msg_context;
146 + u32 port_num = msg->u.event_to_host.port_num;
147 +
148 + if (msg->u.buffer_from_host.drvbuf.magic == MMAL_MAGIC) {
149 + pr_err("%s: MMAL_MSG_TYPE_BUFFER_TO_HOST with bad magic\n",
150 + __func__);
151 + return;
152 + }
153 +
154 + switch (msg->u.event_to_host.port_type) {
155 + case MMAL_PORT_TYPE_CONTROL:
156 + if (port_num) {
157 + pr_err("%s: port_num of %u >= number of ports 1",
158 + __func__, port_num);
159 + return;
160 + }
161 + port = &component->control;
162 + break;
163 + case MMAL_PORT_TYPE_INPUT:
164 + if (port_num >= component->inputs) {
165 + pr_err("%s: port_num of %u >= number of ports %u",
166 + __func__, port_num,
167 + port_num >= component->inputs);
168 + return;
169 + }
170 + port = &component->input[port_num];
171 + break;
172 + case MMAL_PORT_TYPE_OUTPUT:
173 + if (port_num >= component->outputs) {
174 + pr_err("%s: port_num of %u >= number of ports %u",
175 + __func__, port_num,
176 + port_num >= component->outputs);
177 + return;
178 + }
179 + port = &component->output[port_num];
180 + break;
181 + case MMAL_PORT_TYPE_CLOCK:
182 + if (port_num >= component->clocks) {
183 + pr_err("%s: port_num of %u >= number of ports %u",
184 + __func__, port_num,
185 + port_num >= component->clocks);
186 + return;
187 + }
188 + port = &component->clock[port_num];
189 + break;
190 + default:
191 + break;
192 + }
193 +
194 + if (!mutex_trylock(&port->event_context_mutex)) {
195 + pr_err("dropping event 0x%x\n", msg->u.event_to_host.cmd);
196 + return;
197 + }
198 + msg_context = port->event_context;
199 +
200 + if (msg->h.status != MMAL_MSG_STATUS_SUCCESS) {
201 + /* message reception had an error */
202 + //pr_warn
203 + pr_err("%s: error %d in reply\n", __func__, msg->h.status);
204 +
205 + msg_context->u.bulk.status = msg->h.status;
206 + } else if (msg->u.event_to_host.length > MMAL_WORKER_EVENT_SPACE) {
207 + /* data is not in message, queue a bulk receive */
208 + pr_err("%s: payload not in message - bulk receive??! NOT SUPPORTED\n",
209 + __func__);
210 + msg_context->u.bulk.status = -1;
211 + } else {
212 + memcpy(msg_context->u.bulk.buffer->buffer,
213 + msg->u.event_to_host.data,
214 + msg->u.event_to_host.length);
215 +
216 + msg_context->u.bulk.buffer_used =
217 + msg->u.event_to_host.length;
218 +
219 + msg_context->u.bulk.mmal_flags = 0;
220 + msg_context->u.bulk.dts = MMAL_TIME_UNKNOWN;
221 + msg_context->u.bulk.pts = MMAL_TIME_UNKNOWN;
222 + msg_context->u.bulk.cmd = msg->u.event_to_host.cmd;
223 +
224 + pr_debug("event component:%u port type:%d num:%d cmd:0x%x length:%d\n",
225 + msg->u.event_to_host.client_component,
226 + msg->u.event_to_host.port_type,
227 + msg->u.event_to_host.port_num,
228 + msg->u.event_to_host.cmd, msg->u.event_to_host.length);
229 + }
230 +
231 + schedule_work(&msg_context->u.bulk.work);
232 +}
233 +
234 /* deals with receipt of buffer to host message */
235 static void buffer_to_host_cb(struct vchiq_mmal_instance *instance,
236 struct mmal_msg *msg, u32 msg_len)
237 @@ -1340,6 +1433,7 @@ static int port_disable(struct vchiq_mma
238 mmalbuf->mmal_flags = 0;
239 mmalbuf->dts = MMAL_TIME_UNKNOWN;
240 mmalbuf->pts = MMAL_TIME_UNKNOWN;
241 + mmalbuf->cmd = 0;
242 port->buffer_cb(instance,
243 port, 0, mmalbuf);
244 }
245 @@ -1641,6 +1735,43 @@ int mmal_vchi_buffer_cleanup(struct mmal
246 }
247 EXPORT_SYMBOL_GPL(mmal_vchi_buffer_cleanup);
248
249 +static void init_event_context(struct vchiq_mmal_instance *instance,
250 + struct vchiq_mmal_port *port)
251 +{
252 + struct mmal_msg_context *ctx = get_msg_context(instance);
253 +
254 + mutex_init(&port->event_context_mutex);
255 +
256 + port->event_context = ctx;
257 + ctx->u.bulk.instance = instance;
258 + ctx->u.bulk.port = port;
259 + ctx->u.bulk.buffer =
260 + kzalloc(sizeof(*ctx->u.bulk.buffer), GFP_KERNEL);
261 + if (!ctx->u.bulk.buffer)
262 + goto release_msg_context;
263 + ctx->u.bulk.buffer->buffer = kzalloc(MMAL_WORKER_EVENT_SPACE,
264 + GFP_KERNEL);
265 + if (!ctx->u.bulk.buffer->buffer)
266 + goto release_buffer;
267 +
268 + INIT_WORK(&ctx->u.bulk.work, buffer_work_cb);
269 + return;
270 +
271 +release_buffer:
272 + kfree(ctx->u.bulk.buffer);
273 +release_msg_context:
274 + release_msg_context(ctx);
275 +}
276 +
277 +static void free_event_context(struct vchiq_mmal_port *port)
278 +{
279 + struct mmal_msg_context *ctx = port->event_context;
280 +
281 + kfree(ctx->u.bulk.buffer->buffer);
282 + kfree(ctx->u.bulk.buffer);
283 + release_msg_context(ctx);
284 +}
285 +
286 /* Initialise a mmal component and its ports
287 *
288 */
289 @@ -1684,6 +1815,7 @@ int vchiq_mmal_component_init(struct vch
290 ret = port_info_get(instance, &component->control);
291 if (ret < 0)
292 goto release_component;
293 + init_event_context(instance, &component->control);
294
295 for (idx = 0; idx < component->inputs; idx++) {
296 component->input[idx].type = MMAL_PORT_TYPE_INPUT;
297 @@ -1694,6 +1826,7 @@ int vchiq_mmal_component_init(struct vch
298 ret = port_info_get(instance, &component->input[idx]);
299 if (ret < 0)
300 goto release_component;
301 + init_event_context(instance, &component->input[idx]);
302 }
303
304 for (idx = 0; idx < component->outputs; idx++) {
305 @@ -1705,6 +1838,7 @@ int vchiq_mmal_component_init(struct vch
306 ret = port_info_get(instance, &component->output[idx]);
307 if (ret < 0)
308 goto release_component;
309 + init_event_context(instance, &component->output[idx]);
310 }
311
312 for (idx = 0; idx < component->clocks; idx++) {
313 @@ -1716,6 +1850,7 @@ int vchiq_mmal_component_init(struct vch
314 ret = port_info_get(instance, &component->clock[idx]);
315 if (ret < 0)
316 goto release_component;
317 + init_event_context(instance, &component->clock[idx]);
318 }
319
320 *component_out = component;
321 @@ -1741,7 +1876,7 @@ EXPORT_SYMBOL_GPL(vchiq_mmal_component_i
322 int vchiq_mmal_component_finalise(struct vchiq_mmal_instance *instance,
323 struct vchiq_mmal_component *component)
324 {
325 - int ret;
326 + int ret, idx;
327
328 if (mutex_lock_interruptible(&instance->vchiq_mutex))
329 return -EINTR;
330 @@ -1753,6 +1888,13 @@ int vchiq_mmal_component_finalise(struct
331
332 component->in_use = 0;
333
334 + for (idx = 0; idx < component->inputs; idx++)
335 + free_event_context(&component->input[idx]);
336 + for (idx = 0; idx < component->outputs; idx++)
337 + free_event_context(&component->output[idx]);
338 + for (idx = 0; idx < component->clocks; idx++)
339 + free_event_context(&component->clock[idx]);
340 +
341 mutex_unlock(&instance->vchiq_mutex);
342
343 return ret;
344 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
345 +++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
346 @@ -78,6 +78,10 @@ struct vchiq_mmal_port {
347 vchiq_mmal_buffer_cb buffer_cb;
348 /* callback context */
349 void *cb_ctx;
350 +
351 + /* ensure serialised use of the one event context structure */
352 + struct mutex event_context_mutex;
353 + struct mmal_msg_context *event_context;
354 };
355
356 struct vchiq_mmal_component {