brcm2708: update to latest patches from RPi foundation
[openwrt/openwrt.git] / target / linux / brcm2708 / patches-4.19 / 950-0232-staging-vc04_services-Split-vchiq-mmal-into-a-module.patch
diff --git a/target/linux/brcm2708/patches-4.19/950-0232-staging-vc04_services-Split-vchiq-mmal-into-a-module.patch b/target/linux/brcm2708/patches-4.19/950-0232-staging-vc04_services-Split-vchiq-mmal-into-a-module.patch
new file mode 100644 (file)
index 0000000..1cd23da
--- /dev/null
@@ -0,0 +1,7535 @@
+From e7723c6bcf31a440b8762e9e22497ff3fbbb7056 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 24 Sep 2018 16:30:37 +0100
+Subject: [PATCH] staging: vc04_services: Split vchiq-mmal into a
+ module
+
+In preparation for adding a video codec V4L2 module which also
+wants to use vchiq-mmal functions, split it out into an
+independent module.
+The minimum number of changes have been made to achieve this
+(eg straight moves where possible) so existing checkpatch
+errors will still be present.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ drivers/staging/vc04_services/Kconfig         |  1 +
+ drivers/staging/vc04_services/Makefile        |  1 +
+ .../vc04_services/bcm2835-camera/Kconfig      |  2 +-
+ .../vc04_services/bcm2835-camera/Makefile     |  4 ++--
+ .../staging/vc04_services/vchiq-mmal/Kconfig  |  7 ++++++
+ .../staging/vc04_services/vchiq-mmal/Makefile |  8 +++++++
+ .../mmal-common.h                             |  0
+ .../mmal-encodings.h                          |  0
+ .../mmal-msg-common.h                         |  0
+ .../mmal-msg-format.h                         |  0
+ .../mmal-msg-port.h                           |  0
+ .../{bcm2835-camera => vchiq-mmal}/mmal-msg.h |  0
+ .../mmal-parameters.h                         |  0
+ .../mmal-vchiq.c                              | 22 +++++++++++++++++++
+ .../mmal-vchiq.h                              |  0
+ 15 files changed, 42 insertions(+), 3 deletions(-)
+ create mode 100644 drivers/staging/vc04_services/vchiq-mmal/Kconfig
+ create mode 100644 drivers/staging/vc04_services/vchiq-mmal/Makefile
+ rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-common.h (100%)
+ rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-encodings.h (100%)
+ rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-msg-common.h (100%)
+ rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-msg-format.h (100%)
+ rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-msg-port.h (100%)
+ rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-msg.h (100%)
+ rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-parameters.h (100%)
+ rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-vchiq.c (98%)
+ rename drivers/staging/vc04_services/{bcm2835-camera => vchiq-mmal}/mmal-vchiq.h (100%)
+
+--- a/drivers/staging/vc04_services/Kconfig
++++ b/drivers/staging/vc04_services/Kconfig
+@@ -21,6 +21,7 @@ config BCM2835_VCHIQ
+ source "drivers/staging/vc04_services/bcm2835-audio/Kconfig"
+ source "drivers/staging/vc04_services/bcm2835-camera/Kconfig"
++source "drivers/staging/vc04_services/vchiq-mmal/Kconfig"
+ endif
+--- a/drivers/staging/vc04_services/Makefile
++++ b/drivers/staging/vc04_services/Makefile
+@@ -12,6 +12,7 @@ vchiq-objs := \
+ obj-$(CONFIG_SND_BCM2835)     += bcm2835-audio/
+ obj-$(CONFIG_VIDEO_BCM2835)   += bcm2835-camera/
++obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += vchiq-mmal/
+ ccflags-y += -Idrivers/staging/vc04_services -D__VCCOREVER__=0x04000000
+--- a/drivers/staging/vc04_services/bcm2835-camera/Kconfig
++++ b/drivers/staging/vc04_services/bcm2835-camera/Kconfig
+@@ -2,7 +2,7 @@ config VIDEO_BCM2835
+       tristate "BCM2835 Camera"
+       depends on MEDIA_SUPPORT
+       depends on VIDEO_V4L2 && (ARCH_BCM2835 || COMPILE_TEST)
+-      select BCM2835_VCHIQ
++      select BCM2835_VCHIQ_MMAL
+       select VIDEOBUF2_VMALLOC
+       select BTREE
+       help
+--- a/drivers/staging/vc04_services/bcm2835-camera/Makefile
++++ b/drivers/staging/vc04_services/bcm2835-camera/Makefile
+@@ -1,11 +1,11 @@
+ # SPDX-License-Identifier: GPL-2.0
+ bcm2835-v4l2-$(CONFIG_VIDEO_BCM2835) := \
+       bcm2835-camera.o \
+-      controls.o \
+-      mmal-vchiq.o
++      controls.o
+ obj-$(CONFIG_VIDEO_BCM2835) += bcm2835-v4l2.o
+ ccflags-y += \
+       -Idrivers/staging/vc04_services \
++      -Idrivers/staging/vc04_services/vchiq-mmal \
+       -D__VCCOREVER__=0x04000000
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/Kconfig
+@@ -0,0 +1,7 @@
++config BCM2835_VCHIQ_MMAL
++      tristate "BCM2835 MMAL VCHIQ service"
++      depends on (ARCH_BCM2835 || COMPILE_TEST)
++      select BCM2835_VCHIQ
++      help
++        Enables the MMAL API over VCHIQ as used for the
++        majority of the multimedia services on VideoCore.
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/Makefile
+@@ -0,0 +1,8 @@
++# SPDX-License-Identifier: GPL-2.0
++bcm2835-mmal-vchiq-objs := mmal-vchiq.o
++
++obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += bcm2835-mmal-vchiq.o
++
++ccflags-y += \
++      -Idrivers/staging/vc04_services \
++      -D__VCCOREVER__=0x04000000
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c
++++ /dev/null
+@@ -1,1899 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0
+-/*
+- * Broadcom BM2835 V4L2 driver
+- *
+- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+- *
+- * Authors: Vincent Sanders @ Collabora
+- *          Dave Stevenson @ Broadcom
+- *            (now dave.stevenson@raspberrypi.org)
+- *          Simon Mellor @ Broadcom
+- *          Luke Diamand @ Broadcom
+- *
+- * V4L2 driver MMAL vchiq interface code
+- */
+-
+-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+-
+-#include <linux/errno.h>
+-#include <linux/kernel.h>
+-#include <linux/mutex.h>
+-#include <linux/mm.h>
+-#include <linux/slab.h>
+-#include <linux/completion.h>
+-#include <linux/vmalloc.h>
+-#include <asm/cacheflush.h>
+-#include <media/videobuf2-vmalloc.h>
+-
+-#include "mmal-common.h"
+-#include "mmal-vchiq.h"
+-#include "mmal-msg.h"
+-
+-#define USE_VCHIQ_ARM
+-#include "interface/vchi/vchi.h"
+-
+-/* maximum number of components supported */
+-#define VCHIQ_MMAL_MAX_COMPONENTS 4
+-
+-/*#define FULL_MSG_DUMP 1*/
+-
+-#ifdef DEBUG
+-static const char *const msg_type_names[] = {
+-      "UNKNOWN",
+-      "QUIT",
+-      "SERVICE_CLOSED",
+-      "GET_VERSION",
+-      "COMPONENT_CREATE",
+-      "COMPONENT_DESTROY",
+-      "COMPONENT_ENABLE",
+-      "COMPONENT_DISABLE",
+-      "PORT_INFO_GET",
+-      "PORT_INFO_SET",
+-      "PORT_ACTION",
+-      "BUFFER_FROM_HOST",
+-      "BUFFER_TO_HOST",
+-      "GET_STATS",
+-      "PORT_PARAMETER_SET",
+-      "PORT_PARAMETER_GET",
+-      "EVENT_TO_HOST",
+-      "GET_CORE_STATS_FOR_PORT",
+-      "OPAQUE_ALLOCATOR",
+-      "CONSUME_MEM",
+-      "LMK",
+-      "OPAQUE_ALLOCATOR_DESC",
+-      "DRM_GET_LHS32",
+-      "DRM_GET_TIME",
+-      "BUFFER_FROM_HOST_ZEROLEN",
+-      "PORT_FLUSH",
+-      "HOST_LOG",
+-};
+-#endif
+-
+-static const char *const port_action_type_names[] = {
+-      "UNKNOWN",
+-      "ENABLE",
+-      "DISABLE",
+-      "FLUSH",
+-      "CONNECT",
+-      "DISCONNECT",
+-      "SET_REQUIREMENTS",
+-};
+-
+-#if defined(DEBUG)
+-#if defined(FULL_MSG_DUMP)
+-#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE)                             \
+-      do {                                                            \
+-              pr_debug(TITLE" type:%s(%d) length:%d\n",               \
+-                       msg_type_names[(MSG)->h.type],                 \
+-                       (MSG)->h.type, (MSG_LEN));                     \
+-              print_hex_dump(KERN_DEBUG, "<<h: ", DUMP_PREFIX_OFFSET, \
+-                             16, 4, (MSG),                            \
+-                             sizeof(struct mmal_msg_header), 1);      \
+-              print_hex_dump(KERN_DEBUG, "<<p: ", DUMP_PREFIX_OFFSET, \
+-                             16, 4,                                   \
+-                             ((u8 *)(MSG)) + sizeof(struct mmal_msg_header),\
+-                             (MSG_LEN) - sizeof(struct mmal_msg_header), 1); \
+-      } while (0)
+-#else
+-#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE)                             \
+-      {                                                               \
+-              pr_debug(TITLE" type:%s(%d) length:%d\n",               \
+-                       msg_type_names[(MSG)->h.type],                 \
+-                       (MSG)->h.type, (MSG_LEN));                     \
+-      }
+-#endif
+-#else
+-#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE)
+-#endif
+-
+-struct vchiq_mmal_instance;
+-
+-/* normal message context */
+-struct mmal_msg_context {
+-      struct vchiq_mmal_instance *instance;
+-
+-      /* Index in the context_map idr so that we can find the
+-       * mmal_msg_context again when servicing the VCHI reply.
+-       */
+-      int handle;
+-
+-      union {
+-              struct {
+-                      /* work struct for buffer_cb callback */
+-                      struct work_struct work;
+-                      /* work struct for deferred callback */
+-                      struct work_struct buffer_to_host_work;
+-                      /* mmal instance */
+-                      struct vchiq_mmal_instance *instance;
+-                      /* mmal port */
+-                      struct vchiq_mmal_port *port;
+-                      /* actual buffer used to store bulk reply */
+-                      struct mmal_buffer *buffer;
+-                      /* amount of buffer used */
+-                      unsigned long buffer_used;
+-                      /* MMAL buffer flags */
+-                      u32 mmal_flags;
+-                      /* Presentation and Decode timestamps */
+-                      s64 pts;
+-                      s64 dts;
+-
+-                      int status;     /* context status */
+-
+-              } bulk;         /* bulk data */
+-
+-              struct {
+-                      /* message handle to release */
+-                      VCHI_HELD_MSG_T msg_handle;
+-                      /* pointer to received message */
+-                      struct mmal_msg *msg;
+-                      /* received message length */
+-                      u32 msg_len;
+-                      /* completion upon reply */
+-                      struct completion cmplt;
+-              } sync;         /* synchronous response */
+-      } u;
+-
+-};
+-
+-struct vchiq_mmal_instance {
+-      VCHI_SERVICE_HANDLE_T handle;
+-
+-      /* ensure serialised access to service */
+-      struct mutex vchiq_mutex;
+-
+-      /* vmalloc page to receive scratch bulk xfers into */
+-      void *bulk_scratch;
+-
+-      struct idr context_map;
+-      /* protect accesses to context_map */
+-      struct mutex context_map_lock;
+-
+-      /* component to use next */
+-      int component_idx;
+-      struct vchiq_mmal_component component[VCHIQ_MMAL_MAX_COMPONENTS];
+-
+-      /* ordered workqueue to process all bulk operations */
+-      struct workqueue_struct *bulk_wq;
+-};
+-
+-static struct mmal_msg_context *
+-get_msg_context(struct vchiq_mmal_instance *instance)
+-{
+-      struct mmal_msg_context *msg_context;
+-      int handle;
+-
+-      /* todo: should this be allocated from a pool to avoid kzalloc */
+-      msg_context = kzalloc(sizeof(*msg_context), GFP_KERNEL);
+-
+-      if (!msg_context)
+-              return ERR_PTR(-ENOMEM);
+-
+-      /* Create an ID that will be passed along with our message so
+-       * that when we service the VCHI reply, we can look up what
+-       * message is being replied to.
+-       */
+-      mutex_lock(&instance->context_map_lock);
+-      handle = idr_alloc(&instance->context_map, msg_context,
+-                         0, 0, GFP_KERNEL);
+-      mutex_unlock(&instance->context_map_lock);
+-
+-      if (handle < 0) {
+-              kfree(msg_context);
+-              return ERR_PTR(handle);
+-      }
+-
+-      msg_context->instance = instance;
+-      msg_context->handle = handle;
+-
+-      return msg_context;
+-}
+-
+-static struct mmal_msg_context *
+-lookup_msg_context(struct vchiq_mmal_instance *instance, int handle)
+-{
+-      return idr_find(&instance->context_map, handle);
+-}
+-
+-static void
+-release_msg_context(struct mmal_msg_context *msg_context)
+-{
+-      struct vchiq_mmal_instance *instance = msg_context->instance;
+-
+-      mutex_lock(&instance->context_map_lock);
+-      idr_remove(&instance->context_map, msg_context->handle);
+-      mutex_unlock(&instance->context_map_lock);
+-      kfree(msg_context);
+-}
+-
+-/* deals with receipt of event to host message */
+-static void event_to_host_cb(struct vchiq_mmal_instance *instance,
+-                           struct mmal_msg *msg, u32 msg_len)
+-{
+-      pr_debug("unhandled event\n");
+-      pr_debug("component:%u port type:%d num:%d cmd:0x%x length:%d\n",
+-               msg->u.event_to_host.client_component,
+-               msg->u.event_to_host.port_type,
+-               msg->u.event_to_host.port_num,
+-               msg->u.event_to_host.cmd, msg->u.event_to_host.length);
+-}
+-
+-/* workqueue scheduled callback
+- *
+- * we do this because it is important we do not call any other vchiq
+- * sync calls from witin the message delivery thread
+- */
+-static void buffer_work_cb(struct work_struct *work)
+-{
+-      struct mmal_msg_context *msg_context =
+-              container_of(work, struct mmal_msg_context, u.bulk.work);
+-
+-      atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu);
+-
+-      msg_context->u.bulk.port->buffer_cb(msg_context->u.bulk.instance,
+-                                          msg_context->u.bulk.port,
+-                                          msg_context->u.bulk.status,
+-                                          msg_context->u.bulk.buffer,
+-                                          msg_context->u.bulk.buffer_used,
+-                                          msg_context->u.bulk.mmal_flags,
+-                                          msg_context->u.bulk.dts,
+-                                          msg_context->u.bulk.pts);
+-}
+-
+-/* workqueue scheduled callback to handle receiving buffers
+- *
+- * VCHI will allow up to 4 bulk receives to be scheduled before blocking.
+- * If we block in the service_callback context then we can't process the
+- * VCHI_CALLBACK_BULK_RECEIVED message that would otherwise allow the blocked
+- * vchi_bulk_queue_receive() call to complete.
+- */
+-static void buffer_to_host_work_cb(struct work_struct *work)
+-{
+-      struct mmal_msg_context *msg_context =
+-              container_of(work, struct mmal_msg_context,
+-                           u.bulk.buffer_to_host_work);
+-      struct vchiq_mmal_instance *instance = msg_context->instance;
+-      unsigned long len = msg_context->u.bulk.buffer_used;
+-      int ret;
+-
+-      if (!len)
+-              /* Dummy receive to ensure the buffers remain in order */
+-              len = 8;
+-      /* queue the bulk submission */
+-      vchi_service_use(instance->handle);
+-      ret = vchi_bulk_queue_receive(instance->handle,
+-                                    msg_context->u.bulk.buffer->buffer,
+-                                    /* Actual receive needs to be a multiple
+-                                     * of 4 bytes
+-                                     */
+-                                    (len + 3) & ~3,
+-                                    VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE |
+-                                    VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
+-                                    msg_context);
+-
+-      vchi_service_release(instance->handle);
+-
+-      if (ret != 0)
+-              pr_err("%s: ctx: %p, vchi_bulk_queue_receive failed %d\n",
+-                     __func__, msg_context, ret);
+-}
+-
+-/* enqueue a bulk receive for a given message context */
+-static int bulk_receive(struct vchiq_mmal_instance *instance,
+-                      struct mmal_msg *msg,
+-                      struct mmal_msg_context *msg_context)
+-{
+-      unsigned long rd_len;
+-
+-      rd_len = msg->u.buffer_from_host.buffer_header.length;
+-
+-      if (!msg_context->u.bulk.buffer) {
+-              pr_err("bulk.buffer not configured - error in buffer_from_host\n");
+-
+-              /* todo: this is a serious error, we should never have
+-               * committed a buffer_to_host operation to the mmal
+-               * port without the buffer to back it up (underflow
+-               * handling) and there is no obvious way to deal with
+-               * this - how is the mmal servie going to react when
+-               * we fail to do the xfer and reschedule a buffer when
+-               * it arrives? perhaps a starved flag to indicate a
+-               * waiting bulk receive?
+-               */
+-
+-              return -EINVAL;
+-      }
+-
+-      /* ensure we do not overrun the available buffer */
+-      if (rd_len > msg_context->u.bulk.buffer->buffer_size) {
+-              rd_len = msg_context->u.bulk.buffer->buffer_size;
+-              pr_warn("short read as not enough receive buffer space\n");
+-              /* todo: is this the correct response, what happens to
+-               * the rest of the message data?
+-               */
+-      }
+-
+-      /* store length */
+-      msg_context->u.bulk.buffer_used = rd_len;
+-      msg_context->u.bulk.dts = msg->u.buffer_from_host.buffer_header.dts;
+-      msg_context->u.bulk.pts = msg->u.buffer_from_host.buffer_header.pts;
+-
+-      queue_work(msg_context->instance->bulk_wq,
+-                 &msg_context->u.bulk.buffer_to_host_work);
+-
+-      return 0;
+-}
+-
+-/* data in message, memcpy from packet into output buffer */
+-static int inline_receive(struct vchiq_mmal_instance *instance,
+-                        struct mmal_msg *msg,
+-                        struct mmal_msg_context *msg_context)
+-{
+-      memcpy(msg_context->u.bulk.buffer->buffer,
+-             msg->u.buffer_from_host.short_data,
+-             msg->u.buffer_from_host.payload_in_message);
+-
+-      msg_context->u.bulk.buffer_used =
+-          msg->u.buffer_from_host.payload_in_message;
+-
+-      return 0;
+-}
+-
+-/* queue the buffer availability with MMAL_MSG_TYPE_BUFFER_FROM_HOST */
+-static int
+-buffer_from_host(struct vchiq_mmal_instance *instance,
+-               struct vchiq_mmal_port *port, struct mmal_buffer *buf)
+-{
+-      struct mmal_msg_context *msg_context;
+-      struct mmal_msg m;
+-      int ret;
+-
+-      if (!port->enabled)
+-              return -EINVAL;
+-
+-      pr_debug("instance:%p buffer:%p\n", instance->handle, buf);
+-
+-      /* get context */
+-      if (!buf->msg_context) {
+-              pr_err("%s: msg_context not allocated, buf %p\n", __func__,
+-                     buf);
+-              return -EINVAL;
+-      }
+-      msg_context = buf->msg_context;
+-
+-      /* store bulk message context for when data arrives */
+-      msg_context->u.bulk.instance = instance;
+-      msg_context->u.bulk.port = port;
+-      msg_context->u.bulk.buffer = buf;
+-      msg_context->u.bulk.buffer_used = 0;
+-
+-      /* initialise work structure ready to schedule callback */
+-      INIT_WORK(&msg_context->u.bulk.work, buffer_work_cb);
+-      INIT_WORK(&msg_context->u.bulk.buffer_to_host_work,
+-                buffer_to_host_work_cb);
+-
+-      atomic_inc(&port->buffers_with_vpu);
+-
+-      /* prep the buffer from host message */
+-      memset(&m, 0xbc, sizeof(m));    /* just to make debug clearer */
+-
+-      m.h.type = MMAL_MSG_TYPE_BUFFER_FROM_HOST;
+-      m.h.magic = MMAL_MAGIC;
+-      m.h.context = msg_context->handle;
+-      m.h.status = 0;
+-
+-      /* drvbuf is our private data passed back */
+-      m.u.buffer_from_host.drvbuf.magic = MMAL_MAGIC;
+-      m.u.buffer_from_host.drvbuf.component_handle = port->component->handle;
+-      m.u.buffer_from_host.drvbuf.port_handle = port->handle;
+-      m.u.buffer_from_host.drvbuf.client_context = msg_context->handle;
+-
+-      /* buffer header */
+-      m.u.buffer_from_host.buffer_header.cmd = 0;
+-      m.u.buffer_from_host.buffer_header.data =
+-              (u32)(unsigned long)buf->buffer;
+-      m.u.buffer_from_host.buffer_header.alloc_size = buf->buffer_size;
+-      m.u.buffer_from_host.buffer_header.length = 0;  /* nothing used yet */
+-      m.u.buffer_from_host.buffer_header.offset = 0;  /* no offset */
+-      m.u.buffer_from_host.buffer_header.flags = 0;   /* no flags */
+-      m.u.buffer_from_host.buffer_header.pts = MMAL_TIME_UNKNOWN;
+-      m.u.buffer_from_host.buffer_header.dts = MMAL_TIME_UNKNOWN;
+-
+-      /* clear buffer type sepecific data */
+-      memset(&m.u.buffer_from_host.buffer_header_type_specific, 0,
+-             sizeof(m.u.buffer_from_host.buffer_header_type_specific));
+-
+-      /* no payload in message */
+-      m.u.buffer_from_host.payload_in_message = 0;
+-
+-      vchi_service_use(instance->handle);
+-
+-      ret = vchi_queue_kernel_message(instance->handle,
+-                                      &m,
+-                                      sizeof(struct mmal_msg_header) +
+-                                      sizeof(m.u.buffer_from_host));
+-
+-      vchi_service_release(instance->handle);
+-
+-      return ret;
+-}
+-
+-/* deals with receipt of buffer to host message */
+-static void buffer_to_host_cb(struct vchiq_mmal_instance *instance,
+-                            struct mmal_msg *msg, u32 msg_len)
+-{
+-      struct mmal_msg_context *msg_context;
+-      u32 handle;
+-
+-      pr_debug("%s: instance:%p msg:%p msg_len:%d\n",
+-               __func__, instance, msg, msg_len);
+-
+-      if (msg->u.buffer_from_host.drvbuf.magic == MMAL_MAGIC) {
+-              handle = msg->u.buffer_from_host.drvbuf.client_context;
+-              msg_context = lookup_msg_context(instance, handle);
+-
+-              if (!msg_context) {
+-                      pr_err("drvbuf.client_context(%u) is invalid\n",
+-                             handle);
+-                      return;
+-              }
+-      } else {
+-              pr_err("MMAL_MSG_TYPE_BUFFER_TO_HOST with bad magic\n");
+-              return;
+-      }
+-
+-      msg_context->u.bulk.mmal_flags =
+-                              msg->u.buffer_from_host.buffer_header.flags;
+-
+-      if (msg->h.status != MMAL_MSG_STATUS_SUCCESS) {
+-              /* message reception had an error */
+-              pr_warn("error %d in reply\n", msg->h.status);
+-
+-              msg_context->u.bulk.status = msg->h.status;
+-
+-      } else if (msg->u.buffer_from_host.buffer_header.length == 0) {
+-              /* empty buffer */
+-              if (msg->u.buffer_from_host.buffer_header.flags &
+-                  MMAL_BUFFER_HEADER_FLAG_EOS) {
+-                      msg_context->u.bulk.status =
+-                          bulk_receive(instance, msg, msg_context);
+-                      if (msg_context->u.bulk.status == 0)
+-                              return; /* successful bulk submission, bulk
+-                                       * completion will trigger callback
+-                                       */
+-              } else {
+-                      /* do callback with empty buffer - not EOS though */
+-                      msg_context->u.bulk.status = 0;
+-                      msg_context->u.bulk.buffer_used = 0;
+-              }
+-      } else if (msg->u.buffer_from_host.payload_in_message == 0) {
+-              /* data is not in message, queue a bulk receive */
+-              msg_context->u.bulk.status =
+-                  bulk_receive(instance, msg, msg_context);
+-              if (msg_context->u.bulk.status == 0)
+-                      return; /* successful bulk submission, bulk
+-                               * completion will trigger callback
+-                               */
+-
+-              /* failed to submit buffer, this will end badly */
+-              pr_err("error %d on bulk submission\n",
+-                     msg_context->u.bulk.status);
+-
+-      } else if (msg->u.buffer_from_host.payload_in_message <=
+-                 MMAL_VC_SHORT_DATA) {
+-              /* data payload within message */
+-              msg_context->u.bulk.status = inline_receive(instance, msg,
+-                                                          msg_context);
+-      } else {
+-              pr_err("message with invalid short payload\n");
+-
+-              /* signal error */
+-              msg_context->u.bulk.status = -EINVAL;
+-              msg_context->u.bulk.buffer_used =
+-                  msg->u.buffer_from_host.payload_in_message;
+-      }
+-
+-      /* schedule the port callback */
+-      schedule_work(&msg_context->u.bulk.work);
+-}
+-
+-static void bulk_receive_cb(struct vchiq_mmal_instance *instance,
+-                          struct mmal_msg_context *msg_context)
+-{
+-      msg_context->u.bulk.status = 0;
+-
+-      /* schedule the port callback */
+-      schedule_work(&msg_context->u.bulk.work);
+-}
+-
+-static void bulk_abort_cb(struct vchiq_mmal_instance *instance,
+-                        struct mmal_msg_context *msg_context)
+-{
+-      pr_err("%s: bulk ABORTED msg_context:%p\n", __func__, msg_context);
+-
+-      msg_context->u.bulk.status = -EINTR;
+-
+-      schedule_work(&msg_context->u.bulk.work);
+-}
+-
+-/* incoming event service callback */
+-static void service_callback(void *param,
+-                           const VCHI_CALLBACK_REASON_T reason,
+-                           void *bulk_ctx)
+-{
+-      struct vchiq_mmal_instance *instance = param;
+-      int status;
+-      u32 msg_len;
+-      struct mmal_msg *msg;
+-      VCHI_HELD_MSG_T msg_handle;
+-      struct mmal_msg_context *msg_context;
+-
+-      if (!instance) {
+-              pr_err("Message callback passed NULL instance\n");
+-              return;
+-      }
+-
+-      switch (reason) {
+-      case VCHI_CALLBACK_MSG_AVAILABLE:
+-              status = vchi_msg_hold(instance->handle, (void **)&msg,
+-                                     &msg_len, VCHI_FLAGS_NONE, &msg_handle);
+-              if (status) {
+-                      pr_err("Unable to dequeue a message (%d)\n", status);
+-                      break;
+-              }
+-
+-              DBG_DUMP_MSG(msg, msg_len, "<<< reply message");
+-
+-              /* handling is different for buffer messages */
+-              switch (msg->h.type) {
+-              case MMAL_MSG_TYPE_BUFFER_FROM_HOST:
+-                      vchi_held_msg_release(&msg_handle);
+-                      break;
+-
+-              case MMAL_MSG_TYPE_EVENT_TO_HOST:
+-                      event_to_host_cb(instance, msg, msg_len);
+-                      vchi_held_msg_release(&msg_handle);
+-
+-                      break;
+-
+-              case MMAL_MSG_TYPE_BUFFER_TO_HOST:
+-                      buffer_to_host_cb(instance, msg, msg_len);
+-                      vchi_held_msg_release(&msg_handle);
+-                      break;
+-
+-              default:
+-                      /* messages dependent on header context to complete */
+-                      if (!msg->h.context) {
+-                              pr_err("received message context was null!\n");
+-                              vchi_held_msg_release(&msg_handle);
+-                              break;
+-                      }
+-
+-                      msg_context = lookup_msg_context(instance,
+-                                                       msg->h.context);
+-                      if (!msg_context) {
+-                              pr_err("received invalid message context %u!\n",
+-                                     msg->h.context);
+-                              vchi_held_msg_release(&msg_handle);
+-                              break;
+-                      }
+-
+-                      /* fill in context values */
+-                      msg_context->u.sync.msg_handle = msg_handle;
+-                      msg_context->u.sync.msg = msg;
+-                      msg_context->u.sync.msg_len = msg_len;
+-
+-                      /* todo: should this check (completion_done()
+-                       * == 1) for no one waiting? or do we need a
+-                       * flag to tell us the completion has been
+-                       * interrupted so we can free the message and
+-                       * its context. This probably also solves the
+-                       * message arriving after interruption todo
+-                       * below
+-                       */
+-
+-                      /* complete message so caller knows it happened */
+-                      complete(&msg_context->u.sync.cmplt);
+-                      break;
+-              }
+-
+-              break;
+-
+-      case VCHI_CALLBACK_BULK_RECEIVED:
+-              bulk_receive_cb(instance, bulk_ctx);
+-              break;
+-
+-      case VCHI_CALLBACK_BULK_RECEIVE_ABORTED:
+-              bulk_abort_cb(instance, bulk_ctx);
+-              break;
+-
+-      case VCHI_CALLBACK_SERVICE_CLOSED:
+-              /* TODO: consider if this requires action if received when
+-               * driver is not explicitly closing the service
+-               */
+-              break;
+-
+-      default:
+-              pr_err("Received unhandled message reason %d\n", reason);
+-              break;
+-      }
+-}
+-
+-static int send_synchronous_mmal_msg(struct vchiq_mmal_instance *instance,
+-                                   struct mmal_msg *msg,
+-                                   unsigned int payload_len,
+-                                   struct mmal_msg **msg_out,
+-                                   VCHI_HELD_MSG_T *msg_handle_out)
+-{
+-      struct mmal_msg_context *msg_context;
+-      int ret;
+-      unsigned long timeout;
+-
+-      /* payload size must not cause message to exceed max size */
+-      if (payload_len >
+-          (MMAL_MSG_MAX_SIZE - sizeof(struct mmal_msg_header))) {
+-              pr_err("payload length %d exceeds max:%d\n", payload_len,
+-                     (int)(MMAL_MSG_MAX_SIZE -
+-                          sizeof(struct mmal_msg_header)));
+-              return -EINVAL;
+-      }
+-
+-      msg_context = get_msg_context(instance);
+-      if (IS_ERR(msg_context))
+-              return PTR_ERR(msg_context);
+-
+-      init_completion(&msg_context->u.sync.cmplt);
+-
+-      msg->h.magic = MMAL_MAGIC;
+-      msg->h.context = msg_context->handle;
+-      msg->h.status = 0;
+-
+-      DBG_DUMP_MSG(msg, (sizeof(struct mmal_msg_header) + payload_len),
+-                   ">>> sync message");
+-
+-      vchi_service_use(instance->handle);
+-
+-      ret = vchi_queue_kernel_message(instance->handle,
+-                                      msg,
+-                                      sizeof(struct mmal_msg_header) +
+-                                      payload_len);
+-
+-      vchi_service_release(instance->handle);
+-
+-      if (ret) {
+-              pr_err("error %d queuing message\n", ret);
+-              release_msg_context(msg_context);
+-              return ret;
+-      }
+-
+-      timeout = wait_for_completion_timeout(&msg_context->u.sync.cmplt,
+-                                            3 * HZ);
+-      if (timeout == 0) {
+-              pr_err("timed out waiting for sync completion\n");
+-              ret = -ETIME;
+-              /* todo: what happens if the message arrives after aborting */
+-              release_msg_context(msg_context);
+-              return ret;
+-      }
+-
+-      *msg_out = msg_context->u.sync.msg;
+-      *msg_handle_out = msg_context->u.sync.msg_handle;
+-      release_msg_context(msg_context);
+-
+-      return 0;
+-}
+-
+-static void dump_port_info(struct vchiq_mmal_port *port)
+-{
+-      pr_debug("port handle:0x%x enabled:%d\n", port->handle, port->enabled);
+-
+-      pr_debug("buffer minimum num:%d size:%d align:%d\n",
+-               port->minimum_buffer.num,
+-               port->minimum_buffer.size, port->minimum_buffer.alignment);
+-
+-      pr_debug("buffer recommended num:%d size:%d align:%d\n",
+-               port->recommended_buffer.num,
+-               port->recommended_buffer.size,
+-               port->recommended_buffer.alignment);
+-
+-      pr_debug("buffer current values num:%d size:%d align:%d\n",
+-               port->current_buffer.num,
+-               port->current_buffer.size, port->current_buffer.alignment);
+-
+-      pr_debug("elementary stream: type:%d encoding:0x%x variant:0x%x\n",
+-               port->format.type,
+-               port->format.encoding, port->format.encoding_variant);
+-
+-      pr_debug("                  bitrate:%d flags:0x%x\n",
+-               port->format.bitrate, port->format.flags);
+-
+-      if (port->format.type == MMAL_ES_TYPE_VIDEO) {
+-              pr_debug
+-                  ("es video format: width:%d height:%d colourspace:0x%x\n",
+-                   port->es.video.width, port->es.video.height,
+-                   port->es.video.color_space);
+-
+-              pr_debug("               : crop xywh %d,%d,%d,%d\n",
+-                       port->es.video.crop.x,
+-                       port->es.video.crop.y,
+-                       port->es.video.crop.width, port->es.video.crop.height);
+-              pr_debug("               : framerate %d/%d  aspect %d/%d\n",
+-                       port->es.video.frame_rate.num,
+-                       port->es.video.frame_rate.den,
+-                       port->es.video.par.num, port->es.video.par.den);
+-      }
+-}
+-
+-static void port_to_mmal_msg(struct vchiq_mmal_port *port, struct mmal_port *p)
+-{
+-      /* todo do readonly fields need setting at all? */
+-      p->type = port->type;
+-      p->index = port->index;
+-      p->index_all = 0;
+-      p->is_enabled = port->enabled;
+-      p->buffer_num_min = port->minimum_buffer.num;
+-      p->buffer_size_min = port->minimum_buffer.size;
+-      p->buffer_alignment_min = port->minimum_buffer.alignment;
+-      p->buffer_num_recommended = port->recommended_buffer.num;
+-      p->buffer_size_recommended = port->recommended_buffer.size;
+-
+-      /* only three writable fields in a port */
+-      p->buffer_num = port->current_buffer.num;
+-      p->buffer_size = port->current_buffer.size;
+-      p->userdata = (u32)(unsigned long)port;
+-}
+-
+-static int port_info_set(struct vchiq_mmal_instance *instance,
+-                       struct vchiq_mmal_port *port)
+-{
+-      int ret;
+-      struct mmal_msg m;
+-      struct mmal_msg *rmsg;
+-      VCHI_HELD_MSG_T rmsg_handle;
+-
+-      pr_debug("setting port info port %p\n", port);
+-      if (!port)
+-              return -1;
+-      dump_port_info(port);
+-
+-      m.h.type = MMAL_MSG_TYPE_PORT_INFO_SET;
+-
+-      m.u.port_info_set.component_handle = port->component->handle;
+-      m.u.port_info_set.port_type = port->type;
+-      m.u.port_info_set.port_index = port->index;
+-
+-      port_to_mmal_msg(port, &m.u.port_info_set.port);
+-
+-      /* elementary stream format setup */
+-      m.u.port_info_set.format.type = port->format.type;
+-      m.u.port_info_set.format.encoding = port->format.encoding;
+-      m.u.port_info_set.format.encoding_variant =
+-          port->format.encoding_variant;
+-      m.u.port_info_set.format.bitrate = port->format.bitrate;
+-      m.u.port_info_set.format.flags = port->format.flags;
+-
+-      memcpy(&m.u.port_info_set.es, &port->es,
+-             sizeof(union mmal_es_specific_format));
+-
+-      m.u.port_info_set.format.extradata_size = port->format.extradata_size;
+-      memcpy(&m.u.port_info_set.extradata, port->format.extradata,
+-             port->format.extradata_size);
+-
+-      ret = send_synchronous_mmal_msg(instance, &m,
+-                                      sizeof(m.u.port_info_set),
+-                                      &rmsg, &rmsg_handle);
+-      if (ret)
+-              return ret;
+-
+-      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_INFO_SET) {
+-              /* got an unexpected message type in reply */
+-              ret = -EINVAL;
+-              goto release_msg;
+-      }
+-
+-      /* return operation status */
+-      ret = -rmsg->u.port_info_get_reply.status;
+-
+-      pr_debug("%s:result:%d component:0x%x port:%d\n", __func__, ret,
+-               port->component->handle, port->handle);
+-
+-release_msg:
+-      vchi_held_msg_release(&rmsg_handle);
+-
+-      return ret;
+-}
+-
+-/* use port info get message to retrieve port information */
+-static int port_info_get(struct vchiq_mmal_instance *instance,
+-                       struct vchiq_mmal_port *port)
+-{
+-      int ret;
+-      struct mmal_msg m;
+-      struct mmal_msg *rmsg;
+-      VCHI_HELD_MSG_T rmsg_handle;
+-
+-      /* port info time */
+-      m.h.type = MMAL_MSG_TYPE_PORT_INFO_GET;
+-      m.u.port_info_get.component_handle = port->component->handle;
+-      m.u.port_info_get.port_type = port->type;
+-      m.u.port_info_get.index = port->index;
+-
+-      ret = send_synchronous_mmal_msg(instance, &m,
+-                                      sizeof(m.u.port_info_get),
+-                                      &rmsg, &rmsg_handle);
+-      if (ret)
+-              return ret;
+-
+-      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_INFO_GET) {
+-              /* got an unexpected message type in reply */
+-              ret = -EINVAL;
+-              goto release_msg;
+-      }
+-
+-      /* return operation status */
+-      ret = -rmsg->u.port_info_get_reply.status;
+-      if (ret != MMAL_MSG_STATUS_SUCCESS)
+-              goto release_msg;
+-
+-      if (rmsg->u.port_info_get_reply.port.is_enabled == 0)
+-              port->enabled = false;
+-      else
+-              port->enabled = true;
+-
+-      /* copy the values out of the message */
+-      port->handle = rmsg->u.port_info_get_reply.port_handle;
+-
+-      /* port type and index cached to use on port info set because
+-       * it does not use a port handle
+-       */
+-      port->type = rmsg->u.port_info_get_reply.port_type;
+-      port->index = rmsg->u.port_info_get_reply.port_index;
+-
+-      port->minimum_buffer.num =
+-          rmsg->u.port_info_get_reply.port.buffer_num_min;
+-      port->minimum_buffer.size =
+-          rmsg->u.port_info_get_reply.port.buffer_size_min;
+-      port->minimum_buffer.alignment =
+-          rmsg->u.port_info_get_reply.port.buffer_alignment_min;
+-
+-      port->recommended_buffer.alignment =
+-          rmsg->u.port_info_get_reply.port.buffer_alignment_min;
+-      port->recommended_buffer.num =
+-          rmsg->u.port_info_get_reply.port.buffer_num_recommended;
+-
+-      port->current_buffer.num = rmsg->u.port_info_get_reply.port.buffer_num;
+-      port->current_buffer.size =
+-          rmsg->u.port_info_get_reply.port.buffer_size;
+-
+-      /* stream format */
+-      port->format.type = rmsg->u.port_info_get_reply.format.type;
+-      port->format.encoding = rmsg->u.port_info_get_reply.format.encoding;
+-      port->format.encoding_variant =
+-          rmsg->u.port_info_get_reply.format.encoding_variant;
+-      port->format.bitrate = rmsg->u.port_info_get_reply.format.bitrate;
+-      port->format.flags = rmsg->u.port_info_get_reply.format.flags;
+-
+-      /* elementary stream format */
+-      memcpy(&port->es,
+-             &rmsg->u.port_info_get_reply.es,
+-             sizeof(union mmal_es_specific_format));
+-      port->format.es = &port->es;
+-
+-      port->format.extradata_size =
+-          rmsg->u.port_info_get_reply.format.extradata_size;
+-      memcpy(port->format.extradata,
+-             rmsg->u.port_info_get_reply.extradata,
+-             port->format.extradata_size);
+-
+-      pr_debug("received port info\n");
+-      dump_port_info(port);
+-
+-release_msg:
+-
+-      pr_debug("%s:result:%d component:0x%x port:%d\n",
+-               __func__, ret, port->component->handle, port->handle);
+-
+-      vchi_held_msg_release(&rmsg_handle);
+-
+-      return ret;
+-}
+-
+-/* create comonent on vc */
+-static int create_component(struct vchiq_mmal_instance *instance,
+-                          struct vchiq_mmal_component *component,
+-                          const char *name)
+-{
+-      int ret;
+-      struct mmal_msg m;
+-      struct mmal_msg *rmsg;
+-      VCHI_HELD_MSG_T rmsg_handle;
+-
+-      /* build component create message */
+-      m.h.type = MMAL_MSG_TYPE_COMPONENT_CREATE;
+-      m.u.component_create.client_component = (u32)(unsigned long)component;
+-      strncpy(m.u.component_create.name, name,
+-              sizeof(m.u.component_create.name));
+-
+-      ret = send_synchronous_mmal_msg(instance, &m,
+-                                      sizeof(m.u.component_create),
+-                                      &rmsg, &rmsg_handle);
+-      if (ret)
+-              return ret;
+-
+-      if (rmsg->h.type != m.h.type) {
+-              /* got an unexpected message type in reply */
+-              ret = -EINVAL;
+-              goto release_msg;
+-      }
+-
+-      ret = -rmsg->u.component_create_reply.status;
+-      if (ret != MMAL_MSG_STATUS_SUCCESS)
+-              goto release_msg;
+-
+-      /* a valid component response received */
+-      component->handle = rmsg->u.component_create_reply.component_handle;
+-      component->inputs = rmsg->u.component_create_reply.input_num;
+-      component->outputs = rmsg->u.component_create_reply.output_num;
+-      component->clocks = rmsg->u.component_create_reply.clock_num;
+-
+-      pr_debug("Component handle:0x%x in:%d out:%d clock:%d\n",
+-               component->handle,
+-               component->inputs, component->outputs, component->clocks);
+-
+-release_msg:
+-      vchi_held_msg_release(&rmsg_handle);
+-
+-      return ret;
+-}
+-
+-/* destroys a component on vc */
+-static int destroy_component(struct vchiq_mmal_instance *instance,
+-                           struct vchiq_mmal_component *component)
+-{
+-      int ret;
+-      struct mmal_msg m;
+-      struct mmal_msg *rmsg;
+-      VCHI_HELD_MSG_T rmsg_handle;
+-
+-      m.h.type = MMAL_MSG_TYPE_COMPONENT_DESTROY;
+-      m.u.component_destroy.component_handle = component->handle;
+-
+-      ret = send_synchronous_mmal_msg(instance, &m,
+-                                      sizeof(m.u.component_destroy),
+-                                      &rmsg, &rmsg_handle);
+-      if (ret)
+-              return ret;
+-
+-      if (rmsg->h.type != m.h.type) {
+-              /* got an unexpected message type in reply */
+-              ret = -EINVAL;
+-              goto release_msg;
+-      }
+-
+-      ret = -rmsg->u.component_destroy_reply.status;
+-
+-release_msg:
+-
+-      vchi_held_msg_release(&rmsg_handle);
+-
+-      return ret;
+-}
+-
+-/* enable a component on vc */
+-static int enable_component(struct vchiq_mmal_instance *instance,
+-                          struct vchiq_mmal_component *component)
+-{
+-      int ret;
+-      struct mmal_msg m;
+-      struct mmal_msg *rmsg;
+-      VCHI_HELD_MSG_T rmsg_handle;
+-
+-      m.h.type = MMAL_MSG_TYPE_COMPONENT_ENABLE;
+-      m.u.component_enable.component_handle = component->handle;
+-
+-      ret = send_synchronous_mmal_msg(instance, &m,
+-                                      sizeof(m.u.component_enable),
+-                                      &rmsg, &rmsg_handle);
+-      if (ret)
+-              return ret;
+-
+-      if (rmsg->h.type != m.h.type) {
+-              /* got an unexpected message type in reply */
+-              ret = -EINVAL;
+-              goto release_msg;
+-      }
+-
+-      ret = -rmsg->u.component_enable_reply.status;
+-
+-release_msg:
+-      vchi_held_msg_release(&rmsg_handle);
+-
+-      return ret;
+-}
+-
+-/* disable a component on vc */
+-static int disable_component(struct vchiq_mmal_instance *instance,
+-                           struct vchiq_mmal_component *component)
+-{
+-      int ret;
+-      struct mmal_msg m;
+-      struct mmal_msg *rmsg;
+-      VCHI_HELD_MSG_T rmsg_handle;
+-
+-      m.h.type = MMAL_MSG_TYPE_COMPONENT_DISABLE;
+-      m.u.component_disable.component_handle = component->handle;
+-
+-      ret = send_synchronous_mmal_msg(instance, &m,
+-                                      sizeof(m.u.component_disable),
+-                                      &rmsg, &rmsg_handle);
+-      if (ret)
+-              return ret;
+-
+-      if (rmsg->h.type != m.h.type) {
+-              /* got an unexpected message type in reply */
+-              ret = -EINVAL;
+-              goto release_msg;
+-      }
+-
+-      ret = -rmsg->u.component_disable_reply.status;
+-
+-release_msg:
+-
+-      vchi_held_msg_release(&rmsg_handle);
+-
+-      return ret;
+-}
+-
+-/* get version of mmal implementation */
+-static int get_version(struct vchiq_mmal_instance *instance,
+-                     u32 *major_out, u32 *minor_out)
+-{
+-      int ret;
+-      struct mmal_msg m;
+-      struct mmal_msg *rmsg;
+-      VCHI_HELD_MSG_T rmsg_handle;
+-
+-      m.h.type = MMAL_MSG_TYPE_GET_VERSION;
+-
+-      ret = send_synchronous_mmal_msg(instance, &m,
+-                                      sizeof(m.u.version),
+-                                      &rmsg, &rmsg_handle);
+-      if (ret)
+-              return ret;
+-
+-      if (rmsg->h.type != m.h.type) {
+-              /* got an unexpected message type in reply */
+-              ret = -EINVAL;
+-              goto release_msg;
+-      }
+-
+-      *major_out = rmsg->u.version.major;
+-      *minor_out = rmsg->u.version.minor;
+-
+-release_msg:
+-      vchi_held_msg_release(&rmsg_handle);
+-
+-      return ret;
+-}
+-
+-/* do a port action with a port as a parameter */
+-static int port_action_port(struct vchiq_mmal_instance *instance,
+-                          struct vchiq_mmal_port *port,
+-                          enum mmal_msg_port_action_type action_type)
+-{
+-      int ret;
+-      struct mmal_msg m;
+-      struct mmal_msg *rmsg;
+-      VCHI_HELD_MSG_T rmsg_handle;
+-
+-      m.h.type = MMAL_MSG_TYPE_PORT_ACTION;
+-      m.u.port_action_port.component_handle = port->component->handle;
+-      m.u.port_action_port.port_handle = port->handle;
+-      m.u.port_action_port.action = action_type;
+-
+-      port_to_mmal_msg(port, &m.u.port_action_port.port);
+-
+-      ret = send_synchronous_mmal_msg(instance, &m,
+-                                      sizeof(m.u.port_action_port),
+-                                      &rmsg, &rmsg_handle);
+-      if (ret)
+-              return ret;
+-
+-      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_ACTION) {
+-              /* got an unexpected message type in reply */
+-              ret = -EINVAL;
+-              goto release_msg;
+-      }
+-
+-      ret = -rmsg->u.port_action_reply.status;
+-
+-      pr_debug("%s:result:%d component:0x%x port:%d action:%s(%d)\n",
+-               __func__,
+-               ret, port->component->handle, port->handle,
+-               port_action_type_names[action_type], action_type);
+-
+-release_msg:
+-      vchi_held_msg_release(&rmsg_handle);
+-
+-      return ret;
+-}
+-
+-/* do a port action with handles as parameters */
+-static int port_action_handle(struct vchiq_mmal_instance *instance,
+-                            struct vchiq_mmal_port *port,
+-                            enum mmal_msg_port_action_type action_type,
+-                            u32 connect_component_handle,
+-                            u32 connect_port_handle)
+-{
+-      int ret;
+-      struct mmal_msg m;
+-      struct mmal_msg *rmsg;
+-      VCHI_HELD_MSG_T rmsg_handle;
+-
+-      m.h.type = MMAL_MSG_TYPE_PORT_ACTION;
+-
+-      m.u.port_action_handle.component_handle = port->component->handle;
+-      m.u.port_action_handle.port_handle = port->handle;
+-      m.u.port_action_handle.action = action_type;
+-
+-      m.u.port_action_handle.connect_component_handle =
+-          connect_component_handle;
+-      m.u.port_action_handle.connect_port_handle = connect_port_handle;
+-
+-      ret = send_synchronous_mmal_msg(instance, &m,
+-                                      sizeof(m.u.port_action_handle),
+-                                      &rmsg, &rmsg_handle);
+-      if (ret)
+-              return ret;
+-
+-      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_ACTION) {
+-              /* got an unexpected message type in reply */
+-              ret = -EINVAL;
+-              goto release_msg;
+-      }
+-
+-      ret = -rmsg->u.port_action_reply.status;
+-
+-      pr_debug("%s:result:%d component:0x%x port:%d action:%s(%d) connect component:0x%x connect port:%d\n",
+-               __func__,
+-               ret, port->component->handle, port->handle,
+-               port_action_type_names[action_type],
+-               action_type, connect_component_handle, connect_port_handle);
+-
+-release_msg:
+-      vchi_held_msg_release(&rmsg_handle);
+-
+-      return ret;
+-}
+-
+-static int port_parameter_set(struct vchiq_mmal_instance *instance,
+-                            struct vchiq_mmal_port *port,
+-                            u32 parameter_id, void *value, u32 value_size)
+-{
+-      int ret;
+-      struct mmal_msg m;
+-      struct mmal_msg *rmsg;
+-      VCHI_HELD_MSG_T rmsg_handle;
+-
+-      m.h.type = MMAL_MSG_TYPE_PORT_PARAMETER_SET;
+-
+-      m.u.port_parameter_set.component_handle = port->component->handle;
+-      m.u.port_parameter_set.port_handle = port->handle;
+-      m.u.port_parameter_set.id = parameter_id;
+-      m.u.port_parameter_set.size = (2 * sizeof(u32)) + value_size;
+-      memcpy(&m.u.port_parameter_set.value, value, value_size);
+-
+-      ret = send_synchronous_mmal_msg(instance, &m,
+-                                      (4 * sizeof(u32)) + value_size,
+-                                      &rmsg, &rmsg_handle);
+-      if (ret)
+-              return ret;
+-
+-      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_PARAMETER_SET) {
+-              /* got an unexpected message type in reply */
+-              ret = -EINVAL;
+-              goto release_msg;
+-      }
+-
+-      ret = -rmsg->u.port_parameter_set_reply.status;
+-
+-      pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n",
+-               __func__,
+-               ret, port->component->handle, port->handle, parameter_id);
+-
+-release_msg:
+-      vchi_held_msg_release(&rmsg_handle);
+-
+-      return ret;
+-}
+-
+-static int port_parameter_get(struct vchiq_mmal_instance *instance,
+-                            struct vchiq_mmal_port *port,
+-                            u32 parameter_id, void *value, u32 *value_size)
+-{
+-      int ret;
+-      struct mmal_msg m;
+-      struct mmal_msg *rmsg;
+-      VCHI_HELD_MSG_T rmsg_handle;
+-
+-      m.h.type = MMAL_MSG_TYPE_PORT_PARAMETER_GET;
+-
+-      m.u.port_parameter_get.component_handle = port->component->handle;
+-      m.u.port_parameter_get.port_handle = port->handle;
+-      m.u.port_parameter_get.id = parameter_id;
+-      m.u.port_parameter_get.size = (2 * sizeof(u32)) + *value_size;
+-
+-      ret = send_synchronous_mmal_msg(instance, &m,
+-                                      sizeof(struct
+-                                             mmal_msg_port_parameter_get),
+-                                      &rmsg, &rmsg_handle);
+-      if (ret)
+-              return ret;
+-
+-      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_PARAMETER_GET) {
+-              /* got an unexpected message type in reply */
+-              pr_err("Incorrect reply type %d\n", rmsg->h.type);
+-              ret = -EINVAL;
+-              goto release_msg;
+-      }
+-
+-      ret = -rmsg->u.port_parameter_get_reply.status;
+-      /* port_parameter_get_reply.size includes the header,
+-       * whilst *value_size doesn't.
+-       */
+-      rmsg->u.port_parameter_get_reply.size -= (2 * sizeof(u32));
+-
+-      if (ret || rmsg->u.port_parameter_get_reply.size > *value_size) {
+-              /* Copy only as much as we have space for
+-               * but report true size of parameter
+-               */
+-              memcpy(value, &rmsg->u.port_parameter_get_reply.value,
+-                     *value_size);
+-              *value_size = rmsg->u.port_parameter_get_reply.size;
+-      } else {
+-              memcpy(value, &rmsg->u.port_parameter_get_reply.value,
+-                     rmsg->u.port_parameter_get_reply.size);
+-      }
+-
+-      pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n", __func__,
+-               ret, port->component->handle, port->handle, parameter_id);
+-
+-release_msg:
+-      vchi_held_msg_release(&rmsg_handle);
+-
+-      return ret;
+-}
+-
+-/* disables a port and drains buffers from it */
+-static int port_disable(struct vchiq_mmal_instance *instance,
+-                      struct vchiq_mmal_port *port)
+-{
+-      int ret;
+-      struct list_head *q, *buf_head;
+-      unsigned long flags = 0;
+-
+-      if (!port->enabled)
+-              return 0;
+-
+-      port->enabled = false;
+-
+-      ret = port_action_port(instance, port,
+-                             MMAL_MSG_PORT_ACTION_TYPE_DISABLE);
+-      if (ret == 0) {
+-              /*
+-               * Drain all queued buffers on port. This should only
+-               * apply to buffers that have been queued before the port
+-               * has been enabled. If the port has been enabled and buffers
+-               * passed, then the buffers should have been removed from this
+-               * list, and we should get the relevant callbacks via VCHIQ
+-               * to release the buffers.
+-               */
+-              spin_lock_irqsave(&port->slock, flags);
+-
+-              list_for_each_safe(buf_head, q, &port->buffers) {
+-                      struct mmal_buffer *mmalbuf;
+-
+-                      mmalbuf = list_entry(buf_head, struct mmal_buffer,
+-                                           list);
+-                      list_del(buf_head);
+-                      if (port->buffer_cb)
+-                              port->buffer_cb(instance,
+-                                              port, 0, mmalbuf, 0, 0,
+-                                              MMAL_TIME_UNKNOWN,
+-                                              MMAL_TIME_UNKNOWN);
+-              }
+-
+-              spin_unlock_irqrestore(&port->slock, flags);
+-
+-              ret = port_info_get(instance, port);
+-      }
+-
+-      return ret;
+-}
+-
+-/* enable a port */
+-static int port_enable(struct vchiq_mmal_instance *instance,
+-                     struct vchiq_mmal_port *port)
+-{
+-      unsigned int hdr_count;
+-      struct list_head *q, *buf_head;
+-      int ret;
+-
+-      if (port->enabled)
+-              return 0;
+-
+-      ret = port_action_port(instance, port,
+-                             MMAL_MSG_PORT_ACTION_TYPE_ENABLE);
+-      if (ret)
+-              goto done;
+-
+-      port->enabled = true;
+-
+-      if (port->buffer_cb) {
+-              /* send buffer headers to videocore */
+-              hdr_count = 1;
+-              list_for_each_safe(buf_head, q, &port->buffers) {
+-                      struct mmal_buffer *mmalbuf;
+-
+-                      mmalbuf = list_entry(buf_head, struct mmal_buffer,
+-                                           list);
+-                      ret = buffer_from_host(instance, port, mmalbuf);
+-                      if (ret)
+-                              goto done;
+-
+-                      list_del(buf_head);
+-                      hdr_count++;
+-                      if (hdr_count > port->current_buffer.num)
+-                              break;
+-              }
+-      }
+-
+-      ret = port_info_get(instance, port);
+-
+-done:
+-      return ret;
+-}
+-
+-/* ------------------------------------------------------------------
+- * Exported API
+- *------------------------------------------------------------------
+- */
+-
+-int vchiq_mmal_port_set_format(struct vchiq_mmal_instance *instance,
+-                             struct vchiq_mmal_port *port)
+-{
+-      int ret;
+-
+-      if (mutex_lock_interruptible(&instance->vchiq_mutex))
+-              return -EINTR;
+-
+-      ret = port_info_set(instance, port);
+-      if (ret)
+-              goto release_unlock;
+-
+-      /* read what has actually been set */
+-      ret = port_info_get(instance, port);
+-
+-release_unlock:
+-      mutex_unlock(&instance->vchiq_mutex);
+-
+-      return ret;
+-}
+-
+-int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance,
+-                                struct vchiq_mmal_port *port,
+-                                u32 parameter, void *value, u32 value_size)
+-{
+-      int ret;
+-
+-      if (mutex_lock_interruptible(&instance->vchiq_mutex))
+-              return -EINTR;
+-
+-      ret = port_parameter_set(instance, port, parameter, value, value_size);
+-
+-      mutex_unlock(&instance->vchiq_mutex);
+-
+-      return ret;
+-}
+-
+-int vchiq_mmal_port_parameter_get(struct vchiq_mmal_instance *instance,
+-                                struct vchiq_mmal_port *port,
+-                                u32 parameter, void *value, u32 *value_size)
+-{
+-      int ret;
+-
+-      if (mutex_lock_interruptible(&instance->vchiq_mutex))
+-              return -EINTR;
+-
+-      ret = port_parameter_get(instance, port, parameter, value, value_size);
+-
+-      mutex_unlock(&instance->vchiq_mutex);
+-
+-      return ret;
+-}
+-
+-/* enable a port
+- *
+- * enables a port and queues buffers for satisfying callbacks if we
+- * provide a callback handler
+- */
+-int vchiq_mmal_port_enable(struct vchiq_mmal_instance *instance,
+-                         struct vchiq_mmal_port *port,
+-                         vchiq_mmal_buffer_cb buffer_cb)
+-{
+-      int ret;
+-
+-      if (mutex_lock_interruptible(&instance->vchiq_mutex))
+-              return -EINTR;
+-
+-      /* already enabled - noop */
+-      if (port->enabled) {
+-              ret = 0;
+-              goto unlock;
+-      }
+-
+-      port->buffer_cb = buffer_cb;
+-
+-      ret = port_enable(instance, port);
+-
+-unlock:
+-      mutex_unlock(&instance->vchiq_mutex);
+-
+-      return ret;
+-}
+-
+-int vchiq_mmal_port_disable(struct vchiq_mmal_instance *instance,
+-                          struct vchiq_mmal_port *port)
+-{
+-      int ret;
+-
+-      if (mutex_lock_interruptible(&instance->vchiq_mutex))
+-              return -EINTR;
+-
+-      if (!port->enabled) {
+-              mutex_unlock(&instance->vchiq_mutex);
+-              return 0;
+-      }
+-
+-      ret = port_disable(instance, port);
+-
+-      mutex_unlock(&instance->vchiq_mutex);
+-
+-      return ret;
+-}
+-
+-/* ports will be connected in a tunneled manner so data buffers
+- * are not handled by client.
+- */
+-int vchiq_mmal_port_connect_tunnel(struct vchiq_mmal_instance *instance,
+-                                 struct vchiq_mmal_port *src,
+-                                 struct vchiq_mmal_port *dst)
+-{
+-      int ret;
+-
+-      if (mutex_lock_interruptible(&instance->vchiq_mutex))
+-              return -EINTR;
+-
+-      /* disconnect ports if connected */
+-      if (src->connected) {
+-              ret = port_disable(instance, src);
+-              if (ret) {
+-                      pr_err("failed disabling src port(%d)\n", ret);
+-                      goto release_unlock;
+-              }
+-
+-              /* do not need to disable the destination port as they
+-               * are connected and it is done automatically
+-               */
+-
+-              ret = port_action_handle(instance, src,
+-                                       MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT,
+-                                       src->connected->component->handle,
+-                                       src->connected->handle);
+-              if (ret < 0) {
+-                      pr_err("failed disconnecting src port\n");
+-                      goto release_unlock;
+-              }
+-              src->connected->enabled = false;
+-              src->connected = NULL;
+-      }
+-
+-      if (!dst) {
+-              /* do not make new connection */
+-              ret = 0;
+-              pr_debug("not making new connection\n");
+-              goto release_unlock;
+-      }
+-
+-      /* copy src port format to dst */
+-      dst->format.encoding = src->format.encoding;
+-      dst->es.video.width = src->es.video.width;
+-      dst->es.video.height = src->es.video.height;
+-      dst->es.video.crop.x = src->es.video.crop.x;
+-      dst->es.video.crop.y = src->es.video.crop.y;
+-      dst->es.video.crop.width = src->es.video.crop.width;
+-      dst->es.video.crop.height = src->es.video.crop.height;
+-      dst->es.video.frame_rate.num = src->es.video.frame_rate.num;
+-      dst->es.video.frame_rate.den = src->es.video.frame_rate.den;
+-
+-      /* set new format */
+-      ret = port_info_set(instance, dst);
+-      if (ret) {
+-              pr_debug("setting port info failed\n");
+-              goto release_unlock;
+-      }
+-
+-      /* read what has actually been set */
+-      ret = port_info_get(instance, dst);
+-      if (ret) {
+-              pr_debug("read back port info failed\n");
+-              goto release_unlock;
+-      }
+-
+-      /* connect two ports together */
+-      ret = port_action_handle(instance, src,
+-                               MMAL_MSG_PORT_ACTION_TYPE_CONNECT,
+-                               dst->component->handle, dst->handle);
+-      if (ret < 0) {
+-              pr_debug("connecting port %d:%d to %d:%d failed\n",
+-                       src->component->handle, src->handle,
+-                       dst->component->handle, dst->handle);
+-              goto release_unlock;
+-      }
+-      src->connected = dst;
+-
+-release_unlock:
+-
+-      mutex_unlock(&instance->vchiq_mutex);
+-
+-      return ret;
+-}
+-
+-int vchiq_mmal_submit_buffer(struct vchiq_mmal_instance *instance,
+-                           struct vchiq_mmal_port *port,
+-                           struct mmal_buffer *buffer)
+-{
+-      unsigned long flags = 0;
+-      int ret;
+-
+-      ret = buffer_from_host(instance, port, buffer);
+-      if (ret == -EINVAL) {
+-              /* Port is disabled. Queue for when it is enabled. */
+-              spin_lock_irqsave(&port->slock, flags);
+-              list_add_tail(&buffer->list, &port->buffers);
+-              spin_unlock_irqrestore(&port->slock, flags);
+-      }
+-
+-      return 0;
+-}
+-
+-int mmal_vchi_buffer_init(struct vchiq_mmal_instance *instance,
+-                        struct mmal_buffer *buf)
+-{
+-      struct mmal_msg_context *msg_context = get_msg_context(instance);
+-
+-      if (IS_ERR(msg_context))
+-              return (PTR_ERR(msg_context));
+-
+-      buf->msg_context = msg_context;
+-      return 0;
+-}
+-
+-int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf)
+-{
+-      struct mmal_msg_context *msg_context = buf->msg_context;
+-
+-      if (msg_context)
+-              release_msg_context(msg_context);
+-      buf->msg_context = NULL;
+-
+-      return 0;
+-}
+-
+-/* Initialise a mmal component and its ports
+- *
+- */
+-int vchiq_mmal_component_init(struct vchiq_mmal_instance *instance,
+-                            const char *name,
+-                            struct vchiq_mmal_component **component_out)
+-{
+-      int ret;
+-      int idx;                /* port index */
+-      struct vchiq_mmal_component *component;
+-
+-      if (mutex_lock_interruptible(&instance->vchiq_mutex))
+-              return -EINTR;
+-
+-      if (instance->component_idx == VCHIQ_MMAL_MAX_COMPONENTS) {
+-              ret = -EINVAL;  /* todo is this correct error? */
+-              goto unlock;
+-      }
+-
+-      component = &instance->component[instance->component_idx];
+-
+-      ret = create_component(instance, component, name);
+-      if (ret < 0) {
+-              pr_err("%s: failed to create component %d (Not enough GPU mem?)\n",
+-                     __func__, ret);
+-              goto unlock;
+-      }
+-
+-      /* ports info needs gathering */
+-      component->control.type = MMAL_PORT_TYPE_CONTROL;
+-      component->control.index = 0;
+-      component->control.component = component;
+-      spin_lock_init(&component->control.slock);
+-      INIT_LIST_HEAD(&component->control.buffers);
+-      ret = port_info_get(instance, &component->control);
+-      if (ret < 0)
+-              goto release_component;
+-
+-      for (idx = 0; idx < component->inputs; idx++) {
+-              component->input[idx].type = MMAL_PORT_TYPE_INPUT;
+-              component->input[idx].index = idx;
+-              component->input[idx].component = component;
+-              spin_lock_init(&component->input[idx].slock);
+-              INIT_LIST_HEAD(&component->input[idx].buffers);
+-              ret = port_info_get(instance, &component->input[idx]);
+-              if (ret < 0)
+-                      goto release_component;
+-      }
+-
+-      for (idx = 0; idx < component->outputs; idx++) {
+-              component->output[idx].type = MMAL_PORT_TYPE_OUTPUT;
+-              component->output[idx].index = idx;
+-              component->output[idx].component = component;
+-              spin_lock_init(&component->output[idx].slock);
+-              INIT_LIST_HEAD(&component->output[idx].buffers);
+-              ret = port_info_get(instance, &component->output[idx]);
+-              if (ret < 0)
+-                      goto release_component;
+-      }
+-
+-      for (idx = 0; idx < component->clocks; idx++) {
+-              component->clock[idx].type = MMAL_PORT_TYPE_CLOCK;
+-              component->clock[idx].index = idx;
+-              component->clock[idx].component = component;
+-              spin_lock_init(&component->clock[idx].slock);
+-              INIT_LIST_HEAD(&component->clock[idx].buffers);
+-              ret = port_info_get(instance, &component->clock[idx]);
+-              if (ret < 0)
+-                      goto release_component;
+-      }
+-
+-      instance->component_idx++;
+-
+-      *component_out = component;
+-
+-      mutex_unlock(&instance->vchiq_mutex);
+-
+-      return 0;
+-
+-release_component:
+-      destroy_component(instance, component);
+-unlock:
+-      mutex_unlock(&instance->vchiq_mutex);
+-
+-      return ret;
+-}
+-
+-/*
+- * cause a mmal component to be destroyed
+- */
+-int vchiq_mmal_component_finalise(struct vchiq_mmal_instance *instance,
+-                                struct vchiq_mmal_component *component)
+-{
+-      int ret;
+-
+-      if (mutex_lock_interruptible(&instance->vchiq_mutex))
+-              return -EINTR;
+-
+-      if (component->enabled)
+-              ret = disable_component(instance, component);
+-
+-      ret = destroy_component(instance, component);
+-
+-      mutex_unlock(&instance->vchiq_mutex);
+-
+-      return ret;
+-}
+-
+-/*
+- * cause a mmal component to be enabled
+- */
+-int vchiq_mmal_component_enable(struct vchiq_mmal_instance *instance,
+-                              struct vchiq_mmal_component *component)
+-{
+-      int ret;
+-
+-      if (mutex_lock_interruptible(&instance->vchiq_mutex))
+-              return -EINTR;
+-
+-      if (component->enabled) {
+-              mutex_unlock(&instance->vchiq_mutex);
+-              return 0;
+-      }
+-
+-      ret = enable_component(instance, component);
+-      if (ret == 0)
+-              component->enabled = true;
+-
+-      mutex_unlock(&instance->vchiq_mutex);
+-
+-      return ret;
+-}
+-
+-/*
+- * cause a mmal component to be enabled
+- */
+-int vchiq_mmal_component_disable(struct vchiq_mmal_instance *instance,
+-                               struct vchiq_mmal_component *component)
+-{
+-      int ret;
+-
+-      if (mutex_lock_interruptible(&instance->vchiq_mutex))
+-              return -EINTR;
+-
+-      if (!component->enabled) {
+-              mutex_unlock(&instance->vchiq_mutex);
+-              return 0;
+-      }
+-
+-      ret = disable_component(instance, component);
+-      if (ret == 0)
+-              component->enabled = false;
+-
+-      mutex_unlock(&instance->vchiq_mutex);
+-
+-      return ret;
+-}
+-
+-int vchiq_mmal_version(struct vchiq_mmal_instance *instance,
+-                     u32 *major_out, u32 *minor_out)
+-{
+-      int ret;
+-
+-      if (mutex_lock_interruptible(&instance->vchiq_mutex))
+-              return -EINTR;
+-
+-      ret = get_version(instance, major_out, minor_out);
+-
+-      mutex_unlock(&instance->vchiq_mutex);
+-
+-      return ret;
+-}
+-
+-int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance)
+-{
+-      int status = 0;
+-
+-      if (!instance)
+-              return -EINVAL;
+-
+-      if (mutex_lock_interruptible(&instance->vchiq_mutex))
+-              return -EINTR;
+-
+-      vchi_service_use(instance->handle);
+-
+-      status = vchi_service_close(instance->handle);
+-      if (status != 0)
+-              pr_err("mmal-vchiq: VCHIQ close failed\n");
+-
+-      mutex_unlock(&instance->vchiq_mutex);
+-
+-      flush_workqueue(instance->bulk_wq);
+-      destroy_workqueue(instance->bulk_wq);
+-
+-      vfree(instance->bulk_scratch);
+-
+-      idr_destroy(&instance->context_map);
+-
+-      kfree(instance);
+-
+-      return status;
+-}
+-
+-int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance)
+-{
+-      int status;
+-      struct vchiq_mmal_instance *instance;
+-      static VCHI_CONNECTION_T *vchi_connection;
+-      static VCHI_INSTANCE_T vchi_instance;
+-      SERVICE_CREATION_T params = {
+-              .version                = VCHI_VERSION_EX(VC_MMAL_VER, VC_MMAL_MIN_VER),
+-              .service_id             = VC_MMAL_SERVER_NAME,
+-              .connection             = vchi_connection,
+-              .rx_fifo_size           = 0,
+-              .tx_fifo_size           = 0,
+-              .callback               = service_callback,
+-              .callback_param         = NULL,
+-              .want_unaligned_bulk_rx = 1,
+-              .want_unaligned_bulk_tx = 1,
+-              .want_crc               = 0
+-      };
+-
+-      /* compile time checks to ensure structure size as they are
+-       * directly (de)serialised from memory.
+-       */
+-
+-      /* ensure the header structure has packed to the correct size */
+-      BUILD_BUG_ON(sizeof(struct mmal_msg_header) != 24);
+-
+-      /* ensure message structure does not exceed maximum length */
+-      BUILD_BUG_ON(sizeof(struct mmal_msg) > MMAL_MSG_MAX_SIZE);
+-
+-      /* mmal port struct is correct size */
+-      BUILD_BUG_ON(sizeof(struct mmal_port) != 64);
+-
+-      /* create a vchi instance */
+-      status = vchi_initialise(&vchi_instance);
+-      if (status) {
+-              pr_err("Failed to initialise VCHI instance (status=%d)\n",
+-                     status);
+-              return -EIO;
+-      }
+-
+-      status = vchi_connect(NULL, 0, vchi_instance);
+-      if (status) {
+-              pr_err("Failed to connect VCHI instance (status=%d)\n", status);
+-              return -EIO;
+-      }
+-
+-      instance = kzalloc(sizeof(*instance), GFP_KERNEL);
+-
+-      if (!instance)
+-              return -ENOMEM;
+-
+-      mutex_init(&instance->vchiq_mutex);
+-
+-      instance->bulk_scratch = vmalloc(PAGE_SIZE);
+-
+-      mutex_init(&instance->context_map_lock);
+-      idr_init_base(&instance->context_map, 1);
+-
+-      params.callback_param = instance;
+-
+-      instance->bulk_wq = alloc_ordered_workqueue("mmal-vchiq",
+-                                                  WQ_MEM_RECLAIM);
+-      if (!instance->bulk_wq)
+-              goto err_free;
+-
+-      status = vchi_service_open(vchi_instance, &params, &instance->handle);
+-      if (status) {
+-              pr_err("Failed to open VCHI service connection (status=%d)\n",
+-                     status);
+-              goto err_close_services;
+-      }
+-
+-      vchi_service_release(instance->handle);
+-
+-      *out_instance = instance;
+-
+-      return 0;
+-
+-err_close_services:
+-      vchi_service_close(instance->handle);
+-      destroy_workqueue(instance->bulk_wq);
+-err_free:
+-      vfree(instance->bulk_scratch);
+-      kfree(instance);
+-      return -ENODEV;
+-}
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -0,0 +1,1921 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Broadcom BM2835 V4L2 driver
++ *
++ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
++ *
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
++ *
++ * V4L2 driver MMAL vchiq interface code
++ */
++
++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
++
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/mutex.h>
++#include <linux/mm.h>
++#include <linux/slab.h>
++#include <linux/completion.h>
++#include <linux/vmalloc.h>
++#include <asm/cacheflush.h>
++#include <media/videobuf2-vmalloc.h>
++
++#include "mmal-common.h"
++#include "mmal-vchiq.h"
++#include "mmal-msg.h"
++
++#define USE_VCHIQ_ARM
++#include "interface/vchi/vchi.h"
++
++MODULE_DESCRIPTION("BCM2835 MMAL VCHIQ interface");
++MODULE_AUTHOR("Dave Stevenson, <dave.stevenson@raspberrypi.org>");
++MODULE_LICENSE("GPL");
++MODULE_VERSION("0.0.1");
++
++/* maximum number of components supported */
++#define VCHIQ_MMAL_MAX_COMPONENTS 4
++
++/*#define FULL_MSG_DUMP 1*/
++
++#ifdef DEBUG
++static const char *const msg_type_names[] = {
++      "UNKNOWN",
++      "QUIT",
++      "SERVICE_CLOSED",
++      "GET_VERSION",
++      "COMPONENT_CREATE",
++      "COMPONENT_DESTROY",
++      "COMPONENT_ENABLE",
++      "COMPONENT_DISABLE",
++      "PORT_INFO_GET",
++      "PORT_INFO_SET",
++      "PORT_ACTION",
++      "BUFFER_FROM_HOST",
++      "BUFFER_TO_HOST",
++      "GET_STATS",
++      "PORT_PARAMETER_SET",
++      "PORT_PARAMETER_GET",
++      "EVENT_TO_HOST",
++      "GET_CORE_STATS_FOR_PORT",
++      "OPAQUE_ALLOCATOR",
++      "CONSUME_MEM",
++      "LMK",
++      "OPAQUE_ALLOCATOR_DESC",
++      "DRM_GET_LHS32",
++      "DRM_GET_TIME",
++      "BUFFER_FROM_HOST_ZEROLEN",
++      "PORT_FLUSH",
++      "HOST_LOG",
++};
++#endif
++
++static const char *const port_action_type_names[] = {
++      "UNKNOWN",
++      "ENABLE",
++      "DISABLE",
++      "FLUSH",
++      "CONNECT",
++      "DISCONNECT",
++      "SET_REQUIREMENTS",
++};
++
++#if defined(DEBUG)
++#if defined(FULL_MSG_DUMP)
++#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE)                             \
++      do {                                                            \
++              pr_debug(TITLE" type:%s(%d) length:%d\n",               \
++                       msg_type_names[(MSG)->h.type],                 \
++                       (MSG)->h.type, (MSG_LEN));                     \
++              print_hex_dump(KERN_DEBUG, "<<h: ", DUMP_PREFIX_OFFSET, \
++                             16, 4, (MSG),                            \
++                             sizeof(struct mmal_msg_header), 1);      \
++              print_hex_dump(KERN_DEBUG, "<<p: ", DUMP_PREFIX_OFFSET, \
++                             16, 4,                                   \
++                             ((u8 *)(MSG)) + sizeof(struct mmal_msg_header),\
++                             (MSG_LEN) - sizeof(struct mmal_msg_header), 1); \
++      } while (0)
++#else
++#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE)                             \
++      {                                                               \
++              pr_debug(TITLE" type:%s(%d) length:%d\n",               \
++                       msg_type_names[(MSG)->h.type],                 \
++                       (MSG)->h.type, (MSG_LEN));                     \
++      }
++#endif
++#else
++#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE)
++#endif
++
++struct vchiq_mmal_instance;
++
++/* normal message context */
++struct mmal_msg_context {
++      struct vchiq_mmal_instance *instance;
++
++      /* Index in the context_map idr so that we can find the
++       * mmal_msg_context again when servicing the VCHI reply.
++       */
++      int handle;
++
++      union {
++              struct {
++                      /* work struct for buffer_cb callback */
++                      struct work_struct work;
++                      /* work struct for deferred callback */
++                      struct work_struct buffer_to_host_work;
++                      /* mmal instance */
++                      struct vchiq_mmal_instance *instance;
++                      /* mmal port */
++                      struct vchiq_mmal_port *port;
++                      /* actual buffer used to store bulk reply */
++                      struct mmal_buffer *buffer;
++                      /* amount of buffer used */
++                      unsigned long buffer_used;
++                      /* MMAL buffer flags */
++                      u32 mmal_flags;
++                      /* Presentation and Decode timestamps */
++                      s64 pts;
++                      s64 dts;
++
++                      int status;     /* context status */
++
++              } bulk;         /* bulk data */
++
++              struct {
++                      /* message handle to release */
++                      VCHI_HELD_MSG_T msg_handle;
++                      /* pointer to received message */
++                      struct mmal_msg *msg;
++                      /* received message length */
++                      u32 msg_len;
++                      /* completion upon reply */
++                      struct completion cmplt;
++              } sync;         /* synchronous response */
++      } u;
++
++};
++
++struct vchiq_mmal_instance {
++      VCHI_SERVICE_HANDLE_T handle;
++
++      /* ensure serialised access to service */
++      struct mutex vchiq_mutex;
++
++      /* vmalloc page to receive scratch bulk xfers into */
++      void *bulk_scratch;
++
++      struct idr context_map;
++      /* protect accesses to context_map */
++      struct mutex context_map_lock;
++
++      /* component to use next */
++      int component_idx;
++      struct vchiq_mmal_component component[VCHIQ_MMAL_MAX_COMPONENTS];
++
++      /* ordered workqueue to process all bulk operations */
++      struct workqueue_struct *bulk_wq;
++};
++
++static struct mmal_msg_context *
++get_msg_context(struct vchiq_mmal_instance *instance)
++{
++      struct mmal_msg_context *msg_context;
++      int handle;
++
++      /* todo: should this be allocated from a pool to avoid kzalloc */
++      msg_context = kzalloc(sizeof(*msg_context), GFP_KERNEL);
++
++      if (!msg_context)
++              return ERR_PTR(-ENOMEM);
++
++      /* Create an ID that will be passed along with our message so
++       * that when we service the VCHI reply, we can look up what
++       * message is being replied to.
++       */
++      mutex_lock(&instance->context_map_lock);
++      handle = idr_alloc(&instance->context_map, msg_context,
++                         0, 0, GFP_KERNEL);
++      mutex_unlock(&instance->context_map_lock);
++
++      if (handle < 0) {
++              kfree(msg_context);
++              return ERR_PTR(handle);
++      }
++
++      msg_context->instance = instance;
++      msg_context->handle = handle;
++
++      return msg_context;
++}
++
++static struct mmal_msg_context *
++lookup_msg_context(struct vchiq_mmal_instance *instance, int handle)
++{
++      return idr_find(&instance->context_map, handle);
++}
++
++static void
++release_msg_context(struct mmal_msg_context *msg_context)
++{
++      struct vchiq_mmal_instance *instance = msg_context->instance;
++
++      mutex_lock(&instance->context_map_lock);
++      idr_remove(&instance->context_map, msg_context->handle);
++      mutex_unlock(&instance->context_map_lock);
++      kfree(msg_context);
++}
++
++/* deals with receipt of event to host message */
++static void event_to_host_cb(struct vchiq_mmal_instance *instance,
++                           struct mmal_msg *msg, u32 msg_len)
++{
++      pr_debug("unhandled event\n");
++      pr_debug("component:%u port type:%d num:%d cmd:0x%x length:%d\n",
++               msg->u.event_to_host.client_component,
++               msg->u.event_to_host.port_type,
++               msg->u.event_to_host.port_num,
++               msg->u.event_to_host.cmd, msg->u.event_to_host.length);
++}
++
++/* workqueue scheduled callback
++ *
++ * we do this because it is important we do not call any other vchiq
++ * sync calls from witin the message delivery thread
++ */
++static void buffer_work_cb(struct work_struct *work)
++{
++      struct mmal_msg_context *msg_context =
++              container_of(work, struct mmal_msg_context, u.bulk.work);
++
++      atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu);
++
++      msg_context->u.bulk.port->buffer_cb(msg_context->u.bulk.instance,
++                                          msg_context->u.bulk.port,
++                                          msg_context->u.bulk.status,
++                                          msg_context->u.bulk.buffer,
++                                          msg_context->u.bulk.buffer_used,
++                                          msg_context->u.bulk.mmal_flags,
++                                          msg_context->u.bulk.dts,
++                                          msg_context->u.bulk.pts);
++}
++
++/* workqueue scheduled callback to handle receiving buffers
++ *
++ * VCHI will allow up to 4 bulk receives to be scheduled before blocking.
++ * If we block in the service_callback context then we can't process the
++ * VCHI_CALLBACK_BULK_RECEIVED message that would otherwise allow the blocked
++ * vchi_bulk_queue_receive() call to complete.
++ */
++static void buffer_to_host_work_cb(struct work_struct *work)
++{
++      struct mmal_msg_context *msg_context =
++              container_of(work, struct mmal_msg_context,
++                           u.bulk.buffer_to_host_work);
++      struct vchiq_mmal_instance *instance = msg_context->instance;
++      unsigned long len = msg_context->u.bulk.buffer_used;
++      int ret;
++
++      if (!len)
++              /* Dummy receive to ensure the buffers remain in order */
++              len = 8;
++      /* queue the bulk submission */
++      vchi_service_use(instance->handle);
++      ret = vchi_bulk_queue_receive(instance->handle,
++                                    msg_context->u.bulk.buffer->buffer,
++                                    /* Actual receive needs to be a multiple
++                                     * of 4 bytes
++                                     */
++                                    (len + 3) & ~3,
++                                    VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE |
++                                    VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
++                                    msg_context);
++
++      vchi_service_release(instance->handle);
++
++      if (ret != 0)
++              pr_err("%s: ctx: %p, vchi_bulk_queue_receive failed %d\n",
++                     __func__, msg_context, ret);
++}
++
++/* enqueue a bulk receive for a given message context */
++static int bulk_receive(struct vchiq_mmal_instance *instance,
++                      struct mmal_msg *msg,
++                      struct mmal_msg_context *msg_context)
++{
++      unsigned long rd_len;
++
++      rd_len = msg->u.buffer_from_host.buffer_header.length;
++
++      if (!msg_context->u.bulk.buffer) {
++              pr_err("bulk.buffer not configured - error in buffer_from_host\n");
++
++              /* todo: this is a serious error, we should never have
++               * committed a buffer_to_host operation to the mmal
++               * port without the buffer to back it up (underflow
++               * handling) and there is no obvious way to deal with
++               * this - how is the mmal servie going to react when
++               * we fail to do the xfer and reschedule a buffer when
++               * it arrives? perhaps a starved flag to indicate a
++               * waiting bulk receive?
++               */
++
++              return -EINVAL;
++      }
++
++      /* ensure we do not overrun the available buffer */
++      if (rd_len > msg_context->u.bulk.buffer->buffer_size) {
++              rd_len = msg_context->u.bulk.buffer->buffer_size;
++              pr_warn("short read as not enough receive buffer space\n");
++              /* todo: is this the correct response, what happens to
++               * the rest of the message data?
++               */
++      }
++
++      /* store length */
++      msg_context->u.bulk.buffer_used = rd_len;
++      msg_context->u.bulk.dts = msg->u.buffer_from_host.buffer_header.dts;
++      msg_context->u.bulk.pts = msg->u.buffer_from_host.buffer_header.pts;
++
++      queue_work(msg_context->instance->bulk_wq,
++                 &msg_context->u.bulk.buffer_to_host_work);
++
++      return 0;
++}
++
++/* data in message, memcpy from packet into output buffer */
++static int inline_receive(struct vchiq_mmal_instance *instance,
++                        struct mmal_msg *msg,
++                        struct mmal_msg_context *msg_context)
++{
++      memcpy(msg_context->u.bulk.buffer->buffer,
++             msg->u.buffer_from_host.short_data,
++             msg->u.buffer_from_host.payload_in_message);
++
++      msg_context->u.bulk.buffer_used =
++          msg->u.buffer_from_host.payload_in_message;
++
++      return 0;
++}
++
++/* queue the buffer availability with MMAL_MSG_TYPE_BUFFER_FROM_HOST */
++static int
++buffer_from_host(struct vchiq_mmal_instance *instance,
++               struct vchiq_mmal_port *port, struct mmal_buffer *buf)
++{
++      struct mmal_msg_context *msg_context;
++      struct mmal_msg m;
++      int ret;
++
++      if (!port->enabled)
++              return -EINVAL;
++
++      pr_debug("instance:%p buffer:%p\n", instance->handle, buf);
++
++      /* get context */
++      if (!buf->msg_context) {
++              pr_err("%s: msg_context not allocated, buf %p\n", __func__,
++                     buf);
++              return -EINVAL;
++      }
++      msg_context = buf->msg_context;
++
++      /* store bulk message context for when data arrives */
++      msg_context->u.bulk.instance = instance;
++      msg_context->u.bulk.port = port;
++      msg_context->u.bulk.buffer = buf;
++      msg_context->u.bulk.buffer_used = 0;
++
++      /* initialise work structure ready to schedule callback */
++      INIT_WORK(&msg_context->u.bulk.work, buffer_work_cb);
++      INIT_WORK(&msg_context->u.bulk.buffer_to_host_work,
++                buffer_to_host_work_cb);
++
++      atomic_inc(&port->buffers_with_vpu);
++
++      /* prep the buffer from host message */
++      memset(&m, 0xbc, sizeof(m));    /* just to make debug clearer */
++
++      m.h.type = MMAL_MSG_TYPE_BUFFER_FROM_HOST;
++      m.h.magic = MMAL_MAGIC;
++      m.h.context = msg_context->handle;
++      m.h.status = 0;
++
++      /* drvbuf is our private data passed back */
++      m.u.buffer_from_host.drvbuf.magic = MMAL_MAGIC;
++      m.u.buffer_from_host.drvbuf.component_handle = port->component->handle;
++      m.u.buffer_from_host.drvbuf.port_handle = port->handle;
++      m.u.buffer_from_host.drvbuf.client_context = msg_context->handle;
++
++      /* buffer header */
++      m.u.buffer_from_host.buffer_header.cmd = 0;
++      m.u.buffer_from_host.buffer_header.data =
++              (u32)(unsigned long)buf->buffer;
++      m.u.buffer_from_host.buffer_header.alloc_size = buf->buffer_size;
++      m.u.buffer_from_host.buffer_header.length = 0;  /* nothing used yet */
++      m.u.buffer_from_host.buffer_header.offset = 0;  /* no offset */
++      m.u.buffer_from_host.buffer_header.flags = 0;   /* no flags */
++      m.u.buffer_from_host.buffer_header.pts = MMAL_TIME_UNKNOWN;
++      m.u.buffer_from_host.buffer_header.dts = MMAL_TIME_UNKNOWN;
++
++      /* clear buffer type sepecific data */
++      memset(&m.u.buffer_from_host.buffer_header_type_specific, 0,
++             sizeof(m.u.buffer_from_host.buffer_header_type_specific));
++
++      /* no payload in message */
++      m.u.buffer_from_host.payload_in_message = 0;
++
++      vchi_service_use(instance->handle);
++
++      ret = vchi_queue_kernel_message(instance->handle,
++                                      &m,
++                                      sizeof(struct mmal_msg_header) +
++                                      sizeof(m.u.buffer_from_host));
++
++      vchi_service_release(instance->handle);
++
++      return ret;
++}
++
++/* deals with receipt of buffer to host message */
++static void buffer_to_host_cb(struct vchiq_mmal_instance *instance,
++                            struct mmal_msg *msg, u32 msg_len)
++{
++      struct mmal_msg_context *msg_context;
++      u32 handle;
++
++      pr_debug("%s: instance:%p msg:%p msg_len:%d\n",
++               __func__, instance, msg, msg_len);
++
++      if (msg->u.buffer_from_host.drvbuf.magic == MMAL_MAGIC) {
++              handle = msg->u.buffer_from_host.drvbuf.client_context;
++              msg_context = lookup_msg_context(instance, handle);
++
++              if (!msg_context) {
++                      pr_err("drvbuf.client_context(%u) is invalid\n",
++                             handle);
++                      return;
++              }
++      } else {
++              pr_err("MMAL_MSG_TYPE_BUFFER_TO_HOST with bad magic\n");
++              return;
++      }
++
++      msg_context->u.bulk.mmal_flags =
++                              msg->u.buffer_from_host.buffer_header.flags;
++
++      if (msg->h.status != MMAL_MSG_STATUS_SUCCESS) {
++              /* message reception had an error */
++              pr_warn("error %d in reply\n", msg->h.status);
++
++              msg_context->u.bulk.status = msg->h.status;
++
++      } else if (msg->u.buffer_from_host.buffer_header.length == 0) {
++              /* empty buffer */
++              if (msg->u.buffer_from_host.buffer_header.flags &
++                  MMAL_BUFFER_HEADER_FLAG_EOS) {
++                      msg_context->u.bulk.status =
++                          bulk_receive(instance, msg, msg_context);
++                      if (msg_context->u.bulk.status == 0)
++                              return; /* successful bulk submission, bulk
++                                       * completion will trigger callback
++                                       */
++              } else {
++                      /* do callback with empty buffer - not EOS though */
++                      msg_context->u.bulk.status = 0;
++                      msg_context->u.bulk.buffer_used = 0;
++              }
++      } else if (msg->u.buffer_from_host.payload_in_message == 0) {
++              /* data is not in message, queue a bulk receive */
++              msg_context->u.bulk.status =
++                  bulk_receive(instance, msg, msg_context);
++              if (msg_context->u.bulk.status == 0)
++                      return; /* successful bulk submission, bulk
++                               * completion will trigger callback
++                               */
++
++              /* failed to submit buffer, this will end badly */
++              pr_err("error %d on bulk submission\n",
++                     msg_context->u.bulk.status);
++
++      } else if (msg->u.buffer_from_host.payload_in_message <=
++                 MMAL_VC_SHORT_DATA) {
++              /* data payload within message */
++              msg_context->u.bulk.status = inline_receive(instance, msg,
++                                                          msg_context);
++      } else {
++              pr_err("message with invalid short payload\n");
++
++              /* signal error */
++              msg_context->u.bulk.status = -EINVAL;
++              msg_context->u.bulk.buffer_used =
++                  msg->u.buffer_from_host.payload_in_message;
++      }
++
++      /* schedule the port callback */
++      schedule_work(&msg_context->u.bulk.work);
++}
++
++static void bulk_receive_cb(struct vchiq_mmal_instance *instance,
++                          struct mmal_msg_context *msg_context)
++{
++      msg_context->u.bulk.status = 0;
++
++      /* schedule the port callback */
++      schedule_work(&msg_context->u.bulk.work);
++}
++
++static void bulk_abort_cb(struct vchiq_mmal_instance *instance,
++                        struct mmal_msg_context *msg_context)
++{
++      pr_err("%s: bulk ABORTED msg_context:%p\n", __func__, msg_context);
++
++      msg_context->u.bulk.status = -EINTR;
++
++      schedule_work(&msg_context->u.bulk.work);
++}
++
++/* incoming event service callback */
++static void service_callback(void *param,
++                           const VCHI_CALLBACK_REASON_T reason,
++                           void *bulk_ctx)
++{
++      struct vchiq_mmal_instance *instance = param;
++      int status;
++      u32 msg_len;
++      struct mmal_msg *msg;
++      VCHI_HELD_MSG_T msg_handle;
++      struct mmal_msg_context *msg_context;
++
++      if (!instance) {
++              pr_err("Message callback passed NULL instance\n");
++              return;
++      }
++
++      switch (reason) {
++      case VCHI_CALLBACK_MSG_AVAILABLE:
++              status = vchi_msg_hold(instance->handle, (void **)&msg,
++                                     &msg_len, VCHI_FLAGS_NONE, &msg_handle);
++              if (status) {
++                      pr_err("Unable to dequeue a message (%d)\n", status);
++                      break;
++              }
++
++              DBG_DUMP_MSG(msg, msg_len, "<<< reply message");
++
++              /* handling is different for buffer messages */
++              switch (msg->h.type) {
++              case MMAL_MSG_TYPE_BUFFER_FROM_HOST:
++                      vchi_held_msg_release(&msg_handle);
++                      break;
++
++              case MMAL_MSG_TYPE_EVENT_TO_HOST:
++                      event_to_host_cb(instance, msg, msg_len);
++                      vchi_held_msg_release(&msg_handle);
++
++                      break;
++
++              case MMAL_MSG_TYPE_BUFFER_TO_HOST:
++                      buffer_to_host_cb(instance, msg, msg_len);
++                      vchi_held_msg_release(&msg_handle);
++                      break;
++
++              default:
++                      /* messages dependent on header context to complete */
++                      if (!msg->h.context) {
++                              pr_err("received message context was null!\n");
++                              vchi_held_msg_release(&msg_handle);
++                              break;
++                      }
++
++                      msg_context = lookup_msg_context(instance,
++                                                       msg->h.context);
++                      if (!msg_context) {
++                              pr_err("received invalid message context %u!\n",
++                                     msg->h.context);
++                              vchi_held_msg_release(&msg_handle);
++                              break;
++                      }
++
++                      /* fill in context values */
++                      msg_context->u.sync.msg_handle = msg_handle;
++                      msg_context->u.sync.msg = msg;
++                      msg_context->u.sync.msg_len = msg_len;
++
++                      /* todo: should this check (completion_done()
++                       * == 1) for no one waiting? or do we need a
++                       * flag to tell us the completion has been
++                       * interrupted so we can free the message and
++                       * its context. This probably also solves the
++                       * message arriving after interruption todo
++                       * below
++                       */
++
++                      /* complete message so caller knows it happened */
++                      complete(&msg_context->u.sync.cmplt);
++                      break;
++              }
++
++              break;
++
++      case VCHI_CALLBACK_BULK_RECEIVED:
++              bulk_receive_cb(instance, bulk_ctx);
++              break;
++
++      case VCHI_CALLBACK_BULK_RECEIVE_ABORTED:
++              bulk_abort_cb(instance, bulk_ctx);
++              break;
++
++      case VCHI_CALLBACK_SERVICE_CLOSED:
++              /* TODO: consider if this requires action if received when
++               * driver is not explicitly closing the service
++               */
++              break;
++
++      default:
++              pr_err("Received unhandled message reason %d\n", reason);
++              break;
++      }
++}
++
++static int send_synchronous_mmal_msg(struct vchiq_mmal_instance *instance,
++                                   struct mmal_msg *msg,
++                                   unsigned int payload_len,
++                                   struct mmal_msg **msg_out,
++                                   VCHI_HELD_MSG_T *msg_handle_out)
++{
++      struct mmal_msg_context *msg_context;
++      int ret;
++      unsigned long timeout;
++
++      /* payload size must not cause message to exceed max size */
++      if (payload_len >
++          (MMAL_MSG_MAX_SIZE - sizeof(struct mmal_msg_header))) {
++              pr_err("payload length %d exceeds max:%d\n", payload_len,
++                     (int)(MMAL_MSG_MAX_SIZE -
++                          sizeof(struct mmal_msg_header)));
++              return -EINVAL;
++      }
++
++      msg_context = get_msg_context(instance);
++      if (IS_ERR(msg_context))
++              return PTR_ERR(msg_context);
++
++      init_completion(&msg_context->u.sync.cmplt);
++
++      msg->h.magic = MMAL_MAGIC;
++      msg->h.context = msg_context->handle;
++      msg->h.status = 0;
++
++      DBG_DUMP_MSG(msg, (sizeof(struct mmal_msg_header) + payload_len),
++                   ">>> sync message");
++
++      vchi_service_use(instance->handle);
++
++      ret = vchi_queue_kernel_message(instance->handle,
++                                      msg,
++                                      sizeof(struct mmal_msg_header) +
++                                      payload_len);
++
++      vchi_service_release(instance->handle);
++
++      if (ret) {
++              pr_err("error %d queuing message\n", ret);
++              release_msg_context(msg_context);
++              return ret;
++      }
++
++      timeout = wait_for_completion_timeout(&msg_context->u.sync.cmplt,
++                                            3 * HZ);
++      if (timeout == 0) {
++              pr_err("timed out waiting for sync completion\n");
++              ret = -ETIME;
++              /* todo: what happens if the message arrives after aborting */
++              release_msg_context(msg_context);
++              return ret;
++      }
++
++      *msg_out = msg_context->u.sync.msg;
++      *msg_handle_out = msg_context->u.sync.msg_handle;
++      release_msg_context(msg_context);
++
++      return 0;
++}
++
++static void dump_port_info(struct vchiq_mmal_port *port)
++{
++      pr_debug("port handle:0x%x enabled:%d\n", port->handle, port->enabled);
++
++      pr_debug("buffer minimum num:%d size:%d align:%d\n",
++               port->minimum_buffer.num,
++               port->minimum_buffer.size, port->minimum_buffer.alignment);
++
++      pr_debug("buffer recommended num:%d size:%d align:%d\n",
++               port->recommended_buffer.num,
++               port->recommended_buffer.size,
++               port->recommended_buffer.alignment);
++
++      pr_debug("buffer current values num:%d size:%d align:%d\n",
++               port->current_buffer.num,
++               port->current_buffer.size, port->current_buffer.alignment);
++
++      pr_debug("elementary stream: type:%d encoding:0x%x variant:0x%x\n",
++               port->format.type,
++               port->format.encoding, port->format.encoding_variant);
++
++      pr_debug("                  bitrate:%d flags:0x%x\n",
++               port->format.bitrate, port->format.flags);
++
++      if (port->format.type == MMAL_ES_TYPE_VIDEO) {
++              pr_debug
++                  ("es video format: width:%d height:%d colourspace:0x%x\n",
++                   port->es.video.width, port->es.video.height,
++                   port->es.video.color_space);
++
++              pr_debug("               : crop xywh %d,%d,%d,%d\n",
++                       port->es.video.crop.x,
++                       port->es.video.crop.y,
++                       port->es.video.crop.width, port->es.video.crop.height);
++              pr_debug("               : framerate %d/%d  aspect %d/%d\n",
++                       port->es.video.frame_rate.num,
++                       port->es.video.frame_rate.den,
++                       port->es.video.par.num, port->es.video.par.den);
++      }
++}
++
++static void port_to_mmal_msg(struct vchiq_mmal_port *port, struct mmal_port *p)
++{
++      /* todo do readonly fields need setting at all? */
++      p->type = port->type;
++      p->index = port->index;
++      p->index_all = 0;
++      p->is_enabled = port->enabled;
++      p->buffer_num_min = port->minimum_buffer.num;
++      p->buffer_size_min = port->minimum_buffer.size;
++      p->buffer_alignment_min = port->minimum_buffer.alignment;
++      p->buffer_num_recommended = port->recommended_buffer.num;
++      p->buffer_size_recommended = port->recommended_buffer.size;
++
++      /* only three writable fields in a port */
++      p->buffer_num = port->current_buffer.num;
++      p->buffer_size = port->current_buffer.size;
++      p->userdata = (u32)(unsigned long)port;
++}
++
++static int port_info_set(struct vchiq_mmal_instance *instance,
++                       struct vchiq_mmal_port *port)
++{
++      int ret;
++      struct mmal_msg m;
++      struct mmal_msg *rmsg;
++      VCHI_HELD_MSG_T rmsg_handle;
++
++      pr_debug("setting port info port %p\n", port);
++      if (!port)
++              return -1;
++      dump_port_info(port);
++
++      m.h.type = MMAL_MSG_TYPE_PORT_INFO_SET;
++
++      m.u.port_info_set.component_handle = port->component->handle;
++      m.u.port_info_set.port_type = port->type;
++      m.u.port_info_set.port_index = port->index;
++
++      port_to_mmal_msg(port, &m.u.port_info_set.port);
++
++      /* elementary stream format setup */
++      m.u.port_info_set.format.type = port->format.type;
++      m.u.port_info_set.format.encoding = port->format.encoding;
++      m.u.port_info_set.format.encoding_variant =
++          port->format.encoding_variant;
++      m.u.port_info_set.format.bitrate = port->format.bitrate;
++      m.u.port_info_set.format.flags = port->format.flags;
++
++      memcpy(&m.u.port_info_set.es, &port->es,
++             sizeof(union mmal_es_specific_format));
++
++      m.u.port_info_set.format.extradata_size = port->format.extradata_size;
++      memcpy(&m.u.port_info_set.extradata, port->format.extradata,
++             port->format.extradata_size);
++
++      ret = send_synchronous_mmal_msg(instance, &m,
++                                      sizeof(m.u.port_info_set),
++                                      &rmsg, &rmsg_handle);
++      if (ret)
++              return ret;
++
++      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_INFO_SET) {
++              /* got an unexpected message type in reply */
++              ret = -EINVAL;
++              goto release_msg;
++      }
++
++      /* return operation status */
++      ret = -rmsg->u.port_info_get_reply.status;
++
++      pr_debug("%s:result:%d component:0x%x port:%d\n", __func__, ret,
++               port->component->handle, port->handle);
++
++release_msg:
++      vchi_held_msg_release(&rmsg_handle);
++
++      return ret;
++}
++
++/* use port info get message to retrieve port information */
++static int port_info_get(struct vchiq_mmal_instance *instance,
++                       struct vchiq_mmal_port *port)
++{
++      int ret;
++      struct mmal_msg m;
++      struct mmal_msg *rmsg;
++      VCHI_HELD_MSG_T rmsg_handle;
++
++      /* port info time */
++      m.h.type = MMAL_MSG_TYPE_PORT_INFO_GET;
++      m.u.port_info_get.component_handle = port->component->handle;
++      m.u.port_info_get.port_type = port->type;
++      m.u.port_info_get.index = port->index;
++
++      ret = send_synchronous_mmal_msg(instance, &m,
++                                      sizeof(m.u.port_info_get),
++                                      &rmsg, &rmsg_handle);
++      if (ret)
++              return ret;
++
++      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_INFO_GET) {
++              /* got an unexpected message type in reply */
++              ret = -EINVAL;
++              goto release_msg;
++      }
++
++      /* return operation status */
++      ret = -rmsg->u.port_info_get_reply.status;
++      if (ret != MMAL_MSG_STATUS_SUCCESS)
++              goto release_msg;
++
++      if (rmsg->u.port_info_get_reply.port.is_enabled == 0)
++              port->enabled = false;
++      else
++              port->enabled = true;
++
++      /* copy the values out of the message */
++      port->handle = rmsg->u.port_info_get_reply.port_handle;
++
++      /* port type and index cached to use on port info set because
++       * it does not use a port handle
++       */
++      port->type = rmsg->u.port_info_get_reply.port_type;
++      port->index = rmsg->u.port_info_get_reply.port_index;
++
++      port->minimum_buffer.num =
++          rmsg->u.port_info_get_reply.port.buffer_num_min;
++      port->minimum_buffer.size =
++          rmsg->u.port_info_get_reply.port.buffer_size_min;
++      port->minimum_buffer.alignment =
++          rmsg->u.port_info_get_reply.port.buffer_alignment_min;
++
++      port->recommended_buffer.alignment =
++          rmsg->u.port_info_get_reply.port.buffer_alignment_min;
++      port->recommended_buffer.num =
++          rmsg->u.port_info_get_reply.port.buffer_num_recommended;
++
++      port->current_buffer.num = rmsg->u.port_info_get_reply.port.buffer_num;
++      port->current_buffer.size =
++          rmsg->u.port_info_get_reply.port.buffer_size;
++
++      /* stream format */
++      port->format.type = rmsg->u.port_info_get_reply.format.type;
++      port->format.encoding = rmsg->u.port_info_get_reply.format.encoding;
++      port->format.encoding_variant =
++          rmsg->u.port_info_get_reply.format.encoding_variant;
++      port->format.bitrate = rmsg->u.port_info_get_reply.format.bitrate;
++      port->format.flags = rmsg->u.port_info_get_reply.format.flags;
++
++      /* elementary stream format */
++      memcpy(&port->es,
++             &rmsg->u.port_info_get_reply.es,
++             sizeof(union mmal_es_specific_format));
++      port->format.es = &port->es;
++
++      port->format.extradata_size =
++          rmsg->u.port_info_get_reply.format.extradata_size;
++      memcpy(port->format.extradata,
++             rmsg->u.port_info_get_reply.extradata,
++             port->format.extradata_size);
++
++      pr_debug("received port info\n");
++      dump_port_info(port);
++
++release_msg:
++
++      pr_debug("%s:result:%d component:0x%x port:%d\n",
++               __func__, ret, port->component->handle, port->handle);
++
++      vchi_held_msg_release(&rmsg_handle);
++
++      return ret;
++}
++
++/* create comonent on vc */
++static int create_component(struct vchiq_mmal_instance *instance,
++                          struct vchiq_mmal_component *component,
++                          const char *name)
++{
++      int ret;
++      struct mmal_msg m;
++      struct mmal_msg *rmsg;
++      VCHI_HELD_MSG_T rmsg_handle;
++
++      /* build component create message */
++      m.h.type = MMAL_MSG_TYPE_COMPONENT_CREATE;
++      m.u.component_create.client_component = (u32)(unsigned long)component;
++      strncpy(m.u.component_create.name, name,
++              sizeof(m.u.component_create.name));
++
++      ret = send_synchronous_mmal_msg(instance, &m,
++                                      sizeof(m.u.component_create),
++                                      &rmsg, &rmsg_handle);
++      if (ret)
++              return ret;
++
++      if (rmsg->h.type != m.h.type) {
++              /* got an unexpected message type in reply */
++              ret = -EINVAL;
++              goto release_msg;
++      }
++
++      ret = -rmsg->u.component_create_reply.status;
++      if (ret != MMAL_MSG_STATUS_SUCCESS)
++              goto release_msg;
++
++      /* a valid component response received */
++      component->handle = rmsg->u.component_create_reply.component_handle;
++      component->inputs = rmsg->u.component_create_reply.input_num;
++      component->outputs = rmsg->u.component_create_reply.output_num;
++      component->clocks = rmsg->u.component_create_reply.clock_num;
++
++      pr_debug("Component handle:0x%x in:%d out:%d clock:%d\n",
++               component->handle,
++               component->inputs, component->outputs, component->clocks);
++
++release_msg:
++      vchi_held_msg_release(&rmsg_handle);
++
++      return ret;
++}
++
++/* destroys a component on vc */
++static int destroy_component(struct vchiq_mmal_instance *instance,
++                           struct vchiq_mmal_component *component)
++{
++      int ret;
++      struct mmal_msg m;
++      struct mmal_msg *rmsg;
++      VCHI_HELD_MSG_T rmsg_handle;
++
++      m.h.type = MMAL_MSG_TYPE_COMPONENT_DESTROY;
++      m.u.component_destroy.component_handle = component->handle;
++
++      ret = send_synchronous_mmal_msg(instance, &m,
++                                      sizeof(m.u.component_destroy),
++                                      &rmsg, &rmsg_handle);
++      if (ret)
++              return ret;
++
++      if (rmsg->h.type != m.h.type) {
++              /* got an unexpected message type in reply */
++              ret = -EINVAL;
++              goto release_msg;
++      }
++
++      ret = -rmsg->u.component_destroy_reply.status;
++
++release_msg:
++
++      vchi_held_msg_release(&rmsg_handle);
++
++      return ret;
++}
++
++/* enable a component on vc */
++static int enable_component(struct vchiq_mmal_instance *instance,
++                          struct vchiq_mmal_component *component)
++{
++      int ret;
++      struct mmal_msg m;
++      struct mmal_msg *rmsg;
++      VCHI_HELD_MSG_T rmsg_handle;
++
++      m.h.type = MMAL_MSG_TYPE_COMPONENT_ENABLE;
++      m.u.component_enable.component_handle = component->handle;
++
++      ret = send_synchronous_mmal_msg(instance, &m,
++                                      sizeof(m.u.component_enable),
++                                      &rmsg, &rmsg_handle);
++      if (ret)
++              return ret;
++
++      if (rmsg->h.type != m.h.type) {
++              /* got an unexpected message type in reply */
++              ret = -EINVAL;
++              goto release_msg;
++      }
++
++      ret = -rmsg->u.component_enable_reply.status;
++
++release_msg:
++      vchi_held_msg_release(&rmsg_handle);
++
++      return ret;
++}
++
++/* disable a component on vc */
++static int disable_component(struct vchiq_mmal_instance *instance,
++                           struct vchiq_mmal_component *component)
++{
++      int ret;
++      struct mmal_msg m;
++      struct mmal_msg *rmsg;
++      VCHI_HELD_MSG_T rmsg_handle;
++
++      m.h.type = MMAL_MSG_TYPE_COMPONENT_DISABLE;
++      m.u.component_disable.component_handle = component->handle;
++
++      ret = send_synchronous_mmal_msg(instance, &m,
++                                      sizeof(m.u.component_disable),
++                                      &rmsg, &rmsg_handle);
++      if (ret)
++              return ret;
++
++      if (rmsg->h.type != m.h.type) {
++              /* got an unexpected message type in reply */
++              ret = -EINVAL;
++              goto release_msg;
++      }
++
++      ret = -rmsg->u.component_disable_reply.status;
++
++release_msg:
++
++      vchi_held_msg_release(&rmsg_handle);
++
++      return ret;
++}
++
++/* get version of mmal implementation */
++static int get_version(struct vchiq_mmal_instance *instance,
++                     u32 *major_out, u32 *minor_out)
++{
++      int ret;
++      struct mmal_msg m;
++      struct mmal_msg *rmsg;
++      VCHI_HELD_MSG_T rmsg_handle;
++
++      m.h.type = MMAL_MSG_TYPE_GET_VERSION;
++
++      ret = send_synchronous_mmal_msg(instance, &m,
++                                      sizeof(m.u.version),
++                                      &rmsg, &rmsg_handle);
++      if (ret)
++              return ret;
++
++      if (rmsg->h.type != m.h.type) {
++              /* got an unexpected message type in reply */
++              ret = -EINVAL;
++              goto release_msg;
++      }
++
++      *major_out = rmsg->u.version.major;
++      *minor_out = rmsg->u.version.minor;
++
++release_msg:
++      vchi_held_msg_release(&rmsg_handle);
++
++      return ret;
++}
++
++/* do a port action with a port as a parameter */
++static int port_action_port(struct vchiq_mmal_instance *instance,
++                          struct vchiq_mmal_port *port,
++                          enum mmal_msg_port_action_type action_type)
++{
++      int ret;
++      struct mmal_msg m;
++      struct mmal_msg *rmsg;
++      VCHI_HELD_MSG_T rmsg_handle;
++
++      m.h.type = MMAL_MSG_TYPE_PORT_ACTION;
++      m.u.port_action_port.component_handle = port->component->handle;
++      m.u.port_action_port.port_handle = port->handle;
++      m.u.port_action_port.action = action_type;
++
++      port_to_mmal_msg(port, &m.u.port_action_port.port);
++
++      ret = send_synchronous_mmal_msg(instance, &m,
++                                      sizeof(m.u.port_action_port),
++                                      &rmsg, &rmsg_handle);
++      if (ret)
++              return ret;
++
++      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_ACTION) {
++              /* got an unexpected message type in reply */
++              ret = -EINVAL;
++              goto release_msg;
++      }
++
++      ret = -rmsg->u.port_action_reply.status;
++
++      pr_debug("%s:result:%d component:0x%x port:%d action:%s(%d)\n",
++               __func__,
++               ret, port->component->handle, port->handle,
++               port_action_type_names[action_type], action_type);
++
++release_msg:
++      vchi_held_msg_release(&rmsg_handle);
++
++      return ret;
++}
++
++/* do a port action with handles as parameters */
++static int port_action_handle(struct vchiq_mmal_instance *instance,
++                            struct vchiq_mmal_port *port,
++                            enum mmal_msg_port_action_type action_type,
++                            u32 connect_component_handle,
++                            u32 connect_port_handle)
++{
++      int ret;
++      struct mmal_msg m;
++      struct mmal_msg *rmsg;
++      VCHI_HELD_MSG_T rmsg_handle;
++
++      m.h.type = MMAL_MSG_TYPE_PORT_ACTION;
++
++      m.u.port_action_handle.component_handle = port->component->handle;
++      m.u.port_action_handle.port_handle = port->handle;
++      m.u.port_action_handle.action = action_type;
++
++      m.u.port_action_handle.connect_component_handle =
++          connect_component_handle;
++      m.u.port_action_handle.connect_port_handle = connect_port_handle;
++
++      ret = send_synchronous_mmal_msg(instance, &m,
++                                      sizeof(m.u.port_action_handle),
++                                      &rmsg, &rmsg_handle);
++      if (ret)
++              return ret;
++
++      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_ACTION) {
++              /* got an unexpected message type in reply */
++              ret = -EINVAL;
++              goto release_msg;
++      }
++
++      ret = -rmsg->u.port_action_reply.status;
++
++      pr_debug("%s:result:%d component:0x%x port:%d action:%s(%d) connect component:0x%x connect port:%d\n",
++               __func__,
++               ret, port->component->handle, port->handle,
++               port_action_type_names[action_type],
++               action_type, connect_component_handle, connect_port_handle);
++
++release_msg:
++      vchi_held_msg_release(&rmsg_handle);
++
++      return ret;
++}
++
++static int port_parameter_set(struct vchiq_mmal_instance *instance,
++                            struct vchiq_mmal_port *port,
++                            u32 parameter_id, void *value, u32 value_size)
++{
++      int ret;
++      struct mmal_msg m;
++      struct mmal_msg *rmsg;
++      VCHI_HELD_MSG_T rmsg_handle;
++
++      m.h.type = MMAL_MSG_TYPE_PORT_PARAMETER_SET;
++
++      m.u.port_parameter_set.component_handle = port->component->handle;
++      m.u.port_parameter_set.port_handle = port->handle;
++      m.u.port_parameter_set.id = parameter_id;
++      m.u.port_parameter_set.size = (2 * sizeof(u32)) + value_size;
++      memcpy(&m.u.port_parameter_set.value, value, value_size);
++
++      ret = send_synchronous_mmal_msg(instance, &m,
++                                      (4 * sizeof(u32)) + value_size,
++                                      &rmsg, &rmsg_handle);
++      if (ret)
++              return ret;
++
++      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_PARAMETER_SET) {
++              /* got an unexpected message type in reply */
++              ret = -EINVAL;
++              goto release_msg;
++      }
++
++      ret = -rmsg->u.port_parameter_set_reply.status;
++
++      pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n",
++               __func__,
++               ret, port->component->handle, port->handle, parameter_id);
++
++release_msg:
++      vchi_held_msg_release(&rmsg_handle);
++
++      return ret;
++}
++
++static int port_parameter_get(struct vchiq_mmal_instance *instance,
++                            struct vchiq_mmal_port *port,
++                            u32 parameter_id, void *value, u32 *value_size)
++{
++      int ret;
++      struct mmal_msg m;
++      struct mmal_msg *rmsg;
++      VCHI_HELD_MSG_T rmsg_handle;
++
++      m.h.type = MMAL_MSG_TYPE_PORT_PARAMETER_GET;
++
++      m.u.port_parameter_get.component_handle = port->component->handle;
++      m.u.port_parameter_get.port_handle = port->handle;
++      m.u.port_parameter_get.id = parameter_id;
++      m.u.port_parameter_get.size = (2 * sizeof(u32)) + *value_size;
++
++      ret = send_synchronous_mmal_msg(instance, &m,
++                                      sizeof(struct
++                                             mmal_msg_port_parameter_get),
++                                      &rmsg, &rmsg_handle);
++      if (ret)
++              return ret;
++
++      if (rmsg->h.type != MMAL_MSG_TYPE_PORT_PARAMETER_GET) {
++              /* got an unexpected message type in reply */
++              pr_err("Incorrect reply type %d\n", rmsg->h.type);
++              ret = -EINVAL;
++              goto release_msg;
++      }
++
++      ret = -rmsg->u.port_parameter_get_reply.status;
++      /* port_parameter_get_reply.size includes the header,
++       * whilst *value_size doesn't.
++       */
++      rmsg->u.port_parameter_get_reply.size -= (2 * sizeof(u32));
++
++      if (ret || rmsg->u.port_parameter_get_reply.size > *value_size) {
++              /* Copy only as much as we have space for
++               * but report true size of parameter
++               */
++              memcpy(value, &rmsg->u.port_parameter_get_reply.value,
++                     *value_size);
++              *value_size = rmsg->u.port_parameter_get_reply.size;
++      } else {
++              memcpy(value, &rmsg->u.port_parameter_get_reply.value,
++                     rmsg->u.port_parameter_get_reply.size);
++      }
++
++      pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n", __func__,
++               ret, port->component->handle, port->handle, parameter_id);
++
++release_msg:
++      vchi_held_msg_release(&rmsg_handle);
++
++      return ret;
++}
++
++/* disables a port and drains buffers from it */
++static int port_disable(struct vchiq_mmal_instance *instance,
++                      struct vchiq_mmal_port *port)
++{
++      int ret;
++      struct list_head *q, *buf_head;
++      unsigned long flags = 0;
++
++      if (!port->enabled)
++              return 0;
++
++      port->enabled = false;
++
++      ret = port_action_port(instance, port,
++                             MMAL_MSG_PORT_ACTION_TYPE_DISABLE);
++      if (ret == 0) {
++              /*
++               * Drain all queued buffers on port. This should only
++               * apply to buffers that have been queued before the port
++               * has been enabled. If the port has been enabled and buffers
++               * passed, then the buffers should have been removed from this
++               * list, and we should get the relevant callbacks via VCHIQ
++               * to release the buffers.
++               */
++              spin_lock_irqsave(&port->slock, flags);
++
++              list_for_each_safe(buf_head, q, &port->buffers) {
++                      struct mmal_buffer *mmalbuf;
++
++                      mmalbuf = list_entry(buf_head, struct mmal_buffer,
++                                           list);
++                      list_del(buf_head);
++                      if (port->buffer_cb)
++                              port->buffer_cb(instance,
++                                              port, 0, mmalbuf, 0, 0,
++                                              MMAL_TIME_UNKNOWN,
++                                              MMAL_TIME_UNKNOWN);
++              }
++
++              spin_unlock_irqrestore(&port->slock, flags);
++
++              ret = port_info_get(instance, port);
++      }
++
++      return ret;
++}
++
++/* enable a port */
++static int port_enable(struct vchiq_mmal_instance *instance,
++                     struct vchiq_mmal_port *port)
++{
++      unsigned int hdr_count;
++      struct list_head *q, *buf_head;
++      int ret;
++
++      if (port->enabled)
++              return 0;
++
++      ret = port_action_port(instance, port,
++                             MMAL_MSG_PORT_ACTION_TYPE_ENABLE);
++      if (ret)
++              goto done;
++
++      port->enabled = true;
++
++      if (port->buffer_cb) {
++              /* send buffer headers to videocore */
++              hdr_count = 1;
++              list_for_each_safe(buf_head, q, &port->buffers) {
++                      struct mmal_buffer *mmalbuf;
++
++                      mmalbuf = list_entry(buf_head, struct mmal_buffer,
++                                           list);
++                      ret = buffer_from_host(instance, port, mmalbuf);
++                      if (ret)
++                              goto done;
++
++                      list_del(buf_head);
++                      hdr_count++;
++                      if (hdr_count > port->current_buffer.num)
++                              break;
++              }
++      }
++
++      ret = port_info_get(instance, port);
++
++done:
++      return ret;
++}
++
++/* ------------------------------------------------------------------
++ * Exported API
++ *------------------------------------------------------------------
++ */
++
++int vchiq_mmal_port_set_format(struct vchiq_mmal_instance *instance,
++                             struct vchiq_mmal_port *port)
++{
++      int ret;
++
++      if (mutex_lock_interruptible(&instance->vchiq_mutex))
++              return -EINTR;
++
++      ret = port_info_set(instance, port);
++      if (ret)
++              goto release_unlock;
++
++      /* read what has actually been set */
++      ret = port_info_get(instance, port);
++
++release_unlock:
++      mutex_unlock(&instance->vchiq_mutex);
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_port_set_format);
++
++int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance,
++                                struct vchiq_mmal_port *port,
++                                u32 parameter, void *value, u32 value_size)
++{
++      int ret;
++
++      if (mutex_lock_interruptible(&instance->vchiq_mutex))
++              return -EINTR;
++
++      ret = port_parameter_set(instance, port, parameter, value, value_size);
++
++      mutex_unlock(&instance->vchiq_mutex);
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_port_parameter_set);
++
++int vchiq_mmal_port_parameter_get(struct vchiq_mmal_instance *instance,
++                                struct vchiq_mmal_port *port,
++                                u32 parameter, void *value, u32 *value_size)
++{
++      int ret;
++
++      if (mutex_lock_interruptible(&instance->vchiq_mutex))
++              return -EINTR;
++
++      ret = port_parameter_get(instance, port, parameter, value, value_size);
++
++      mutex_unlock(&instance->vchiq_mutex);
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_port_parameter_get);
++
++/* enable a port
++ *
++ * enables a port and queues buffers for satisfying callbacks if we
++ * provide a callback handler
++ */
++int vchiq_mmal_port_enable(struct vchiq_mmal_instance *instance,
++                         struct vchiq_mmal_port *port,
++                         vchiq_mmal_buffer_cb buffer_cb)
++{
++      int ret;
++
++      if (mutex_lock_interruptible(&instance->vchiq_mutex))
++              return -EINTR;
++
++      /* already enabled - noop */
++      if (port->enabled) {
++              ret = 0;
++              goto unlock;
++      }
++
++      port->buffer_cb = buffer_cb;
++
++      ret = port_enable(instance, port);
++
++unlock:
++      mutex_unlock(&instance->vchiq_mutex);
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_port_enable);
++
++int vchiq_mmal_port_disable(struct vchiq_mmal_instance *instance,
++                          struct vchiq_mmal_port *port)
++{
++      int ret;
++
++      if (mutex_lock_interruptible(&instance->vchiq_mutex))
++              return -EINTR;
++
++      if (!port->enabled) {
++              mutex_unlock(&instance->vchiq_mutex);
++              return 0;
++      }
++
++      ret = port_disable(instance, port);
++
++      mutex_unlock(&instance->vchiq_mutex);
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_port_disable);
++
++/* ports will be connected in a tunneled manner so data buffers
++ * are not handled by client.
++ */
++int vchiq_mmal_port_connect_tunnel(struct vchiq_mmal_instance *instance,
++                                 struct vchiq_mmal_port *src,
++                                 struct vchiq_mmal_port *dst)
++{
++      int ret;
++
++      if (mutex_lock_interruptible(&instance->vchiq_mutex))
++              return -EINTR;
++
++      /* disconnect ports if connected */
++      if (src->connected) {
++              ret = port_disable(instance, src);
++              if (ret) {
++                      pr_err("failed disabling src port(%d)\n", ret);
++                      goto release_unlock;
++              }
++
++              /* do not need to disable the destination port as they
++               * are connected and it is done automatically
++               */
++
++              ret = port_action_handle(instance, src,
++                                       MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT,
++                                       src->connected->component->handle,
++                                       src->connected->handle);
++              if (ret < 0) {
++                      pr_err("failed disconnecting src port\n");
++                      goto release_unlock;
++              }
++              src->connected->enabled = false;
++              src->connected = NULL;
++      }
++
++      if (!dst) {
++              /* do not make new connection */
++              ret = 0;
++              pr_debug("not making new connection\n");
++              goto release_unlock;
++      }
++
++      /* copy src port format to dst */
++      dst->format.encoding = src->format.encoding;
++      dst->es.video.width = src->es.video.width;
++      dst->es.video.height = src->es.video.height;
++      dst->es.video.crop.x = src->es.video.crop.x;
++      dst->es.video.crop.y = src->es.video.crop.y;
++      dst->es.video.crop.width = src->es.video.crop.width;
++      dst->es.video.crop.height = src->es.video.crop.height;
++      dst->es.video.frame_rate.num = src->es.video.frame_rate.num;
++      dst->es.video.frame_rate.den = src->es.video.frame_rate.den;
++
++      /* set new format */
++      ret = port_info_set(instance, dst);
++      if (ret) {
++              pr_debug("setting port info failed\n");
++              goto release_unlock;
++      }
++
++      /* read what has actually been set */
++      ret = port_info_get(instance, dst);
++      if (ret) {
++              pr_debug("read back port info failed\n");
++              goto release_unlock;
++      }
++
++      /* connect two ports together */
++      ret = port_action_handle(instance, src,
++                               MMAL_MSG_PORT_ACTION_TYPE_CONNECT,
++                               dst->component->handle, dst->handle);
++      if (ret < 0) {
++              pr_debug("connecting port %d:%d to %d:%d failed\n",
++                       src->component->handle, src->handle,
++                       dst->component->handle, dst->handle);
++              goto release_unlock;
++      }
++      src->connected = dst;
++
++release_unlock:
++
++      mutex_unlock(&instance->vchiq_mutex);
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_port_connect_tunnel);
++
++int vchiq_mmal_submit_buffer(struct vchiq_mmal_instance *instance,
++                           struct vchiq_mmal_port *port,
++                           struct mmal_buffer *buffer)
++{
++      unsigned long flags = 0;
++      int ret;
++
++      ret = buffer_from_host(instance, port, buffer);
++      if (ret == -EINVAL) {
++              /* Port is disabled. Queue for when it is enabled. */
++              spin_lock_irqsave(&port->slock, flags);
++              list_add_tail(&buffer->list, &port->buffers);
++              spin_unlock_irqrestore(&port->slock, flags);
++      }
++
++      return 0;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_submit_buffer);
++
++int mmal_vchi_buffer_init(struct vchiq_mmal_instance *instance,
++                        struct mmal_buffer *buf)
++{
++      struct mmal_msg_context *msg_context = get_msg_context(instance);
++
++      if (IS_ERR(msg_context))
++              return (PTR_ERR(msg_context));
++
++      buf->msg_context = msg_context;
++      return 0;
++}
++EXPORT_SYMBOL_GPL(mmal_vchi_buffer_init);
++
++int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf)
++{
++      struct mmal_msg_context *msg_context = buf->msg_context;
++
++      if (msg_context)
++              release_msg_context(msg_context);
++      buf->msg_context = NULL;
++
++      return 0;
++}
++EXPORT_SYMBOL_GPL(mmal_vchi_buffer_cleanup);
++
++/* Initialise a mmal component and its ports
++ *
++ */
++int vchiq_mmal_component_init(struct vchiq_mmal_instance *instance,
++                            const char *name,
++                            struct vchiq_mmal_component **component_out)
++{
++      int ret;
++      int idx;                /* port index */
++      struct vchiq_mmal_component *component;
++
++      if (mutex_lock_interruptible(&instance->vchiq_mutex))
++              return -EINTR;
++
++      if (instance->component_idx == VCHIQ_MMAL_MAX_COMPONENTS) {
++              ret = -EINVAL;  /* todo is this correct error? */
++              goto unlock;
++      }
++
++      component = &instance->component[instance->component_idx];
++
++      ret = create_component(instance, component, name);
++      if (ret < 0) {
++              pr_err("%s: failed to create component %d (Not enough GPU mem?)\n",
++                     __func__, ret);
++              goto unlock;
++      }
++
++      /* ports info needs gathering */
++      component->control.type = MMAL_PORT_TYPE_CONTROL;
++      component->control.index = 0;
++      component->control.component = component;
++      spin_lock_init(&component->control.slock);
++      INIT_LIST_HEAD(&component->control.buffers);
++      ret = port_info_get(instance, &component->control);
++      if (ret < 0)
++              goto release_component;
++
++      for (idx = 0; idx < component->inputs; idx++) {
++              component->input[idx].type = MMAL_PORT_TYPE_INPUT;
++              component->input[idx].index = idx;
++              component->input[idx].component = component;
++              spin_lock_init(&component->input[idx].slock);
++              INIT_LIST_HEAD(&component->input[idx].buffers);
++              ret = port_info_get(instance, &component->input[idx]);
++              if (ret < 0)
++                      goto release_component;
++      }
++
++      for (idx = 0; idx < component->outputs; idx++) {
++              component->output[idx].type = MMAL_PORT_TYPE_OUTPUT;
++              component->output[idx].index = idx;
++              component->output[idx].component = component;
++              spin_lock_init(&component->output[idx].slock);
++              INIT_LIST_HEAD(&component->output[idx].buffers);
++              ret = port_info_get(instance, &component->output[idx]);
++              if (ret < 0)
++                      goto release_component;
++      }
++
++      for (idx = 0; idx < component->clocks; idx++) {
++              component->clock[idx].type = MMAL_PORT_TYPE_CLOCK;
++              component->clock[idx].index = idx;
++              component->clock[idx].component = component;
++              spin_lock_init(&component->clock[idx].slock);
++              INIT_LIST_HEAD(&component->clock[idx].buffers);
++              ret = port_info_get(instance, &component->clock[idx]);
++              if (ret < 0)
++                      goto release_component;
++      }
++
++      instance->component_idx++;
++
++      *component_out = component;
++
++      mutex_unlock(&instance->vchiq_mutex);
++
++      return 0;
++
++release_component:
++      destroy_component(instance, component);
++unlock:
++      mutex_unlock(&instance->vchiq_mutex);
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_component_init);
++
++/*
++ * cause a mmal component to be destroyed
++ */
++int vchiq_mmal_component_finalise(struct vchiq_mmal_instance *instance,
++                                struct vchiq_mmal_component *component)
++{
++      int ret;
++
++      if (mutex_lock_interruptible(&instance->vchiq_mutex))
++              return -EINTR;
++
++      if (component->enabled)
++              ret = disable_component(instance, component);
++
++      ret = destroy_component(instance, component);
++
++      mutex_unlock(&instance->vchiq_mutex);
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_component_finalise);
++
++/*
++ * cause a mmal component to be enabled
++ */
++int vchiq_mmal_component_enable(struct vchiq_mmal_instance *instance,
++                              struct vchiq_mmal_component *component)
++{
++      int ret;
++
++      if (mutex_lock_interruptible(&instance->vchiq_mutex))
++              return -EINTR;
++
++      if (component->enabled) {
++              mutex_unlock(&instance->vchiq_mutex);
++              return 0;
++      }
++
++      ret = enable_component(instance, component);
++      if (ret == 0)
++              component->enabled = true;
++
++      mutex_unlock(&instance->vchiq_mutex);
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_component_enable);
++
++/*
++ * cause a mmal component to be enabled
++ */
++int vchiq_mmal_component_disable(struct vchiq_mmal_instance *instance,
++                               struct vchiq_mmal_component *component)
++{
++      int ret;
++
++      if (mutex_lock_interruptible(&instance->vchiq_mutex))
++              return -EINTR;
++
++      if (!component->enabled) {
++              mutex_unlock(&instance->vchiq_mutex);
++              return 0;
++      }
++
++      ret = disable_component(instance, component);
++      if (ret == 0)
++              component->enabled = false;
++
++      mutex_unlock(&instance->vchiq_mutex);
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_component_disable);
++
++int vchiq_mmal_version(struct vchiq_mmal_instance *instance,
++                     u32 *major_out, u32 *minor_out)
++{
++      int ret;
++
++      if (mutex_lock_interruptible(&instance->vchiq_mutex))
++              return -EINTR;
++
++      ret = get_version(instance, major_out, minor_out);
++
++      mutex_unlock(&instance->vchiq_mutex);
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_version);
++
++int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance)
++{
++      int status = 0;
++
++      if (!instance)
++              return -EINVAL;
++
++      if (mutex_lock_interruptible(&instance->vchiq_mutex))
++              return -EINTR;
++
++      vchi_service_use(instance->handle);
++
++      status = vchi_service_close(instance->handle);
++      if (status != 0)
++              pr_err("mmal-vchiq: VCHIQ close failed\n");
++
++      mutex_unlock(&instance->vchiq_mutex);
++
++      flush_workqueue(instance->bulk_wq);
++      destroy_workqueue(instance->bulk_wq);
++
++      vfree(instance->bulk_scratch);
++
++      idr_destroy(&instance->context_map);
++
++      kfree(instance);
++
++      return status;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_finalise);
++
++int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance)
++{
++      int status;
++      struct vchiq_mmal_instance *instance;
++      static VCHI_CONNECTION_T *vchi_connection;
++      static VCHI_INSTANCE_T vchi_instance;
++      SERVICE_CREATION_T params = {
++              .version                = VCHI_VERSION_EX(VC_MMAL_VER, VC_MMAL_MIN_VER),
++              .service_id             = VC_MMAL_SERVER_NAME,
++              .connection             = vchi_connection,
++              .rx_fifo_size           = 0,
++              .tx_fifo_size           = 0,
++              .callback               = service_callback,
++              .callback_param         = NULL,
++              .want_unaligned_bulk_rx = 1,
++              .want_unaligned_bulk_tx = 1,
++              .want_crc               = 0
++      };
++
++      /* compile time checks to ensure structure size as they are
++       * directly (de)serialised from memory.
++       */
++
++      /* ensure the header structure has packed to the correct size */
++      BUILD_BUG_ON(sizeof(struct mmal_msg_header) != 24);
++
++      /* ensure message structure does not exceed maximum length */
++      BUILD_BUG_ON(sizeof(struct mmal_msg) > MMAL_MSG_MAX_SIZE);
++
++      /* mmal port struct is correct size */
++      BUILD_BUG_ON(sizeof(struct mmal_port) != 64);
++
++      /* create a vchi instance */
++      status = vchi_initialise(&vchi_instance);
++      if (status) {
++              pr_err("Failed to initialise VCHI instance (status=%d)\n",
++                     status);
++              return -EIO;
++      }
++
++      status = vchi_connect(NULL, 0, vchi_instance);
++      if (status) {
++              pr_err("Failed to connect VCHI instance (status=%d)\n", status);
++              return -EIO;
++      }
++
++      instance = kzalloc(sizeof(*instance), GFP_KERNEL);
++
++      if (!instance)
++              return -ENOMEM;
++
++      mutex_init(&instance->vchiq_mutex);
++
++      instance->bulk_scratch = vmalloc(PAGE_SIZE);
++
++      mutex_init(&instance->context_map_lock);
++      idr_init_base(&instance->context_map, 1);
++
++      params.callback_param = instance;
++
++      instance->bulk_wq = alloc_ordered_workqueue("mmal-vchiq",
++                                                  WQ_MEM_RECLAIM);
++      if (!instance->bulk_wq)
++              goto err_free;
++
++      status = vchi_service_open(vchi_instance, &params, &instance->handle);
++      if (status) {
++              pr_err("Failed to open VCHI service connection (status=%d)\n",
++                     status);
++              goto err_close_services;
++      }
++
++      vchi_service_release(instance->handle);
++
++      *out_instance = instance;
++
++      return 0;
++
++err_close_services:
++      vchi_service_close(instance->handle);
++      destroy_workqueue(instance->bulk_wq);
++err_free:
++      vfree(instance->bulk_scratch);
++      kfree(instance);
++      return -ENODEV;
++}
++EXPORT_SYMBOL_GPL(vchiq_mmal_init);
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-common.h
++++ /dev/null
+@@ -1,61 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Broadcom BM2835 V4L2 driver
+- *
+- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+- *
+- * Authors: Vincent Sanders @ Collabora
+- *          Dave Stevenson @ Broadcom
+- *            (now dave.stevenson@raspberrypi.org)
+- *          Simon Mellor @ Broadcom
+- *          Luke Diamand @ Broadcom
+- *
+- * MMAL structures
+- *
+- */
+-#ifndef MMAL_COMMON_H
+-#define MMAL_COMMON_H
+-
+-#define MMAL_FOURCC(a, b, c, d) ((a) | (b << 8) | (c << 16) | (d << 24))
+-#define MMAL_MAGIC MMAL_FOURCC('m', 'm', 'a', 'l')
+-
+-/** Special value signalling that time is not known */
+-#define MMAL_TIME_UNKNOWN BIT_ULL(63)
+-
+-struct mmal_msg_context;
+-
+-/* mapping between v4l and mmal video modes */
+-struct mmal_fmt {
+-      char  *name;
+-      u32   fourcc;          /* v4l2 format id */
+-      int   flags;           /* v4l2 flags field */
+-      u32   mmal;
+-      int   depth;
+-      u32   mmal_component;  /* MMAL component index to be used to encode */
+-      u32   ybbp;            /* depth of first Y plane for planar formats */
+-      bool  remove_padding;  /* Does the GPU have to remove padding,
+-                              * or can we do hide padding via bytesperline.
+-                              */
+-};
+-
+-/* buffer for one video frame */
+-struct mmal_buffer {
+-      /* v4l buffer data -- must be first */
+-      struct vb2_v4l2_buffer  vb;
+-
+-      /* list of buffers available */
+-      struct list_head        list;
+-
+-      void *buffer; /* buffer pointer */
+-      unsigned long buffer_size; /* size of allocated buffer */
+-
+-      struct mmal_msg_context *msg_context;
+-};
+-
+-/* */
+-struct mmal_colourfx {
+-      s32 enable;
+-      u32 u;
+-      u32 v;
+-};
+-#endif
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-encodings.h
++++ /dev/null
+@@ -1,124 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Broadcom BM2835 V4L2 driver
+- *
+- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+- *
+- * Authors: Vincent Sanders @ Collabora
+- *          Dave Stevenson @ Broadcom
+- *            (now dave.stevenson@raspberrypi.org)
+- *          Simon Mellor @ Broadcom
+- *          Luke Diamand @ Broadcom
+- */
+-#ifndef MMAL_ENCODINGS_H
+-#define MMAL_ENCODINGS_H
+-
+-#define MMAL_ENCODING_H264             MMAL_FOURCC('H', '2', '6', '4')
+-#define MMAL_ENCODING_H263             MMAL_FOURCC('H', '2', '6', '3')
+-#define MMAL_ENCODING_MP4V             MMAL_FOURCC('M', 'P', '4', 'V')
+-#define MMAL_ENCODING_MP2V             MMAL_FOURCC('M', 'P', '2', 'V')
+-#define MMAL_ENCODING_MP1V             MMAL_FOURCC('M', 'P', '1', 'V')
+-#define MMAL_ENCODING_WMV3             MMAL_FOURCC('W', 'M', 'V', '3')
+-#define MMAL_ENCODING_WMV2             MMAL_FOURCC('W', 'M', 'V', '2')
+-#define MMAL_ENCODING_WMV1             MMAL_FOURCC('W', 'M', 'V', '1')
+-#define MMAL_ENCODING_WVC1             MMAL_FOURCC('W', 'V', 'C', '1')
+-#define MMAL_ENCODING_VP8              MMAL_FOURCC('V', 'P', '8', ' ')
+-#define MMAL_ENCODING_VP7              MMAL_FOURCC('V', 'P', '7', ' ')
+-#define MMAL_ENCODING_VP6              MMAL_FOURCC('V', 'P', '6', ' ')
+-#define MMAL_ENCODING_THEORA           MMAL_FOURCC('T', 'H', 'E', 'O')
+-#define MMAL_ENCODING_SPARK            MMAL_FOURCC('S', 'P', 'R', 'K')
+-#define MMAL_ENCODING_MJPEG            MMAL_FOURCC('M', 'J', 'P', 'G')
+-
+-#define MMAL_ENCODING_JPEG             MMAL_FOURCC('J', 'P', 'E', 'G')
+-#define MMAL_ENCODING_GIF              MMAL_FOURCC('G', 'I', 'F', ' ')
+-#define MMAL_ENCODING_PNG              MMAL_FOURCC('P', 'N', 'G', ' ')
+-#define MMAL_ENCODING_PPM              MMAL_FOURCC('P', 'P', 'M', ' ')
+-#define MMAL_ENCODING_TGA              MMAL_FOURCC('T', 'G', 'A', ' ')
+-#define MMAL_ENCODING_BMP              MMAL_FOURCC('B', 'M', 'P', ' ')
+-
+-#define MMAL_ENCODING_I420             MMAL_FOURCC('I', '4', '2', '0')
+-#define MMAL_ENCODING_I420_SLICE       MMAL_FOURCC('S', '4', '2', '0')
+-#define MMAL_ENCODING_YV12             MMAL_FOURCC('Y', 'V', '1', '2')
+-#define MMAL_ENCODING_I422             MMAL_FOURCC('I', '4', '2', '2')
+-#define MMAL_ENCODING_I422_SLICE       MMAL_FOURCC('S', '4', '2', '2')
+-#define MMAL_ENCODING_YUYV             MMAL_FOURCC('Y', 'U', 'Y', 'V')
+-#define MMAL_ENCODING_YVYU             MMAL_FOURCC('Y', 'V', 'Y', 'U')
+-#define MMAL_ENCODING_UYVY             MMAL_FOURCC('U', 'Y', 'V', 'Y')
+-#define MMAL_ENCODING_VYUY             MMAL_FOURCC('V', 'Y', 'U', 'Y')
+-#define MMAL_ENCODING_NV12             MMAL_FOURCC('N', 'V', '1', '2')
+-#define MMAL_ENCODING_NV21             MMAL_FOURCC('N', 'V', '2', '1')
+-#define MMAL_ENCODING_ARGB             MMAL_FOURCC('A', 'R', 'G', 'B')
+-#define MMAL_ENCODING_RGBA             MMAL_FOURCC('R', 'G', 'B', 'A')
+-#define MMAL_ENCODING_ABGR             MMAL_FOURCC('A', 'B', 'G', 'R')
+-#define MMAL_ENCODING_BGRA             MMAL_FOURCC('B', 'G', 'R', 'A')
+-#define MMAL_ENCODING_RGB16            MMAL_FOURCC('R', 'G', 'B', '2')
+-#define MMAL_ENCODING_RGB24            MMAL_FOURCC('R', 'G', 'B', '3')
+-#define MMAL_ENCODING_RGB32            MMAL_FOURCC('R', 'G', 'B', '4')
+-#define MMAL_ENCODING_BGR16            MMAL_FOURCC('B', 'G', 'R', '2')
+-#define MMAL_ENCODING_BGR24            MMAL_FOURCC('B', 'G', 'R', '3')
+-#define MMAL_ENCODING_BGR32            MMAL_FOURCC('B', 'G', 'R', '4')
+-
+-/** SAND Video (YUVUV128) format, native format understood by VideoCore.
+- * This format is *not* opaque - if requested you will receive full frames
+- * of YUV_UV video.
+- */
+-#define MMAL_ENCODING_YUVUV128         MMAL_FOURCC('S', 'A', 'N', 'D')
+-
+-/** VideoCore opaque image format, image handles are returned to
+- * the host but not the actual image data.
+- */
+-#define MMAL_ENCODING_OPAQUE           MMAL_FOURCC('O', 'P', 'Q', 'V')
+-
+-/** An EGL image handle
+- */
+-#define MMAL_ENCODING_EGL_IMAGE        MMAL_FOURCC('E', 'G', 'L', 'I')
+-
+-/* }@ */
+-
+-/** \name Pre-defined audio encodings */
+-/* @{ */
+-#define MMAL_ENCODING_PCM_UNSIGNED_BE  MMAL_FOURCC('P', 'C', 'M', 'U')
+-#define MMAL_ENCODING_PCM_UNSIGNED_LE  MMAL_FOURCC('p', 'c', 'm', 'u')
+-#define MMAL_ENCODING_PCM_SIGNED_BE    MMAL_FOURCC('P', 'C', 'M', 'S')
+-#define MMAL_ENCODING_PCM_SIGNED_LE    MMAL_FOURCC('p', 'c', 'm', 's')
+-#define MMAL_ENCODING_PCM_FLOAT_BE     MMAL_FOURCC('P', 'C', 'M', 'F')
+-#define MMAL_ENCODING_PCM_FLOAT_LE     MMAL_FOURCC('p', 'c', 'm', 'f')
+-
+-/* Pre-defined H264 encoding variants */
+-
+-/** ISO 14496-10 Annex B byte stream format */
+-#define MMAL_ENCODING_VARIANT_H264_DEFAULT   0
+-/** ISO 14496-15 AVC stream format */
+-#define MMAL_ENCODING_VARIANT_H264_AVC1      MMAL_FOURCC('A', 'V', 'C', '1')
+-/** Implicitly delineated NAL units without emulation prevention */
+-#define MMAL_ENCODING_VARIANT_H264_RAW       MMAL_FOURCC('R', 'A', 'W', ' ')
+-
+-/** \defgroup MmalColorSpace List of pre-defined video color spaces
+- * This defines a list of common color spaces. This list isn't exhaustive and
+- * is only provided as a convenience to avoid clients having to use FourCC
+- * codes directly. However components are allowed to define and use their own
+- * FourCC codes.
+- */
+-/* @{ */
+-
+-/** Unknown color space */
+-#define MMAL_COLOR_SPACE_UNKNOWN       0
+-/** ITU-R BT.601-5 [SDTV] */
+-#define MMAL_COLOR_SPACE_ITUR_BT601    MMAL_FOURCC('Y', '6', '0', '1')
+-/** ITU-R BT.709-3 [HDTV] */
+-#define MMAL_COLOR_SPACE_ITUR_BT709    MMAL_FOURCC('Y', '7', '0', '9')
+-/** JPEG JFIF */
+-#define MMAL_COLOR_SPACE_JPEG_JFIF     MMAL_FOURCC('Y', 'J', 'F', 'I')
+-/** Title 47 Code of Federal Regulations (2003) 73.682 (a) (20) */
+-#define MMAL_COLOR_SPACE_FCC           MMAL_FOURCC('Y', 'F', 'C', 'C')
+-/** Society of Motion Picture and Television Engineers 240M (1999) */
+-#define MMAL_COLOR_SPACE_SMPTE240M     MMAL_FOURCC('Y', '2', '4', '0')
+-/** ITU-R BT.470-2 System M */
+-#define MMAL_COLOR_SPACE_BT470_2_M     MMAL_FOURCC('Y', '_', '_', 'M')
+-/** ITU-R BT.470-2 System BG */
+-#define MMAL_COLOR_SPACE_BT470_2_BG    MMAL_FOURCC('Y', '_', 'B', 'G')
+-/** JPEG JFIF, but with 16..255 luma */
+-#define MMAL_COLOR_SPACE_JFIF_Y16_255  MMAL_FOURCC('Y', 'Y', '1', '6')
+-/* @} MmalColorSpace List */
+-
+-#endif /* MMAL_ENCODINGS_H */
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-common.h
++++ /dev/null
+@@ -1,48 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Broadcom BM2835 V4L2 driver
+- *
+- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+- *
+- * Authors: Vincent Sanders @ Collabora
+- *          Dave Stevenson @ Broadcom
+- *            (now dave.stevenson@raspberrypi.org)
+- *          Simon Mellor @ Broadcom
+- *          Luke Diamand @ Broadcom
+- */
+-
+-#ifndef MMAL_MSG_COMMON_H
+-#define MMAL_MSG_COMMON_H
+-
+-enum mmal_msg_status {
+-      MMAL_MSG_STATUS_SUCCESS = 0, /**< Success */
+-      MMAL_MSG_STATUS_ENOMEM,      /**< Out of memory */
+-      MMAL_MSG_STATUS_ENOSPC,      /**< Out of resources other than memory */
+-      MMAL_MSG_STATUS_EINVAL,      /**< Argument is invalid */
+-      MMAL_MSG_STATUS_ENOSYS,      /**< Function not implemented */
+-      MMAL_MSG_STATUS_ENOENT,      /**< No such file or directory */
+-      MMAL_MSG_STATUS_ENXIO,       /**< No such device or address */
+-      MMAL_MSG_STATUS_EIO,         /**< I/O error */
+-      MMAL_MSG_STATUS_ESPIPE,      /**< Illegal seek */
+-      MMAL_MSG_STATUS_ECORRUPT,    /**< Data is corrupt \attention */
+-      MMAL_MSG_STATUS_ENOTREADY,   /**< Component is not ready */
+-      MMAL_MSG_STATUS_ECONFIG,     /**< Component is not configured */
+-      MMAL_MSG_STATUS_EISCONN,     /**< Port is already connected */
+-      MMAL_MSG_STATUS_ENOTCONN,    /**< Port is disconnected */
+-      MMAL_MSG_STATUS_EAGAIN,      /**< Resource temporarily unavailable. */
+-      MMAL_MSG_STATUS_EFAULT,      /**< Bad address */
+-};
+-
+-struct mmal_rect {
+-      s32 x;      /**< x coordinate (from left) */
+-      s32 y;      /**< y coordinate (from top) */
+-      s32 width;  /**< width */
+-      s32 height; /**< height */
+-};
+-
+-struct mmal_rational {
+-      s32 num;    /**< Numerator */
+-      s32 den;    /**< Denominator */
+-};
+-
+-#endif /* MMAL_MSG_COMMON_H */
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-format.h
++++ /dev/null
+@@ -1,106 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Broadcom BM2835 V4L2 driver
+- *
+- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+- *
+- * Authors: Vincent Sanders @ Collabora
+- *          Dave Stevenson @ Broadcom
+- *            (now dave.stevenson@raspberrypi.org)
+- *          Simon Mellor @ Broadcom
+- *          Luke Diamand @ Broadcom
+- */
+-
+-#ifndef MMAL_MSG_FORMAT_H
+-#define MMAL_MSG_FORMAT_H
+-
+-#include "mmal-msg-common.h"
+-
+-/* MMAL_ES_FORMAT_T */
+-
+-struct mmal_audio_format {
+-      u32 channels;           /* Number of audio channels */
+-      u32 sample_rate;        /* Sample rate */
+-
+-      u32 bits_per_sample;    /* Bits per sample */
+-      u32 block_align;        /* Size of a block of data */
+-};
+-
+-struct mmal_video_format {
+-      u32 width;              /* Width of frame in pixels */
+-      u32 height;             /* Height of frame in rows of pixels */
+-      struct mmal_rect crop;  /* Visible region of the frame */
+-      struct mmal_rational frame_rate;        /* Frame rate */
+-      struct mmal_rational par;               /* Pixel aspect ratio */
+-
+-      /*
+-       * FourCC specifying the color space of the video stream. See the
+-       * MmalColorSpace "pre-defined color spaces" for some examples.
+-       */
+-      u32 color_space;
+-};
+-
+-struct mmal_subpicture_format {
+-      u32 x_offset;
+-      u32 y_offset;
+-};
+-
+-union mmal_es_specific_format {
+-      struct mmal_audio_format audio;
+-      struct mmal_video_format video;
+-      struct mmal_subpicture_format subpicture;
+-};
+-
+-/* Definition of an elementary stream format (MMAL_ES_FORMAT_T) */
+-struct mmal_es_format_local {
+-      u32 type;       /* enum mmal_es_type */
+-
+-      u32 encoding;   /* FourCC specifying encoding of the elementary
+-                       * stream.
+-                       */
+-      u32 encoding_variant;   /* FourCC specifying the specific
+-                               * encoding variant of the elementary
+-                               * stream.
+-                               */
+-
+-      union mmal_es_specific_format *es;      /* Type specific
+-                                               * information for the
+-                                               * elementary stream
+-                                               */
+-
+-      u32 bitrate;    /* Bitrate in bits per second */
+-      u32 flags;      /* Flags describing properties of the elementary
+-                       * stream.
+-                       */
+-
+-      u32 extradata_size;     /* Size of the codec specific data */
+-      u8  *extradata;         /* Codec specific data */
+-};
+-
+-/* Remote definition of an elementary stream format (MMAL_ES_FORMAT_T) */
+-struct mmal_es_format {
+-      u32 type;       /* enum mmal_es_type */
+-
+-      u32 encoding;   /* FourCC specifying encoding of the elementary
+-                       * stream.
+-                       */
+-      u32 encoding_variant;   /* FourCC specifying the specific
+-                               * encoding variant of the elementary
+-                               * stream.
+-                               */
+-
+-      u32 es; /* Type specific
+-               * information for the
+-               * elementary stream
+-               */
+-
+-      u32 bitrate;    /* Bitrate in bits per second */
+-      u32 flags;      /* Flags describing properties of the elementary
+-                       * stream.
+-                       */
+-
+-      u32 extradata_size;     /* Size of the codec specific data */
+-      u32 extradata;          /* Codec specific data */
+-};
+-
+-#endif /* MMAL_MSG_FORMAT_H */
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg-port.h
++++ /dev/null
+@@ -1,109 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Broadcom BM2835 V4L2 driver
+- *
+- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+- *
+- * Authors: Vincent Sanders @ Collabora
+- *          Dave Stevenson @ Broadcom
+- *            (now dave.stevenson@raspberrypi.org)
+- *          Simon Mellor @ Broadcom
+- *          Luke Diamand @ Broadcom
+- */
+-
+-/* MMAL_PORT_TYPE_T */
+-enum mmal_port_type {
+-      MMAL_PORT_TYPE_UNKNOWN = 0,     /* Unknown port type */
+-      MMAL_PORT_TYPE_CONTROL,         /* Control port */
+-      MMAL_PORT_TYPE_INPUT,           /* Input port */
+-      MMAL_PORT_TYPE_OUTPUT,          /* Output port */
+-      MMAL_PORT_TYPE_CLOCK,           /* Clock port */
+-};
+-
+-/* The port is pass-through and doesn't need buffer headers allocated */
+-#define MMAL_PORT_CAPABILITY_PASSTHROUGH                       0x01
+-/*
+- *The port wants to allocate the buffer payloads.
+- * This signals a preference that payload allocation should be done
+- * on this port for efficiency reasons.
+- */
+-#define MMAL_PORT_CAPABILITY_ALLOCATION                        0x02
+-/*
+- * The port supports format change events.
+- * This applies to input ports and is used to let the client know
+- * whether the port supports being reconfigured via a format
+- * change event (i.e. without having to disable the port).
+- */
+-#define MMAL_PORT_CAPABILITY_SUPPORTS_EVENT_FORMAT_CHANGE      0x04
+-
+-/*
+- * mmal port structure (MMAL_PORT_T)
+- *
+- * most elements are informational only, the pointer values for
+- * interogation messages are generally provided as additional
+- * structures within the message. When used to set values only the
+- * buffer_num, buffer_size and userdata parameters are writable.
+- */
+-struct mmal_port {
+-      u32 priv;       /* Private member used by the framework */
+-      u32 name;       /* Port name. Used for debugging purposes (RO) */
+-
+-      u32 type;       /* Type of the port (RO) enum mmal_port_type */
+-      u16 index;      /* Index of the port in its type list (RO) */
+-      u16 index_all;  /* Index of the port in the list of all ports (RO) */
+-
+-      u32 is_enabled; /* Indicates whether the port is enabled or not (RO) */
+-      u32 format;     /* Format of the elementary stream */
+-
+-      u32 buffer_num_min;     /* Minimum number of buffers the port
+-                               *   requires (RO).  This is set by the
+-                               *   component.
+-                               */
+-
+-      u32 buffer_size_min;    /* Minimum size of buffers the port
+-                               * requires (RO).  This is set by the
+-                               * component.
+-                               */
+-
+-      u32 buffer_alignment_min;/* Minimum alignment requirement for
+-                                * the buffers (RO).  A value of
+-                                * zero means no special alignment
+-                                * requirements.  This is set by the
+-                                * component.
+-                                */
+-
+-      u32 buffer_num_recommended;     /* Number of buffers the port
+-                                       * recommends for optimal
+-                                       * performance (RO).  A value of
+-                                       * zero means no special
+-                                       * recommendation.  This is set
+-                                       * by the component.
+-                                       */
+-
+-      u32 buffer_size_recommended;    /* Size of buffers the port
+-                                       * recommends for optimal
+-                                       * performance (RO).  A value of
+-                                       * zero means no special
+-                                       * recommendation.  This is set
+-                                       * by the component.
+-                                       */
+-
+-      u32 buffer_num; /* Actual number of buffers the port will use.
+-                       * This is set by the client.
+-                       */
+-
+-      u32 buffer_size; /* Actual maximum size of the buffers that
+-                        * will be sent to the port. This is set by
+-                        * the client.
+-                        */
+-
+-      u32 component;  /* Component this port belongs to (Read Only) */
+-
+-      u32 userdata;   /* Field reserved for use by the client */
+-
+-      u32 capabilities;       /* Flags describing the capabilities of a
+-                               * port (RO).  Bitwise combination of \ref
+-                               * portcapabilities "Port capabilities"
+-                               * values.
+-                               */
+-};
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-msg.h
++++ /dev/null
+@@ -1,406 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Broadcom BM2835 V4L2 driver
+- *
+- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+- *
+- * Authors: Vincent Sanders @ Collabora
+- *          Dave Stevenson @ Broadcom
+- *            (now dave.stevenson@raspberrypi.org)
+- *          Simon Mellor @ Broadcom
+- *          Luke Diamand @ Broadcom
+- */
+-
+-/*
+- * all the data structures which serialise the MMAL protocol. note
+- * these are directly mapped onto the recived message data.
+- *
+- * BEWARE: They seem to *assume* pointers are u32 and that there is no
+- * structure padding!
+- *
+- * NOTE: this implementation uses kernel types to ensure sizes. Rather
+- * than assigning values to enums to force their size the
+- * implementation uses fixed size types and not the enums (though the
+- * comments have the actual enum type
+- */
+-#ifndef MMAL_MSG_H
+-#define MMAL_MSG_H
+-
+-#define VC_MMAL_VER 15
+-#define VC_MMAL_MIN_VER 10
+-#define VC_MMAL_SERVER_NAME  MAKE_FOURCC("mmal")
+-
+-/* max total message size is 512 bytes */
+-#define MMAL_MSG_MAX_SIZE 512
+-/* with six 32bit header elements max payload is therefore 488 bytes */
+-#define MMAL_MSG_MAX_PAYLOAD 488
+-
+-#include "mmal-msg-common.h"
+-#include "mmal-msg-format.h"
+-#include "mmal-msg-port.h"
+-
+-enum mmal_msg_type {
+-      MMAL_MSG_TYPE_QUIT = 1,
+-      MMAL_MSG_TYPE_SERVICE_CLOSED,
+-      MMAL_MSG_TYPE_GET_VERSION,
+-      MMAL_MSG_TYPE_COMPONENT_CREATE,
+-      MMAL_MSG_TYPE_COMPONENT_DESTROY,        /* 5 */
+-      MMAL_MSG_TYPE_COMPONENT_ENABLE,
+-      MMAL_MSG_TYPE_COMPONENT_DISABLE,
+-      MMAL_MSG_TYPE_PORT_INFO_GET,
+-      MMAL_MSG_TYPE_PORT_INFO_SET,
+-      MMAL_MSG_TYPE_PORT_ACTION,              /* 10 */
+-      MMAL_MSG_TYPE_BUFFER_FROM_HOST,
+-      MMAL_MSG_TYPE_BUFFER_TO_HOST,
+-      MMAL_MSG_TYPE_GET_STATS,
+-      MMAL_MSG_TYPE_PORT_PARAMETER_SET,
+-      MMAL_MSG_TYPE_PORT_PARAMETER_GET,       /* 15 */
+-      MMAL_MSG_TYPE_EVENT_TO_HOST,
+-      MMAL_MSG_TYPE_GET_CORE_STATS_FOR_PORT,
+-      MMAL_MSG_TYPE_OPAQUE_ALLOCATOR,
+-      MMAL_MSG_TYPE_CONSUME_MEM,
+-      MMAL_MSG_TYPE_LMK,                      /* 20 */
+-      MMAL_MSG_TYPE_OPAQUE_ALLOCATOR_DESC,
+-      MMAL_MSG_TYPE_DRM_GET_LHS32,
+-      MMAL_MSG_TYPE_DRM_GET_TIME,
+-      MMAL_MSG_TYPE_BUFFER_FROM_HOST_ZEROLEN,
+-      MMAL_MSG_TYPE_PORT_FLUSH,               /* 25 */
+-      MMAL_MSG_TYPE_HOST_LOG,
+-      MMAL_MSG_TYPE_MSG_LAST
+-};
+-
+-/* port action request messages differ depending on the action type */
+-enum mmal_msg_port_action_type {
+-      MMAL_MSG_PORT_ACTION_TYPE_UNKNOWN = 0,  /* Unknown action */
+-      MMAL_MSG_PORT_ACTION_TYPE_ENABLE,       /* Enable a port */
+-      MMAL_MSG_PORT_ACTION_TYPE_DISABLE,      /* Disable a port */
+-      MMAL_MSG_PORT_ACTION_TYPE_FLUSH,        /* Flush a port */
+-      MMAL_MSG_PORT_ACTION_TYPE_CONNECT,      /* Connect ports */
+-      MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT,   /* Disconnect ports */
+-      MMAL_MSG_PORT_ACTION_TYPE_SET_REQUIREMENTS, /* Set buffer requirements*/
+-};
+-
+-struct mmal_msg_header {
+-      u32 magic;
+-      u32 type;       /* enum mmal_msg_type */
+-
+-      /* Opaque handle to the control service */
+-      u32 control_service;
+-
+-      u32 context;    /* a u32 per message context */
+-      u32 status;     /* The status of the vchiq operation */
+-      u32 padding;
+-};
+-
+-/* Send from VC to host to report version */
+-struct mmal_msg_version {
+-      u32 flags;
+-      u32 major;
+-      u32 minor;
+-      u32 minimum;
+-};
+-
+-/* request to VC to create component */
+-struct mmal_msg_component_create {
+-      u32 client_component;   /* component context */
+-      char name[128];
+-      u32 pid;                /* For debug */
+-};
+-
+-/* reply from VC to component creation request */
+-struct mmal_msg_component_create_reply {
+-      u32 status;     /* enum mmal_msg_status - how does this differ to
+-                       * the one in the header?
+-                       */
+-      u32 component_handle; /* VideoCore handle for component */
+-      u32 input_num;        /* Number of input ports */
+-      u32 output_num;       /* Number of output ports */
+-      u32 clock_num;        /* Number of clock ports */
+-};
+-
+-/* request to VC to destroy a component */
+-struct mmal_msg_component_destroy {
+-      u32 component_handle;
+-};
+-
+-struct mmal_msg_component_destroy_reply {
+-      u32 status; /* The component destruction status */
+-};
+-
+-/* request and reply to VC to enable a component */
+-struct mmal_msg_component_enable {
+-      u32 component_handle;
+-};
+-
+-struct mmal_msg_component_enable_reply {
+-      u32 status; /* The component enable status */
+-};
+-
+-/* request and reply to VC to disable a component */
+-struct mmal_msg_component_disable {
+-      u32 component_handle;
+-};
+-
+-struct mmal_msg_component_disable_reply {
+-      u32 status; /* The component disable status */
+-};
+-
+-/* request to VC to get port information */
+-struct mmal_msg_port_info_get {
+-      u32 component_handle;  /* component handle port is associated with */
+-      u32 port_type;         /* enum mmal_msg_port_type */
+-      u32 index;             /* port index to query */
+-};
+-
+-/* reply from VC to get port info request */
+-struct mmal_msg_port_info_get_reply {
+-      u32 status;             /* enum mmal_msg_status */
+-      u32 component_handle;   /* component handle port is associated with */
+-      u32 port_type;          /* enum mmal_msg_port_type */
+-      u32 port_index;         /* port indexed in query */
+-      s32 found;              /* unused */
+-      u32 port_handle;        /* Handle to use for this port */
+-      struct mmal_port port;
+-      struct mmal_es_format format; /* elementary stream format */
+-      union mmal_es_specific_format es; /* es type specific data */
+-      u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE]; /* es extra data */
+-};
+-
+-/* request to VC to set port information */
+-struct mmal_msg_port_info_set {
+-      u32 component_handle;
+-      u32 port_type;          /* enum mmal_msg_port_type */
+-      u32 port_index;         /* port indexed in query */
+-      struct mmal_port port;
+-      struct mmal_es_format format;
+-      union mmal_es_specific_format es;
+-      u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE];
+-};
+-
+-/* reply from VC to port info set request */
+-struct mmal_msg_port_info_set_reply {
+-      u32 status;
+-      u32 component_handle;   /* component handle port is associated with */
+-      u32 port_type;          /* enum mmal_msg_port_type */
+-      u32 index;              /* port indexed in query */
+-      s32 found;              /* unused */
+-      u32 port_handle;        /* Handle to use for this port */
+-      struct mmal_port port;
+-      struct mmal_es_format format;
+-      union mmal_es_specific_format es;
+-      u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE];
+-};
+-
+-/* port action requests that take a mmal_port as a parameter */
+-struct mmal_msg_port_action_port {
+-      u32 component_handle;
+-      u32 port_handle;
+-      u32 action;             /* enum mmal_msg_port_action_type */
+-      struct mmal_port port;
+-};
+-
+-/* port action requests that take handles as a parameter */
+-struct mmal_msg_port_action_handle {
+-      u32 component_handle;
+-      u32 port_handle;
+-      u32 action;             /* enum mmal_msg_port_action_type */
+-      u32 connect_component_handle;
+-      u32 connect_port_handle;
+-};
+-
+-struct mmal_msg_port_action_reply {
+-      u32 status;     /* The port action operation status */
+-};
+-
+-/* MMAL buffer transfer */
+-
+-/* Size of space reserved in a buffer message for short messages. */
+-#define MMAL_VC_SHORT_DATA 128
+-
+-/* Signals that the current payload is the end of the stream of data */
+-#define MMAL_BUFFER_HEADER_FLAG_EOS                    BIT(0)
+-/* Signals that the start of the current payload starts a frame */
+-#define MMAL_BUFFER_HEADER_FLAG_FRAME_START            BIT(1)
+-/* Signals that the end of the current payload ends a frame */
+-#define MMAL_BUFFER_HEADER_FLAG_FRAME_END              BIT(2)
+-/* Signals that the current payload contains only complete frames (>1) */
+-#define MMAL_BUFFER_HEADER_FLAG_FRAME                  \
+-      (MMAL_BUFFER_HEADER_FLAG_FRAME_START | \
+-       MMAL_BUFFER_HEADER_FLAG_FRAME_END)
+-/* Signals that the current payload is a keyframe (i.e. self decodable) */
+-#define MMAL_BUFFER_HEADER_FLAG_KEYFRAME               BIT(3)
+-/*
+- * Signals a discontinuity in the stream of data (e.g. after a seek).
+- * Can be used for instance by a decoder to reset its state
+- */
+-#define MMAL_BUFFER_HEADER_FLAG_DISCONTINUITY          BIT(4)
+-/*
+- * Signals a buffer containing some kind of config data for the component
+- * (e.g. codec config data)
+- */
+-#define MMAL_BUFFER_HEADER_FLAG_CONFIG                 BIT(5)
+-/* Signals an encrypted payload */
+-#define MMAL_BUFFER_HEADER_FLAG_ENCRYPTED              BIT(6)
+-/* Signals a buffer containing side information */
+-#define MMAL_BUFFER_HEADER_FLAG_CODECSIDEINFO          BIT(7)
+-/*
+- * Signals a buffer which is the snapshot/postview image from a stills
+- * capture
+- */
+-#define MMAL_BUFFER_HEADER_FLAGS_SNAPSHOT              BIT(8)
+-/* Signals a buffer which contains data known to be corrupted */
+-#define MMAL_BUFFER_HEADER_FLAG_CORRUPTED              BIT(9)
+-/* Signals that a buffer failed to be transmitted */
+-#define MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED    BIT(10)
+-
+-struct mmal_driver_buffer {
+-      u32 magic;
+-      u32 component_handle;
+-      u32 port_handle;
+-      u32 client_context;
+-};
+-
+-/* buffer header */
+-struct mmal_buffer_header {
+-      u32 next;       /* next header */
+-      u32 priv;       /* framework private data */
+-      u32 cmd;
+-      u32 data;
+-      u32 alloc_size;
+-      u32 length;
+-      u32 offset;
+-      u32 flags;
+-      s64 pts;
+-      s64 dts;
+-      u32 type;
+-      u32 user_data;
+-};
+-
+-struct mmal_buffer_header_type_specific {
+-      union {
+-              struct {
+-              u32 planes;
+-              u32 offset[4];
+-              u32 pitch[4];
+-              u32 flags;
+-              } video;
+-      } u;
+-};
+-
+-struct mmal_msg_buffer_from_host {
+-      /*
+-       *The front 32 bytes of the buffer header are copied
+-       * back to us in the reply to allow for context. This
+-       * area is used to store two mmal_driver_buffer structures to
+-       * allow for multiple concurrent service users.
+-       */
+-      /* control data */
+-      struct mmal_driver_buffer drvbuf;
+-
+-      /* referenced control data for passthrough buffer management */
+-      struct mmal_driver_buffer drvbuf_ref;
+-      struct mmal_buffer_header buffer_header; /* buffer header itself */
+-      struct mmal_buffer_header_type_specific buffer_header_type_specific;
+-      s32 is_zero_copy;
+-      s32 has_reference;
+-
+-      /* allows short data to be xfered in control message */
+-      u32 payload_in_message;
+-      u8 short_data[MMAL_VC_SHORT_DATA];
+-};
+-
+-/* port parameter setting */
+-
+-#define MMAL_WORKER_PORT_PARAMETER_SPACE      96
+-
+-struct mmal_msg_port_parameter_set {
+-      u32 component_handle;   /* component */
+-      u32 port_handle;        /* port */
+-      u32 id;                 /* Parameter ID  */
+-      u32 size;               /* Parameter size */
+-      uint32_t value[MMAL_WORKER_PORT_PARAMETER_SPACE];
+-};
+-
+-struct mmal_msg_port_parameter_set_reply {
+-      u32 status;     /* enum mmal_msg_status todo: how does this
+-                       * differ to the one in the header?
+-                       */
+-};
+-
+-/* port parameter getting */
+-
+-struct mmal_msg_port_parameter_get {
+-      u32 component_handle;   /* component */
+-      u32 port_handle;        /* port */
+-      u32 id;                 /* Parameter ID  */
+-      u32 size;               /* Parameter size */
+-};
+-
+-struct mmal_msg_port_parameter_get_reply {
+-      u32 status;             /* Status of mmal_port_parameter_get call */
+-      u32 id;                 /* Parameter ID  */
+-      u32 size;               /* Parameter size */
+-      uint32_t value[MMAL_WORKER_PORT_PARAMETER_SPACE];
+-};
+-
+-/* event messages */
+-#define MMAL_WORKER_EVENT_SPACE 256
+-
+-struct mmal_msg_event_to_host {
+-      u32 client_component;   /* component context */
+-
+-      u32 port_type;
+-      u32 port_num;
+-
+-      u32 cmd;
+-      u32 length;
+-      u8 data[MMAL_WORKER_EVENT_SPACE];
+-      u32 delayed_buffer;
+-};
+-
+-/* all mmal messages are serialised through this structure */
+-struct mmal_msg {
+-      /* header */
+-      struct mmal_msg_header h;
+-      /* payload */
+-      union {
+-              struct mmal_msg_version version;
+-
+-              struct mmal_msg_component_create component_create;
+-              struct mmal_msg_component_create_reply component_create_reply;
+-
+-              struct mmal_msg_component_destroy component_destroy;
+-              struct mmal_msg_component_destroy_reply component_destroy_reply;
+-
+-              struct mmal_msg_component_enable component_enable;
+-              struct mmal_msg_component_enable_reply component_enable_reply;
+-
+-              struct mmal_msg_component_disable component_disable;
+-              struct mmal_msg_component_disable_reply component_disable_reply;
+-
+-              struct mmal_msg_port_info_get port_info_get;
+-              struct mmal_msg_port_info_get_reply port_info_get_reply;
+-
+-              struct mmal_msg_port_info_set port_info_set;
+-              struct mmal_msg_port_info_set_reply port_info_set_reply;
+-
+-              struct mmal_msg_port_action_port port_action_port;
+-              struct mmal_msg_port_action_handle port_action_handle;
+-              struct mmal_msg_port_action_reply port_action_reply;
+-
+-              struct mmal_msg_buffer_from_host buffer_from_host;
+-
+-              struct mmal_msg_port_parameter_set port_parameter_set;
+-              struct mmal_msg_port_parameter_set_reply
+-                      port_parameter_set_reply;
+-              struct mmal_msg_port_parameter_get
+-                      port_parameter_get;
+-              struct mmal_msg_port_parameter_get_reply
+-                      port_parameter_get_reply;
+-
+-              struct mmal_msg_event_to_host event_to_host;
+-
+-              u8 payload[MMAL_MSG_MAX_PAYLOAD];
+-      } u;
+-};
+-#endif
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-parameters.h
++++ /dev/null
+@@ -1,755 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Broadcom BM2835 V4L2 driver
+- *
+- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+- *
+- * Authors: Vincent Sanders @ Collabora
+- *          Dave Stevenson @ Broadcom
+- *            (now dave.stevenson@raspberrypi.org)
+- *          Simon Mellor @ Broadcom
+- *          Luke Diamand @ Broadcom
+- */
+-
+-/* common parameters */
+-
+-/** @name Parameter groups
+- * Parameters are divided into groups, and then allocated sequentially within
+- * a group using an enum.
+- * @{
+- */
+-
+-#ifndef MMAL_PARAMETERS_H
+-#define MMAL_PARAMETERS_H
+-
+-/** Common parameter ID group, used with many types of component. */
+-#define MMAL_PARAMETER_GROUP_COMMON           (0 << 16)
+-/** Camera-specific parameter ID group. */
+-#define MMAL_PARAMETER_GROUP_CAMERA           (1 << 16)
+-/** Video-specific parameter ID group. */
+-#define MMAL_PARAMETER_GROUP_VIDEO            (2 << 16)
+-/** Audio-specific parameter ID group. */
+-#define MMAL_PARAMETER_GROUP_AUDIO            (3 << 16)
+-/** Clock-specific parameter ID group. */
+-#define MMAL_PARAMETER_GROUP_CLOCK            (4 << 16)
+-/** Miracast-specific parameter ID group. */
+-#define MMAL_PARAMETER_GROUP_MIRACAST         (5 << 16)
+-
+-/* Common parameters */
+-enum mmal_parameter_common_type {
+-      /**< Never a valid parameter ID */
+-      MMAL_PARAMETER_UNUSED = MMAL_PARAMETER_GROUP_COMMON,
+-
+-              /**< MMAL_PARAMETER_ENCODING_T */
+-      MMAL_PARAMETER_SUPPORTED_ENCODINGS,
+-              /**< MMAL_PARAMETER_URI_T */
+-      MMAL_PARAMETER_URI,
+-              /** MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T */
+-      MMAL_PARAMETER_CHANGE_EVENT_REQUEST,
+-              /** MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_ZERO_COPY,
+-              /**< MMAL_PARAMETER_BUFFER_REQUIREMENTS_T */
+-      MMAL_PARAMETER_BUFFER_REQUIREMENTS,
+-              /**< MMAL_PARAMETER_STATISTICS_T */
+-      MMAL_PARAMETER_STATISTICS,
+-              /**< MMAL_PARAMETER_CORE_STATISTICS_T */
+-      MMAL_PARAMETER_CORE_STATISTICS,
+-              /**< MMAL_PARAMETER_MEM_USAGE_T */
+-      MMAL_PARAMETER_MEM_USAGE,
+-              /**< MMAL_PARAMETER_UINT32_T */
+-      MMAL_PARAMETER_BUFFER_FLAG_FILTER,
+-              /**< MMAL_PARAMETER_SEEK_T */
+-      MMAL_PARAMETER_SEEK,
+-              /**< MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_POWERMON_ENABLE,
+-              /**< MMAL_PARAMETER_LOGGING_T */
+-      MMAL_PARAMETER_LOGGING,
+-              /**< MMAL_PARAMETER_UINT64_T */
+-      MMAL_PARAMETER_SYSTEM_TIME,
+-              /**< MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_NO_IMAGE_PADDING,
+-};
+-
+-/* camera parameters */
+-
+-enum mmal_parameter_camera_type {
+-      /* 0 */
+-              /** @ref MMAL_PARAMETER_THUMBNAIL_CONFIG_T */
+-      MMAL_PARAMETER_THUMBNAIL_CONFIGURATION =
+-              MMAL_PARAMETER_GROUP_CAMERA,
+-              /**< Unused? */
+-      MMAL_PARAMETER_CAPTURE_QUALITY,
+-              /**< @ref MMAL_PARAMETER_INT32_T */
+-      MMAL_PARAMETER_ROTATION,
+-              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_EXIF_DISABLE,
+-              /**< @ref MMAL_PARAMETER_EXIF_T */
+-      MMAL_PARAMETER_EXIF,
+-              /**< @ref MMAL_PARAM_AWBMODE_T */
+-      MMAL_PARAMETER_AWB_MODE,
+-              /**< @ref MMAL_PARAMETER_IMAGEFX_T */
+-      MMAL_PARAMETER_IMAGE_EFFECT,
+-              /**< @ref MMAL_PARAMETER_COLOURFX_T */
+-      MMAL_PARAMETER_COLOUR_EFFECT,
+-              /**< @ref MMAL_PARAMETER_FLICKERAVOID_T */
+-      MMAL_PARAMETER_FLICKER_AVOID,
+-              /**< @ref MMAL_PARAMETER_FLASH_T */
+-      MMAL_PARAMETER_FLASH,
+-              /**< @ref MMAL_PARAMETER_REDEYE_T */
+-      MMAL_PARAMETER_REDEYE,
+-              /**< @ref MMAL_PARAMETER_FOCUS_T */
+-      MMAL_PARAMETER_FOCUS,
+-              /**< Unused? */
+-      MMAL_PARAMETER_FOCAL_LENGTHS,
+-              /**< @ref MMAL_PARAMETER_INT32_T */
+-      MMAL_PARAMETER_EXPOSURE_COMP,
+-              /**< @ref MMAL_PARAMETER_SCALEFACTOR_T */
+-      MMAL_PARAMETER_ZOOM,
+-              /**< @ref MMAL_PARAMETER_MIRROR_T */
+-      MMAL_PARAMETER_MIRROR,
+-
+-      /* 0x10 */
+-              /**< @ref MMAL_PARAMETER_UINT32_T */
+-      MMAL_PARAMETER_CAMERA_NUM,
+-              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_CAPTURE,
+-              /**< @ref MMAL_PARAMETER_EXPOSUREMODE_T */
+-      MMAL_PARAMETER_EXPOSURE_MODE,
+-              /**< @ref MMAL_PARAMETER_EXPOSUREMETERINGMODE_T */
+-      MMAL_PARAMETER_EXP_METERING_MODE,
+-              /**< @ref MMAL_PARAMETER_FOCUS_STATUS_T */
+-      MMAL_PARAMETER_FOCUS_STATUS,
+-              /**< @ref MMAL_PARAMETER_CAMERA_CONFIG_T */
+-      MMAL_PARAMETER_CAMERA_CONFIG,
+-              /**< @ref MMAL_PARAMETER_CAPTURE_STATUS_T */
+-      MMAL_PARAMETER_CAPTURE_STATUS,
+-              /**< @ref MMAL_PARAMETER_FACE_TRACK_T */
+-      MMAL_PARAMETER_FACE_TRACK,
+-              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_DRAW_BOX_FACES_AND_FOCUS,
+-              /**< @ref MMAL_PARAMETER_UINT32_T */
+-      MMAL_PARAMETER_JPEG_Q_FACTOR,
+-              /**< @ref MMAL_PARAMETER_FRAME_RATE_T */
+-      MMAL_PARAMETER_FRAME_RATE,
+-              /**< @ref MMAL_PARAMETER_CAMERA_STC_MODE_T */
+-      MMAL_PARAMETER_USE_STC,
+-              /**< @ref MMAL_PARAMETER_CAMERA_INFO_T */
+-      MMAL_PARAMETER_CAMERA_INFO,
+-              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_VIDEO_STABILISATION,
+-              /**< @ref MMAL_PARAMETER_FACE_TRACK_RESULTS_T */
+-      MMAL_PARAMETER_FACE_TRACK_RESULTS,
+-              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_ENABLE_RAW_CAPTURE,
+-
+-      /* 0x20 */
+-              /**< @ref MMAL_PARAMETER_URI_T */
+-      MMAL_PARAMETER_DPF_FILE,
+-              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_ENABLE_DPF_FILE,
+-              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_DPF_FAIL_IS_FATAL,
+-              /**< @ref MMAL_PARAMETER_CAPTUREMODE_T */
+-      MMAL_PARAMETER_CAPTURE_MODE,
+-              /**< @ref MMAL_PARAMETER_FOCUS_REGIONS_T */
+-      MMAL_PARAMETER_FOCUS_REGIONS,
+-              /**< @ref MMAL_PARAMETER_INPUT_CROP_T */
+-      MMAL_PARAMETER_INPUT_CROP,
+-              /**< @ref MMAL_PARAMETER_SENSOR_INFORMATION_T */
+-      MMAL_PARAMETER_SENSOR_INFORMATION,
+-              /**< @ref MMAL_PARAMETER_FLASH_SELECT_T */
+-      MMAL_PARAMETER_FLASH_SELECT,
+-              /**< @ref MMAL_PARAMETER_FIELD_OF_VIEW_T */
+-      MMAL_PARAMETER_FIELD_OF_VIEW,
+-              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_HIGH_DYNAMIC_RANGE,
+-              /**< @ref MMAL_PARAMETER_DRC_T */
+-      MMAL_PARAMETER_DYNAMIC_RANGE_COMPRESSION,
+-              /**< @ref MMAL_PARAMETER_ALGORITHM_CONTROL_T */
+-      MMAL_PARAMETER_ALGORITHM_CONTROL,
+-              /**< @ref MMAL_PARAMETER_RATIONAL_T */
+-      MMAL_PARAMETER_SHARPNESS,
+-              /**< @ref MMAL_PARAMETER_RATIONAL_T */
+-      MMAL_PARAMETER_CONTRAST,
+-              /**< @ref MMAL_PARAMETER_RATIONAL_T */
+-      MMAL_PARAMETER_BRIGHTNESS,
+-              /**< @ref MMAL_PARAMETER_RATIONAL_T */
+-      MMAL_PARAMETER_SATURATION,
+-
+-      /* 0x30 */
+-              /**< @ref MMAL_PARAMETER_UINT32_T */
+-      MMAL_PARAMETER_ISO,
+-              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_ANTISHAKE,
+-              /** @ref MMAL_PARAMETER_IMAGEFX_PARAMETERS_T */
+-      MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS,
+-              /** @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_CAMERA_BURST_CAPTURE,
+-              /** @ref MMAL_PARAMETER_UINT32_T */
+-      MMAL_PARAMETER_CAMERA_MIN_ISO,
+-              /** @ref MMAL_PARAMETER_CAMERA_USE_CASE_T */
+-      MMAL_PARAMETER_CAMERA_USE_CASE,
+-              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_CAPTURE_STATS_PASS,
+-              /** @ref MMAL_PARAMETER_UINT32_T */
+-      MMAL_PARAMETER_CAMERA_CUSTOM_SENSOR_CONFIG,
+-              /** @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_ENABLE_REGISTER_FILE,
+-              /** @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_REGISTER_FAIL_IS_FATAL,
+-              /** @ref MMAL_PARAMETER_CONFIGFILE_T */
+-      MMAL_PARAMETER_CONFIGFILE_REGISTERS,
+-              /** @ref MMAL_PARAMETER_CONFIGFILE_CHUNK_T */
+-      MMAL_PARAMETER_CONFIGFILE_CHUNK_REGISTERS,
+-              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_JPEG_ATTACH_LOG,
+-              /**< @ref MMAL_PARAMETER_ZEROSHUTTERLAG_T */
+-      MMAL_PARAMETER_ZERO_SHUTTER_LAG,
+-              /**< @ref MMAL_PARAMETER_FPS_RANGE_T */
+-      MMAL_PARAMETER_FPS_RANGE,
+-              /**< @ref MMAL_PARAMETER_INT32_T */
+-      MMAL_PARAMETER_CAPTURE_EXPOSURE_COMP,
+-
+-      /* 0x40 */
+-              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_SW_SHARPEN_DISABLE,
+-              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_FLASH_REQUIRED,
+-              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_SW_SATURATION_DISABLE,
+-      /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
+-      MMAL_PARAMETER_SHUTTER_SPEED,
+-              /**< Takes a @ref MMAL_PARAMETER_AWB_GAINS_T */
+-      MMAL_PARAMETER_CUSTOM_AWB_GAINS,
+-};
+-
+-struct mmal_parameter_rational {
+-      s32 num;    /**< Numerator */
+-      s32 den;    /**< Denominator */
+-};
+-
+-enum mmal_parameter_camera_config_timestamp_mode {
+-      MMAL_PARAM_TIMESTAMP_MODE_ZERO = 0, /* Always timestamp frames as 0 */
+-      MMAL_PARAM_TIMESTAMP_MODE_RAW_STC,  /* Use the raw STC value
+-                                           * for the frame timestamp
+-                                           */
+-      MMAL_PARAM_TIMESTAMP_MODE_RESET_STC, /* Use the STC timestamp
+-                                            * but subtract the
+-                                            * timestamp of the first
+-                                            * frame sent to give a
+-                                            * zero based timestamp.
+-                                            */
+-};
+-
+-struct mmal_parameter_fps_range {
+-      /**< Low end of the permitted framerate range */
+-      struct mmal_parameter_rational  fps_low;
+-      /**< High end of the permitted framerate range */
+-      struct mmal_parameter_rational  fps_high;
+-};
+-
+-/* camera configuration parameter */
+-struct mmal_parameter_camera_config {
+-      /* Parameters for setting up the image pools */
+-      u32 max_stills_w; /* Max size of stills capture */
+-      u32 max_stills_h;
+-      u32 stills_yuv422; /* Allow YUV422 stills capture */
+-      u32 one_shot_stills; /* Continuous or one shot stills captures. */
+-
+-      u32 max_preview_video_w; /* Max size of the preview or video
+-                                * capture frames
+-                                */
+-      u32 max_preview_video_h;
+-      u32 num_preview_video_frames;
+-
+-      /** Sets the height of the circular buffer for stills capture. */
+-      u32 stills_capture_circular_buffer_height;
+-
+-      /** Allows preview/encode to resume as fast as possible after the stills
+-       * input frame has been received, and then processes the still frame in
+-       * the background whilst preview/encode has resumed.
+-       * Actual mode is controlled by MMAL_PARAMETER_CAPTURE_MODE.
+-       */
+-      u32 fast_preview_resume;
+-
+-      /** Selects algorithm for timestamping frames if
+-       * there is no clock component connected.
+-       * enum mmal_parameter_camera_config_timestamp_mode
+-       */
+-      s32 use_stc_timestamp;
+-};
+-
+-enum mmal_parameter_exposuremode {
+-      MMAL_PARAM_EXPOSUREMODE_OFF,
+-      MMAL_PARAM_EXPOSUREMODE_AUTO,
+-      MMAL_PARAM_EXPOSUREMODE_NIGHT,
+-      MMAL_PARAM_EXPOSUREMODE_NIGHTPREVIEW,
+-      MMAL_PARAM_EXPOSUREMODE_BACKLIGHT,
+-      MMAL_PARAM_EXPOSUREMODE_SPOTLIGHT,
+-      MMAL_PARAM_EXPOSUREMODE_SPORTS,
+-      MMAL_PARAM_EXPOSUREMODE_SNOW,
+-      MMAL_PARAM_EXPOSUREMODE_BEACH,
+-      MMAL_PARAM_EXPOSUREMODE_VERYLONG,
+-      MMAL_PARAM_EXPOSUREMODE_FIXEDFPS,
+-      MMAL_PARAM_EXPOSUREMODE_ANTISHAKE,
+-      MMAL_PARAM_EXPOSUREMODE_FIREWORKS,
+-};
+-
+-enum mmal_parameter_exposuremeteringmode {
+-      MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE,
+-      MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT,
+-      MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT,
+-      MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX,
+-};
+-
+-enum mmal_parameter_awbmode {
+-      MMAL_PARAM_AWBMODE_OFF,
+-      MMAL_PARAM_AWBMODE_AUTO,
+-      MMAL_PARAM_AWBMODE_SUNLIGHT,
+-      MMAL_PARAM_AWBMODE_CLOUDY,
+-      MMAL_PARAM_AWBMODE_SHADE,
+-      MMAL_PARAM_AWBMODE_TUNGSTEN,
+-      MMAL_PARAM_AWBMODE_FLUORESCENT,
+-      MMAL_PARAM_AWBMODE_INCANDESCENT,
+-      MMAL_PARAM_AWBMODE_FLASH,
+-      MMAL_PARAM_AWBMODE_HORIZON,
+-};
+-
+-enum mmal_parameter_imagefx {
+-      MMAL_PARAM_IMAGEFX_NONE,
+-      MMAL_PARAM_IMAGEFX_NEGATIVE,
+-      MMAL_PARAM_IMAGEFX_SOLARIZE,
+-      MMAL_PARAM_IMAGEFX_POSTERIZE,
+-      MMAL_PARAM_IMAGEFX_WHITEBOARD,
+-      MMAL_PARAM_IMAGEFX_BLACKBOARD,
+-      MMAL_PARAM_IMAGEFX_SKETCH,
+-      MMAL_PARAM_IMAGEFX_DENOISE,
+-      MMAL_PARAM_IMAGEFX_EMBOSS,
+-      MMAL_PARAM_IMAGEFX_OILPAINT,
+-      MMAL_PARAM_IMAGEFX_HATCH,
+-      MMAL_PARAM_IMAGEFX_GPEN,
+-      MMAL_PARAM_IMAGEFX_PASTEL,
+-      MMAL_PARAM_IMAGEFX_WATERCOLOUR,
+-      MMAL_PARAM_IMAGEFX_FILM,
+-      MMAL_PARAM_IMAGEFX_BLUR,
+-      MMAL_PARAM_IMAGEFX_SATURATION,
+-      MMAL_PARAM_IMAGEFX_COLOURSWAP,
+-      MMAL_PARAM_IMAGEFX_WASHEDOUT,
+-      MMAL_PARAM_IMAGEFX_POSTERISE,
+-      MMAL_PARAM_IMAGEFX_COLOURPOINT,
+-      MMAL_PARAM_IMAGEFX_COLOURBALANCE,
+-      MMAL_PARAM_IMAGEFX_CARTOON,
+-};
+-
+-enum MMAL_PARAM_FLICKERAVOID_T {
+-      MMAL_PARAM_FLICKERAVOID_OFF,
+-      MMAL_PARAM_FLICKERAVOID_AUTO,
+-      MMAL_PARAM_FLICKERAVOID_50HZ,
+-      MMAL_PARAM_FLICKERAVOID_60HZ,
+-      MMAL_PARAM_FLICKERAVOID_MAX = 0x7FFFFFFF
+-};
+-
+-struct mmal_parameter_awbgains {
+-      struct mmal_parameter_rational r_gain;  /**< Red gain */
+-      struct mmal_parameter_rational b_gain;  /**< Blue gain */
+-};
+-
+-/** Manner of video rate control */
+-enum mmal_parameter_rate_control_mode {
+-      MMAL_VIDEO_RATECONTROL_DEFAULT,
+-      MMAL_VIDEO_RATECONTROL_VARIABLE,
+-      MMAL_VIDEO_RATECONTROL_CONSTANT,
+-      MMAL_VIDEO_RATECONTROL_VARIABLE_SKIP_FRAMES,
+-      MMAL_VIDEO_RATECONTROL_CONSTANT_SKIP_FRAMES
+-};
+-
+-enum mmal_video_profile {
+-      MMAL_VIDEO_PROFILE_H263_BASELINE,
+-      MMAL_VIDEO_PROFILE_H263_H320CODING,
+-      MMAL_VIDEO_PROFILE_H263_BACKWARDCOMPATIBLE,
+-      MMAL_VIDEO_PROFILE_H263_ISWV2,
+-      MMAL_VIDEO_PROFILE_H263_ISWV3,
+-      MMAL_VIDEO_PROFILE_H263_HIGHCOMPRESSION,
+-      MMAL_VIDEO_PROFILE_H263_INTERNET,
+-      MMAL_VIDEO_PROFILE_H263_INTERLACE,
+-      MMAL_VIDEO_PROFILE_H263_HIGHLATENCY,
+-      MMAL_VIDEO_PROFILE_MP4V_SIMPLE,
+-      MMAL_VIDEO_PROFILE_MP4V_SIMPLESCALABLE,
+-      MMAL_VIDEO_PROFILE_MP4V_CORE,
+-      MMAL_VIDEO_PROFILE_MP4V_MAIN,
+-      MMAL_VIDEO_PROFILE_MP4V_NBIT,
+-      MMAL_VIDEO_PROFILE_MP4V_SCALABLETEXTURE,
+-      MMAL_VIDEO_PROFILE_MP4V_SIMPLEFACE,
+-      MMAL_VIDEO_PROFILE_MP4V_SIMPLEFBA,
+-      MMAL_VIDEO_PROFILE_MP4V_BASICANIMATED,
+-      MMAL_VIDEO_PROFILE_MP4V_HYBRID,
+-      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDREALTIME,
+-      MMAL_VIDEO_PROFILE_MP4V_CORESCALABLE,
+-      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDCODING,
+-      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDCORE,
+-      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDSCALABLE,
+-      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDSIMPLE,
+-      MMAL_VIDEO_PROFILE_H264_BASELINE,
+-      MMAL_VIDEO_PROFILE_H264_MAIN,
+-      MMAL_VIDEO_PROFILE_H264_EXTENDED,
+-      MMAL_VIDEO_PROFILE_H264_HIGH,
+-      MMAL_VIDEO_PROFILE_H264_HIGH10,
+-      MMAL_VIDEO_PROFILE_H264_HIGH422,
+-      MMAL_VIDEO_PROFILE_H264_HIGH444,
+-      MMAL_VIDEO_PROFILE_H264_CONSTRAINED_BASELINE,
+-      MMAL_VIDEO_PROFILE_DUMMY = 0x7FFFFFFF
+-};
+-
+-enum mmal_video_level {
+-      MMAL_VIDEO_LEVEL_H263_10,
+-      MMAL_VIDEO_LEVEL_H263_20,
+-      MMAL_VIDEO_LEVEL_H263_30,
+-      MMAL_VIDEO_LEVEL_H263_40,
+-      MMAL_VIDEO_LEVEL_H263_45,
+-      MMAL_VIDEO_LEVEL_H263_50,
+-      MMAL_VIDEO_LEVEL_H263_60,
+-      MMAL_VIDEO_LEVEL_H263_70,
+-      MMAL_VIDEO_LEVEL_MP4V_0,
+-      MMAL_VIDEO_LEVEL_MP4V_0b,
+-      MMAL_VIDEO_LEVEL_MP4V_1,
+-      MMAL_VIDEO_LEVEL_MP4V_2,
+-      MMAL_VIDEO_LEVEL_MP4V_3,
+-      MMAL_VIDEO_LEVEL_MP4V_4,
+-      MMAL_VIDEO_LEVEL_MP4V_4a,
+-      MMAL_VIDEO_LEVEL_MP4V_5,
+-      MMAL_VIDEO_LEVEL_MP4V_6,
+-      MMAL_VIDEO_LEVEL_H264_1,
+-      MMAL_VIDEO_LEVEL_H264_1b,
+-      MMAL_VIDEO_LEVEL_H264_11,
+-      MMAL_VIDEO_LEVEL_H264_12,
+-      MMAL_VIDEO_LEVEL_H264_13,
+-      MMAL_VIDEO_LEVEL_H264_2,
+-      MMAL_VIDEO_LEVEL_H264_21,
+-      MMAL_VIDEO_LEVEL_H264_22,
+-      MMAL_VIDEO_LEVEL_H264_3,
+-      MMAL_VIDEO_LEVEL_H264_31,
+-      MMAL_VIDEO_LEVEL_H264_32,
+-      MMAL_VIDEO_LEVEL_H264_4,
+-      MMAL_VIDEO_LEVEL_H264_41,
+-      MMAL_VIDEO_LEVEL_H264_42,
+-      MMAL_VIDEO_LEVEL_H264_5,
+-      MMAL_VIDEO_LEVEL_H264_51,
+-      MMAL_VIDEO_LEVEL_DUMMY = 0x7FFFFFFF
+-};
+-
+-struct mmal_parameter_video_profile {
+-      enum mmal_video_profile profile;
+-      enum mmal_video_level level;
+-};
+-
+-/* video parameters */
+-
+-enum mmal_parameter_video_type {
+-      /** @ref MMAL_DISPLAYREGION_T */
+-      MMAL_PARAMETER_DISPLAYREGION = MMAL_PARAMETER_GROUP_VIDEO,
+-
+-      /** @ref MMAL_PARAMETER_VIDEO_PROFILE_T */
+-      MMAL_PARAMETER_SUPPORTED_PROFILES,
+-
+-      /** @ref MMAL_PARAMETER_VIDEO_PROFILE_T */
+-      MMAL_PARAMETER_PROFILE,
+-
+-      /** @ref MMAL_PARAMETER_UINT32_T */
+-      MMAL_PARAMETER_INTRAPERIOD,
+-
+-      /** @ref MMAL_PARAMETER_VIDEO_RATECONTROL_T */
+-      MMAL_PARAMETER_RATECONTROL,
+-
+-      /** @ref MMAL_PARAMETER_VIDEO_NALUNITFORMAT_T */
+-      MMAL_PARAMETER_NALUNITFORMAT,
+-
+-      /** @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_MINIMISE_FRAGMENTATION,
+-
+-      /** @ref MMAL_PARAMETER_UINT32_T.
+-       * Setting the value to zero resets to the default (one slice per
+-       * frame).
+-       */
+-      MMAL_PARAMETER_MB_ROWS_PER_SLICE,
+-
+-      /** @ref MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION_T */
+-      MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION,
+-
+-      /** @ref MMAL_PARAMETER_VIDEO_EEDE_ENABLE_T */
+-      MMAL_PARAMETER_VIDEO_EEDE_ENABLE,
+-
+-      /** @ref MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE_T */
+-      MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE,
+-
+-      /** @ref MMAL_PARAMETER_BOOLEAN_T. Request an I-frame. */
+-      MMAL_PARAMETER_VIDEO_REQUEST_I_FRAME,
+-      /** @ref MMAL_PARAMETER_VIDEO_INTRA_REFRESH_T */
+-      MMAL_PARAMETER_VIDEO_INTRA_REFRESH,
+-
+-      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
+-      MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT,
+-
+-      /** @ref MMAL_PARAMETER_UINT32_T. Run-time bit rate control */
+-      MMAL_PARAMETER_VIDEO_BIT_RATE,
+-
+-      /** @ref MMAL_PARAMETER_FRAME_RATE_T */
+-      MMAL_PARAMETER_VIDEO_FRAME_RATE,
+-
+-      /** @ref MMAL_PARAMETER_UINT32_T. */
+-      MMAL_PARAMETER_VIDEO_ENCODE_MIN_QUANT,
+-
+-      /** @ref MMAL_PARAMETER_UINT32_T. */
+-      MMAL_PARAMETER_VIDEO_ENCODE_MAX_QUANT,
+-
+-      /** @ref MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL_T. */
+-      MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL,
+-
+-      MMAL_PARAMETER_EXTRA_BUFFERS, /**< @ref MMAL_PARAMETER_UINT32_T. */
+-      /** @ref MMAL_PARAMETER_UINT32_T.
+-       * Changing this parameter from the default can reduce frame rate
+-       * because image buffers need to be re-pitched.
+-       */
+-      MMAL_PARAMETER_VIDEO_ALIGN_HORIZ,
+-
+-      /** @ref MMAL_PARAMETER_UINT32_T.
+-       * Changing this parameter from the default can reduce frame rate
+-       * because image buffers need to be re-pitched.
+-       */
+-      MMAL_PARAMETER_VIDEO_ALIGN_VERT,
+-
+-      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
+-      MMAL_PARAMETER_VIDEO_DROPPABLE_PFRAMES,
+-
+-      /** @ref MMAL_PARAMETER_UINT32_T. */
+-      MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT,
+-
+-      /**< @ref MMAL_PARAMETER_UINT32_T. */
+-      MMAL_PARAMETER_VIDEO_ENCODE_QP_P,
+-
+-      /**< @ref MMAL_PARAMETER_UINT32_T. */
+-      MMAL_PARAMETER_VIDEO_ENCODE_RC_SLICE_DQUANT,
+-
+-      /** @ref MMAL_PARAMETER_UINT32_T */
+-      MMAL_PARAMETER_VIDEO_ENCODE_FRAME_LIMIT_BITS,
+-
+-      /** @ref MMAL_PARAMETER_UINT32_T. */
+-      MMAL_PARAMETER_VIDEO_ENCODE_PEAK_RATE,
+-
+-      /* H264 specific parameters */
+-
+-      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
+-      MMAL_PARAMETER_VIDEO_ENCODE_H264_DISABLE_CABAC,
+-
+-      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
+-      MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_LATENCY,
+-
+-      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
+-      MMAL_PARAMETER_VIDEO_ENCODE_H264_AU_DELIMITERS,
+-
+-      /** @ref MMAL_PARAMETER_UINT32_T. */
+-      MMAL_PARAMETER_VIDEO_ENCODE_H264_DEBLOCK_IDC,
+-
+-      /** @ref MMAL_PARAMETER_VIDEO_ENCODER_H264_MB_INTRA_MODES_T. */
+-      MMAL_PARAMETER_VIDEO_ENCODE_H264_MB_INTRA_MODE,
+-
+-      /** @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_VIDEO_ENCODE_HEADER_ON_OPEN,
+-
+-      /** @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_VIDEO_ENCODE_PRECODE_FOR_QP,
+-
+-      /** @ref MMAL_PARAMETER_VIDEO_DRM_INIT_INFO_T. */
+-      MMAL_PARAMETER_VIDEO_DRM_INIT_INFO,
+-
+-      /** @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_VIDEO_TIMESTAMP_FIFO,
+-
+-      /** @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_VIDEO_DECODE_ERROR_CONCEALMENT,
+-
+-      /** @ref MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER_T. */
+-      MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER,
+-
+-      /** @ref MMAL_PARAMETER_BYTES_T */
+-      MMAL_PARAMETER_VIDEO_DECODE_CONFIG_VD3,
+-
+-      /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_VIDEO_ENCODE_H264_VCL_HRD_PARAMETERS,
+-
+-      /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_DELAY_HRD_FLAG,
+-
+-      /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+-      MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER
+-};
+-
+-/** Valid mirror modes */
+-enum mmal_parameter_mirror {
+-      MMAL_PARAM_MIRROR_NONE,
+-      MMAL_PARAM_MIRROR_VERTICAL,
+-      MMAL_PARAM_MIRROR_HORIZONTAL,
+-      MMAL_PARAM_MIRROR_BOTH,
+-};
+-
+-enum mmal_parameter_displaytransform {
+-      MMAL_DISPLAY_ROT0 = 0,
+-      MMAL_DISPLAY_MIRROR_ROT0 = 1,
+-      MMAL_DISPLAY_MIRROR_ROT180 = 2,
+-      MMAL_DISPLAY_ROT180 = 3,
+-      MMAL_DISPLAY_MIRROR_ROT90 = 4,
+-      MMAL_DISPLAY_ROT270 = 5,
+-      MMAL_DISPLAY_ROT90 = 6,
+-      MMAL_DISPLAY_MIRROR_ROT270 = 7,
+-};
+-
+-enum mmal_parameter_displaymode {
+-      MMAL_DISPLAY_MODE_FILL = 0,
+-      MMAL_DISPLAY_MODE_LETTERBOX = 1,
+-};
+-
+-enum mmal_parameter_displayset {
+-      MMAL_DISPLAY_SET_NONE = 0,
+-      MMAL_DISPLAY_SET_NUM = 1,
+-      MMAL_DISPLAY_SET_FULLSCREEN = 2,
+-      MMAL_DISPLAY_SET_TRANSFORM = 4,
+-      MMAL_DISPLAY_SET_DEST_RECT = 8,
+-      MMAL_DISPLAY_SET_SRC_RECT = 0x10,
+-      MMAL_DISPLAY_SET_MODE = 0x20,
+-      MMAL_DISPLAY_SET_PIXEL = 0x40,
+-      MMAL_DISPLAY_SET_NOASPECT = 0x80,
+-      MMAL_DISPLAY_SET_LAYER = 0x100,
+-      MMAL_DISPLAY_SET_COPYPROTECT = 0x200,
+-      MMAL_DISPLAY_SET_ALPHA = 0x400,
+-};
+-
+-/* rectangle, used lots so it gets its own struct */
+-struct vchiq_mmal_rect {
+-      s32 x;
+-      s32 y;
+-      s32 width;
+-      s32 height;
+-};
+-
+-struct mmal_parameter_displayregion {
+-      /** Bitfield that indicates which fields are set and should be
+-       * used. All other fields will maintain their current value.
+-       * \ref MMAL_DISPLAYSET_T defines the bits that can be
+-       * combined.
+-       */
+-      u32 set;
+-
+-      /** Describes the display output device, with 0 typically
+-       * being a directly connected LCD display.  The actual values
+-       * will depend on the hardware.  Code using hard-wired numbers
+-       * (e.g. 2) is certain to fail.
+-       */
+-
+-      u32 display_num;
+-      /** Indicates that we are using the full device screen area,
+-       * rather than a window of the display.  If zero, then
+-       * dest_rect is used to specify a region of the display to
+-       * use.
+-       */
+-
+-      s32 fullscreen;
+-      /** Indicates any rotation or flipping used to map frames onto
+-       * the natural display orientation.
+-       */
+-      u32 transform; /* enum mmal_parameter_displaytransform */
+-
+-      /** Where to display the frame within the screen, if
+-       * fullscreen is zero.
+-       */
+-      struct vchiq_mmal_rect dest_rect;
+-
+-      /** Indicates which area of the frame to display. If all
+-       * values are zero, the whole frame will be used.
+-       */
+-      struct vchiq_mmal_rect src_rect;
+-
+-      /** If set to non-zero, indicates that any display scaling
+-       * should disregard the aspect ratio of the frame region being
+-       * displayed.
+-       */
+-      s32 noaspect;
+-
+-      /** Indicates how the image should be scaled to fit the
+-       * display. \code MMAL_DISPLAY_MODE_FILL \endcode indicates
+-       * that the image should fill the screen by potentially
+-       * cropping the frames.  Setting \code mode \endcode to \code
+-       * MMAL_DISPLAY_MODE_LETTERBOX \endcode indicates that all the
+-       * source region should be displayed and black bars added if
+-       * necessary.
+-       */
+-      u32 mode; /* enum mmal_parameter_displaymode */
+-
+-      /** If non-zero, defines the width of a source pixel relative
+-       * to \code pixel_y \endcode.  If zero, then pixels default to
+-       * being square.
+-       */
+-      u32 pixel_x;
+-
+-      /** If non-zero, defines the height of a source pixel relative
+-       * to \code pixel_x \endcode.  If zero, then pixels default to
+-       * being square.
+-       */
+-      u32 pixel_y;
+-
+-      /** Sets the relative depth of the images, with greater values
+-       * being in front of smaller values.
+-       */
+-      u32 layer;
+-
+-      /** Set to non-zero to ensure copy protection is used on
+-       * output.
+-       */
+-      s32 copyprotect_required;
+-
+-      /** Level of opacity of the layer, where zero is fully
+-       * transparent and 255 is fully opaque.
+-       */
+-      u32 alpha;
+-};
+-
+-#define MMAL_MAX_IMAGEFX_PARAMETERS 5
+-
+-struct mmal_parameter_imagefx_parameters {
+-      enum mmal_parameter_imagefx effect;
+-      u32 num_effect_params;
+-      u32 effect_parameter[MMAL_MAX_IMAGEFX_PARAMETERS];
+-};
+-
+-#define MMAL_PARAMETER_CAMERA_INFO_MAX_CAMERAS 4
+-#define MMAL_PARAMETER_CAMERA_INFO_MAX_FLASHES 2
+-#define MMAL_PARAMETER_CAMERA_INFO_MAX_STR_LEN 16
+-
+-struct mmal_parameter_camera_info_camera_t {
+-      u32    port_id;
+-      u32    max_width;
+-      u32    max_height;
+-      u32    lens_present;
+-      u8     camera_name[MMAL_PARAMETER_CAMERA_INFO_MAX_STR_LEN];
+-};
+-
+-enum mmal_parameter_camera_info_flash_type_t {
+-      /* Make values explicit to ensure they match values in config ini */
+-      MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_XENON = 0,
+-      MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_LED   = 1,
+-      MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_OTHER = 2,
+-      MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_MAX = 0x7FFFFFFF
+-};
+-
+-struct mmal_parameter_camera_info_flash_t {
+-      enum mmal_parameter_camera_info_flash_type_t flash_type;
+-};
+-
+-struct mmal_parameter_camera_info_t {
+-      u32                            num_cameras;
+-      u32                            num_flashes;
+-      struct mmal_parameter_camera_info_camera_t
+-                              cameras[MMAL_PARAMETER_CAMERA_INFO_MAX_CAMERAS];
+-      struct mmal_parameter_camera_info_flash_t
+-                              flashes[MMAL_PARAMETER_CAMERA_INFO_MAX_FLASHES];
+-};
+-
+-#endif
+--- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h
++++ /dev/null
+@@ -1,166 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-/*
+- * Broadcom BM2835 V4L2 driver
+- *
+- * Copyright © 2013 Raspberry Pi (Trading) Ltd.
+- *
+- * Authors: Vincent Sanders @ Collabora
+- *          Dave Stevenson @ Broadcom
+- *            (now dave.stevenson@raspberrypi.org)
+- *          Simon Mellor @ Broadcom
+- *          Luke Diamand @ Broadcom
+- *
+- * MMAL interface to VCHIQ message passing
+- */
+-
+-#ifndef MMAL_VCHIQ_H
+-#define MMAL_VCHIQ_H
+-
+-#include "mmal-msg-format.h"
+-
+-#define MAX_PORT_COUNT 4
+-
+-/* Maximum size of the format extradata. */
+-#define MMAL_FORMAT_EXTRADATA_MAX_SIZE 128
+-
+-struct vchiq_mmal_instance;
+-
+-enum vchiq_mmal_es_type {
+-      MMAL_ES_TYPE_UNKNOWN,     /**< Unknown elementary stream type */
+-      MMAL_ES_TYPE_CONTROL,     /**< Elementary stream of control commands */
+-      MMAL_ES_TYPE_AUDIO,       /**< Audio elementary stream */
+-      MMAL_ES_TYPE_VIDEO,       /**< Video elementary stream */
+-      MMAL_ES_TYPE_SUBPICTURE   /**< Sub-picture elementary stream */
+-};
+-
+-struct vchiq_mmal_port_buffer {
+-      unsigned int num; /* number of buffers */
+-      u32 size; /* size of buffers */
+-      u32 alignment; /* alignment of buffers */
+-};
+-
+-struct vchiq_mmal_port;
+-
+-typedef void (*vchiq_mmal_buffer_cb)(
+-              struct vchiq_mmal_instance  *instance,
+-              struct vchiq_mmal_port *port,
+-              int status, struct mmal_buffer *buffer,
+-              unsigned long length, u32 mmal_flags, s64 dts, s64 pts);
+-
+-struct vchiq_mmal_port {
+-      bool enabled;
+-      u32 handle;
+-      u32 type; /* port type, cached to use on port info set */
+-      u32 index; /* port index, cached to use on port info set */
+-
+-      /* component port belongs to, allows simple deref */
+-      struct vchiq_mmal_component *component;
+-
+-      struct vchiq_mmal_port *connected; /* port conencted to */
+-
+-      /* buffer info */
+-      struct vchiq_mmal_port_buffer minimum_buffer;
+-      struct vchiq_mmal_port_buffer recommended_buffer;
+-      struct vchiq_mmal_port_buffer current_buffer;
+-
+-      /* stream format */
+-      struct mmal_es_format_local format;
+-      /* elementary stream format */
+-      union mmal_es_specific_format es;
+-
+-      /* data buffers to fill */
+-      struct list_head buffers;
+-      /* lock to serialise adding and removing buffers from list */
+-      spinlock_t slock;
+-
+-      /* Count of buffers the VPU has yet to return */
+-      atomic_t buffers_with_vpu;
+-      /* callback on buffer completion */
+-      vchiq_mmal_buffer_cb buffer_cb;
+-      /* callback context */
+-      void *cb_ctx;
+-};
+-
+-struct vchiq_mmal_component {
+-      bool enabled;
+-      u32 handle;  /* VideoCore handle for component */
+-      u32 inputs;  /* Number of input ports */
+-      u32 outputs; /* Number of output ports */
+-      u32 clocks;  /* Number of clock ports */
+-      struct vchiq_mmal_port control; /* control port */
+-      struct vchiq_mmal_port input[MAX_PORT_COUNT]; /* input ports */
+-      struct vchiq_mmal_port output[MAX_PORT_COUNT]; /* output ports */
+-      struct vchiq_mmal_port clock[MAX_PORT_COUNT]; /* clock ports */
+-};
+-
+-int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance);
+-int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance);
+-
+-/* Initialise a mmal component and its ports
+- *
+- */
+-int vchiq_mmal_component_init(
+-              struct vchiq_mmal_instance *instance,
+-              const char *name,
+-              struct vchiq_mmal_component **component_out);
+-
+-int vchiq_mmal_component_finalise(
+-              struct vchiq_mmal_instance *instance,
+-              struct vchiq_mmal_component *component);
+-
+-int vchiq_mmal_component_enable(
+-              struct vchiq_mmal_instance *instance,
+-              struct vchiq_mmal_component *component);
+-
+-int vchiq_mmal_component_disable(
+-              struct vchiq_mmal_instance *instance,
+-              struct vchiq_mmal_component *component);
+-
+-/* enable a mmal port
+- *
+- * enables a port and if a buffer callback provided enque buffer
+- * headers as appropriate for the port.
+- */
+-int vchiq_mmal_port_enable(
+-              struct vchiq_mmal_instance *instance,
+-              struct vchiq_mmal_port *port,
+-              vchiq_mmal_buffer_cb buffer_cb);
+-
+-/* disable a port
+- *
+- * disable a port will dequeue any pending buffers
+- */
+-int vchiq_mmal_port_disable(struct vchiq_mmal_instance *instance,
+-                          struct vchiq_mmal_port *port);
+-
+-int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance,
+-                                struct vchiq_mmal_port *port,
+-                                u32 parameter,
+-                                void *value,
+-                                u32 value_size);
+-
+-int vchiq_mmal_port_parameter_get(struct vchiq_mmal_instance *instance,
+-                                struct vchiq_mmal_port *port,
+-                                u32 parameter,
+-                                void *value,
+-                                u32 *value_size);
+-
+-int vchiq_mmal_port_set_format(struct vchiq_mmal_instance *instance,
+-                             struct vchiq_mmal_port *port);
+-
+-int vchiq_mmal_port_connect_tunnel(struct vchiq_mmal_instance *instance,
+-                                 struct vchiq_mmal_port *src,
+-                                 struct vchiq_mmal_port *dst);
+-
+-int vchiq_mmal_version(struct vchiq_mmal_instance *instance,
+-                     u32 *major_out,
+-                     u32 *minor_out);
+-
+-int vchiq_mmal_submit_buffer(struct vchiq_mmal_instance *instance,
+-                           struct vchiq_mmal_port *port,
+-                           struct mmal_buffer *buf);
+-
+-int mmal_vchi_buffer_init(struct vchiq_mmal_instance *instance,
+-                        struct mmal_buffer *buf);
+-int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf);
+-#endif /* MMAL_VCHIQ_H */
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
+@@ -0,0 +1,61 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Broadcom BM2835 V4L2 driver
++ *
++ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
++ *
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
++ *
++ * MMAL structures
++ *
++ */
++#ifndef MMAL_COMMON_H
++#define MMAL_COMMON_H
++
++#define MMAL_FOURCC(a, b, c, d) ((a) | (b << 8) | (c << 16) | (d << 24))
++#define MMAL_MAGIC MMAL_FOURCC('m', 'm', 'a', 'l')
++
++/** Special value signalling that time is not known */
++#define MMAL_TIME_UNKNOWN BIT_ULL(63)
++
++struct mmal_msg_context;
++
++/* mapping between v4l and mmal video modes */
++struct mmal_fmt {
++      char  *name;
++      u32   fourcc;          /* v4l2 format id */
++      int   flags;           /* v4l2 flags field */
++      u32   mmal;
++      int   depth;
++      u32   mmal_component;  /* MMAL component index to be used to encode */
++      u32   ybbp;            /* depth of first Y plane for planar formats */
++      bool  remove_padding;  /* Does the GPU have to remove padding,
++                              * or can we do hide padding via bytesperline.
++                              */
++};
++
++/* buffer for one video frame */
++struct mmal_buffer {
++      /* v4l buffer data -- must be first */
++      struct vb2_v4l2_buffer  vb;
++
++      /* list of buffers available */
++      struct list_head        list;
++
++      void *buffer; /* buffer pointer */
++      unsigned long buffer_size; /* size of allocated buffer */
++
++      struct mmal_msg_context *msg_context;
++};
++
++/* */
++struct mmal_colourfx {
++      s32 enable;
++      u32 u;
++      u32 v;
++};
++#endif
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-encodings.h
+@@ -0,0 +1,124 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Broadcom BM2835 V4L2 driver
++ *
++ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
++ *
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
++ */
++#ifndef MMAL_ENCODINGS_H
++#define MMAL_ENCODINGS_H
++
++#define MMAL_ENCODING_H264             MMAL_FOURCC('H', '2', '6', '4')
++#define MMAL_ENCODING_H263             MMAL_FOURCC('H', '2', '6', '3')
++#define MMAL_ENCODING_MP4V             MMAL_FOURCC('M', 'P', '4', 'V')
++#define MMAL_ENCODING_MP2V             MMAL_FOURCC('M', 'P', '2', 'V')
++#define MMAL_ENCODING_MP1V             MMAL_FOURCC('M', 'P', '1', 'V')
++#define MMAL_ENCODING_WMV3             MMAL_FOURCC('W', 'M', 'V', '3')
++#define MMAL_ENCODING_WMV2             MMAL_FOURCC('W', 'M', 'V', '2')
++#define MMAL_ENCODING_WMV1             MMAL_FOURCC('W', 'M', 'V', '1')
++#define MMAL_ENCODING_WVC1             MMAL_FOURCC('W', 'V', 'C', '1')
++#define MMAL_ENCODING_VP8              MMAL_FOURCC('V', 'P', '8', ' ')
++#define MMAL_ENCODING_VP7              MMAL_FOURCC('V', 'P', '7', ' ')
++#define MMAL_ENCODING_VP6              MMAL_FOURCC('V', 'P', '6', ' ')
++#define MMAL_ENCODING_THEORA           MMAL_FOURCC('T', 'H', 'E', 'O')
++#define MMAL_ENCODING_SPARK            MMAL_FOURCC('S', 'P', 'R', 'K')
++#define MMAL_ENCODING_MJPEG            MMAL_FOURCC('M', 'J', 'P', 'G')
++
++#define MMAL_ENCODING_JPEG             MMAL_FOURCC('J', 'P', 'E', 'G')
++#define MMAL_ENCODING_GIF              MMAL_FOURCC('G', 'I', 'F', ' ')
++#define MMAL_ENCODING_PNG              MMAL_FOURCC('P', 'N', 'G', ' ')
++#define MMAL_ENCODING_PPM              MMAL_FOURCC('P', 'P', 'M', ' ')
++#define MMAL_ENCODING_TGA              MMAL_FOURCC('T', 'G', 'A', ' ')
++#define MMAL_ENCODING_BMP              MMAL_FOURCC('B', 'M', 'P', ' ')
++
++#define MMAL_ENCODING_I420             MMAL_FOURCC('I', '4', '2', '0')
++#define MMAL_ENCODING_I420_SLICE       MMAL_FOURCC('S', '4', '2', '0')
++#define MMAL_ENCODING_YV12             MMAL_FOURCC('Y', 'V', '1', '2')
++#define MMAL_ENCODING_I422             MMAL_FOURCC('I', '4', '2', '2')
++#define MMAL_ENCODING_I422_SLICE       MMAL_FOURCC('S', '4', '2', '2')
++#define MMAL_ENCODING_YUYV             MMAL_FOURCC('Y', 'U', 'Y', 'V')
++#define MMAL_ENCODING_YVYU             MMAL_FOURCC('Y', 'V', 'Y', 'U')
++#define MMAL_ENCODING_UYVY             MMAL_FOURCC('U', 'Y', 'V', 'Y')
++#define MMAL_ENCODING_VYUY             MMAL_FOURCC('V', 'Y', 'U', 'Y')
++#define MMAL_ENCODING_NV12             MMAL_FOURCC('N', 'V', '1', '2')
++#define MMAL_ENCODING_NV21             MMAL_FOURCC('N', 'V', '2', '1')
++#define MMAL_ENCODING_ARGB             MMAL_FOURCC('A', 'R', 'G', 'B')
++#define MMAL_ENCODING_RGBA             MMAL_FOURCC('R', 'G', 'B', 'A')
++#define MMAL_ENCODING_ABGR             MMAL_FOURCC('A', 'B', 'G', 'R')
++#define MMAL_ENCODING_BGRA             MMAL_FOURCC('B', 'G', 'R', 'A')
++#define MMAL_ENCODING_RGB16            MMAL_FOURCC('R', 'G', 'B', '2')
++#define MMAL_ENCODING_RGB24            MMAL_FOURCC('R', 'G', 'B', '3')
++#define MMAL_ENCODING_RGB32            MMAL_FOURCC('R', 'G', 'B', '4')
++#define MMAL_ENCODING_BGR16            MMAL_FOURCC('B', 'G', 'R', '2')
++#define MMAL_ENCODING_BGR24            MMAL_FOURCC('B', 'G', 'R', '3')
++#define MMAL_ENCODING_BGR32            MMAL_FOURCC('B', 'G', 'R', '4')
++
++/** SAND Video (YUVUV128) format, native format understood by VideoCore.
++ * This format is *not* opaque - if requested you will receive full frames
++ * of YUV_UV video.
++ */
++#define MMAL_ENCODING_YUVUV128         MMAL_FOURCC('S', 'A', 'N', 'D')
++
++/** VideoCore opaque image format, image handles are returned to
++ * the host but not the actual image data.
++ */
++#define MMAL_ENCODING_OPAQUE           MMAL_FOURCC('O', 'P', 'Q', 'V')
++
++/** An EGL image handle
++ */
++#define MMAL_ENCODING_EGL_IMAGE        MMAL_FOURCC('E', 'G', 'L', 'I')
++
++/* }@ */
++
++/** \name Pre-defined audio encodings */
++/* @{ */
++#define MMAL_ENCODING_PCM_UNSIGNED_BE  MMAL_FOURCC('P', 'C', 'M', 'U')
++#define MMAL_ENCODING_PCM_UNSIGNED_LE  MMAL_FOURCC('p', 'c', 'm', 'u')
++#define MMAL_ENCODING_PCM_SIGNED_BE    MMAL_FOURCC('P', 'C', 'M', 'S')
++#define MMAL_ENCODING_PCM_SIGNED_LE    MMAL_FOURCC('p', 'c', 'm', 's')
++#define MMAL_ENCODING_PCM_FLOAT_BE     MMAL_FOURCC('P', 'C', 'M', 'F')
++#define MMAL_ENCODING_PCM_FLOAT_LE     MMAL_FOURCC('p', 'c', 'm', 'f')
++
++/* Pre-defined H264 encoding variants */
++
++/** ISO 14496-10 Annex B byte stream format */
++#define MMAL_ENCODING_VARIANT_H264_DEFAULT   0
++/** ISO 14496-15 AVC stream format */
++#define MMAL_ENCODING_VARIANT_H264_AVC1      MMAL_FOURCC('A', 'V', 'C', '1')
++/** Implicitly delineated NAL units without emulation prevention */
++#define MMAL_ENCODING_VARIANT_H264_RAW       MMAL_FOURCC('R', 'A', 'W', ' ')
++
++/** \defgroup MmalColorSpace List of pre-defined video color spaces
++ * This defines a list of common color spaces. This list isn't exhaustive and
++ * is only provided as a convenience to avoid clients having to use FourCC
++ * codes directly. However components are allowed to define and use their own
++ * FourCC codes.
++ */
++/* @{ */
++
++/** Unknown color space */
++#define MMAL_COLOR_SPACE_UNKNOWN       0
++/** ITU-R BT.601-5 [SDTV] */
++#define MMAL_COLOR_SPACE_ITUR_BT601    MMAL_FOURCC('Y', '6', '0', '1')
++/** ITU-R BT.709-3 [HDTV] */
++#define MMAL_COLOR_SPACE_ITUR_BT709    MMAL_FOURCC('Y', '7', '0', '9')
++/** JPEG JFIF */
++#define MMAL_COLOR_SPACE_JPEG_JFIF     MMAL_FOURCC('Y', 'J', 'F', 'I')
++/** Title 47 Code of Federal Regulations (2003) 73.682 (a) (20) */
++#define MMAL_COLOR_SPACE_FCC           MMAL_FOURCC('Y', 'F', 'C', 'C')
++/** Society of Motion Picture and Television Engineers 240M (1999) */
++#define MMAL_COLOR_SPACE_SMPTE240M     MMAL_FOURCC('Y', '2', '4', '0')
++/** ITU-R BT.470-2 System M */
++#define MMAL_COLOR_SPACE_BT470_2_M     MMAL_FOURCC('Y', '_', '_', 'M')
++/** ITU-R BT.470-2 System BG */
++#define MMAL_COLOR_SPACE_BT470_2_BG    MMAL_FOURCC('Y', '_', 'B', 'G')
++/** JPEG JFIF, but with 16..255 luma */
++#define MMAL_COLOR_SPACE_JFIF_Y16_255  MMAL_FOURCC('Y', 'Y', '1', '6')
++/* @} MmalColorSpace List */
++
++#endif /* MMAL_ENCODINGS_H */
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-common.h
+@@ -0,0 +1,48 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Broadcom BM2835 V4L2 driver
++ *
++ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
++ *
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
++ */
++
++#ifndef MMAL_MSG_COMMON_H
++#define MMAL_MSG_COMMON_H
++
++enum mmal_msg_status {
++      MMAL_MSG_STATUS_SUCCESS = 0, /**< Success */
++      MMAL_MSG_STATUS_ENOMEM,      /**< Out of memory */
++      MMAL_MSG_STATUS_ENOSPC,      /**< Out of resources other than memory */
++      MMAL_MSG_STATUS_EINVAL,      /**< Argument is invalid */
++      MMAL_MSG_STATUS_ENOSYS,      /**< Function not implemented */
++      MMAL_MSG_STATUS_ENOENT,      /**< No such file or directory */
++      MMAL_MSG_STATUS_ENXIO,       /**< No such device or address */
++      MMAL_MSG_STATUS_EIO,         /**< I/O error */
++      MMAL_MSG_STATUS_ESPIPE,      /**< Illegal seek */
++      MMAL_MSG_STATUS_ECORRUPT,    /**< Data is corrupt \attention */
++      MMAL_MSG_STATUS_ENOTREADY,   /**< Component is not ready */
++      MMAL_MSG_STATUS_ECONFIG,     /**< Component is not configured */
++      MMAL_MSG_STATUS_EISCONN,     /**< Port is already connected */
++      MMAL_MSG_STATUS_ENOTCONN,    /**< Port is disconnected */
++      MMAL_MSG_STATUS_EAGAIN,      /**< Resource temporarily unavailable. */
++      MMAL_MSG_STATUS_EFAULT,      /**< Bad address */
++};
++
++struct mmal_rect {
++      s32 x;      /**< x coordinate (from left) */
++      s32 y;      /**< y coordinate (from top) */
++      s32 width;  /**< width */
++      s32 height; /**< height */
++};
++
++struct mmal_rational {
++      s32 num;    /**< Numerator */
++      s32 den;    /**< Denominator */
++};
++
++#endif /* MMAL_MSG_COMMON_H */
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-format.h
+@@ -0,0 +1,106 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Broadcom BM2835 V4L2 driver
++ *
++ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
++ *
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
++ */
++
++#ifndef MMAL_MSG_FORMAT_H
++#define MMAL_MSG_FORMAT_H
++
++#include "mmal-msg-common.h"
++
++/* MMAL_ES_FORMAT_T */
++
++struct mmal_audio_format {
++      u32 channels;           /* Number of audio channels */
++      u32 sample_rate;        /* Sample rate */
++
++      u32 bits_per_sample;    /* Bits per sample */
++      u32 block_align;        /* Size of a block of data */
++};
++
++struct mmal_video_format {
++      u32 width;              /* Width of frame in pixels */
++      u32 height;             /* Height of frame in rows of pixels */
++      struct mmal_rect crop;  /* Visible region of the frame */
++      struct mmal_rational frame_rate;        /* Frame rate */
++      struct mmal_rational par;               /* Pixel aspect ratio */
++
++      /*
++       * FourCC specifying the color space of the video stream. See the
++       * MmalColorSpace "pre-defined color spaces" for some examples.
++       */
++      u32 color_space;
++};
++
++struct mmal_subpicture_format {
++      u32 x_offset;
++      u32 y_offset;
++};
++
++union mmal_es_specific_format {
++      struct mmal_audio_format audio;
++      struct mmal_video_format video;
++      struct mmal_subpicture_format subpicture;
++};
++
++/* Definition of an elementary stream format (MMAL_ES_FORMAT_T) */
++struct mmal_es_format_local {
++      u32 type;       /* enum mmal_es_type */
++
++      u32 encoding;   /* FourCC specifying encoding of the elementary
++                       * stream.
++                       */
++      u32 encoding_variant;   /* FourCC specifying the specific
++                               * encoding variant of the elementary
++                               * stream.
++                               */
++
++      union mmal_es_specific_format *es;      /* Type specific
++                                               * information for the
++                                               * elementary stream
++                                               */
++
++      u32 bitrate;    /* Bitrate in bits per second */
++      u32 flags;      /* Flags describing properties of the elementary
++                       * stream.
++                       */
++
++      u32 extradata_size;     /* Size of the codec specific data */
++      u8  *extradata;         /* Codec specific data */
++};
++
++/* Remote definition of an elementary stream format (MMAL_ES_FORMAT_T) */
++struct mmal_es_format {
++      u32 type;       /* enum mmal_es_type */
++
++      u32 encoding;   /* FourCC specifying encoding of the elementary
++                       * stream.
++                       */
++      u32 encoding_variant;   /* FourCC specifying the specific
++                               * encoding variant of the elementary
++                               * stream.
++                               */
++
++      u32 es; /* Type specific
++               * information for the
++               * elementary stream
++               */
++
++      u32 bitrate;    /* Bitrate in bits per second */
++      u32 flags;      /* Flags describing properties of the elementary
++                       * stream.
++                       */
++
++      u32 extradata_size;     /* Size of the codec specific data */
++      u32 extradata;          /* Codec specific data */
++};
++
++#endif /* MMAL_MSG_FORMAT_H */
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-port.h
+@@ -0,0 +1,109 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Broadcom BM2835 V4L2 driver
++ *
++ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
++ *
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
++ */
++
++/* MMAL_PORT_TYPE_T */
++enum mmal_port_type {
++      MMAL_PORT_TYPE_UNKNOWN = 0,     /* Unknown port type */
++      MMAL_PORT_TYPE_CONTROL,         /* Control port */
++      MMAL_PORT_TYPE_INPUT,           /* Input port */
++      MMAL_PORT_TYPE_OUTPUT,          /* Output port */
++      MMAL_PORT_TYPE_CLOCK,           /* Clock port */
++};
++
++/* The port is pass-through and doesn't need buffer headers allocated */
++#define MMAL_PORT_CAPABILITY_PASSTHROUGH                       0x01
++/*
++ *The port wants to allocate the buffer payloads.
++ * This signals a preference that payload allocation should be done
++ * on this port for efficiency reasons.
++ */
++#define MMAL_PORT_CAPABILITY_ALLOCATION                        0x02
++/*
++ * The port supports format change events.
++ * This applies to input ports and is used to let the client know
++ * whether the port supports being reconfigured via a format
++ * change event (i.e. without having to disable the port).
++ */
++#define MMAL_PORT_CAPABILITY_SUPPORTS_EVENT_FORMAT_CHANGE      0x04
++
++/*
++ * mmal port structure (MMAL_PORT_T)
++ *
++ * most elements are informational only, the pointer values for
++ * interogation messages are generally provided as additional
++ * structures within the message. When used to set values only the
++ * buffer_num, buffer_size and userdata parameters are writable.
++ */
++struct mmal_port {
++      u32 priv;       /* Private member used by the framework */
++      u32 name;       /* Port name. Used for debugging purposes (RO) */
++
++      u32 type;       /* Type of the port (RO) enum mmal_port_type */
++      u16 index;      /* Index of the port in its type list (RO) */
++      u16 index_all;  /* Index of the port in the list of all ports (RO) */
++
++      u32 is_enabled; /* Indicates whether the port is enabled or not (RO) */
++      u32 format;     /* Format of the elementary stream */
++
++      u32 buffer_num_min;     /* Minimum number of buffers the port
++                               *   requires (RO).  This is set by the
++                               *   component.
++                               */
++
++      u32 buffer_size_min;    /* Minimum size of buffers the port
++                               * requires (RO).  This is set by the
++                               * component.
++                               */
++
++      u32 buffer_alignment_min;/* Minimum alignment requirement for
++                                * the buffers (RO).  A value of
++                                * zero means no special alignment
++                                * requirements.  This is set by the
++                                * component.
++                                */
++
++      u32 buffer_num_recommended;     /* Number of buffers the port
++                                       * recommends for optimal
++                                       * performance (RO).  A value of
++                                       * zero means no special
++                                       * recommendation.  This is set
++                                       * by the component.
++                                       */
++
++      u32 buffer_size_recommended;    /* Size of buffers the port
++                                       * recommends for optimal
++                                       * performance (RO).  A value of
++                                       * zero means no special
++                                       * recommendation.  This is set
++                                       * by the component.
++                                       */
++
++      u32 buffer_num; /* Actual number of buffers the port will use.
++                       * This is set by the client.
++                       */
++
++      u32 buffer_size; /* Actual maximum size of the buffers that
++                        * will be sent to the port. This is set by
++                        * the client.
++                        */
++
++      u32 component;  /* Component this port belongs to (Read Only) */
++
++      u32 userdata;   /* Field reserved for use by the client */
++
++      u32 capabilities;       /* Flags describing the capabilities of a
++                               * port (RO).  Bitwise combination of \ref
++                               * portcapabilities "Port capabilities"
++                               * values.
++                               */
++};
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h
+@@ -0,0 +1,406 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Broadcom BM2835 V4L2 driver
++ *
++ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
++ *
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
++ */
++
++/*
++ * all the data structures which serialise the MMAL protocol. note
++ * these are directly mapped onto the recived message data.
++ *
++ * BEWARE: They seem to *assume* pointers are u32 and that there is no
++ * structure padding!
++ *
++ * NOTE: this implementation uses kernel types to ensure sizes. Rather
++ * than assigning values to enums to force their size the
++ * implementation uses fixed size types and not the enums (though the
++ * comments have the actual enum type
++ */
++#ifndef MMAL_MSG_H
++#define MMAL_MSG_H
++
++#define VC_MMAL_VER 15
++#define VC_MMAL_MIN_VER 10
++#define VC_MMAL_SERVER_NAME  MAKE_FOURCC("mmal")
++
++/* max total message size is 512 bytes */
++#define MMAL_MSG_MAX_SIZE 512
++/* with six 32bit header elements max payload is therefore 488 bytes */
++#define MMAL_MSG_MAX_PAYLOAD 488
++
++#include "mmal-msg-common.h"
++#include "mmal-msg-format.h"
++#include "mmal-msg-port.h"
++
++enum mmal_msg_type {
++      MMAL_MSG_TYPE_QUIT = 1,
++      MMAL_MSG_TYPE_SERVICE_CLOSED,
++      MMAL_MSG_TYPE_GET_VERSION,
++      MMAL_MSG_TYPE_COMPONENT_CREATE,
++      MMAL_MSG_TYPE_COMPONENT_DESTROY,        /* 5 */
++      MMAL_MSG_TYPE_COMPONENT_ENABLE,
++      MMAL_MSG_TYPE_COMPONENT_DISABLE,
++      MMAL_MSG_TYPE_PORT_INFO_GET,
++      MMAL_MSG_TYPE_PORT_INFO_SET,
++      MMAL_MSG_TYPE_PORT_ACTION,              /* 10 */
++      MMAL_MSG_TYPE_BUFFER_FROM_HOST,
++      MMAL_MSG_TYPE_BUFFER_TO_HOST,
++      MMAL_MSG_TYPE_GET_STATS,
++      MMAL_MSG_TYPE_PORT_PARAMETER_SET,
++      MMAL_MSG_TYPE_PORT_PARAMETER_GET,       /* 15 */
++      MMAL_MSG_TYPE_EVENT_TO_HOST,
++      MMAL_MSG_TYPE_GET_CORE_STATS_FOR_PORT,
++      MMAL_MSG_TYPE_OPAQUE_ALLOCATOR,
++      MMAL_MSG_TYPE_CONSUME_MEM,
++      MMAL_MSG_TYPE_LMK,                      /* 20 */
++      MMAL_MSG_TYPE_OPAQUE_ALLOCATOR_DESC,
++      MMAL_MSG_TYPE_DRM_GET_LHS32,
++      MMAL_MSG_TYPE_DRM_GET_TIME,
++      MMAL_MSG_TYPE_BUFFER_FROM_HOST_ZEROLEN,
++      MMAL_MSG_TYPE_PORT_FLUSH,               /* 25 */
++      MMAL_MSG_TYPE_HOST_LOG,
++      MMAL_MSG_TYPE_MSG_LAST
++};
++
++/* port action request messages differ depending on the action type */
++enum mmal_msg_port_action_type {
++      MMAL_MSG_PORT_ACTION_TYPE_UNKNOWN = 0,  /* Unknown action */
++      MMAL_MSG_PORT_ACTION_TYPE_ENABLE,       /* Enable a port */
++      MMAL_MSG_PORT_ACTION_TYPE_DISABLE,      /* Disable a port */
++      MMAL_MSG_PORT_ACTION_TYPE_FLUSH,        /* Flush a port */
++      MMAL_MSG_PORT_ACTION_TYPE_CONNECT,      /* Connect ports */
++      MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT,   /* Disconnect ports */
++      MMAL_MSG_PORT_ACTION_TYPE_SET_REQUIREMENTS, /* Set buffer requirements*/
++};
++
++struct mmal_msg_header {
++      u32 magic;
++      u32 type;       /* enum mmal_msg_type */
++
++      /* Opaque handle to the control service */
++      u32 control_service;
++
++      u32 context;    /* a u32 per message context */
++      u32 status;     /* The status of the vchiq operation */
++      u32 padding;
++};
++
++/* Send from VC to host to report version */
++struct mmal_msg_version {
++      u32 flags;
++      u32 major;
++      u32 minor;
++      u32 minimum;
++};
++
++/* request to VC to create component */
++struct mmal_msg_component_create {
++      u32 client_component;   /* component context */
++      char name[128];
++      u32 pid;                /* For debug */
++};
++
++/* reply from VC to component creation request */
++struct mmal_msg_component_create_reply {
++      u32 status;     /* enum mmal_msg_status - how does this differ to
++                       * the one in the header?
++                       */
++      u32 component_handle; /* VideoCore handle for component */
++      u32 input_num;        /* Number of input ports */
++      u32 output_num;       /* Number of output ports */
++      u32 clock_num;        /* Number of clock ports */
++};
++
++/* request to VC to destroy a component */
++struct mmal_msg_component_destroy {
++      u32 component_handle;
++};
++
++struct mmal_msg_component_destroy_reply {
++      u32 status; /* The component destruction status */
++};
++
++/* request and reply to VC to enable a component */
++struct mmal_msg_component_enable {
++      u32 component_handle;
++};
++
++struct mmal_msg_component_enable_reply {
++      u32 status; /* The component enable status */
++};
++
++/* request and reply to VC to disable a component */
++struct mmal_msg_component_disable {
++      u32 component_handle;
++};
++
++struct mmal_msg_component_disable_reply {
++      u32 status; /* The component disable status */
++};
++
++/* request to VC to get port information */
++struct mmal_msg_port_info_get {
++      u32 component_handle;  /* component handle port is associated with */
++      u32 port_type;         /* enum mmal_msg_port_type */
++      u32 index;             /* port index to query */
++};
++
++/* reply from VC to get port info request */
++struct mmal_msg_port_info_get_reply {
++      u32 status;             /* enum mmal_msg_status */
++      u32 component_handle;   /* component handle port is associated with */
++      u32 port_type;          /* enum mmal_msg_port_type */
++      u32 port_index;         /* port indexed in query */
++      s32 found;              /* unused */
++      u32 port_handle;        /* Handle to use for this port */
++      struct mmal_port port;
++      struct mmal_es_format format; /* elementary stream format */
++      union mmal_es_specific_format es; /* es type specific data */
++      u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE]; /* es extra data */
++};
++
++/* request to VC to set port information */
++struct mmal_msg_port_info_set {
++      u32 component_handle;
++      u32 port_type;          /* enum mmal_msg_port_type */
++      u32 port_index;         /* port indexed in query */
++      struct mmal_port port;
++      struct mmal_es_format format;
++      union mmal_es_specific_format es;
++      u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE];
++};
++
++/* reply from VC to port info set request */
++struct mmal_msg_port_info_set_reply {
++      u32 status;
++      u32 component_handle;   /* component handle port is associated with */
++      u32 port_type;          /* enum mmal_msg_port_type */
++      u32 index;              /* port indexed in query */
++      s32 found;              /* unused */
++      u32 port_handle;        /* Handle to use for this port */
++      struct mmal_port port;
++      struct mmal_es_format format;
++      union mmal_es_specific_format es;
++      u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE];
++};
++
++/* port action requests that take a mmal_port as a parameter */
++struct mmal_msg_port_action_port {
++      u32 component_handle;
++      u32 port_handle;
++      u32 action;             /* enum mmal_msg_port_action_type */
++      struct mmal_port port;
++};
++
++/* port action requests that take handles as a parameter */
++struct mmal_msg_port_action_handle {
++      u32 component_handle;
++      u32 port_handle;
++      u32 action;             /* enum mmal_msg_port_action_type */
++      u32 connect_component_handle;
++      u32 connect_port_handle;
++};
++
++struct mmal_msg_port_action_reply {
++      u32 status;     /* The port action operation status */
++};
++
++/* MMAL buffer transfer */
++
++/* Size of space reserved in a buffer message for short messages. */
++#define MMAL_VC_SHORT_DATA 128
++
++/* Signals that the current payload is the end of the stream of data */
++#define MMAL_BUFFER_HEADER_FLAG_EOS                    BIT(0)
++/* Signals that the start of the current payload starts a frame */
++#define MMAL_BUFFER_HEADER_FLAG_FRAME_START            BIT(1)
++/* Signals that the end of the current payload ends a frame */
++#define MMAL_BUFFER_HEADER_FLAG_FRAME_END              BIT(2)
++/* Signals that the current payload contains only complete frames (>1) */
++#define MMAL_BUFFER_HEADER_FLAG_FRAME                  \
++      (MMAL_BUFFER_HEADER_FLAG_FRAME_START | \
++       MMAL_BUFFER_HEADER_FLAG_FRAME_END)
++/* Signals that the current payload is a keyframe (i.e. self decodable) */
++#define MMAL_BUFFER_HEADER_FLAG_KEYFRAME               BIT(3)
++/*
++ * Signals a discontinuity in the stream of data (e.g. after a seek).
++ * Can be used for instance by a decoder to reset its state
++ */
++#define MMAL_BUFFER_HEADER_FLAG_DISCONTINUITY          BIT(4)
++/*
++ * Signals a buffer containing some kind of config data for the component
++ * (e.g. codec config data)
++ */
++#define MMAL_BUFFER_HEADER_FLAG_CONFIG                 BIT(5)
++/* Signals an encrypted payload */
++#define MMAL_BUFFER_HEADER_FLAG_ENCRYPTED              BIT(6)
++/* Signals a buffer containing side information */
++#define MMAL_BUFFER_HEADER_FLAG_CODECSIDEINFO          BIT(7)
++/*
++ * Signals a buffer which is the snapshot/postview image from a stills
++ * capture
++ */
++#define MMAL_BUFFER_HEADER_FLAGS_SNAPSHOT              BIT(8)
++/* Signals a buffer which contains data known to be corrupted */
++#define MMAL_BUFFER_HEADER_FLAG_CORRUPTED              BIT(9)
++/* Signals that a buffer failed to be transmitted */
++#define MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED    BIT(10)
++
++struct mmal_driver_buffer {
++      u32 magic;
++      u32 component_handle;
++      u32 port_handle;
++      u32 client_context;
++};
++
++/* buffer header */
++struct mmal_buffer_header {
++      u32 next;       /* next header */
++      u32 priv;       /* framework private data */
++      u32 cmd;
++      u32 data;
++      u32 alloc_size;
++      u32 length;
++      u32 offset;
++      u32 flags;
++      s64 pts;
++      s64 dts;
++      u32 type;
++      u32 user_data;
++};
++
++struct mmal_buffer_header_type_specific {
++      union {
++              struct {
++              u32 planes;
++              u32 offset[4];
++              u32 pitch[4];
++              u32 flags;
++              } video;
++      } u;
++};
++
++struct mmal_msg_buffer_from_host {
++      /*
++       *The front 32 bytes of the buffer header are copied
++       * back to us in the reply to allow for context. This
++       * area is used to store two mmal_driver_buffer structures to
++       * allow for multiple concurrent service users.
++       */
++      /* control data */
++      struct mmal_driver_buffer drvbuf;
++
++      /* referenced control data for passthrough buffer management */
++      struct mmal_driver_buffer drvbuf_ref;
++      struct mmal_buffer_header buffer_header; /* buffer header itself */
++      struct mmal_buffer_header_type_specific buffer_header_type_specific;
++      s32 is_zero_copy;
++      s32 has_reference;
++
++      /* allows short data to be xfered in control message */
++      u32 payload_in_message;
++      u8 short_data[MMAL_VC_SHORT_DATA];
++};
++
++/* port parameter setting */
++
++#define MMAL_WORKER_PORT_PARAMETER_SPACE      96
++
++struct mmal_msg_port_parameter_set {
++      u32 component_handle;   /* component */
++      u32 port_handle;        /* port */
++      u32 id;                 /* Parameter ID  */
++      u32 size;               /* Parameter size */
++      uint32_t value[MMAL_WORKER_PORT_PARAMETER_SPACE];
++};
++
++struct mmal_msg_port_parameter_set_reply {
++      u32 status;     /* enum mmal_msg_status todo: how does this
++                       * differ to the one in the header?
++                       */
++};
++
++/* port parameter getting */
++
++struct mmal_msg_port_parameter_get {
++      u32 component_handle;   /* component */
++      u32 port_handle;        /* port */
++      u32 id;                 /* Parameter ID  */
++      u32 size;               /* Parameter size */
++};
++
++struct mmal_msg_port_parameter_get_reply {
++      u32 status;             /* Status of mmal_port_parameter_get call */
++      u32 id;                 /* Parameter ID  */
++      u32 size;               /* Parameter size */
++      uint32_t value[MMAL_WORKER_PORT_PARAMETER_SPACE];
++};
++
++/* event messages */
++#define MMAL_WORKER_EVENT_SPACE 256
++
++struct mmal_msg_event_to_host {
++      u32 client_component;   /* component context */
++
++      u32 port_type;
++      u32 port_num;
++
++      u32 cmd;
++      u32 length;
++      u8 data[MMAL_WORKER_EVENT_SPACE];
++      u32 delayed_buffer;
++};
++
++/* all mmal messages are serialised through this structure */
++struct mmal_msg {
++      /* header */
++      struct mmal_msg_header h;
++      /* payload */
++      union {
++              struct mmal_msg_version version;
++
++              struct mmal_msg_component_create component_create;
++              struct mmal_msg_component_create_reply component_create_reply;
++
++              struct mmal_msg_component_destroy component_destroy;
++              struct mmal_msg_component_destroy_reply component_destroy_reply;
++
++              struct mmal_msg_component_enable component_enable;
++              struct mmal_msg_component_enable_reply component_enable_reply;
++
++              struct mmal_msg_component_disable component_disable;
++              struct mmal_msg_component_disable_reply component_disable_reply;
++
++              struct mmal_msg_port_info_get port_info_get;
++              struct mmal_msg_port_info_get_reply port_info_get_reply;
++
++              struct mmal_msg_port_info_set port_info_set;
++              struct mmal_msg_port_info_set_reply port_info_set_reply;
++
++              struct mmal_msg_port_action_port port_action_port;
++              struct mmal_msg_port_action_handle port_action_handle;
++              struct mmal_msg_port_action_reply port_action_reply;
++
++              struct mmal_msg_buffer_from_host buffer_from_host;
++
++              struct mmal_msg_port_parameter_set port_parameter_set;
++              struct mmal_msg_port_parameter_set_reply
++                      port_parameter_set_reply;
++              struct mmal_msg_port_parameter_get
++                      port_parameter_get;
++              struct mmal_msg_port_parameter_get_reply
++                      port_parameter_get_reply;
++
++              struct mmal_msg_event_to_host event_to_host;
++
++              u8 payload[MMAL_MSG_MAX_PAYLOAD];
++      } u;
++};
++#endif
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h
+@@ -0,0 +1,755 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Broadcom BM2835 V4L2 driver
++ *
++ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
++ *
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
++ */
++
++/* common parameters */
++
++/** @name Parameter groups
++ * Parameters are divided into groups, and then allocated sequentially within
++ * a group using an enum.
++ * @{
++ */
++
++#ifndef MMAL_PARAMETERS_H
++#define MMAL_PARAMETERS_H
++
++/** Common parameter ID group, used with many types of component. */
++#define MMAL_PARAMETER_GROUP_COMMON           (0 << 16)
++/** Camera-specific parameter ID group. */
++#define MMAL_PARAMETER_GROUP_CAMERA           (1 << 16)
++/** Video-specific parameter ID group. */
++#define MMAL_PARAMETER_GROUP_VIDEO            (2 << 16)
++/** Audio-specific parameter ID group. */
++#define MMAL_PARAMETER_GROUP_AUDIO            (3 << 16)
++/** Clock-specific parameter ID group. */
++#define MMAL_PARAMETER_GROUP_CLOCK            (4 << 16)
++/** Miracast-specific parameter ID group. */
++#define MMAL_PARAMETER_GROUP_MIRACAST         (5 << 16)
++
++/* Common parameters */
++enum mmal_parameter_common_type {
++      /**< Never a valid parameter ID */
++      MMAL_PARAMETER_UNUSED = MMAL_PARAMETER_GROUP_COMMON,
++
++              /**< MMAL_PARAMETER_ENCODING_T */
++      MMAL_PARAMETER_SUPPORTED_ENCODINGS,
++              /**< MMAL_PARAMETER_URI_T */
++      MMAL_PARAMETER_URI,
++              /** MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T */
++      MMAL_PARAMETER_CHANGE_EVENT_REQUEST,
++              /** MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_ZERO_COPY,
++              /**< MMAL_PARAMETER_BUFFER_REQUIREMENTS_T */
++      MMAL_PARAMETER_BUFFER_REQUIREMENTS,
++              /**< MMAL_PARAMETER_STATISTICS_T */
++      MMAL_PARAMETER_STATISTICS,
++              /**< MMAL_PARAMETER_CORE_STATISTICS_T */
++      MMAL_PARAMETER_CORE_STATISTICS,
++              /**< MMAL_PARAMETER_MEM_USAGE_T */
++      MMAL_PARAMETER_MEM_USAGE,
++              /**< MMAL_PARAMETER_UINT32_T */
++      MMAL_PARAMETER_BUFFER_FLAG_FILTER,
++              /**< MMAL_PARAMETER_SEEK_T */
++      MMAL_PARAMETER_SEEK,
++              /**< MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_POWERMON_ENABLE,
++              /**< MMAL_PARAMETER_LOGGING_T */
++      MMAL_PARAMETER_LOGGING,
++              /**< MMAL_PARAMETER_UINT64_T */
++      MMAL_PARAMETER_SYSTEM_TIME,
++              /**< MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_NO_IMAGE_PADDING,
++};
++
++/* camera parameters */
++
++enum mmal_parameter_camera_type {
++      /* 0 */
++              /** @ref MMAL_PARAMETER_THUMBNAIL_CONFIG_T */
++      MMAL_PARAMETER_THUMBNAIL_CONFIGURATION =
++              MMAL_PARAMETER_GROUP_CAMERA,
++              /**< Unused? */
++      MMAL_PARAMETER_CAPTURE_QUALITY,
++              /**< @ref MMAL_PARAMETER_INT32_T */
++      MMAL_PARAMETER_ROTATION,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_EXIF_DISABLE,
++              /**< @ref MMAL_PARAMETER_EXIF_T */
++      MMAL_PARAMETER_EXIF,
++              /**< @ref MMAL_PARAM_AWBMODE_T */
++      MMAL_PARAMETER_AWB_MODE,
++              /**< @ref MMAL_PARAMETER_IMAGEFX_T */
++      MMAL_PARAMETER_IMAGE_EFFECT,
++              /**< @ref MMAL_PARAMETER_COLOURFX_T */
++      MMAL_PARAMETER_COLOUR_EFFECT,
++              /**< @ref MMAL_PARAMETER_FLICKERAVOID_T */
++      MMAL_PARAMETER_FLICKER_AVOID,
++              /**< @ref MMAL_PARAMETER_FLASH_T */
++      MMAL_PARAMETER_FLASH,
++              /**< @ref MMAL_PARAMETER_REDEYE_T */
++      MMAL_PARAMETER_REDEYE,
++              /**< @ref MMAL_PARAMETER_FOCUS_T */
++      MMAL_PARAMETER_FOCUS,
++              /**< Unused? */
++      MMAL_PARAMETER_FOCAL_LENGTHS,
++              /**< @ref MMAL_PARAMETER_INT32_T */
++      MMAL_PARAMETER_EXPOSURE_COMP,
++              /**< @ref MMAL_PARAMETER_SCALEFACTOR_T */
++      MMAL_PARAMETER_ZOOM,
++              /**< @ref MMAL_PARAMETER_MIRROR_T */
++      MMAL_PARAMETER_MIRROR,
++
++      /* 0x10 */
++              /**< @ref MMAL_PARAMETER_UINT32_T */
++      MMAL_PARAMETER_CAMERA_NUM,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_CAPTURE,
++              /**< @ref MMAL_PARAMETER_EXPOSUREMODE_T */
++      MMAL_PARAMETER_EXPOSURE_MODE,
++              /**< @ref MMAL_PARAMETER_EXPOSUREMETERINGMODE_T */
++      MMAL_PARAMETER_EXP_METERING_MODE,
++              /**< @ref MMAL_PARAMETER_FOCUS_STATUS_T */
++      MMAL_PARAMETER_FOCUS_STATUS,
++              /**< @ref MMAL_PARAMETER_CAMERA_CONFIG_T */
++      MMAL_PARAMETER_CAMERA_CONFIG,
++              /**< @ref MMAL_PARAMETER_CAPTURE_STATUS_T */
++      MMAL_PARAMETER_CAPTURE_STATUS,
++              /**< @ref MMAL_PARAMETER_FACE_TRACK_T */
++      MMAL_PARAMETER_FACE_TRACK,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_DRAW_BOX_FACES_AND_FOCUS,
++              /**< @ref MMAL_PARAMETER_UINT32_T */
++      MMAL_PARAMETER_JPEG_Q_FACTOR,
++              /**< @ref MMAL_PARAMETER_FRAME_RATE_T */
++      MMAL_PARAMETER_FRAME_RATE,
++              /**< @ref MMAL_PARAMETER_CAMERA_STC_MODE_T */
++      MMAL_PARAMETER_USE_STC,
++              /**< @ref MMAL_PARAMETER_CAMERA_INFO_T */
++      MMAL_PARAMETER_CAMERA_INFO,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_VIDEO_STABILISATION,
++              /**< @ref MMAL_PARAMETER_FACE_TRACK_RESULTS_T */
++      MMAL_PARAMETER_FACE_TRACK_RESULTS,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_ENABLE_RAW_CAPTURE,
++
++      /* 0x20 */
++              /**< @ref MMAL_PARAMETER_URI_T */
++      MMAL_PARAMETER_DPF_FILE,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_ENABLE_DPF_FILE,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_DPF_FAIL_IS_FATAL,
++              /**< @ref MMAL_PARAMETER_CAPTUREMODE_T */
++      MMAL_PARAMETER_CAPTURE_MODE,
++              /**< @ref MMAL_PARAMETER_FOCUS_REGIONS_T */
++      MMAL_PARAMETER_FOCUS_REGIONS,
++              /**< @ref MMAL_PARAMETER_INPUT_CROP_T */
++      MMAL_PARAMETER_INPUT_CROP,
++              /**< @ref MMAL_PARAMETER_SENSOR_INFORMATION_T */
++      MMAL_PARAMETER_SENSOR_INFORMATION,
++              /**< @ref MMAL_PARAMETER_FLASH_SELECT_T */
++      MMAL_PARAMETER_FLASH_SELECT,
++              /**< @ref MMAL_PARAMETER_FIELD_OF_VIEW_T */
++      MMAL_PARAMETER_FIELD_OF_VIEW,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_HIGH_DYNAMIC_RANGE,
++              /**< @ref MMAL_PARAMETER_DRC_T */
++      MMAL_PARAMETER_DYNAMIC_RANGE_COMPRESSION,
++              /**< @ref MMAL_PARAMETER_ALGORITHM_CONTROL_T */
++      MMAL_PARAMETER_ALGORITHM_CONTROL,
++              /**< @ref MMAL_PARAMETER_RATIONAL_T */
++      MMAL_PARAMETER_SHARPNESS,
++              /**< @ref MMAL_PARAMETER_RATIONAL_T */
++      MMAL_PARAMETER_CONTRAST,
++              /**< @ref MMAL_PARAMETER_RATIONAL_T */
++      MMAL_PARAMETER_BRIGHTNESS,
++              /**< @ref MMAL_PARAMETER_RATIONAL_T */
++      MMAL_PARAMETER_SATURATION,
++
++      /* 0x30 */
++              /**< @ref MMAL_PARAMETER_UINT32_T */
++      MMAL_PARAMETER_ISO,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_ANTISHAKE,
++              /** @ref MMAL_PARAMETER_IMAGEFX_PARAMETERS_T */
++      MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS,
++              /** @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_CAMERA_BURST_CAPTURE,
++              /** @ref MMAL_PARAMETER_UINT32_T */
++      MMAL_PARAMETER_CAMERA_MIN_ISO,
++              /** @ref MMAL_PARAMETER_CAMERA_USE_CASE_T */
++      MMAL_PARAMETER_CAMERA_USE_CASE,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_CAPTURE_STATS_PASS,
++              /** @ref MMAL_PARAMETER_UINT32_T */
++      MMAL_PARAMETER_CAMERA_CUSTOM_SENSOR_CONFIG,
++              /** @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_ENABLE_REGISTER_FILE,
++              /** @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_REGISTER_FAIL_IS_FATAL,
++              /** @ref MMAL_PARAMETER_CONFIGFILE_T */
++      MMAL_PARAMETER_CONFIGFILE_REGISTERS,
++              /** @ref MMAL_PARAMETER_CONFIGFILE_CHUNK_T */
++      MMAL_PARAMETER_CONFIGFILE_CHUNK_REGISTERS,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_JPEG_ATTACH_LOG,
++              /**< @ref MMAL_PARAMETER_ZEROSHUTTERLAG_T */
++      MMAL_PARAMETER_ZERO_SHUTTER_LAG,
++              /**< @ref MMAL_PARAMETER_FPS_RANGE_T */
++      MMAL_PARAMETER_FPS_RANGE,
++              /**< @ref MMAL_PARAMETER_INT32_T */
++      MMAL_PARAMETER_CAPTURE_EXPOSURE_COMP,
++
++      /* 0x40 */
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_SW_SHARPEN_DISABLE,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_FLASH_REQUIRED,
++              /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_SW_SATURATION_DISABLE,
++      /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
++      MMAL_PARAMETER_SHUTTER_SPEED,
++              /**< Takes a @ref MMAL_PARAMETER_AWB_GAINS_T */
++      MMAL_PARAMETER_CUSTOM_AWB_GAINS,
++};
++
++struct mmal_parameter_rational {
++      s32 num;    /**< Numerator */
++      s32 den;    /**< Denominator */
++};
++
++enum mmal_parameter_camera_config_timestamp_mode {
++      MMAL_PARAM_TIMESTAMP_MODE_ZERO = 0, /* Always timestamp frames as 0 */
++      MMAL_PARAM_TIMESTAMP_MODE_RAW_STC,  /* Use the raw STC value
++                                           * for the frame timestamp
++                                           */
++      MMAL_PARAM_TIMESTAMP_MODE_RESET_STC, /* Use the STC timestamp
++                                            * but subtract the
++                                            * timestamp of the first
++                                            * frame sent to give a
++                                            * zero based timestamp.
++                                            */
++};
++
++struct mmal_parameter_fps_range {
++      /**< Low end of the permitted framerate range */
++      struct mmal_parameter_rational  fps_low;
++      /**< High end of the permitted framerate range */
++      struct mmal_parameter_rational  fps_high;
++};
++
++/* camera configuration parameter */
++struct mmal_parameter_camera_config {
++      /* Parameters for setting up the image pools */
++      u32 max_stills_w; /* Max size of stills capture */
++      u32 max_stills_h;
++      u32 stills_yuv422; /* Allow YUV422 stills capture */
++      u32 one_shot_stills; /* Continuous or one shot stills captures. */
++
++      u32 max_preview_video_w; /* Max size of the preview or video
++                                * capture frames
++                                */
++      u32 max_preview_video_h;
++      u32 num_preview_video_frames;
++
++      /** Sets the height of the circular buffer for stills capture. */
++      u32 stills_capture_circular_buffer_height;
++
++      /** Allows preview/encode to resume as fast as possible after the stills
++       * input frame has been received, and then processes the still frame in
++       * the background whilst preview/encode has resumed.
++       * Actual mode is controlled by MMAL_PARAMETER_CAPTURE_MODE.
++       */
++      u32 fast_preview_resume;
++
++      /** Selects algorithm for timestamping frames if
++       * there is no clock component connected.
++       * enum mmal_parameter_camera_config_timestamp_mode
++       */
++      s32 use_stc_timestamp;
++};
++
++enum mmal_parameter_exposuremode {
++      MMAL_PARAM_EXPOSUREMODE_OFF,
++      MMAL_PARAM_EXPOSUREMODE_AUTO,
++      MMAL_PARAM_EXPOSUREMODE_NIGHT,
++      MMAL_PARAM_EXPOSUREMODE_NIGHTPREVIEW,
++      MMAL_PARAM_EXPOSUREMODE_BACKLIGHT,
++      MMAL_PARAM_EXPOSUREMODE_SPOTLIGHT,
++      MMAL_PARAM_EXPOSUREMODE_SPORTS,
++      MMAL_PARAM_EXPOSUREMODE_SNOW,
++      MMAL_PARAM_EXPOSUREMODE_BEACH,
++      MMAL_PARAM_EXPOSUREMODE_VERYLONG,
++      MMAL_PARAM_EXPOSUREMODE_FIXEDFPS,
++      MMAL_PARAM_EXPOSUREMODE_ANTISHAKE,
++      MMAL_PARAM_EXPOSUREMODE_FIREWORKS,
++};
++
++enum mmal_parameter_exposuremeteringmode {
++      MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE,
++      MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT,
++      MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT,
++      MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX,
++};
++
++enum mmal_parameter_awbmode {
++      MMAL_PARAM_AWBMODE_OFF,
++      MMAL_PARAM_AWBMODE_AUTO,
++      MMAL_PARAM_AWBMODE_SUNLIGHT,
++      MMAL_PARAM_AWBMODE_CLOUDY,
++      MMAL_PARAM_AWBMODE_SHADE,
++      MMAL_PARAM_AWBMODE_TUNGSTEN,
++      MMAL_PARAM_AWBMODE_FLUORESCENT,
++      MMAL_PARAM_AWBMODE_INCANDESCENT,
++      MMAL_PARAM_AWBMODE_FLASH,
++      MMAL_PARAM_AWBMODE_HORIZON,
++};
++
++enum mmal_parameter_imagefx {
++      MMAL_PARAM_IMAGEFX_NONE,
++      MMAL_PARAM_IMAGEFX_NEGATIVE,
++      MMAL_PARAM_IMAGEFX_SOLARIZE,
++      MMAL_PARAM_IMAGEFX_POSTERIZE,
++      MMAL_PARAM_IMAGEFX_WHITEBOARD,
++      MMAL_PARAM_IMAGEFX_BLACKBOARD,
++      MMAL_PARAM_IMAGEFX_SKETCH,
++      MMAL_PARAM_IMAGEFX_DENOISE,
++      MMAL_PARAM_IMAGEFX_EMBOSS,
++      MMAL_PARAM_IMAGEFX_OILPAINT,
++      MMAL_PARAM_IMAGEFX_HATCH,
++      MMAL_PARAM_IMAGEFX_GPEN,
++      MMAL_PARAM_IMAGEFX_PASTEL,
++      MMAL_PARAM_IMAGEFX_WATERCOLOUR,
++      MMAL_PARAM_IMAGEFX_FILM,
++      MMAL_PARAM_IMAGEFX_BLUR,
++      MMAL_PARAM_IMAGEFX_SATURATION,
++      MMAL_PARAM_IMAGEFX_COLOURSWAP,
++      MMAL_PARAM_IMAGEFX_WASHEDOUT,
++      MMAL_PARAM_IMAGEFX_POSTERISE,
++      MMAL_PARAM_IMAGEFX_COLOURPOINT,
++      MMAL_PARAM_IMAGEFX_COLOURBALANCE,
++      MMAL_PARAM_IMAGEFX_CARTOON,
++};
++
++enum MMAL_PARAM_FLICKERAVOID_T {
++      MMAL_PARAM_FLICKERAVOID_OFF,
++      MMAL_PARAM_FLICKERAVOID_AUTO,
++      MMAL_PARAM_FLICKERAVOID_50HZ,
++      MMAL_PARAM_FLICKERAVOID_60HZ,
++      MMAL_PARAM_FLICKERAVOID_MAX = 0x7FFFFFFF
++};
++
++struct mmal_parameter_awbgains {
++      struct mmal_parameter_rational r_gain;  /**< Red gain */
++      struct mmal_parameter_rational b_gain;  /**< Blue gain */
++};
++
++/** Manner of video rate control */
++enum mmal_parameter_rate_control_mode {
++      MMAL_VIDEO_RATECONTROL_DEFAULT,
++      MMAL_VIDEO_RATECONTROL_VARIABLE,
++      MMAL_VIDEO_RATECONTROL_CONSTANT,
++      MMAL_VIDEO_RATECONTROL_VARIABLE_SKIP_FRAMES,
++      MMAL_VIDEO_RATECONTROL_CONSTANT_SKIP_FRAMES
++};
++
++enum mmal_video_profile {
++      MMAL_VIDEO_PROFILE_H263_BASELINE,
++      MMAL_VIDEO_PROFILE_H263_H320CODING,
++      MMAL_VIDEO_PROFILE_H263_BACKWARDCOMPATIBLE,
++      MMAL_VIDEO_PROFILE_H263_ISWV2,
++      MMAL_VIDEO_PROFILE_H263_ISWV3,
++      MMAL_VIDEO_PROFILE_H263_HIGHCOMPRESSION,
++      MMAL_VIDEO_PROFILE_H263_INTERNET,
++      MMAL_VIDEO_PROFILE_H263_INTERLACE,
++      MMAL_VIDEO_PROFILE_H263_HIGHLATENCY,
++      MMAL_VIDEO_PROFILE_MP4V_SIMPLE,
++      MMAL_VIDEO_PROFILE_MP4V_SIMPLESCALABLE,
++      MMAL_VIDEO_PROFILE_MP4V_CORE,
++      MMAL_VIDEO_PROFILE_MP4V_MAIN,
++      MMAL_VIDEO_PROFILE_MP4V_NBIT,
++      MMAL_VIDEO_PROFILE_MP4V_SCALABLETEXTURE,
++      MMAL_VIDEO_PROFILE_MP4V_SIMPLEFACE,
++      MMAL_VIDEO_PROFILE_MP4V_SIMPLEFBA,
++      MMAL_VIDEO_PROFILE_MP4V_BASICANIMATED,
++      MMAL_VIDEO_PROFILE_MP4V_HYBRID,
++      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDREALTIME,
++      MMAL_VIDEO_PROFILE_MP4V_CORESCALABLE,
++      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDCODING,
++      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDCORE,
++      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDSCALABLE,
++      MMAL_VIDEO_PROFILE_MP4V_ADVANCEDSIMPLE,
++      MMAL_VIDEO_PROFILE_H264_BASELINE,
++      MMAL_VIDEO_PROFILE_H264_MAIN,
++      MMAL_VIDEO_PROFILE_H264_EXTENDED,
++      MMAL_VIDEO_PROFILE_H264_HIGH,
++      MMAL_VIDEO_PROFILE_H264_HIGH10,
++      MMAL_VIDEO_PROFILE_H264_HIGH422,
++      MMAL_VIDEO_PROFILE_H264_HIGH444,
++      MMAL_VIDEO_PROFILE_H264_CONSTRAINED_BASELINE,
++      MMAL_VIDEO_PROFILE_DUMMY = 0x7FFFFFFF
++};
++
++enum mmal_video_level {
++      MMAL_VIDEO_LEVEL_H263_10,
++      MMAL_VIDEO_LEVEL_H263_20,
++      MMAL_VIDEO_LEVEL_H263_30,
++      MMAL_VIDEO_LEVEL_H263_40,
++      MMAL_VIDEO_LEVEL_H263_45,
++      MMAL_VIDEO_LEVEL_H263_50,
++      MMAL_VIDEO_LEVEL_H263_60,
++      MMAL_VIDEO_LEVEL_H263_70,
++      MMAL_VIDEO_LEVEL_MP4V_0,
++      MMAL_VIDEO_LEVEL_MP4V_0b,
++      MMAL_VIDEO_LEVEL_MP4V_1,
++      MMAL_VIDEO_LEVEL_MP4V_2,
++      MMAL_VIDEO_LEVEL_MP4V_3,
++      MMAL_VIDEO_LEVEL_MP4V_4,
++      MMAL_VIDEO_LEVEL_MP4V_4a,
++      MMAL_VIDEO_LEVEL_MP4V_5,
++      MMAL_VIDEO_LEVEL_MP4V_6,
++      MMAL_VIDEO_LEVEL_H264_1,
++      MMAL_VIDEO_LEVEL_H264_1b,
++      MMAL_VIDEO_LEVEL_H264_11,
++      MMAL_VIDEO_LEVEL_H264_12,
++      MMAL_VIDEO_LEVEL_H264_13,
++      MMAL_VIDEO_LEVEL_H264_2,
++      MMAL_VIDEO_LEVEL_H264_21,
++      MMAL_VIDEO_LEVEL_H264_22,
++      MMAL_VIDEO_LEVEL_H264_3,
++      MMAL_VIDEO_LEVEL_H264_31,
++      MMAL_VIDEO_LEVEL_H264_32,
++      MMAL_VIDEO_LEVEL_H264_4,
++      MMAL_VIDEO_LEVEL_H264_41,
++      MMAL_VIDEO_LEVEL_H264_42,
++      MMAL_VIDEO_LEVEL_H264_5,
++      MMAL_VIDEO_LEVEL_H264_51,
++      MMAL_VIDEO_LEVEL_DUMMY = 0x7FFFFFFF
++};
++
++struct mmal_parameter_video_profile {
++      enum mmal_video_profile profile;
++      enum mmal_video_level level;
++};
++
++/* video parameters */
++
++enum mmal_parameter_video_type {
++      /** @ref MMAL_DISPLAYREGION_T */
++      MMAL_PARAMETER_DISPLAYREGION = MMAL_PARAMETER_GROUP_VIDEO,
++
++      /** @ref MMAL_PARAMETER_VIDEO_PROFILE_T */
++      MMAL_PARAMETER_SUPPORTED_PROFILES,
++
++      /** @ref MMAL_PARAMETER_VIDEO_PROFILE_T */
++      MMAL_PARAMETER_PROFILE,
++
++      /** @ref MMAL_PARAMETER_UINT32_T */
++      MMAL_PARAMETER_INTRAPERIOD,
++
++      /** @ref MMAL_PARAMETER_VIDEO_RATECONTROL_T */
++      MMAL_PARAMETER_RATECONTROL,
++
++      /** @ref MMAL_PARAMETER_VIDEO_NALUNITFORMAT_T */
++      MMAL_PARAMETER_NALUNITFORMAT,
++
++      /** @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_MINIMISE_FRAGMENTATION,
++
++      /** @ref MMAL_PARAMETER_UINT32_T.
++       * Setting the value to zero resets to the default (one slice per
++       * frame).
++       */
++      MMAL_PARAMETER_MB_ROWS_PER_SLICE,
++
++      /** @ref MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION_T */
++      MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION,
++
++      /** @ref MMAL_PARAMETER_VIDEO_EEDE_ENABLE_T */
++      MMAL_PARAMETER_VIDEO_EEDE_ENABLE,
++
++      /** @ref MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE_T */
++      MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE,
++
++      /** @ref MMAL_PARAMETER_BOOLEAN_T. Request an I-frame. */
++      MMAL_PARAMETER_VIDEO_REQUEST_I_FRAME,
++      /** @ref MMAL_PARAMETER_VIDEO_INTRA_REFRESH_T */
++      MMAL_PARAMETER_VIDEO_INTRA_REFRESH,
++
++      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
++      MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT,
++
++      /** @ref MMAL_PARAMETER_UINT32_T. Run-time bit rate control */
++      MMAL_PARAMETER_VIDEO_BIT_RATE,
++
++      /** @ref MMAL_PARAMETER_FRAME_RATE_T */
++      MMAL_PARAMETER_VIDEO_FRAME_RATE,
++
++      /** @ref MMAL_PARAMETER_UINT32_T. */
++      MMAL_PARAMETER_VIDEO_ENCODE_MIN_QUANT,
++
++      /** @ref MMAL_PARAMETER_UINT32_T. */
++      MMAL_PARAMETER_VIDEO_ENCODE_MAX_QUANT,
++
++      /** @ref MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL_T. */
++      MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL,
++
++      MMAL_PARAMETER_EXTRA_BUFFERS, /**< @ref MMAL_PARAMETER_UINT32_T. */
++      /** @ref MMAL_PARAMETER_UINT32_T.
++       * Changing this parameter from the default can reduce frame rate
++       * because image buffers need to be re-pitched.
++       */
++      MMAL_PARAMETER_VIDEO_ALIGN_HORIZ,
++
++      /** @ref MMAL_PARAMETER_UINT32_T.
++       * Changing this parameter from the default can reduce frame rate
++       * because image buffers need to be re-pitched.
++       */
++      MMAL_PARAMETER_VIDEO_ALIGN_VERT,
++
++      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
++      MMAL_PARAMETER_VIDEO_DROPPABLE_PFRAMES,
++
++      /** @ref MMAL_PARAMETER_UINT32_T. */
++      MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT,
++
++      /**< @ref MMAL_PARAMETER_UINT32_T. */
++      MMAL_PARAMETER_VIDEO_ENCODE_QP_P,
++
++      /**< @ref MMAL_PARAMETER_UINT32_T. */
++      MMAL_PARAMETER_VIDEO_ENCODE_RC_SLICE_DQUANT,
++
++      /** @ref MMAL_PARAMETER_UINT32_T */
++      MMAL_PARAMETER_VIDEO_ENCODE_FRAME_LIMIT_BITS,
++
++      /** @ref MMAL_PARAMETER_UINT32_T. */
++      MMAL_PARAMETER_VIDEO_ENCODE_PEAK_RATE,
++
++      /* H264 specific parameters */
++
++      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
++      MMAL_PARAMETER_VIDEO_ENCODE_H264_DISABLE_CABAC,
++
++      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
++      MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_LATENCY,
++
++      /** @ref MMAL_PARAMETER_BOOLEAN_T. */
++      MMAL_PARAMETER_VIDEO_ENCODE_H264_AU_DELIMITERS,
++
++      /** @ref MMAL_PARAMETER_UINT32_T. */
++      MMAL_PARAMETER_VIDEO_ENCODE_H264_DEBLOCK_IDC,
++
++      /** @ref MMAL_PARAMETER_VIDEO_ENCODER_H264_MB_INTRA_MODES_T. */
++      MMAL_PARAMETER_VIDEO_ENCODE_H264_MB_INTRA_MODE,
++
++      /** @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_VIDEO_ENCODE_HEADER_ON_OPEN,
++
++      /** @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_VIDEO_ENCODE_PRECODE_FOR_QP,
++
++      /** @ref MMAL_PARAMETER_VIDEO_DRM_INIT_INFO_T. */
++      MMAL_PARAMETER_VIDEO_DRM_INIT_INFO,
++
++      /** @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_VIDEO_TIMESTAMP_FIFO,
++
++      /** @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_VIDEO_DECODE_ERROR_CONCEALMENT,
++
++      /** @ref MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER_T. */
++      MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER,
++
++      /** @ref MMAL_PARAMETER_BYTES_T */
++      MMAL_PARAMETER_VIDEO_DECODE_CONFIG_VD3,
++
++      /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_VIDEO_ENCODE_H264_VCL_HRD_PARAMETERS,
++
++      /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_DELAY_HRD_FLAG,
++
++      /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++      MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER
++};
++
++/** Valid mirror modes */
++enum mmal_parameter_mirror {
++      MMAL_PARAM_MIRROR_NONE,
++      MMAL_PARAM_MIRROR_VERTICAL,
++      MMAL_PARAM_MIRROR_HORIZONTAL,
++      MMAL_PARAM_MIRROR_BOTH,
++};
++
++enum mmal_parameter_displaytransform {
++      MMAL_DISPLAY_ROT0 = 0,
++      MMAL_DISPLAY_MIRROR_ROT0 = 1,
++      MMAL_DISPLAY_MIRROR_ROT180 = 2,
++      MMAL_DISPLAY_ROT180 = 3,
++      MMAL_DISPLAY_MIRROR_ROT90 = 4,
++      MMAL_DISPLAY_ROT270 = 5,
++      MMAL_DISPLAY_ROT90 = 6,
++      MMAL_DISPLAY_MIRROR_ROT270 = 7,
++};
++
++enum mmal_parameter_displaymode {
++      MMAL_DISPLAY_MODE_FILL = 0,
++      MMAL_DISPLAY_MODE_LETTERBOX = 1,
++};
++
++enum mmal_parameter_displayset {
++      MMAL_DISPLAY_SET_NONE = 0,
++      MMAL_DISPLAY_SET_NUM = 1,
++      MMAL_DISPLAY_SET_FULLSCREEN = 2,
++      MMAL_DISPLAY_SET_TRANSFORM = 4,
++      MMAL_DISPLAY_SET_DEST_RECT = 8,
++      MMAL_DISPLAY_SET_SRC_RECT = 0x10,
++      MMAL_DISPLAY_SET_MODE = 0x20,
++      MMAL_DISPLAY_SET_PIXEL = 0x40,
++      MMAL_DISPLAY_SET_NOASPECT = 0x80,
++      MMAL_DISPLAY_SET_LAYER = 0x100,
++      MMAL_DISPLAY_SET_COPYPROTECT = 0x200,
++      MMAL_DISPLAY_SET_ALPHA = 0x400,
++};
++
++/* rectangle, used lots so it gets its own struct */
++struct vchiq_mmal_rect {
++      s32 x;
++      s32 y;
++      s32 width;
++      s32 height;
++};
++
++struct mmal_parameter_displayregion {
++      /** Bitfield that indicates which fields are set and should be
++       * used. All other fields will maintain their current value.
++       * \ref MMAL_DISPLAYSET_T defines the bits that can be
++       * combined.
++       */
++      u32 set;
++
++      /** Describes the display output device, with 0 typically
++       * being a directly connected LCD display.  The actual values
++       * will depend on the hardware.  Code using hard-wired numbers
++       * (e.g. 2) is certain to fail.
++       */
++
++      u32 display_num;
++      /** Indicates that we are using the full device screen area,
++       * rather than a window of the display.  If zero, then
++       * dest_rect is used to specify a region of the display to
++       * use.
++       */
++
++      s32 fullscreen;
++      /** Indicates any rotation or flipping used to map frames onto
++       * the natural display orientation.
++       */
++      u32 transform; /* enum mmal_parameter_displaytransform */
++
++      /** Where to display the frame within the screen, if
++       * fullscreen is zero.
++       */
++      struct vchiq_mmal_rect dest_rect;
++
++      /** Indicates which area of the frame to display. If all
++       * values are zero, the whole frame will be used.
++       */
++      struct vchiq_mmal_rect src_rect;
++
++      /** If set to non-zero, indicates that any display scaling
++       * should disregard the aspect ratio of the frame region being
++       * displayed.
++       */
++      s32 noaspect;
++
++      /** Indicates how the image should be scaled to fit the
++       * display. \code MMAL_DISPLAY_MODE_FILL \endcode indicates
++       * that the image should fill the screen by potentially
++       * cropping the frames.  Setting \code mode \endcode to \code
++       * MMAL_DISPLAY_MODE_LETTERBOX \endcode indicates that all the
++       * source region should be displayed and black bars added if
++       * necessary.
++       */
++      u32 mode; /* enum mmal_parameter_displaymode */
++
++      /** If non-zero, defines the width of a source pixel relative
++       * to \code pixel_y \endcode.  If zero, then pixels default to
++       * being square.
++       */
++      u32 pixel_x;
++
++      /** If non-zero, defines the height of a source pixel relative
++       * to \code pixel_x \endcode.  If zero, then pixels default to
++       * being square.
++       */
++      u32 pixel_y;
++
++      /** Sets the relative depth of the images, with greater values
++       * being in front of smaller values.
++       */
++      u32 layer;
++
++      /** Set to non-zero to ensure copy protection is used on
++       * output.
++       */
++      s32 copyprotect_required;
++
++      /** Level of opacity of the layer, where zero is fully
++       * transparent and 255 is fully opaque.
++       */
++      u32 alpha;
++};
++
++#define MMAL_MAX_IMAGEFX_PARAMETERS 5
++
++struct mmal_parameter_imagefx_parameters {
++      enum mmal_parameter_imagefx effect;
++      u32 num_effect_params;
++      u32 effect_parameter[MMAL_MAX_IMAGEFX_PARAMETERS];
++};
++
++#define MMAL_PARAMETER_CAMERA_INFO_MAX_CAMERAS 4
++#define MMAL_PARAMETER_CAMERA_INFO_MAX_FLASHES 2
++#define MMAL_PARAMETER_CAMERA_INFO_MAX_STR_LEN 16
++
++struct mmal_parameter_camera_info_camera_t {
++      u32    port_id;
++      u32    max_width;
++      u32    max_height;
++      u32    lens_present;
++      u8     camera_name[MMAL_PARAMETER_CAMERA_INFO_MAX_STR_LEN];
++};
++
++enum mmal_parameter_camera_info_flash_type_t {
++      /* Make values explicit to ensure they match values in config ini */
++      MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_XENON = 0,
++      MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_LED   = 1,
++      MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_OTHER = 2,
++      MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_MAX = 0x7FFFFFFF
++};
++
++struct mmal_parameter_camera_info_flash_t {
++      enum mmal_parameter_camera_info_flash_type_t flash_type;
++};
++
++struct mmal_parameter_camera_info_t {
++      u32                            num_cameras;
++      u32                            num_flashes;
++      struct mmal_parameter_camera_info_camera_t
++                              cameras[MMAL_PARAMETER_CAMERA_INFO_MAX_CAMERAS];
++      struct mmal_parameter_camera_info_flash_t
++                              flashes[MMAL_PARAMETER_CAMERA_INFO_MAX_FLASHES];
++};
++
++#endif
+--- /dev/null
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
+@@ -0,0 +1,166 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Broadcom BM2835 V4L2 driver
++ *
++ * Copyright © 2013 Raspberry Pi (Trading) Ltd.
++ *
++ * Authors: Vincent Sanders @ Collabora
++ *          Dave Stevenson @ Broadcom
++ *            (now dave.stevenson@raspberrypi.org)
++ *          Simon Mellor @ Broadcom
++ *          Luke Diamand @ Broadcom
++ *
++ * MMAL interface to VCHIQ message passing
++ */
++
++#ifndef MMAL_VCHIQ_H
++#define MMAL_VCHIQ_H
++
++#include "mmal-msg-format.h"
++
++#define MAX_PORT_COUNT 4
++
++/* Maximum size of the format extradata. */
++#define MMAL_FORMAT_EXTRADATA_MAX_SIZE 128
++
++struct vchiq_mmal_instance;
++
++enum vchiq_mmal_es_type {
++      MMAL_ES_TYPE_UNKNOWN,     /**< Unknown elementary stream type */
++      MMAL_ES_TYPE_CONTROL,     /**< Elementary stream of control commands */
++      MMAL_ES_TYPE_AUDIO,       /**< Audio elementary stream */
++      MMAL_ES_TYPE_VIDEO,       /**< Video elementary stream */
++      MMAL_ES_TYPE_SUBPICTURE   /**< Sub-picture elementary stream */
++};
++
++struct vchiq_mmal_port_buffer {
++      unsigned int num; /* number of buffers */
++      u32 size; /* size of buffers */
++      u32 alignment; /* alignment of buffers */
++};
++
++struct vchiq_mmal_port;
++
++typedef void (*vchiq_mmal_buffer_cb)(
++              struct vchiq_mmal_instance  *instance,
++              struct vchiq_mmal_port *port,
++              int status, struct mmal_buffer *buffer,
++              unsigned long length, u32 mmal_flags, s64 dts, s64 pts);
++
++struct vchiq_mmal_port {
++      bool enabled;
++      u32 handle;
++      u32 type; /* port type, cached to use on port info set */
++      u32 index; /* port index, cached to use on port info set */
++
++      /* component port belongs to, allows simple deref */
++      struct vchiq_mmal_component *component;
++
++      struct vchiq_mmal_port *connected; /* port conencted to */
++
++      /* buffer info */
++      struct vchiq_mmal_port_buffer minimum_buffer;
++      struct vchiq_mmal_port_buffer recommended_buffer;
++      struct vchiq_mmal_port_buffer current_buffer;
++
++      /* stream format */
++      struct mmal_es_format_local format;
++      /* elementary stream format */
++      union mmal_es_specific_format es;
++
++      /* data buffers to fill */
++      struct list_head buffers;
++      /* lock to serialise adding and removing buffers from list */
++      spinlock_t slock;
++
++      /* Count of buffers the VPU has yet to return */
++      atomic_t buffers_with_vpu;
++      /* callback on buffer completion */
++      vchiq_mmal_buffer_cb buffer_cb;
++      /* callback context */
++      void *cb_ctx;
++};
++
++struct vchiq_mmal_component {
++      bool enabled;
++      u32 handle;  /* VideoCore handle for component */
++      u32 inputs;  /* Number of input ports */
++      u32 outputs; /* Number of output ports */
++      u32 clocks;  /* Number of clock ports */
++      struct vchiq_mmal_port control; /* control port */
++      struct vchiq_mmal_port input[MAX_PORT_COUNT]; /* input ports */
++      struct vchiq_mmal_port output[MAX_PORT_COUNT]; /* output ports */
++      struct vchiq_mmal_port clock[MAX_PORT_COUNT]; /* clock ports */
++};
++
++int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance);
++int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance);
++
++/* Initialise a mmal component and its ports
++ *
++ */
++int vchiq_mmal_component_init(
++              struct vchiq_mmal_instance *instance,
++              const char *name,
++              struct vchiq_mmal_component **component_out);
++
++int vchiq_mmal_component_finalise(
++              struct vchiq_mmal_instance *instance,
++              struct vchiq_mmal_component *component);
++
++int vchiq_mmal_component_enable(
++              struct vchiq_mmal_instance *instance,
++              struct vchiq_mmal_component *component);
++
++int vchiq_mmal_component_disable(
++              struct vchiq_mmal_instance *instance,
++              struct vchiq_mmal_component *component);
++
++/* enable a mmal port
++ *
++ * enables a port and if a buffer callback provided enque buffer
++ * headers as appropriate for the port.
++ */
++int vchiq_mmal_port_enable(
++              struct vchiq_mmal_instance *instance,
++              struct vchiq_mmal_port *port,
++              vchiq_mmal_buffer_cb buffer_cb);
++
++/* disable a port
++ *
++ * disable a port will dequeue any pending buffers
++ */
++int vchiq_mmal_port_disable(struct vchiq_mmal_instance *instance,
++                          struct vchiq_mmal_port *port);
++
++int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance,
++                                struct vchiq_mmal_port *port,
++                                u32 parameter,
++                                void *value,
++                                u32 value_size);
++
++int vchiq_mmal_port_parameter_get(struct vchiq_mmal_instance *instance,
++                                struct vchiq_mmal_port *port,
++                                u32 parameter,
++                                void *value,
++                                u32 *value_size);
++
++int vchiq_mmal_port_set_format(struct vchiq_mmal_instance *instance,
++                             struct vchiq_mmal_port *port);
++
++int vchiq_mmal_port_connect_tunnel(struct vchiq_mmal_instance *instance,
++                                 struct vchiq_mmal_port *src,
++                                 struct vchiq_mmal_port *dst);
++
++int vchiq_mmal_version(struct vchiq_mmal_instance *instance,
++                     u32 *major_out,
++                     u32 *minor_out);
++
++int vchiq_mmal_submit_buffer(struct vchiq_mmal_instance *instance,
++                           struct vchiq_mmal_port *port,
++                           struct mmal_buffer *buf);
++
++int mmal_vchi_buffer_init(struct vchiq_mmal_instance *instance,
++                        struct mmal_buffer *buf);
++int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf);
++#endif /* MMAL_VCHIQ_H */