aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.4/950-0184-staging-bcm2835_codec-Query-supported-formats-from-t.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/bcm27xx/patches-5.4/950-0184-staging-bcm2835_codec-Query-supported-formats-from-t.patch')
-rw-r--r--target/linux/bcm27xx/patches-5.4/950-0184-staging-bcm2835_codec-Query-supported-formats-from-t.patch727
1 files changed, 727 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.4/950-0184-staging-bcm2835_codec-Query-supported-formats-from-t.patch b/target/linux/bcm27xx/patches-5.4/950-0184-staging-bcm2835_codec-Query-supported-formats-from-t.patch
new file mode 100644
index 0000000000..00c3837c3c
--- /dev/null
+++ b/target/linux/bcm27xx/patches-5.4/950-0184-staging-bcm2835_codec-Query-supported-formats-from-t.patch
@@ -0,0 +1,727 @@
+From 9f6d3fea405751e39801ae101fe2625efb3c6ca4 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Wed, 13 Feb 2019 13:44:00 +0000
+Subject: [PATCH] staging: bcm2835_codec: Query supported formats from
+ the component
+
+The driver was previously working with hard coded tables of
+which video formats were supported by each component.
+The components advertise this information via a MMAL parameter,
+so retrieve the information from there during probe, and store
+in the state structure for that device.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../bcm2835-codec/bcm2835-v4l2-codec.c | 455 +++++++++++++-----
+ 1 file changed, 327 insertions(+), 128 deletions(-)
+
+--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+@@ -88,17 +88,12 @@ struct bcm2835_codec_fmt {
+ int bytesperline_align;
+ u32 flags;
+ u32 mmal_fmt;
+- bool decode_only;
+- bool encode_only;
+ int size_multiplier_x2;
+ };
+
+-/* Supported raw pixel formats. Those supported for both encode and decode
+- * must come first, with those only supported for decode coming after (there
+- * are no formats supported for encode only).
+- */
+-static struct bcm2835_codec_fmt raw_formats[] = {
++static const struct bcm2835_codec_fmt supported_formats[] = {
+ {
++ /* YUV formats */
+ .fourcc = V4L2_PIX_FMT_YUV420,
+ .depth = 8,
+ .bytesperline_align = 32,
+@@ -139,7 +134,6 @@ static struct bcm2835_codec_fmt raw_form
+ .bytesperline_align = 32,
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_YUYV,
+- .encode_only = true,
+ .size_multiplier_x2 = 2,
+ }, {
+ .fourcc = V4L2_PIX_FMT_UYVY,
+@@ -147,7 +141,6 @@ static struct bcm2835_codec_fmt raw_form
+ .bytesperline_align = 32,
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_UYVY,
+- .encode_only = true,
+ .size_multiplier_x2 = 2,
+ }, {
+ .fourcc = V4L2_PIX_FMT_YVYU,
+@@ -155,7 +148,6 @@ static struct bcm2835_codec_fmt raw_form
+ .bytesperline_align = 32,
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_YVYU,
+- .encode_only = true,
+ .size_multiplier_x2 = 2,
+ }, {
+ .fourcc = V4L2_PIX_FMT_VYUY,
+@@ -163,15 +155,14 @@ static struct bcm2835_codec_fmt raw_form
+ .bytesperline_align = 32,
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_VYUY,
+- .encode_only = true,
+ .size_multiplier_x2 = 2,
+ }, {
++ /* RGB formats */
+ .fourcc = V4L2_PIX_FMT_RGB24,
+ .depth = 24,
+ .bytesperline_align = 32,
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_RGB24,
+- .encode_only = true,
+ .size_multiplier_x2 = 2,
+ }, {
+ .fourcc = V4L2_PIX_FMT_BGR24,
+@@ -179,7 +170,6 @@ static struct bcm2835_codec_fmt raw_form
+ .bytesperline_align = 32,
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_BGR24,
+- .encode_only = true,
+ .size_multiplier_x2 = 2,
+ }, {
+ .fourcc = V4L2_PIX_FMT_BGR32,
+@@ -187,17 +177,126 @@ static struct bcm2835_codec_fmt raw_form
+ .bytesperline_align = 32,
+ .flags = 0,
+ .mmal_fmt = MMAL_ENCODING_BGRA,
+- .encode_only = true,
+ .size_multiplier_x2 = 2,
+- },
+-};
+-
+-/* Supported encoded formats. Those supported for both encode and decode
+- * must come first, with those only supported for decode coming after (there
+- * are no formats supported for encode only).
+- */
+-static struct bcm2835_codec_fmt encoded_formats[] = {
+- {
++ }, {
++ /* Bayer formats */
++ /* 8 bit */
++ .fourcc = V4L2_PIX_FMT_SRGGB8,
++ .depth = 8,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB8,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_SBGGR8,
++ .depth = 8,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR8,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_SGRBG8,
++ .depth = 8,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG8,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_SGBRG8,
++ .depth = 8,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG8,
++ .size_multiplier_x2 = 2,
++ }, {
++ /* 10 bit */
++ .fourcc = V4L2_PIX_FMT_SRGGB10P,
++ .depth = 10,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB10P,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_SBGGR10P,
++ .depth = 10,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR10P,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_SGRBG10P,
++ .depth = 10,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG10P,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_SGBRG10P,
++ .depth = 10,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG10P,
++ .size_multiplier_x2 = 2,
++ }, {
++ /* 12 bit */
++ .fourcc = V4L2_PIX_FMT_SRGGB12P,
++ .depth = 12,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB12P,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_SBGGR12P,
++ .depth = 12,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR12P,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_SGRBG12P,
++ .depth = 12,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG12P,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_SGBRG12P,
++ .depth = 12,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG12P,
++ .size_multiplier_x2 = 2,
++ }, {
++ /* 16 bit */
++ .fourcc = V4L2_PIX_FMT_SRGGB16,
++ .depth = 16,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB16,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_SBGGR16,
++ .depth = 16,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR16,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_SGRBG16,
++ .depth = 16,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG16,
++ .size_multiplier_x2 = 2,
++ }, {
++ .fourcc = V4L2_PIX_FMT_SGBRG16,
++ .depth = 16,
++ .bytesperline_align = 32,
++ .flags = 0,
++ .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG16,
++ .size_multiplier_x2 = 2,
++ }, {
++ /* Compressed formats */
+ .fourcc = V4L2_PIX_FMT_H264,
+ .depth = 0,
+ .flags = V4L2_FMT_FLAG_COMPRESSED,
+@@ -212,30 +311,22 @@ static struct bcm2835_codec_fmt encoded_
+ .depth = 0,
+ .flags = V4L2_FMT_FLAG_COMPRESSED,
+ .mmal_fmt = MMAL_ENCODING_MP4V,
+- .decode_only = true,
+ }, {
+ .fourcc = V4L2_PIX_FMT_H263,
+ .depth = 0,
+ .flags = V4L2_FMT_FLAG_COMPRESSED,
+ .mmal_fmt = MMAL_ENCODING_H263,
+- .decode_only = true,
+ }, {
+ .fourcc = V4L2_PIX_FMT_MPEG2,
+ .depth = 0,
+ .flags = V4L2_FMT_FLAG_COMPRESSED,
+ .mmal_fmt = MMAL_ENCODING_MP2V,
+- .decode_only = true,
+ }, {
+ .fourcc = V4L2_PIX_FMT_VP8,
+ .depth = 0,
+ .flags = V4L2_FMT_FLAG_COMPRESSED,
+ .mmal_fmt = MMAL_ENCODING_VP8,
+- .decode_only = true,
+ },
+- /*
+- * This list couold include VP6 and Theorafor decode, but V4L2 doesn't
+- * support them.
+- */
+ };
+
+ struct bcm2835_codec_fmt_list {
+@@ -243,19 +334,6 @@ struct bcm2835_codec_fmt_list {
+ unsigned int num_entries;
+ };
+
+-#define RAW_LIST 0
+-#define ENCODED_LIST 1
+-
+-struct bcm2835_codec_fmt_list formats[] = {
+- {
+- .list = raw_formats,
+- .num_entries = ARRAY_SIZE(raw_formats),
+- }, {
+- .list = encoded_formats,
+- .num_entries = ARRAY_SIZE(encoded_formats),
+- },
+-};
+-
+ struct m2m_mmal_buffer {
+ struct v4l2_m2m_buffer m2m;
+ struct mmal_buffer mmal;
+@@ -284,52 +362,6 @@ struct bcm2835_codec_q_data {
+ bool eos_buffer_in_use; /* debug only */
+ };
+
+-enum {
+- V4L2_M2M_SRC = 0,
+- V4L2_M2M_DST = 1,
+-};
+-
+-static inline struct bcm2835_codec_fmt_list *get_format_list(bool decode,
+- bool capture)
+-{
+- return decode ^ capture ? &formats[ENCODED_LIST] : &formats[RAW_LIST];
+-}
+-
+-static struct bcm2835_codec_fmt *get_default_format(bool decode, bool capture)
+-{
+- return &get_format_list(decode, capture)->list[0];
+-}
+-
+-static struct bcm2835_codec_fmt *find_format(struct v4l2_format *f, bool decode,
+- bool capture)
+-{
+- struct bcm2835_codec_fmt *fmt;
+- unsigned int k;
+- struct bcm2835_codec_fmt_list *fmts = get_format_list(decode, capture);
+-
+- for (k = 0; k < fmts->num_entries; k++) {
+- fmt = &fmts->list[k];
+- if (fmt->fourcc == f->fmt.pix.pixelformat)
+- break;
+- }
+-
+- /*
+- * Some compressed formats are only supported for decoding, not
+- * encoding.
+- */
+- if (!decode && fmts->list[k].decode_only)
+- return NULL;
+-
+- /* Some pixel formats are only supported for encoding, not decoding. */
+- if (decode && fmts->list[k].encode_only)
+- return NULL;
+-
+- if (k == fmts->num_entries)
+- return NULL;
+-
+- return &fmts->list[k];
+-}
+-
+ struct bcm2835_codec_dev {
+ struct platform_device *pdev;
+
+@@ -342,6 +374,9 @@ struct bcm2835_codec_dev {
+
+ /* allocated mmal instance and components */
+ bool decode; /* Is this instance a decoder? */
++ /* The list of formats supported on input and output queues. */
++ struct bcm2835_codec_fmt_list supported_fmts[2];
++
+ struct vchiq_mmal_instance *instance;
+
+ struct v4l2_m2m_dev *m2m_dev;
+@@ -374,8 +409,59 @@ struct bcm2835_codec_ctx {
+ struct bcm2835_codec_driver {
+ struct bcm2835_codec_dev *encode;
+ struct bcm2835_codec_dev *decode;
++ struct bcm2835_codec_dev *isp;
++};
++
++enum {
++ V4L2_M2M_SRC = 0,
++ V4L2_M2M_DST = 1,
+ };
+
++static const struct bcm2835_codec_fmt *get_fmt(u32 mmal_fmt)
++{
++ unsigned int i;
++
++ for (i = 0; i < ARRAY_SIZE(supported_formats); i++) {
++ if (supported_formats[i].mmal_fmt == mmal_fmt)
++ return &supported_formats[i];
++ }
++ return NULL;
++}
++
++static inline
++struct bcm2835_codec_fmt_list *get_format_list(struct bcm2835_codec_dev *dev,
++ bool capture)
++{
++ return &dev->supported_fmts[capture ? 1 : 0];
++}
++
++static
++struct bcm2835_codec_fmt *get_default_format(struct bcm2835_codec_dev *dev,
++ bool capture)
++{
++ return &dev->supported_fmts[capture ? 1 : 0].list[0];
++}
++
++static struct bcm2835_codec_fmt *find_format(struct v4l2_format *f,
++ struct bcm2835_codec_dev *dev,
++ bool capture)
++{
++ struct bcm2835_codec_fmt *fmt;
++ unsigned int k;
++ struct bcm2835_codec_fmt_list *fmts =
++ &dev->supported_fmts[capture ? 1 : 0];
++
++ for (k = 0; k < fmts->num_entries; k++) {
++ fmt = &fmts->list[k];
++ if (fmt->fourcc == f->fmt.pix.pixelformat)
++ break;
++ }
++ if (k == fmts->num_entries)
++ return NULL;
++
++ return &fmts->list[k];
++}
++
+ static inline struct bcm2835_codec_ctx *file2ctx(struct file *file)
+ {
+ return container_of(file->private_data, struct bcm2835_codec_ctx, fh);
+@@ -456,7 +542,6 @@ static inline unsigned int get_bytesperl
+ }
+
+ static void setup_mmal_port_format(struct bcm2835_codec_ctx *ctx,
+- bool decode,
+ struct bcm2835_codec_q_data *q_data,
+ struct vchiq_mmal_port *port)
+ {
+@@ -473,7 +558,7 @@ static void setup_mmal_port_format(struc
+ port->es.video.frame_rate.den = 1;
+ } else {
+ /* Compressed format - leave resolution as 0 for decode */
+- if (decode) {
++ if (ctx->dev->decode) {
+ port->es.video.width = 0;
+ port->es.video.height = 0;
+ port->es.video.crop.width = 0;
+@@ -802,22 +887,15 @@ static int vidioc_querycap(struct file *
+ return 0;
+ }
+
+-static int enum_fmt(struct v4l2_fmtdesc *f, bool decode, bool capture)
++static int enum_fmt(struct v4l2_fmtdesc *f, struct bcm2835_codec_ctx *ctx,
++ bool capture)
+ {
+ struct bcm2835_codec_fmt *fmt;
+- struct bcm2835_codec_fmt_list *fmts = get_format_list(decode, capture);
++ struct bcm2835_codec_fmt_list *fmts =
++ get_format_list(ctx->dev, capture);
+
+ if (f->index < fmts->num_entries) {
+ /* Format found */
+- /* Check format isn't a decode only format when encoding */
+- if (!decode &&
+- fmts->list[f->index].decode_only)
+- return -EINVAL;
+- /* Check format isn't a decode only format when encoding */
+- if (decode &&
+- fmts->list[f->index].encode_only)
+- return -EINVAL;
+-
+ fmt = &fmts->list[f->index];
+ f->pixelformat = fmt->fourcc;
+ f->flags = fmt->flags;
+@@ -833,7 +911,7 @@ static int vidioc_enum_fmt_vid_cap(struc
+ {
+ struct bcm2835_codec_ctx *ctx = file2ctx(file);
+
+- return enum_fmt(f, ctx->dev->decode, true);
++ return enum_fmt(f, ctx, true);
+ }
+
+ static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
+@@ -841,7 +919,7 @@ static int vidioc_enum_fmt_vid_out(struc
+ {
+ struct bcm2835_codec_ctx *ctx = file2ctx(file);
+
+- return enum_fmt(f, ctx->dev->decode, false);
++ return enum_fmt(f, ctx, false);
+ }
+
+ static int vidioc_g_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f)
+@@ -933,11 +1011,11 @@ static int vidioc_try_fmt_vid_cap(struct
+ struct bcm2835_codec_fmt *fmt;
+ struct bcm2835_codec_ctx *ctx = file2ctx(file);
+
+- fmt = find_format(f, ctx->dev->decode, true);
++ fmt = find_format(f, ctx->dev, true);
+ if (!fmt) {
+- f->fmt.pix.pixelformat = get_default_format(ctx->dev->decode,
++ f->fmt.pix.pixelformat = get_default_format(ctx->dev,
+ true)->fourcc;
+- fmt = find_format(f, ctx->dev->decode, true);
++ fmt = find_format(f, ctx->dev, true);
+ }
+
+ return vidioc_try_fmt(f, fmt);
+@@ -949,11 +1027,11 @@ static int vidioc_try_fmt_vid_out(struct
+ struct bcm2835_codec_fmt *fmt;
+ struct bcm2835_codec_ctx *ctx = file2ctx(file);
+
+- fmt = find_format(f, ctx->dev->decode, false);
++ fmt = find_format(f, ctx->dev, false);
+ if (!fmt) {
+- f->fmt.pix.pixelformat = get_default_format(ctx->dev->decode,
++ f->fmt.pix.pixelformat = get_default_format(ctx->dev,
+ false)->fourcc;
+- fmt = find_format(f, ctx->dev->decode, false);
++ fmt = find_format(f, ctx->dev, false);
+ }
+
+ if (!f->fmt.pix.colorspace)
+@@ -988,7 +1066,7 @@ static int vidioc_s_fmt(struct bcm2835_c
+ return -EBUSY;
+ }
+
+- q_data->fmt = find_format(f, ctx->dev->decode,
++ q_data->fmt = find_format(f, ctx->dev,
+ f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE);
+ q_data->crop_width = f->fmt.pix.width;
+ q_data->height = f->fmt.pix.height;
+@@ -1041,7 +1119,7 @@ static int vidioc_s_fmt(struct bcm2835_c
+ if (!port)
+ return 0;
+
+- setup_mmal_port_format(ctx, ctx->dev->decode, q_data, port);
++ setup_mmal_port_format(ctx, q_data, port);
+ ret = vchiq_mmal_port_set_format(ctx->dev->instance, port);
+ if (ret) {
+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed vchiq_mmal_port_set_format on port, ret %d\n",
+@@ -1064,8 +1142,7 @@ static int vidioc_s_fmt(struct bcm2835_c
+ struct bcm2835_codec_q_data *q_data_dst =
+ &ctx->q_data[V4L2_M2M_DST];
+
+- setup_mmal_port_format(ctx, ctx->dev->decode, q_data_dst,
+- port_dst);
++ setup_mmal_port_format(ctx, q_data_dst, port_dst);
+ ret = vchiq_mmal_port_set_format(ctx->dev->instance, port_dst);
+ if (ret) {
+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed vchiq_mmal_port_set_format on output port, ret %d\n",
+@@ -1636,10 +1713,10 @@ static int bcm2835_codec_create_componen
+ MMAL_PARAMETER_ZERO_COPY, &enable,
+ sizeof(enable));
+
+- setup_mmal_port_format(ctx, dev->decode, &ctx->q_data[V4L2_M2M_SRC],
++ setup_mmal_port_format(ctx, &ctx->q_data[V4L2_M2M_SRC],
+ &ctx->component->input[0]);
+
+- setup_mmal_port_format(ctx, dev->decode, &ctx->q_data[V4L2_M2M_DST],
++ setup_mmal_port_format(ctx, &ctx->q_data[V4L2_M2M_DST],
+ &ctx->component->output[0]);
+
+ ret = vchiq_mmal_port_set_format(dev->instance,
+@@ -2025,8 +2102,8 @@ static int bcm2835_codec_open(struct fil
+ goto open_unlock;
+ }
+
+- ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev->decode, false);
+- ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev->decode, true);
++ ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev, false);
++ ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev, true);
+ if (dev->decode) {
+ /*
+ * Input width and height are irrelevant as they will be defined
+@@ -2209,13 +2286,130 @@ static const struct v4l2_m2m_ops m2m_ops
+ .job_abort = job_abort,
+ };
+
++/* Size of the array to provide to the VPU when asking for the list of supported
++ * formats.
++ * The ISP component currently advertises 33 input formats, so add a small
++ * overhead on that.
++ */
++#define MAX_SUPPORTED_ENCODINGS 40
++
++/* Populate dev->supported_fmts with the formats supported by those ports. */
++static int bcm2835_codec_get_supported_fmts(struct bcm2835_codec_dev *dev)
++{
++ struct bcm2835_codec_fmt *list;
++ struct vchiq_mmal_component *component;
++ u32 fourccs[MAX_SUPPORTED_ENCODINGS];
++ u32 param_size = sizeof(fourccs);
++ unsigned int i, j, num_encodings;
++ int ret;
++
++ ret = vchiq_mmal_component_init(dev->instance,
++ dev->decode ?
++ "ril.video_decode" :
++ "ril.video_encode",
++ &component);
++ if (ret < 0) {
++ v4l2_err(&dev->v4l2_dev, "%s: failed to create component\n",
++ __func__);
++ return -ENOMEM;
++ }
++
++ ret = vchiq_mmal_port_parameter_get(dev->instance,
++ &component->input[0],
++ MMAL_PARAMETER_SUPPORTED_ENCODINGS,
++ &fourccs,
++ &param_size);
++
++ if (ret) {
++ if (ret == MMAL_MSG_STATUS_ENOSPC) {
++ v4l2_err(&dev->v4l2_dev, "%s: port has more encoding than we provided space for. Some are dropped.\n",
++ __func__);
++ num_encodings = MAX_SUPPORTED_ENCODINGS;
++ } else {
++ v4l2_err(&dev->v4l2_dev, "%s: get_param ret %u.\n",
++ __func__, ret);
++ ret = -EINVAL;
++ goto destroy_component;
++ }
++ } else {
++ num_encodings = param_size / sizeof(u32);
++ }
++
++ /* Assume at this stage that all encodings will be supported in V4L2.
++ * Any that aren't supported will waste a very small amount of memory.
++ */
++ list = devm_kzalloc(&dev->pdev->dev,
++ sizeof(struct bcm2835_codec_fmt) * num_encodings,
++ GFP_KERNEL);
++ if (!list) {
++ ret = -ENOMEM;
++ goto destroy_component;
++ }
++ dev->supported_fmts[0].list = list;
++
++ for (i = 0, j = 0; i < num_encodings; i++) {
++ const struct bcm2835_codec_fmt *fmt = get_fmt(fourccs[i]);
++
++ if (fmt) {
++ list[j] = *fmt;
++ j++;
++ }
++ }
++ dev->supported_fmts[0].num_entries = j;
++
++ param_size = sizeof(fourccs);
++ ret = vchiq_mmal_port_parameter_get(dev->instance,
++ &component->output[0],
++ MMAL_PARAMETER_SUPPORTED_ENCODINGS,
++ &fourccs,
++ &param_size);
++
++ if (ret) {
++ if (ret == MMAL_MSG_STATUS_ENOSPC) {
++ v4l2_err(&dev->v4l2_dev, "%s: port has more encoding than we provided space for. Some are dropped.\n",
++ __func__);
++ num_encodings = MAX_SUPPORTED_ENCODINGS;
++ } else {
++ ret = -EINVAL;
++ goto destroy_component;
++ }
++ } else {
++ num_encodings = param_size / sizeof(u32);
++ }
++ /* Assume at this stage that all encodings will be supported in V4L2. */
++ list = devm_kzalloc(&dev->pdev->dev,
++ sizeof(struct bcm2835_codec_fmt) * num_encodings,
++ GFP_KERNEL);
++ if (!list) {
++ ret = -ENOMEM;
++ goto destroy_component;
++ }
++ dev->supported_fmts[1].list = list;
++
++ for (i = 0, j = 0; i < num_encodings; i++) {
++ const struct bcm2835_codec_fmt *fmt = get_fmt(fourccs[i]);
++
++ if (fmt) {
++ list[j] = *fmt;
++ j++;
++ }
++ }
++ dev->supported_fmts[1].num_entries = j;
++
++ ret = 0;
++
++destroy_component:
++ vchiq_mmal_component_finalise(dev->instance, component);
++
++ return ret;
++}
++
+ static int bcm2835_codec_create(struct platform_device *pdev,
+ struct bcm2835_codec_dev **new_dev,
+ bool decode)
+ {
+ struct bcm2835_codec_dev *dev;
+ struct video_device *vfd;
+- struct vchiq_mmal_instance *instance = NULL;
+ int video_nr;
+ int ret;
+
+@@ -2227,10 +2421,18 @@ static int bcm2835_codec_create(struct p
+
+ dev->decode = decode;
+
+- ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
++ ret = vchiq_mmal_init(&dev->instance);
+ if (ret)
+ return ret;
+
++ ret = bcm2835_codec_get_supported_fmts(dev);
++ if (ret)
++ goto vchiq_finalise;
++
++ ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
++ if (ret)
++ goto vchiq_finalise;
++
+ atomic_set(&dev->num_inst, 0);
+ mutex_init(&dev->dev_mutex);
+
+@@ -2270,12 +2472,7 @@ static int bcm2835_codec_create(struct p
+ goto err_m2m;
+ }
+
+- ret = vchiq_mmal_init(&instance);
+- if (ret < 0)
+- goto err_m2m;
+- dev->instance = instance;
+-
+- v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s codec\n",
++ v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s\n",
+ dev->decode ? "decode" : "encode");
+ return 0;
+
+@@ -2284,7 +2481,8 @@ err_m2m:
+ video_unregister_device(&dev->vfd);
+ unreg_dev:
+ v4l2_device_unregister(&dev->v4l2_dev);
+-
++vchiq_finalise:
++ vchiq_mmal_finalise(dev->instance);
+ return ret;
+ }
+
+@@ -2297,6 +2495,7 @@ static int bcm2835_codec_destroy(struct
+ v4l2_m2m_release(dev->m2m_dev);
+ video_unregister_device(&dev->vfd);
+ v4l2_device_unregister(&dev->v4l2_dev);
++ vchiq_mmal_finalise(dev->instance);
+
+ return 0;
+ }