From bd10acae08aeb9cd2f555acdbacb98b9fbb02a27 Mon Sep 17 00:00:00 2001 From: Jai Luthra Date: Wed, 29 Oct 2025 16:00:11 +0530 Subject: platform/raspberrypi: Destage VCHIQ MMAL driver Destage the VCHIQ MMAL driver to drivers/platform/raspberrypi. Signed-off-by: Jai Luthra Link: https://patch.msgid.link/20251029-vchiq-destage-v3-7-da8d6c83c2c5@ideasonboard.com Signed-off-by: Greg Kroah-Hartman --- drivers/platform/raspberrypi/Kconfig | 2 + drivers/platform/raspberrypi/Makefile | 1 + drivers/platform/raspberrypi/vchiq-mmal/Kconfig | 7 + drivers/platform/raspberrypi/vchiq-mmal/Makefile | 4 + .../platform/raspberrypi/vchiq-mmal/mmal-common.h | 65 + .../raspberrypi/vchiq-mmal/mmal-encodings.h | 124 ++ .../raspberrypi/vchiq-mmal/mmal-msg-common.h | 45 + .../raspberrypi/vchiq-mmal/mmal-msg-format.h | 108 ++ .../raspberrypi/vchiq-mmal/mmal-msg-port.h | 109 ++ drivers/platform/raspberrypi/vchiq-mmal/mmal-msg.h | 406 ++++ .../raspberrypi/vchiq-mmal/mmal-parameters.h | 752 ++++++++ .../platform/raspberrypi/vchiq-mmal/mmal-vchiq.c | 1949 ++++++++++++++++++++ .../platform/raspberrypi/vchiq-mmal/mmal-vchiq.h | 162 ++ drivers/staging/vc04_services/Kconfig | 2 - drivers/staging/vc04_services/Makefile | 1 - drivers/staging/vc04_services/vchiq-mmal/Kconfig | 7 - drivers/staging/vc04_services/vchiq-mmal/Makefile | 4 - .../staging/vc04_services/vchiq-mmal/mmal-common.h | 65 - .../vc04_services/vchiq-mmal/mmal-encodings.h | 124 -- .../vc04_services/vchiq-mmal/mmal-msg-common.h | 45 - .../vc04_services/vchiq-mmal/mmal-msg-format.h | 108 -- .../vc04_services/vchiq-mmal/mmal-msg-port.h | 109 -- .../staging/vc04_services/vchiq-mmal/mmal-msg.h | 406 ---- .../vc04_services/vchiq-mmal/mmal-parameters.h | 752 -------- .../staging/vc04_services/vchiq-mmal/mmal-vchiq.c | 1949 -------------------- .../staging/vc04_services/vchiq-mmal/mmal-vchiq.h | 162 -- 26 files changed, 3734 insertions(+), 3734 deletions(-) create mode 100644 drivers/platform/raspberrypi/vchiq-mmal/Kconfig create mode 100644 drivers/platform/raspberrypi/vchiq-mmal/Makefile create mode 100644 drivers/platform/raspberrypi/vchiq-mmal/mmal-common.h create mode 100644 drivers/platform/raspberrypi/vchiq-mmal/mmal-encodings.h create mode 100644 drivers/platform/raspberrypi/vchiq-mmal/mmal-msg-common.h create mode 100644 drivers/platform/raspberrypi/vchiq-mmal/mmal-msg-format.h create mode 100644 drivers/platform/raspberrypi/vchiq-mmal/mmal-msg-port.h create mode 100644 drivers/platform/raspberrypi/vchiq-mmal/mmal-msg.h create mode 100644 drivers/platform/raspberrypi/vchiq-mmal/mmal-parameters.h create mode 100644 drivers/platform/raspberrypi/vchiq-mmal/mmal-vchiq.c create mode 100644 drivers/platform/raspberrypi/vchiq-mmal/mmal-vchiq.h delete mode 100644 drivers/staging/vc04_services/vchiq-mmal/Kconfig delete mode 100644 drivers/staging/vc04_services/vchiq-mmal/Makefile delete mode 100644 drivers/staging/vc04_services/vchiq-mmal/mmal-common.h delete mode 100644 drivers/staging/vc04_services/vchiq-mmal/mmal-encodings.h delete mode 100644 drivers/staging/vc04_services/vchiq-mmal/mmal-msg-common.h delete mode 100644 drivers/staging/vc04_services/vchiq-mmal/mmal-msg-format.h delete mode 100644 drivers/staging/vc04_services/vchiq-mmal/mmal-msg-port.h delete mode 100644 drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h delete mode 100644 drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h delete mode 100644 drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c delete mode 100644 drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h (limited to 'drivers') diff --git a/drivers/platform/raspberrypi/Kconfig b/drivers/platform/raspberrypi/Kconfig index 9085e7464ec3..2c928440a47c 100644 --- a/drivers/platform/raspberrypi/Kconfig +++ b/drivers/platform/raspberrypi/Kconfig @@ -47,4 +47,6 @@ config VCHIQ_CDEV endif +source "drivers/platform/raspberrypi/vchiq-mmal/Kconfig" + endif diff --git a/drivers/platform/raspberrypi/Makefile b/drivers/platform/raspberrypi/Makefile index a807571c59a4..2a7c9511e5d8 100644 --- a/drivers/platform/raspberrypi/Makefile +++ b/drivers/platform/raspberrypi/Makefile @@ -12,3 +12,4 @@ ifdef CONFIG_VCHIQ_CDEV vchiq-objs += vchiq-interface/vchiq_dev.o endif +obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += vchiq-mmal/ diff --git a/drivers/platform/raspberrypi/vchiq-mmal/Kconfig b/drivers/platform/raspberrypi/vchiq-mmal/Kconfig new file mode 100644 index 000000000000..c99525a0bb45 --- /dev/null +++ b/drivers/platform/raspberrypi/vchiq-mmal/Kconfig @@ -0,0 +1,7 @@ +config BCM2835_VCHIQ_MMAL + tristate "BCM2835 MMAL VCHIQ service" + depends on BCM2835_VCHIQ + 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/platform/raspberrypi/vchiq-mmal/Makefile b/drivers/platform/raspberrypi/vchiq-mmal/Makefile new file mode 100644 index 000000000000..6937f6534c26 --- /dev/null +++ b/drivers/platform/raspberrypi/vchiq-mmal/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 +bcm2835-mmal-vchiq-objs := mmal-vchiq.o + +obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += bcm2835-mmal-vchiq.o diff --git a/drivers/platform/raspberrypi/vchiq-mmal/mmal-common.h b/drivers/platform/raspberrypi/vchiq-mmal/mmal-common.h new file mode 100644 index 000000000000..b33129403a30 --- /dev/null +++ b/drivers/platform/raspberrypi/vchiq-mmal/mmal-common.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Broadcom BCM2835 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/platform/raspberrypi/vchiq-mmal/mmal-encodings.h b/drivers/platform/raspberrypi/vchiq-mmal/mmal-encodings.h new file mode 100644 index 000000000000..e15ae7b24f73 --- /dev/null +++ b/drivers/platform/raspberrypi/vchiq-mmal/mmal-encodings.h @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Broadcom BCM2835 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/platform/raspberrypi/vchiq-mmal/mmal-msg-common.h b/drivers/platform/raspberrypi/vchiq-mmal/mmal-msg-common.h new file mode 100644 index 000000000000..492d4c5dca08 --- /dev/null +++ b/drivers/platform/raspberrypi/vchiq-mmal/mmal-msg-common.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Broadcom BCM2835 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 + +#include + +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 */ +}; + +#endif /* MMAL_MSG_COMMON_H */ diff --git a/drivers/platform/raspberrypi/vchiq-mmal/mmal-msg-format.h b/drivers/platform/raspberrypi/vchiq-mmal/mmal-msg-format.h new file mode 100644 index 000000000000..5569876d8c7d --- /dev/null +++ b/drivers/platform/raspberrypi/vchiq-mmal/mmal-msg-format.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Broadcom BCM2835 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 + +#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 s32_fract frame_rate; /* Frame rate */ + struct s32_fract 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/platform/raspberrypi/vchiq-mmal/mmal-msg-port.h b/drivers/platform/raspberrypi/vchiq-mmal/mmal-msg-port.h new file mode 100644 index 000000000000..6ee4c1ed7f19 --- /dev/null +++ b/drivers/platform/raspberrypi/vchiq-mmal/mmal-msg-port.h @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Broadcom BCM2835 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/platform/raspberrypi/vchiq-mmal/mmal-msg.h b/drivers/platform/raspberrypi/vchiq-mmal/mmal-msg.h new file mode 100644 index 000000000000..1889494425eb --- /dev/null +++ b/drivers/platform/raspberrypi/vchiq-mmal/mmal-msg.h @@ -0,0 +1,406 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Broadcom BCM2835 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 received 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/platform/raspberrypi/vchiq-mmal/mmal-parameters.h b/drivers/platform/raspberrypi/vchiq-mmal/mmal-parameters.h new file mode 100644 index 000000000000..a0cdd28101f2 --- /dev/null +++ b/drivers/platform/raspberrypi/vchiq-mmal/mmal-parameters.h @@ -0,0 +1,752 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Broadcom BCM2835 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 + +#include + +/** 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, +}; + +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 s32_fract fps_low; + /**< High end of the permitted framerate range */ + struct s32_fract 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 s32_fract r_gain; /**< Red gain */ + struct s32_fract 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/platform/raspberrypi/vchiq-mmal/mmal-vchiq.c b/drivers/platform/raspberrypi/vchiq-mmal/mmal-vchiq.c new file mode 100644 index 000000000000..cd073ed3ea2d --- /dev/null +++ b/drivers/platform/raspberrypi/vchiq-mmal/mmal-vchiq.c @@ -0,0 +1,1949 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Broadcom BCM2835 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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.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; + + 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; + + /* handle for a vchiq instance */ + struct vchiq_instance *vchiq_instance; +}; + +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 within 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->vchiq_instance, instance->service_handle); + ret = vchiq_bulk_receive(instance->vchiq_instance, 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->vchiq_instance, 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 service 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 specific 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->vchiq_instance, instance->service_handle); + + ret = vchiq_queue_kernel_message(instance->vchiq_instance, 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->vchiq_instance, 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 int mmal_service_callback(struct vchiq_instance *vchiq_instance, + enum vchiq_reason reason, struct vchiq_header *header, + unsigned int handle, void *cb_data, + void __user *cb_userdata) +{ + struct vchiq_mmal_instance *instance = vchiq_get_service_userdata(vchiq_instance, 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 0; + } + + 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(vchiq_instance, handle, header); + break; + + case MMAL_MSG_TYPE_EVENT_TO_HOST: + event_to_host_cb(instance, msg, msg_len); + vchiq_release_message(vchiq_instance, handle, header); + + break; + + case MMAL_MSG_TYPE_BUFFER_TO_HOST: + buffer_to_host_cb(instance, msg, msg_len); + vchiq_release_message(vchiq_instance, 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(vchiq_instance, 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(vchiq_instance, 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, cb_data); + break; + + case VCHIQ_BULK_RECEIVE_ABORTED: + bulk_abort_cb(instance, cb_data); + 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 0; +} + +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 time_left; + + /* 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->vchiq_instance, instance->service_handle); + + ret = vchiq_queue_kernel_message(instance->vchiq_instance, instance->service_handle, msg, + sizeof(struct mmal_msg_header) + + payload_len); + + vchiq_release_service(instance->vchiq_instance, instance->service_handle); + + if (ret) { + pr_err("error %d queuing message\n", ret); + release_msg_context(msg_context); + return ret; + } + + time_left = wait_for_completion_timeout(&msg_context->u.sync.cmplt, + SYNC_MSG_TIMEOUT * HZ); + if (time_left == 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.numerator, + port->es.video.frame_rate.denominator, + port->es.video.par.numerator, port->es.video.par.denominator); + } +} + +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->vchiq_instance, 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 = false; + else + port->enabled = true; + + /* copy the values out of the message */ + port->handle = rmsg->u.port_info_get_reply.port_handle; + + /* port type and index cached to use on port info set because + * it does not use a port handle + */ + port->type = rmsg->u.port_info_get_reply.port_type; + port->index = rmsg->u.port_info_get_reply.port_index; + + port->minimum_buffer.num = + rmsg->u.port_info_get_reply.port.buffer_num_min; + port->minimum_buffer.size = + rmsg->u.port_info_get_reply.port.buffer_size_min; + port->minimum_buffer.alignment = + rmsg->u.port_info_get_reply.port.buffer_alignment_min; + + port->recommended_buffer.alignment = + rmsg->u.port_info_get_reply.port.buffer_alignment_min; + port->recommended_buffer.num = + rmsg->u.port_info_get_reply.port.buffer_num_recommended; + + port->current_buffer.num = rmsg->u.port_info_get_reply.port.buffer_num; + port->current_buffer.size = + rmsg->u.port_info_get_reply.port.buffer_size; + + /* stream format */ + port->format.type = rmsg->u.port_info_get_reply.format.type; + port->format.encoding = rmsg->u.port_info_get_reply.format.encoding; + port->format.encoding_variant = + rmsg->u.port_info_get_reply.format.encoding_variant; + port->format.bitrate = rmsg->u.port_info_get_reply.format.bitrate; + port->format.flags = rmsg->u.port_info_get_reply.format.flags; + + /* elementary stream format */ + memcpy(&port->es, + &rmsg->u.port_info_get_reply.es, + sizeof(union mmal_es_specific_format)); + port->format.es = &port->es; + + port->format.extradata_size = + rmsg->u.port_info_get_reply.format.extradata_size; + memcpy(port->format.extradata, + rmsg->u.port_info_get_reply.extradata, + port->format.extradata_size); + + pr_debug("received port info\n"); + dump_port_info(port); + +release_msg: + + pr_debug("%s:result:%d component:0x%x port:%d\n", + __func__, ret, port->component->handle, port->handle); + + vchiq_release_message(instance->vchiq_instance, instance->service_handle, rmsg_handle); + + return ret; +} + +/* create component 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; + strscpy_pad(m.u.component_create.name, name, + sizeof(m.u.component_create.name)); + m.u.component_create.pid = 0; + + 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->vchiq_instance, 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->vchiq_instance, 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->vchiq_instance, 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->vchiq_instance, 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->vchiq_instance, 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->vchiq_instance, 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->vchiq_instance, 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->vchiq_instance, 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->vchiq_instance, 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 = false; + + ret = port_action_port(instance, port, + MMAL_MSG_PORT_ACTION_TYPE_DISABLE); + if (ret == 0) { + /* + * Drain all queued buffers on port. This should only + * apply to buffers that have been queued before the port + * has been enabled. If the port has been enabled and buffers + * passed, then the buffers should have been removed from this + * list, and we should get the relevant callbacks via VCHIQ + * to release the buffers. + */ + spin_lock_irqsave(&port->slock, flags); + + list_for_each_safe(buf_head, q, &port->buffers) { + struct mmal_buffer *mmalbuf; + + mmalbuf = list_entry(buf_head, struct mmal_buffer, + list); + list_del(buf_head); + if (port->buffer_cb) { + 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 = true; + + if (port->buffer_cb) { + /* send buffer headers to videocore */ + hdr_count = 1; + list_for_each_safe(buf_head, q, &port->buffers) { + struct mmal_buffer *mmalbuf; + + mmalbuf = list_entry(buf_head, struct mmal_buffer, + list); + ret = buffer_from_host(instance, port, mmalbuf); + if (ret) + goto done; + + list_del(buf_head); + hdr_count++; + if (hdr_count > port->current_buffer.num) + break; + } + } + + ret = port_info_get(instance, port); + +done: + return ret; +} + +/* ------------------------------------------------------------------ + * Exported API + *------------------------------------------------------------------ + */ + +int vchiq_mmal_port_set_format(struct vchiq_mmal_instance *instance, + struct vchiq_mmal_port *port) +{ + int ret; + + if (mutex_lock_interruptible(&instance->vchiq_mutex)) + return -EINTR; + + ret = port_info_set(instance, port); + if (ret) + goto release_unlock; + + /* read what has actually been set */ + ret = port_info_get(instance, port); + +release_unlock: + mutex_unlock(&instance->vchiq_mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(vchiq_mmal_port_set_format); + +int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance, + struct vchiq_mmal_port *port, + u32 parameter, void *value, u32 value_size) +{ + int ret; + + if (mutex_lock_interruptible(&instance->vchiq_mutex)) + return -EINTR; + + ret = port_parameter_set(instance, port, parameter, value, value_size); + + mutex_unlock(&instance->vchiq_mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(vchiq_mmal_port_parameter_set); + +int vchiq_mmal_port_parameter_get(struct vchiq_mmal_instance *instance, + struct vchiq_mmal_port *port, + u32 parameter, void *value, u32 *value_size) +{ + int ret; + + if (mutex_lock_interruptible(&instance->vchiq_mutex)) + return -EINTR; + + ret = port_parameter_get(instance, port, parameter, value, value_size); + + mutex_unlock(&instance->vchiq_mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(vchiq_mmal_port_parameter_get); + +/* enable a port + * + * enables a port and queues buffers for satisfying callbacks if we + * provide a callback handler + */ +int vchiq_mmal_port_enable(struct vchiq_mmal_instance *instance, + struct vchiq_mmal_port *port, + vchiq_mmal_buffer_cb buffer_cb) +{ + int ret; + + if (mutex_lock_interruptible(&instance->vchiq_mutex)) + return -EINTR; + + /* already enabled - noop */ + if (port->enabled) { + ret = 0; + goto unlock; + } + + port->buffer_cb = buffer_cb; + + ret = port_enable(instance, port); + +unlock: + mutex_unlock(&instance->vchiq_mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(vchiq_mmal_port_enable); + +int vchiq_mmal_port_disable(struct vchiq_mmal_instance *instance, + struct vchiq_mmal_port *port) +{ + int ret; + + if (mutex_lock_interruptible(&instance->vchiq_mutex)) + return -EINTR; + + if (!port->enabled) { + mutex_unlock(&instance->vchiq_mutex); + return 0; + } + + ret = port_disable(instance, port); + + mutex_unlock(&instance->vchiq_mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(vchiq_mmal_port_disable); + +/* ports will be connected in a tunneled manner so data buffers + * are not handled by client. + */ +int vchiq_mmal_port_connect_tunnel(struct vchiq_mmal_instance *instance, + struct vchiq_mmal_port *src, + struct vchiq_mmal_port *dst) +{ + int ret; + + if (mutex_lock_interruptible(&instance->vchiq_mutex)) + return -EINTR; + + /* disconnect ports if connected */ + if (src->connected) { + ret = port_disable(instance, src); + if (ret) { + pr_err("failed disabling src port(%d)\n", ret); + goto release_unlock; + } + + /* do not need to disable the destination port as they + * are connected and it is done automatically + */ + + ret = port_action_handle(instance, src, + MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT, + src->connected->component->handle, + src->connected->handle); + if (ret < 0) { + pr_err("failed disconnecting src port\n"); + goto release_unlock; + } + src->connected->enabled = false; + src->connected = NULL; + } + + if (!dst) { + /* do not make new connection */ + ret = 0; + pr_debug("not making new connection\n"); + goto release_unlock; + } + + /* copy src port format to dst */ + dst->format.encoding = src->format.encoding; + dst->es.video.width = src->es.video.width; + dst->es.video.height = src->es.video.height; + dst->es.video.crop.x = src->es.video.crop.x; + dst->es.video.crop.y = src->es.video.crop.y; + dst->es.video.crop.width = src->es.video.crop.width; + dst->es.video.crop.height = src->es.video.crop.height; + dst->es.video.frame_rate.numerator = src->es.video.frame_rate.numerator; + dst->es.video.frame_rate.denominator = src->es.video.frame_rate.denominator; + + /* 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 = true; + 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 = false; + 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 = false; + + mutex_unlock(&instance->vchiq_mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(vchiq_mmal_component_finalise); + +/* + * cause a mmal component to be enabled + */ +int vchiq_mmal_component_enable(struct vchiq_mmal_instance *instance, + struct vchiq_mmal_component *component) +{ + int ret; + + if (mutex_lock_interruptible(&instance->vchiq_mutex)) + return -EINTR; + + if (component->enabled) { + mutex_unlock(&instance->vchiq_mutex); + return 0; + } + + ret = enable_component(instance, component); + if (ret == 0) + component->enabled = true; + + mutex_unlock(&instance->vchiq_mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(vchiq_mmal_component_enable); + +/* + * cause a mmal component to be enabled + */ +int vchiq_mmal_component_disable(struct vchiq_mmal_instance *instance, + struct vchiq_mmal_component *component) +{ + int ret; + + if (mutex_lock_interruptible(&instance->vchiq_mutex)) + return -EINTR; + + if (!component->enabled) { + mutex_unlock(&instance->vchiq_mutex); + return 0; + } + + ret = disable_component(instance, component); + if (ret == 0) + component->enabled = false; + + mutex_unlock(&instance->vchiq_mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(vchiq_mmal_component_disable); + +int vchiq_mmal_version(struct vchiq_mmal_instance *instance, + u32 *major_out, u32 *minor_out) +{ + int ret; + + if (mutex_lock_interruptible(&instance->vchiq_mutex)) + return -EINTR; + + ret = get_version(instance, major_out, minor_out); + + mutex_unlock(&instance->vchiq_mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(vchiq_mmal_version); + +int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance) +{ + int status = 0; + + if (!instance) + return -EINVAL; + + if (mutex_lock_interruptible(&instance->vchiq_mutex)) + return -EINTR; + + vchiq_use_service(instance->vchiq_instance, instance->service_handle); + + status = vchiq_close_service(instance->vchiq_instance, instance->service_handle); + if (status != 0) + pr_err("mmal-vchiq: VCHIQ close failed\n"); + + mutex_unlock(&instance->vchiq_mutex); + + vchiq_shutdown(instance->vchiq_instance); + destroy_workqueue(instance->bulk_wq); + + idr_destroy(&instance->context_map); + + kfree(instance); + + return status; +} +EXPORT_SYMBOL_GPL(vchiq_mmal_finalise); + +int vchiq_mmal_init(struct device *dev, struct vchiq_mmal_instance **out_instance) +{ + int status; + int err = -ENODEV; + struct vchiq_mmal_instance *instance; + struct vchiq_instance *vchiq_instance; + struct vchiq_service_params_kernel params = { + .version = VC_MMAL_VER, + .version_min = VC_MMAL_MIN_VER, + .fourcc = VCHIQ_MAKE_FOURCC('m', 'm', 'a', 'l'), + .callback = mmal_service_callback, + .userdata = NULL, + }; + struct vchiq_drv_mgmt *mgmt = dev_get_drvdata(dev->parent); + + /* 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(&mgmt->state, &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); + err = -EIO; + goto err_shutdown_vchiq; + } + + instance = kzalloc(sizeof(*instance), GFP_KERNEL); + + if (!instance) { + err = -ENOMEM; + goto err_shutdown_vchiq; + } + + mutex_init(&instance->vchiq_mutex); + + instance->vchiq_instance = vchiq_instance; + + 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, ¶ms, + &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->vchiq_instance, instance->service_handle); + + *out_instance = instance; + + return 0; + +err_close_services: + vchiq_close_service(instance->vchiq_instance, instance->service_handle); + destroy_workqueue(instance->bulk_wq); +err_free: + kfree(instance); +err_shutdown_vchiq: + vchiq_shutdown(vchiq_instance); + return err; +} +EXPORT_SYMBOL_GPL(vchiq_mmal_init); + +MODULE_DESCRIPTION("BCM2835 MMAL VCHIQ interface"); +MODULE_AUTHOR("Dave Stevenson, "); +MODULE_LICENSE("GPL"); diff --git a/drivers/platform/raspberrypi/vchiq-mmal/mmal-vchiq.h b/drivers/platform/raspberrypi/vchiq-mmal/mmal-vchiq.h new file mode 100644 index 000000000000..8c3959f6f97f --- /dev/null +++ b/drivers/platform/raspberrypi/vchiq-mmal/mmal-vchiq.h @@ -0,0 +1,162 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Broadcom BCM2835 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; +struct device; + +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 { + bool enabled; + u32 handle; + u32 type; /* port type, cached to use on port info set */ + u32 index; /* port index, cached to use on port info set */ + + /* component port belongs to, allows simple deref */ + struct vchiq_mmal_component *component; + + struct vchiq_mmal_port *connected; /* port 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 { + bool in_use; + bool enabled; + u32 handle; /* VideoCore handle for component */ + u32 inputs; /* Number of input ports */ + u32 outputs; /* Number of output ports */ + u32 clocks; /* Number of clock ports */ + struct vchiq_mmal_port control; /* control port */ + struct vchiq_mmal_port input[MAX_PORT_COUNT]; /* input ports */ + struct vchiq_mmal_port output[MAX_PORT_COUNT]; /* output ports */ + struct vchiq_mmal_port clock[MAX_PORT_COUNT]; /* clock ports */ + u32 client_component; /* Used to ref back to client struct */ +}; + +int vchiq_mmal_init(struct device *dev, 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, enqueues 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 */ diff --git a/drivers/staging/vc04_services/Kconfig b/drivers/staging/vc04_services/Kconfig index b9e6f369f54c..2f6d1aaffdb2 100644 --- a/drivers/staging/vc04_services/Kconfig +++ b/drivers/staging/vc04_services/Kconfig @@ -3,7 +3,5 @@ if BCM_VIDEOCORE source "drivers/staging/vc04_services/bcm2835-audio/Kconfig" -source "drivers/staging/vc04_services/vchiq-mmal/Kconfig" - endif diff --git a/drivers/staging/vc04_services/Makefile b/drivers/staging/vc04_services/Makefile index 7a716a5c7815..ba15ec663af0 100644 --- a/drivers/staging/vc04_services/Makefile +++ b/drivers/staging/vc04_services/Makefile @@ -1,4 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_SND_BCM2835) += bcm2835-audio/ -obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += vchiq-mmal/ diff --git a/drivers/staging/vc04_services/vchiq-mmal/Kconfig b/drivers/staging/vc04_services/vchiq-mmal/Kconfig deleted file mode 100644 index c99525a0bb45..000000000000 --- a/drivers/staging/vc04_services/vchiq-mmal/Kconfig +++ /dev/null @@ -1,7 +0,0 @@ -config BCM2835_VCHIQ_MMAL - tristate "BCM2835 MMAL VCHIQ service" - depends on BCM2835_VCHIQ - 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 deleted file mode 100644 index 6937f6534c26..000000000000 --- a/drivers/staging/vc04_services/vchiq-mmal/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -bcm2835-mmal-vchiq-objs := mmal-vchiq.o - -obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += bcm2835-mmal-vchiq.o diff --git a/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h b/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h deleted file mode 100644 index b33129403a30..000000000000 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h +++ /dev/null @@ -1,65 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Broadcom BCM2835 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 deleted file mode 100644 index e15ae7b24f73..000000000000 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-encodings.h +++ /dev/null @@ -1,124 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Broadcom BCM2835 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 deleted file mode 100644 index 492d4c5dca08..000000000000 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-common.h +++ /dev/null @@ -1,45 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Broadcom BCM2835 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 - -#include - -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 */ -}; - -#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 deleted file mode 100644 index 5569876d8c7d..000000000000 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-format.h +++ /dev/null @@ -1,108 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Broadcom BCM2835 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 - -#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 s32_fract frame_rate; /* Frame rate */ - struct s32_fract 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 deleted file mode 100644 index 6ee4c1ed7f19..000000000000 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-port.h +++ /dev/null @@ -1,109 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Broadcom BCM2835 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 deleted file mode 100644 index 1889494425eb..000000000000 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h +++ /dev/null @@ -1,406 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Broadcom BCM2835 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 received 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 deleted file mode 100644 index a0cdd28101f2..000000000000 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h +++ /dev/null @@ -1,752 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Broadcom BCM2835 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 - -#include - -/** 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, -}; - -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 s32_fract fps_low; - /**< High end of the permitted framerate range */ - struct s32_fract 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 s32_fract r_gain; /**< Red gain */ - struct s32_fract 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 deleted file mode 100644 index cd073ed3ea2d..000000000000 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c +++ /dev/null @@ -1,1949 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Broadcom BCM2835 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#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.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; - - 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; - - /* handle for a vchiq instance */ - struct vchiq_instance *vchiq_instance; -}; - -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 within 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->vchiq_instance, instance->service_handle); - ret = vchiq_bulk_receive(instance->vchiq_instance, 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->vchiq_instance, 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 service 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 specific 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->vchiq_instance, instance->service_handle); - - ret = vchiq_queue_kernel_message(instance->vchiq_instance, 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->vchiq_instance, 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 int mmal_service_callback(struct vchiq_instance *vchiq_instance, - enum vchiq_reason reason, struct vchiq_header *header, - unsigned int handle, void *cb_data, - void __user *cb_userdata) -{ - struct vchiq_mmal_instance *instance = vchiq_get_service_userdata(vchiq_instance, 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 0; - } - - 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(vchiq_instance, handle, header); - break; - - case MMAL_MSG_TYPE_EVENT_TO_HOST: - event_to_host_cb(instance, msg, msg_len); - vchiq_release_message(vchiq_instance, handle, header); - - break; - - case MMAL_MSG_TYPE_BUFFER_TO_HOST: - buffer_to_host_cb(instance, msg, msg_len); - vchiq_release_message(vchiq_instance, 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(vchiq_instance, 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(vchiq_instance, 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, cb_data); - break; - - case VCHIQ_BULK_RECEIVE_ABORTED: - bulk_abort_cb(instance, cb_data); - 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 0; -} - -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 time_left; - - /* 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->vchiq_instance, instance->service_handle); - - ret = vchiq_queue_kernel_message(instance->vchiq_instance, instance->service_handle, msg, - sizeof(struct mmal_msg_header) + - payload_len); - - vchiq_release_service(instance->vchiq_instance, instance->service_handle); - - if (ret) { - pr_err("error %d queuing message\n", ret); - release_msg_context(msg_context); - return ret; - } - - time_left = wait_for_completion_timeout(&msg_context->u.sync.cmplt, - SYNC_MSG_TIMEOUT * HZ); - if (time_left == 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.numerator, - port->es.video.frame_rate.denominator, - port->es.video.par.numerator, port->es.video.par.denominator); - } -} - -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->vchiq_instance, 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 = false; - else - port->enabled = true; - - /* copy the values out of the message */ - port->handle = rmsg->u.port_info_get_reply.port_handle; - - /* port type and index cached to use on port info set because - * it does not use a port handle - */ - port->type = rmsg->u.port_info_get_reply.port_type; - port->index = rmsg->u.port_info_get_reply.port_index; - - port->minimum_buffer.num = - rmsg->u.port_info_get_reply.port.buffer_num_min; - port->minimum_buffer.size = - rmsg->u.port_info_get_reply.port.buffer_size_min; - port->minimum_buffer.alignment = - rmsg->u.port_info_get_reply.port.buffer_alignment_min; - - port->recommended_buffer.alignment = - rmsg->u.port_info_get_reply.port.buffer_alignment_min; - port->recommended_buffer.num = - rmsg->u.port_info_get_reply.port.buffer_num_recommended; - - port->current_buffer.num = rmsg->u.port_info_get_reply.port.buffer_num; - port->current_buffer.size = - rmsg->u.port_info_get_reply.port.buffer_size; - - /* stream format */ - port->format.type = rmsg->u.port_info_get_reply.format.type; - port->format.encoding = rmsg->u.port_info_get_reply.format.encoding; - port->format.encoding_variant = - rmsg->u.port_info_get_reply.format.encoding_variant; - port->format.bitrate = rmsg->u.port_info_get_reply.format.bitrate; - port->format.flags = rmsg->u.port_info_get_reply.format.flags; - - /* elementary stream format */ - memcpy(&port->es, - &rmsg->u.port_info_get_reply.es, - sizeof(union mmal_es_specific_format)); - port->format.es = &port->es; - - port->format.extradata_size = - rmsg->u.port_info_get_reply.format.extradata_size; - memcpy(port->format.extradata, - rmsg->u.port_info_get_reply.extradata, - port->format.extradata_size); - - pr_debug("received port info\n"); - dump_port_info(port); - -release_msg: - - pr_debug("%s:result:%d component:0x%x port:%d\n", - __func__, ret, port->component->handle, port->handle); - - vchiq_release_message(instance->vchiq_instance, instance->service_handle, rmsg_handle); - - return ret; -} - -/* create component 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; - strscpy_pad(m.u.component_create.name, name, - sizeof(m.u.component_create.name)); - m.u.component_create.pid = 0; - - 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->vchiq_instance, 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->vchiq_instance, 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->vchiq_instance, 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->vchiq_instance, 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->vchiq_instance, 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->vchiq_instance, 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->vchiq_instance, 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->vchiq_instance, 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->vchiq_instance, 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 = false; - - ret = port_action_port(instance, port, - MMAL_MSG_PORT_ACTION_TYPE_DISABLE); - if (ret == 0) { - /* - * Drain all queued buffers on port. This should only - * apply to buffers that have been queued before the port - * has been enabled. If the port has been enabled and buffers - * passed, then the buffers should have been removed from this - * list, and we should get the relevant callbacks via VCHIQ - * to release the buffers. - */ - spin_lock_irqsave(&port->slock, flags); - - list_for_each_safe(buf_head, q, &port->buffers) { - struct mmal_buffer *mmalbuf; - - mmalbuf = list_entry(buf_head, struct mmal_buffer, - list); - list_del(buf_head); - if (port->buffer_cb) { - 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 = true; - - if (port->buffer_cb) { - /* send buffer headers to videocore */ - hdr_count = 1; - list_for_each_safe(buf_head, q, &port->buffers) { - struct mmal_buffer *mmalbuf; - - mmalbuf = list_entry(buf_head, struct mmal_buffer, - list); - ret = buffer_from_host(instance, port, mmalbuf); - if (ret) - goto done; - - list_del(buf_head); - hdr_count++; - if (hdr_count > port->current_buffer.num) - break; - } - } - - ret = port_info_get(instance, port); - -done: - return ret; -} - -/* ------------------------------------------------------------------ - * Exported API - *------------------------------------------------------------------ - */ - -int vchiq_mmal_port_set_format(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *port) -{ - int ret; - - if (mutex_lock_interruptible(&instance->vchiq_mutex)) - return -EINTR; - - ret = port_info_set(instance, port); - if (ret) - goto release_unlock; - - /* read what has actually been set */ - ret = port_info_get(instance, port); - -release_unlock: - mutex_unlock(&instance->vchiq_mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(vchiq_mmal_port_set_format); - -int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *port, - u32 parameter, void *value, u32 value_size) -{ - int ret; - - if (mutex_lock_interruptible(&instance->vchiq_mutex)) - return -EINTR; - - ret = port_parameter_set(instance, port, parameter, value, value_size); - - mutex_unlock(&instance->vchiq_mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(vchiq_mmal_port_parameter_set); - -int vchiq_mmal_port_parameter_get(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *port, - u32 parameter, void *value, u32 *value_size) -{ - int ret; - - if (mutex_lock_interruptible(&instance->vchiq_mutex)) - return -EINTR; - - ret = port_parameter_get(instance, port, parameter, value, value_size); - - mutex_unlock(&instance->vchiq_mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(vchiq_mmal_port_parameter_get); - -/* enable a port - * - * enables a port and queues buffers for satisfying callbacks if we - * provide a callback handler - */ -int vchiq_mmal_port_enable(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *port, - vchiq_mmal_buffer_cb buffer_cb) -{ - int ret; - - if (mutex_lock_interruptible(&instance->vchiq_mutex)) - return -EINTR; - - /* already enabled - noop */ - if (port->enabled) { - ret = 0; - goto unlock; - } - - port->buffer_cb = buffer_cb; - - ret = port_enable(instance, port); - -unlock: - mutex_unlock(&instance->vchiq_mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(vchiq_mmal_port_enable); - -int vchiq_mmal_port_disable(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *port) -{ - int ret; - - if (mutex_lock_interruptible(&instance->vchiq_mutex)) - return -EINTR; - - if (!port->enabled) { - mutex_unlock(&instance->vchiq_mutex); - return 0; - } - - ret = port_disable(instance, port); - - mutex_unlock(&instance->vchiq_mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(vchiq_mmal_port_disable); - -/* ports will be connected in a tunneled manner so data buffers - * are not handled by client. - */ -int vchiq_mmal_port_connect_tunnel(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *src, - struct vchiq_mmal_port *dst) -{ - int ret; - - if (mutex_lock_interruptible(&instance->vchiq_mutex)) - return -EINTR; - - /* disconnect ports if connected */ - if (src->connected) { - ret = port_disable(instance, src); - if (ret) { - pr_err("failed disabling src port(%d)\n", ret); - goto release_unlock; - } - - /* do not need to disable the destination port as they - * are connected and it is done automatically - */ - - ret = port_action_handle(instance, src, - MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT, - src->connected->component->handle, - src->connected->handle); - if (ret < 0) { - pr_err("failed disconnecting src port\n"); - goto release_unlock; - } - src->connected->enabled = false; - src->connected = NULL; - } - - if (!dst) { - /* do not make new connection */ - ret = 0; - pr_debug("not making new connection\n"); - goto release_unlock; - } - - /* copy src port format to dst */ - dst->format.encoding = src->format.encoding; - dst->es.video.width = src->es.video.width; - dst->es.video.height = src->es.video.height; - dst->es.video.crop.x = src->es.video.crop.x; - dst->es.video.crop.y = src->es.video.crop.y; - dst->es.video.crop.width = src->es.video.crop.width; - dst->es.video.crop.height = src->es.video.crop.height; - dst->es.video.frame_rate.numerator = src->es.video.frame_rate.numerator; - dst->es.video.frame_rate.denominator = src->es.video.frame_rate.denominator; - - /* 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 = true; - 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 = false; - 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 = false; - - mutex_unlock(&instance->vchiq_mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(vchiq_mmal_component_finalise); - -/* - * cause a mmal component to be enabled - */ -int vchiq_mmal_component_enable(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_component *component) -{ - int ret; - - if (mutex_lock_interruptible(&instance->vchiq_mutex)) - return -EINTR; - - if (component->enabled) { - mutex_unlock(&instance->vchiq_mutex); - return 0; - } - - ret = enable_component(instance, component); - if (ret == 0) - component->enabled = true; - - mutex_unlock(&instance->vchiq_mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(vchiq_mmal_component_enable); - -/* - * cause a mmal component to be enabled - */ -int vchiq_mmal_component_disable(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_component *component) -{ - int ret; - - if (mutex_lock_interruptible(&instance->vchiq_mutex)) - return -EINTR; - - if (!component->enabled) { - mutex_unlock(&instance->vchiq_mutex); - return 0; - } - - ret = disable_component(instance, component); - if (ret == 0) - component->enabled = false; - - mutex_unlock(&instance->vchiq_mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(vchiq_mmal_component_disable); - -int vchiq_mmal_version(struct vchiq_mmal_instance *instance, - u32 *major_out, u32 *minor_out) -{ - int ret; - - if (mutex_lock_interruptible(&instance->vchiq_mutex)) - return -EINTR; - - ret = get_version(instance, major_out, minor_out); - - mutex_unlock(&instance->vchiq_mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(vchiq_mmal_version); - -int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance) -{ - int status = 0; - - if (!instance) - return -EINVAL; - - if (mutex_lock_interruptible(&instance->vchiq_mutex)) - return -EINTR; - - vchiq_use_service(instance->vchiq_instance, instance->service_handle); - - status = vchiq_close_service(instance->vchiq_instance, instance->service_handle); - if (status != 0) - pr_err("mmal-vchiq: VCHIQ close failed\n"); - - mutex_unlock(&instance->vchiq_mutex); - - vchiq_shutdown(instance->vchiq_instance); - destroy_workqueue(instance->bulk_wq); - - idr_destroy(&instance->context_map); - - kfree(instance); - - return status; -} -EXPORT_SYMBOL_GPL(vchiq_mmal_finalise); - -int vchiq_mmal_init(struct device *dev, struct vchiq_mmal_instance **out_instance) -{ - int status; - int err = -ENODEV; - struct vchiq_mmal_instance *instance; - struct vchiq_instance *vchiq_instance; - struct vchiq_service_params_kernel params = { - .version = VC_MMAL_VER, - .version_min = VC_MMAL_MIN_VER, - .fourcc = VCHIQ_MAKE_FOURCC('m', 'm', 'a', 'l'), - .callback = mmal_service_callback, - .userdata = NULL, - }; - struct vchiq_drv_mgmt *mgmt = dev_get_drvdata(dev->parent); - - /* 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(&mgmt->state, &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); - err = -EIO; - goto err_shutdown_vchiq; - } - - instance = kzalloc(sizeof(*instance), GFP_KERNEL); - - if (!instance) { - err = -ENOMEM; - goto err_shutdown_vchiq; - } - - mutex_init(&instance->vchiq_mutex); - - instance->vchiq_instance = vchiq_instance; - - 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, ¶ms, - &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->vchiq_instance, instance->service_handle); - - *out_instance = instance; - - return 0; - -err_close_services: - vchiq_close_service(instance->vchiq_instance, instance->service_handle); - destroy_workqueue(instance->bulk_wq); -err_free: - kfree(instance); -err_shutdown_vchiq: - vchiq_shutdown(vchiq_instance); - return err; -} -EXPORT_SYMBOL_GPL(vchiq_mmal_init); - -MODULE_DESCRIPTION("BCM2835 MMAL VCHIQ interface"); -MODULE_AUTHOR("Dave Stevenson, "); -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 deleted file mode 100644 index 8c3959f6f97f..000000000000 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h +++ /dev/null @@ -1,162 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Broadcom BCM2835 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; -struct device; - -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 { - bool enabled; - u32 handle; - u32 type; /* port type, cached to use on port info set */ - u32 index; /* port index, cached to use on port info set */ - - /* component port belongs to, allows simple deref */ - struct vchiq_mmal_component *component; - - struct vchiq_mmal_port *connected; /* port 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 { - bool in_use; - bool enabled; - u32 handle; /* VideoCore handle for component */ - u32 inputs; /* Number of input ports */ - u32 outputs; /* Number of output ports */ - u32 clocks; /* Number of clock ports */ - struct vchiq_mmal_port control; /* control port */ - struct vchiq_mmal_port input[MAX_PORT_COUNT]; /* input ports */ - struct vchiq_mmal_port output[MAX_PORT_COUNT]; /* output ports */ - struct vchiq_mmal_port clock[MAX_PORT_COUNT]; /* clock ports */ - u32 client_component; /* Used to ref back to client struct */ -}; - -int vchiq_mmal_init(struct device *dev, 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, enqueues 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 */ -- cgit v1.2.3