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.
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
11 Add support for passing this information out to the client.
13 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
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(-)
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 {
25 struct mmal_msg_context *msg_context;
27 + u32 cmd; /* MMAL command. 0=data. */
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
35 #define MMAL_WORKER_EVENT_SPACE 256
37 +/* Four CC's for events */
38 +#define MMAL_FOURCC(a, b, c, d) ((a) | (b << 8) | (c << 16) | (d << 24))
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')
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 */
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 */
57 + /* Size of buffers the port recommends for optimal performance.
58 + * A value of zero means no special recommendation.
60 + u32 buffer_size_recommended;
61 + /* Number of buffers the port recommends for optimal
62 + * performance. A value of zero means no special recommendation.
64 + u32 buffer_num_recommended;
67 + struct mmal_es_format format;
68 + union mmal_es_specific_format es;
69 + u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE];
72 struct mmal_msg_event_to_host {
73 u32 client_component; /* component context */
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 */
81 + /* MMAL buffer command flag */
84 int status; /* context status */
86 @@ -238,18 +240,6 @@ release_msg_context(struct mmal_msg_cont
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)
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);
102 /* workqueue scheduled callback
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;
111 - atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu);
113 + atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu);
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);
121 + mutex_unlock(&msg_context->u.bulk.port->event_context_mutex);
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;
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
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)
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;
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",
154 + switch (msg->u.event_to_host.port_type) {
155 + case MMAL_PORT_TYPE_CONTROL:
157 + pr_err("%s: port_num of %u >= number of ports 1",
158 + __func__, port_num);
161 + port = &component->control;
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);
170 + port = &component->input[port_num];
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);
179 + port = &component->output[port_num];
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);
188 + port = &component->clock[port_num];
194 + if (!mutex_trylock(&port->event_context_mutex)) {
195 + pr_err("dropping event 0x%x\n", msg->u.event_to_host.cmd);
198 + msg_context = port->event_context;
200 + if (msg->h.status != MMAL_MSG_STATUS_SUCCESS) {
201 + /* message reception had an error */
203 + pr_err("%s: error %d in reply\n", __func__, msg->h.status);
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",
210 + msg_context->u.bulk.status = -1;
212 + memcpy(msg_context->u.bulk.buffer->buffer,
213 + msg->u.event_to_host.data,
214 + msg->u.event_to_host.length);
216 + msg_context->u.bulk.buffer_used =
217 + msg->u.event_to_host.length;
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;
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);
231 + schedule_work(&msg_context->u.bulk.work);
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;
242 port->buffer_cb(instance,
245 @@ -1641,6 +1735,43 @@ int mmal_vchi_buffer_cleanup(struct mmal
247 EXPORT_SYMBOL_GPL(mmal_vchi_buffer_cleanup);
249 +static void init_event_context(struct vchiq_mmal_instance *instance,
250 + struct vchiq_mmal_port *port)
252 + struct mmal_msg_context *ctx = get_msg_context(instance);
254 + mutex_init(&port->event_context_mutex);
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,
265 + if (!ctx->u.bulk.buffer->buffer)
266 + goto release_buffer;
268 + INIT_WORK(&ctx->u.bulk.work, buffer_work_cb);
272 + kfree(ctx->u.bulk.buffer);
273 +release_msg_context:
274 + release_msg_context(ctx);
277 +static void free_event_context(struct vchiq_mmal_port *port)
279 + struct mmal_msg_context *ctx = port->event_context;
281 + kfree(ctx->u.bulk.buffer->buffer);
282 + kfree(ctx->u.bulk.buffer);
283 + release_msg_context(ctx);
286 /* Initialise a mmal component and its ports
289 @@ -1684,6 +1815,7 @@ int vchiq_mmal_component_init(struct vch
290 ret = port_info_get(instance, &component->control);
292 goto release_component;
293 + init_event_context(instance, &component->control);
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]);
300 goto release_component;
301 + init_event_context(instance, &component->input[idx]);
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]);
308 goto release_component;
309 + init_event_context(instance, &component->output[idx]);
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]);
316 goto release_component;
317 + init_event_context(instance, &component->clock[idx]);
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)
328 if (mutex_lock_interruptible(&instance->vchiq_mutex))
330 @@ -1753,6 +1888,13 @@ int vchiq_mmal_component_finalise(struct
332 component->in_use = 0;
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]);
341 mutex_unlock(&instance->vchiq_mutex);
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 */
351 + /* ensure serialised use of the one event context structure */
352 + struct mutex event_context_mutex;
353 + struct mmal_msg_context *event_context;
356 struct vchiq_mmal_component {