You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openwrt/target/linux/bcm27xx/patches-4.19/950-0307-staging-bcm2835_co...

728 lines
20 KiB
Diff

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;
}