brcm2708: organize kernel patches
[openwrt/staging/chunkeey.git] / target / linux / brcm2708 / patches-4.19 / 950-0321-staging-bcm2835_codec-Query-supported-formats-from-t.patch
diff --git a/target/linux/brcm2708/patches-4.19/950-0321-staging-bcm2835_codec-Query-supported-formats-from-t.patch b/target/linux/brcm2708/patches-4.19/950-0321-staging-bcm2835_codec-Query-supported-formats-from-t.patch
new file mode 100644 (file)
index 0000000..5eec74e
--- /dev/null
@@ -0,0 +1,727 @@
+From ce8cc7a85839af588b753ce4af0832db9c467f45 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;
+ }