aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/vc04_services/vchiq-mmal
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/vc04_services/vchiq-mmal')
-rw-r--r--drivers/staging/vc04_services/vchiq-mmal/Kconfig7
-rw-r--r--drivers/staging/vc04_services/vchiq-mmal/Makefile9
-rw-r--r--drivers/staging/vc04_services/vchiq-mmal/mmal-common.h65
-rw-r--r--drivers/staging/vc04_services/vchiq-mmal/mmal-encodings.h124
-rw-r--r--drivers/staging/vc04_services/vchiq-mmal/mmal-msg-common.h48
-rw-r--r--drivers/staging/vc04_services/vchiq-mmal/mmal-msg-format.h106
-rw-r--r--drivers/staging/vc04_services/vchiq-mmal/mmal-msg-port.h109
-rw-r--r--drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h406
-rw-r--r--drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h755
-rw-r--r--drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c1941
-rw-r--r--drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h168
11 files changed, 3738 insertions, 0 deletions
diff --git a/drivers/staging/vc04_services/vchiq-mmal/Kconfig b/drivers/staging/vc04_services/vchiq-mmal/Kconfig
new file mode 100644
index 000000000000..500c0d12e4ff
--- /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)
+ help
+ Enables the MMAL API over VCHIQ interface as used for the
+ majority of the multimedia services on VideoCore.
+ Defaults to Y when the Broadcomd BCM2835 camera host is selected.
diff --git a/drivers/staging/vc04_services/vchiq-mmal/Makefile b/drivers/staging/vc04_services/vchiq-mmal/Makefile
new file mode 100644
index 000000000000..b2a830f48acc
--- /dev/null
+++ b/drivers/staging/vc04_services/vchiq-mmal/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+bcm2835-mmal-vchiq-objs := mmal-vchiq.o
+
+obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += bcm2835-mmal-vchiq.o
+
+ccflags-y += \
+ -I$(srctree)/$(src)/.. \
+ -I$(srctree)/$(src)/../include \
+ -D__VCCOREVER__=0x04000000
diff --git a/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h b/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
new file mode 100644
index 000000000000..5bd7410a034a
--- /dev/null
+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
@@ -0,0 +1,65 @@
+/* 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 {
+ 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;
+
+ unsigned long length;
+ u32 mmal_flags;
+ s64 dts;
+ s64 pts;
+};
+
+/* */
+struct mmal_colourfx {
+ s32 enable;
+ u32 u;
+ u32 v;
+};
+#endif
diff --git a/drivers/staging/vc04_services/vchiq-mmal/mmal-encodings.h b/drivers/staging/vc04_services/vchiq-mmal/mmal-encodings.h
new file mode 100644
index 000000000000..2be9941a1f30
--- /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 */
diff --git a/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-common.h b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-common.h
new file mode 100644
index 000000000000..342c9b670f7e
--- /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 */
diff --git a/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-format.h b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-format.h
new file mode 100644
index 000000000000..a118efd21d98
--- /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 */
diff --git a/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-port.h b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-port.h
new file mode 100644
index 000000000000..3fa3f2a578f0
--- /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.
+ */
+};
diff --git a/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h
new file mode 100644
index 000000000000..b636e889c8a1
--- /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
+
+/* 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"
+#include "mmal-vchiq.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 */
+ u32 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 */
+ u32 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
diff --git a/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h b/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h
new file mode 100644
index 000000000000..a1e39b1b1701
--- /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 {
+ 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 {
+ 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 {
+ /* 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 {
+ enum mmal_parameter_camera_info_flash_type flash_type;
+};
+
+struct mmal_parameter_camera_info {
+ u32 num_cameras;
+ u32 num_flashes;
+ struct mmal_parameter_camera_info_camera
+ cameras[MMAL_PARAMETER_CAMERA_INFO_MAX_CAMERAS];
+ struct mmal_parameter_camera_info_flash
+ flashes[MMAL_PARAMETER_CAMERA_INFO_MAX_FLASHES];
+};
+
+#endif
diff --git a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
new file mode 100644
index 000000000000..e798d494f00f
--- /dev/null
+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
@@ -0,0 +1,1941 @@
+// 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 <linux/raspberrypi/vchiq.h>
+#include <media/videobuf2-vmalloc.h>
+
+#include "mmal-common.h"
+#include "mmal-vchiq.h"
+#include "mmal-msg.h"
+
+/*
+ * maximum number of components supported.
+ * This matches the maximum permitted by default on the VPU
+ */
+#define VCHIQ_MMAL_MAX_COMPONENTS 64
+
+/*
+ * Timeout for synchronous msg responses in seconds.
+ * Helpful to increase this if stopping in the VPU debugger.
+ */
+#define SYNC_MSG_TIMEOUT 3
+
+/*#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 */
+ struct vchiq_header *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 {
+ unsigned int service_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;
+
+ 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);
+ struct mmal_buffer *buffer = msg_context->u.bulk.buffer;
+
+ if (!buffer) {
+ pr_err("%s: ctx: %p, No mmal buffer to pass details\n",
+ __func__, msg_context);
+ return;
+ }
+
+ buffer->length = msg_context->u.bulk.buffer_used;
+ buffer->mmal_flags = msg_context->u.bulk.mmal_flags;
+ buffer->dts = msg_context->u.bulk.dts;
+ buffer->pts = msg_context->u.bulk.pts;
+
+ 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);
+}
+
+/* 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
+ * vchiq_bulk_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 */
+ vchiq_use_service(instance->service_handle);
+ ret = vchiq_bulk_receive(instance->service_handle,
+ msg_context->u.bulk.buffer->buffer,
+ /* Actual receive needs to be a multiple
+ * of 4 bytes
+ */
+ (len + 3) & ~3,
+ msg_context,
+ VCHIQ_BULK_MODE_CALLBACK);
+
+ vchiq_release_service(instance->service_handle);
+
+ if (ret != 0)
+ pr_err("%s: ctx: %p, vchiq_bulk_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:%u buffer:%p\n", instance->service_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;
+
+ vchiq_use_service(instance->service_handle);
+
+ ret = vchiq_queue_kernel_message(instance->service_handle, &m,
+ sizeof(struct mmal_msg_header) +
+ sizeof(m.u.buffer_from_host));
+ if (ret)
+ atomic_dec(&port->buffers_with_vpu);
+
+ vchiq_release_service(instance->service_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 enum vchiq_status service_callback(enum vchiq_reason reason,
+ struct vchiq_header *header,
+ unsigned int handle, void *bulk_ctx)
+{
+ struct vchiq_mmal_instance *instance = vchiq_get_service_userdata(handle);
+ u32 msg_len;
+ struct mmal_msg *msg;
+ struct mmal_msg_context *msg_context;
+
+ if (!instance) {
+ pr_err("Message callback passed NULL instance\n");
+ return VCHIQ_SUCCESS;
+ }
+
+ switch (reason) {
+ case VCHIQ_MESSAGE_AVAILABLE:
+ msg = (void *)header->data;
+ msg_len = header->size;
+
+ 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:
+ vchiq_release_message(handle, header);
+ break;
+
+ case MMAL_MSG_TYPE_EVENT_TO_HOST:
+ event_to_host_cb(instance, msg, msg_len);
+ vchiq_release_message(handle, header);
+
+ break;
+
+ case MMAL_MSG_TYPE_BUFFER_TO_HOST:
+ buffer_to_host_cb(instance, msg, msg_len);
+ vchiq_release_message(handle, header);
+ break;
+
+ default:
+ /* messages dependent on header context to complete */
+ if (!msg->h.context) {
+ pr_err("received message context was null!\n");
+ vchiq_release_message(handle, header);
+ break;
+ }
+
+ msg_context = lookup_msg_context(instance,
+ msg->h.context);
+ if (!msg_context) {
+ pr_err("received invalid message context %u!\n",
+ msg->h.context);
+ vchiq_release_message(handle, header);
+ break;
+ }
+
+ /* fill in context values */
+ msg_context->u.sync.msg_handle = header;
+ 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 VCHIQ_BULK_RECEIVE_DONE:
+ bulk_receive_cb(instance, bulk_ctx);
+ break;
+
+ case VCHIQ_BULK_RECEIVE_ABORTED:
+ bulk_abort_cb(instance, bulk_ctx);
+ break;
+
+ case VCHIQ_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;
+ }
+
+ return VCHIQ_SUCCESS;
+}
+
+static int send_synchronous_mmal_msg(struct vchiq_mmal_instance *instance,
+ struct mmal_msg *msg,
+ unsigned int payload_len,
+ struct mmal_msg **msg_out,
+ struct vchiq_header **msg_handle)
+{
+ 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");
+
+ vchiq_use_service(instance->service_handle);
+
+ ret = vchiq_queue_kernel_message(instance->service_handle, msg,
+ sizeof(struct mmal_msg_header) +
+ payload_len);
+
+ vchiq_release_service(instance->service_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,
+ SYNC_MSG_TIMEOUT * 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 = 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;
+ struct vchiq_header *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:
+ vchiq_release_message(instance->service_handle, 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;
+ struct vchiq_header *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 = 0;
+ else
+ port->enabled = 1;
+
+ /* 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);
+
+ vchiq_release_message(instance->service_handle, 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;
+ struct vchiq_header *rmsg_handle;
+
+ /* build component create message */
+ m.h.type = MMAL_MSG_TYPE_COMPONENT_CREATE;
+ m.u.component_create.client_component = component->client_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:
+ vchiq_release_message(instance->service_handle, 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;
+ struct vchiq_header *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:
+
+ vchiq_release_message(instance->service_handle, 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;
+ struct vchiq_header *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:
+ vchiq_release_message(instance->service_handle, 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;
+ struct vchiq_header *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:
+
+ vchiq_release_message(instance->service_handle, 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;
+ struct vchiq_header *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:
+ vchiq_release_message(instance->service_handle, 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;
+ struct vchiq_header *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:
+ vchiq_release_message(instance->service_handle, 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;
+ struct vchiq_header *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:
+ vchiq_release_message(instance->service_handle, 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;
+ struct vchiq_header *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:
+ vchiq_release_message(instance->service_handle, 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;
+ struct vchiq_header *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);
+ } else {
+ memcpy(value, &rmsg->u.port_parameter_get_reply.value,
+ rmsg->u.port_parameter_get_reply.size);
+ }
+ /* Always report the size of the returned parameter to the caller */
+ *value_size = 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:
+ vchiq_release_message(instance->service_handle, 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 = 0;
+
+ 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) {
+ mmalbuf->length = 0;
+ mmalbuf->mmal_flags = 0;
+ mmalbuf->dts = MMAL_TIME_UNKNOWN;
+ mmalbuf->pts = MMAL_TIME_UNKNOWN;
+ port->buffer_cb(instance,
+ port, 0, mmalbuf);
+ }
+ }
+
+ 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 = 1;
+
+ 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 = 0;
+ 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 = NULL;
+
+ if (mutex_lock_interruptible(&instance->vchiq_mutex))
+ return -EINTR;
+
+ for (idx = 0; idx < VCHIQ_MMAL_MAX_COMPONENTS; idx++) {
+ if (!instance->component[idx].in_use) {
+ component = &instance->component[idx];
+ component->in_use = 1;
+ break;
+ }
+ }
+
+ if (!component) {
+ ret = -EINVAL; /* todo is this correct error? */
+ goto unlock;
+ }
+
+ /* We need a handle to reference back to our component structure.
+ * Use the array index in instance->component rather than rolling
+ * another IDR.
+ */
+ component->client_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;
+ }
+
+ *component_out = component;
+
+ mutex_unlock(&instance->vchiq_mutex);
+
+ return 0;
+
+release_component:
+ destroy_component(instance, component);
+unlock:
+ if (component)
+ component->in_use = 0;
+ 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);
+
+ component->in_use = 0;
+
+ 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 = 0;
+
+ 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;
+
+ vchiq_use_service(instance->service_handle);
+
+ status = vchiq_close_service(instance->service_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 struct vchiq_instance *vchiq_instance;
+ struct vchiq_service_params params = {
+ .version = VC_MMAL_VER,
+ .version_min = VC_MMAL_MIN_VER,
+ .fourcc = VCHIQ_MAKE_FOURCC('m', 'm', 'a', 'l'),
+ .callback = service_callback,
+ .userdata = NULL,
+ };
+
+ /* 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 = vchiq_initialise(&vchiq_instance);
+ if (status) {
+ pr_err("Failed to initialise VCHI instance (status=%d)\n",
+ status);
+ return -EIO;
+ }
+
+ status = vchiq_connect(vchiq_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.userdata = instance;
+
+ instance->bulk_wq = alloc_ordered_workqueue("mmal-vchiq",
+ WQ_MEM_RECLAIM);
+ if (!instance->bulk_wq)
+ goto err_free;
+
+ status = vchiq_open_service(vchiq_instance, &params,
+ &instance->service_handle);
+ if (status) {
+ pr_err("Failed to open VCHI service connection (status=%d)\n",
+ status);
+ goto err_close_services;
+ }
+
+ vchiq_release_service(instance->service_handle);
+
+ *out_instance = instance;
+
+ return 0;
+
+err_close_services:
+ vchiq_close_service(instance->service_handle);
+ destroy_workqueue(instance->bulk_wq);
+err_free:
+ vfree(instance->bulk_scratch);
+ kfree(instance);
+ return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(vchiq_mmal_init);
+
+MODULE_DESCRIPTION("BCM2835 MMAL VCHIQ interface");
+MODULE_AUTHOR("Dave Stevenson, <dave.stevenson@raspberrypi.org>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
new file mode 100644
index 000000000000..1dc81ecf9268
--- /dev/null
+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h
@@ -0,0 +1,168 @@
+/* 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-common.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);
+
+struct vchiq_mmal_port {
+ u32 enabled:1;
+ 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 connected 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 {
+ u32 in_use:1;
+ u32 enabled:1;
+ 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 */
+ u32 client_component; /* Used to ref back to client struct */
+};
+
+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 */