1 From ce8cc7a85839af588b753ce4af0832db9c467f45 Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.org>
3 Date: Wed, 13 Feb 2019 13:44:00 +0000
4 Subject: [PATCH] staging: bcm2835_codec: Query supported formats from
7 The driver was previously working with hard coded tables of
8 which video formats were supported by each component.
9 The components advertise this information via a MMAL parameter,
10 so retrieve the information from there during probe, and store
11 in the state structure for that device.
13 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
15 .../bcm2835-codec/bcm2835-v4l2-codec.c | 455 +++++++++++++-----
16 1 file changed, 327 insertions(+), 128 deletions(-)
18 --- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
19 +++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
20 @@ -88,17 +88,12 @@ struct bcm2835_codec_fmt {
21 int bytesperline_align;
26 int size_multiplier_x2;
29 -/* Supported raw pixel formats. Those supported for both encode and decode
30 - * must come first, with those only supported for decode coming after (there
31 - * are no formats supported for encode only).
33 -static struct bcm2835_codec_fmt raw_formats[] = {
34 +static const struct bcm2835_codec_fmt supported_formats[] = {
37 .fourcc = V4L2_PIX_FMT_YUV420,
39 .bytesperline_align = 32,
40 @@ -139,7 +134,6 @@ static struct bcm2835_codec_fmt raw_form
41 .bytesperline_align = 32,
43 .mmal_fmt = MMAL_ENCODING_YUYV,
44 - .encode_only = true,
45 .size_multiplier_x2 = 2,
47 .fourcc = V4L2_PIX_FMT_UYVY,
48 @@ -147,7 +141,6 @@ static struct bcm2835_codec_fmt raw_form
49 .bytesperline_align = 32,
51 .mmal_fmt = MMAL_ENCODING_UYVY,
52 - .encode_only = true,
53 .size_multiplier_x2 = 2,
55 .fourcc = V4L2_PIX_FMT_YVYU,
56 @@ -155,7 +148,6 @@ static struct bcm2835_codec_fmt raw_form
57 .bytesperline_align = 32,
59 .mmal_fmt = MMAL_ENCODING_YVYU,
60 - .encode_only = true,
61 .size_multiplier_x2 = 2,
63 .fourcc = V4L2_PIX_FMT_VYUY,
64 @@ -163,15 +155,14 @@ static struct bcm2835_codec_fmt raw_form
65 .bytesperline_align = 32,
67 .mmal_fmt = MMAL_ENCODING_VYUY,
68 - .encode_only = true,
69 .size_multiplier_x2 = 2,
72 .fourcc = V4L2_PIX_FMT_RGB24,
74 .bytesperline_align = 32,
76 .mmal_fmt = MMAL_ENCODING_RGB24,
77 - .encode_only = true,
78 .size_multiplier_x2 = 2,
80 .fourcc = V4L2_PIX_FMT_BGR24,
81 @@ -179,7 +170,6 @@ static struct bcm2835_codec_fmt raw_form
82 .bytesperline_align = 32,
84 .mmal_fmt = MMAL_ENCODING_BGR24,
85 - .encode_only = true,
86 .size_multiplier_x2 = 2,
88 .fourcc = V4L2_PIX_FMT_BGR32,
89 @@ -187,17 +177,126 @@ static struct bcm2835_codec_fmt raw_form
90 .bytesperline_align = 32,
92 .mmal_fmt = MMAL_ENCODING_BGRA,
93 - .encode_only = true,
94 .size_multiplier_x2 = 2,
98 -/* Supported encoded formats. Those supported for both encode and decode
99 - * must come first, with those only supported for decode coming after (there
100 - * are no formats supported for encode only).
102 -static struct bcm2835_codec_fmt encoded_formats[] = {
105 + /* Bayer formats */
107 + .fourcc = V4L2_PIX_FMT_SRGGB8,
109 + .bytesperline_align = 32,
111 + .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB8,
112 + .size_multiplier_x2 = 2,
114 + .fourcc = V4L2_PIX_FMT_SBGGR8,
116 + .bytesperline_align = 32,
118 + .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR8,
119 + .size_multiplier_x2 = 2,
121 + .fourcc = V4L2_PIX_FMT_SGRBG8,
123 + .bytesperline_align = 32,
125 + .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG8,
126 + .size_multiplier_x2 = 2,
128 + .fourcc = V4L2_PIX_FMT_SGBRG8,
130 + .bytesperline_align = 32,
132 + .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG8,
133 + .size_multiplier_x2 = 2,
136 + .fourcc = V4L2_PIX_FMT_SRGGB10P,
138 + .bytesperline_align = 32,
140 + .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB10P,
141 + .size_multiplier_x2 = 2,
143 + .fourcc = V4L2_PIX_FMT_SBGGR10P,
145 + .bytesperline_align = 32,
147 + .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR10P,
148 + .size_multiplier_x2 = 2,
150 + .fourcc = V4L2_PIX_FMT_SGRBG10P,
152 + .bytesperline_align = 32,
154 + .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG10P,
155 + .size_multiplier_x2 = 2,
157 + .fourcc = V4L2_PIX_FMT_SGBRG10P,
159 + .bytesperline_align = 32,
161 + .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG10P,
162 + .size_multiplier_x2 = 2,
165 + .fourcc = V4L2_PIX_FMT_SRGGB12P,
167 + .bytesperline_align = 32,
169 + .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB12P,
170 + .size_multiplier_x2 = 2,
172 + .fourcc = V4L2_PIX_FMT_SBGGR12P,
174 + .bytesperline_align = 32,
176 + .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR12P,
177 + .size_multiplier_x2 = 2,
179 + .fourcc = V4L2_PIX_FMT_SGRBG12P,
181 + .bytesperline_align = 32,
183 + .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG12P,
184 + .size_multiplier_x2 = 2,
186 + .fourcc = V4L2_PIX_FMT_SGBRG12P,
188 + .bytesperline_align = 32,
190 + .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG12P,
191 + .size_multiplier_x2 = 2,
194 + .fourcc = V4L2_PIX_FMT_SRGGB16,
196 + .bytesperline_align = 32,
198 + .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB16,
199 + .size_multiplier_x2 = 2,
201 + .fourcc = V4L2_PIX_FMT_SBGGR16,
203 + .bytesperline_align = 32,
205 + .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR16,
206 + .size_multiplier_x2 = 2,
208 + .fourcc = V4L2_PIX_FMT_SGRBG16,
210 + .bytesperline_align = 32,
212 + .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG16,
213 + .size_multiplier_x2 = 2,
215 + .fourcc = V4L2_PIX_FMT_SGBRG16,
217 + .bytesperline_align = 32,
219 + .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG16,
220 + .size_multiplier_x2 = 2,
222 + /* Compressed formats */
223 .fourcc = V4L2_PIX_FMT_H264,
225 .flags = V4L2_FMT_FLAG_COMPRESSED,
226 @@ -212,30 +311,22 @@ static struct bcm2835_codec_fmt encoded_
228 .flags = V4L2_FMT_FLAG_COMPRESSED,
229 .mmal_fmt = MMAL_ENCODING_MP4V,
230 - .decode_only = true,
232 .fourcc = V4L2_PIX_FMT_H263,
234 .flags = V4L2_FMT_FLAG_COMPRESSED,
235 .mmal_fmt = MMAL_ENCODING_H263,
236 - .decode_only = true,
238 .fourcc = V4L2_PIX_FMT_MPEG2,
240 .flags = V4L2_FMT_FLAG_COMPRESSED,
241 .mmal_fmt = MMAL_ENCODING_MP2V,
242 - .decode_only = true,
244 .fourcc = V4L2_PIX_FMT_VP8,
246 .flags = V4L2_FMT_FLAG_COMPRESSED,
247 .mmal_fmt = MMAL_ENCODING_VP8,
248 - .decode_only = true,
251 - * This list couold include VP6 and Theorafor decode, but V4L2 doesn't
256 struct bcm2835_codec_fmt_list {
257 @@ -243,19 +334,6 @@ struct bcm2835_codec_fmt_list {
258 unsigned int num_entries;
262 -#define ENCODED_LIST 1
264 -struct bcm2835_codec_fmt_list formats[] = {
266 - .list = raw_formats,
267 - .num_entries = ARRAY_SIZE(raw_formats),
269 - .list = encoded_formats,
270 - .num_entries = ARRAY_SIZE(encoded_formats),
274 struct m2m_mmal_buffer {
275 struct v4l2_m2m_buffer m2m;
276 struct mmal_buffer mmal;
277 @@ -284,52 +362,6 @@ struct bcm2835_codec_q_data {
278 bool eos_buffer_in_use; /* debug only */
286 -static inline struct bcm2835_codec_fmt_list *get_format_list(bool decode,
289 - return decode ^ capture ? &formats[ENCODED_LIST] : &formats[RAW_LIST];
292 -static struct bcm2835_codec_fmt *get_default_format(bool decode, bool capture)
294 - return &get_format_list(decode, capture)->list[0];
297 -static struct bcm2835_codec_fmt *find_format(struct v4l2_format *f, bool decode,
300 - struct bcm2835_codec_fmt *fmt;
302 - struct bcm2835_codec_fmt_list *fmts = get_format_list(decode, capture);
304 - for (k = 0; k < fmts->num_entries; k++) {
305 - fmt = &fmts->list[k];
306 - if (fmt->fourcc == f->fmt.pix.pixelformat)
311 - * Some compressed formats are only supported for decoding, not
314 - if (!decode && fmts->list[k].decode_only)
317 - /* Some pixel formats are only supported for encoding, not decoding. */
318 - if (decode && fmts->list[k].encode_only)
321 - if (k == fmts->num_entries)
324 - return &fmts->list[k];
327 struct bcm2835_codec_dev {
328 struct platform_device *pdev;
330 @@ -342,6 +374,9 @@ struct bcm2835_codec_dev {
332 /* allocated mmal instance and components */
333 bool decode; /* Is this instance a decoder? */
334 + /* The list of formats supported on input and output queues. */
335 + struct bcm2835_codec_fmt_list supported_fmts[2];
337 struct vchiq_mmal_instance *instance;
339 struct v4l2_m2m_dev *m2m_dev;
340 @@ -374,8 +409,59 @@ struct bcm2835_codec_ctx {
341 struct bcm2835_codec_driver {
342 struct bcm2835_codec_dev *encode;
343 struct bcm2835_codec_dev *decode;
344 + struct bcm2835_codec_dev *isp;
352 +static const struct bcm2835_codec_fmt *get_fmt(u32 mmal_fmt)
356 + for (i = 0; i < ARRAY_SIZE(supported_formats); i++) {
357 + if (supported_formats[i].mmal_fmt == mmal_fmt)
358 + return &supported_formats[i];
364 +struct bcm2835_codec_fmt_list *get_format_list(struct bcm2835_codec_dev *dev,
367 + return &dev->supported_fmts[capture ? 1 : 0];
371 +struct bcm2835_codec_fmt *get_default_format(struct bcm2835_codec_dev *dev,
374 + return &dev->supported_fmts[capture ? 1 : 0].list[0];
377 +static struct bcm2835_codec_fmt *find_format(struct v4l2_format *f,
378 + struct bcm2835_codec_dev *dev,
381 + struct bcm2835_codec_fmt *fmt;
383 + struct bcm2835_codec_fmt_list *fmts =
384 + &dev->supported_fmts[capture ? 1 : 0];
386 + for (k = 0; k < fmts->num_entries; k++) {
387 + fmt = &fmts->list[k];
388 + if (fmt->fourcc == f->fmt.pix.pixelformat)
391 + if (k == fmts->num_entries)
394 + return &fmts->list[k];
397 static inline struct bcm2835_codec_ctx *file2ctx(struct file *file)
399 return container_of(file->private_data, struct bcm2835_codec_ctx, fh);
400 @@ -456,7 +542,6 @@ static inline unsigned int get_bytesperl
403 static void setup_mmal_port_format(struct bcm2835_codec_ctx *ctx,
405 struct bcm2835_codec_q_data *q_data,
406 struct vchiq_mmal_port *port)
408 @@ -473,7 +558,7 @@ static void setup_mmal_port_format(struc
409 port->es.video.frame_rate.den = 1;
411 /* Compressed format - leave resolution as 0 for decode */
413 + if (ctx->dev->decode) {
414 port->es.video.width = 0;
415 port->es.video.height = 0;
416 port->es.video.crop.width = 0;
417 @@ -802,22 +887,15 @@ static int vidioc_querycap(struct file *
421 -static int enum_fmt(struct v4l2_fmtdesc *f, bool decode, bool capture)
422 +static int enum_fmt(struct v4l2_fmtdesc *f, struct bcm2835_codec_ctx *ctx,
425 struct bcm2835_codec_fmt *fmt;
426 - struct bcm2835_codec_fmt_list *fmts = get_format_list(decode, capture);
427 + struct bcm2835_codec_fmt_list *fmts =
428 + get_format_list(ctx->dev, capture);
430 if (f->index < fmts->num_entries) {
432 - /* Check format isn't a decode only format when encoding */
434 - fmts->list[f->index].decode_only)
436 - /* Check format isn't a decode only format when encoding */
438 - fmts->list[f->index].encode_only)
441 fmt = &fmts->list[f->index];
442 f->pixelformat = fmt->fourcc;
443 f->flags = fmt->flags;
444 @@ -833,7 +911,7 @@ static int vidioc_enum_fmt_vid_cap(struc
446 struct bcm2835_codec_ctx *ctx = file2ctx(file);
448 - return enum_fmt(f, ctx->dev->decode, true);
449 + return enum_fmt(f, ctx, true);
452 static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
453 @@ -841,7 +919,7 @@ static int vidioc_enum_fmt_vid_out(struc
455 struct bcm2835_codec_ctx *ctx = file2ctx(file);
457 - return enum_fmt(f, ctx->dev->decode, false);
458 + return enum_fmt(f, ctx, false);
461 static int vidioc_g_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f)
462 @@ -933,11 +1011,11 @@ static int vidioc_try_fmt_vid_cap(struct
463 struct bcm2835_codec_fmt *fmt;
464 struct bcm2835_codec_ctx *ctx = file2ctx(file);
466 - fmt = find_format(f, ctx->dev->decode, true);
467 + fmt = find_format(f, ctx->dev, true);
469 - f->fmt.pix.pixelformat = get_default_format(ctx->dev->decode,
470 + f->fmt.pix.pixelformat = get_default_format(ctx->dev,
472 - fmt = find_format(f, ctx->dev->decode, true);
473 + fmt = find_format(f, ctx->dev, true);
476 return vidioc_try_fmt(f, fmt);
477 @@ -949,11 +1027,11 @@ static int vidioc_try_fmt_vid_out(struct
478 struct bcm2835_codec_fmt *fmt;
479 struct bcm2835_codec_ctx *ctx = file2ctx(file);
481 - fmt = find_format(f, ctx->dev->decode, false);
482 + fmt = find_format(f, ctx->dev, false);
484 - f->fmt.pix.pixelformat = get_default_format(ctx->dev->decode,
485 + f->fmt.pix.pixelformat = get_default_format(ctx->dev,
487 - fmt = find_format(f, ctx->dev->decode, false);
488 + fmt = find_format(f, ctx->dev, false);
491 if (!f->fmt.pix.colorspace)
492 @@ -988,7 +1066,7 @@ static int vidioc_s_fmt(struct bcm2835_c
496 - q_data->fmt = find_format(f, ctx->dev->decode,
497 + q_data->fmt = find_format(f, ctx->dev,
498 f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE);
499 q_data->crop_width = f->fmt.pix.width;
500 q_data->height = f->fmt.pix.height;
501 @@ -1041,7 +1119,7 @@ static int vidioc_s_fmt(struct bcm2835_c
505 - setup_mmal_port_format(ctx, ctx->dev->decode, q_data, port);
506 + setup_mmal_port_format(ctx, q_data, port);
507 ret = vchiq_mmal_port_set_format(ctx->dev->instance, port);
509 v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed vchiq_mmal_port_set_format on port, ret %d\n",
510 @@ -1064,8 +1142,7 @@ static int vidioc_s_fmt(struct bcm2835_c
511 struct bcm2835_codec_q_data *q_data_dst =
512 &ctx->q_data[V4L2_M2M_DST];
514 - setup_mmal_port_format(ctx, ctx->dev->decode, q_data_dst,
516 + setup_mmal_port_format(ctx, q_data_dst, port_dst);
517 ret = vchiq_mmal_port_set_format(ctx->dev->instance, port_dst);
519 v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed vchiq_mmal_port_set_format on output port, ret %d\n",
520 @@ -1636,10 +1713,10 @@ static int bcm2835_codec_create_componen
521 MMAL_PARAMETER_ZERO_COPY, &enable,
524 - setup_mmal_port_format(ctx, dev->decode, &ctx->q_data[V4L2_M2M_SRC],
525 + setup_mmal_port_format(ctx, &ctx->q_data[V4L2_M2M_SRC],
526 &ctx->component->input[0]);
528 - setup_mmal_port_format(ctx, dev->decode, &ctx->q_data[V4L2_M2M_DST],
529 + setup_mmal_port_format(ctx, &ctx->q_data[V4L2_M2M_DST],
530 &ctx->component->output[0]);
532 ret = vchiq_mmal_port_set_format(dev->instance,
533 @@ -2025,8 +2102,8 @@ static int bcm2835_codec_open(struct fil
537 - ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev->decode, false);
538 - ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev->decode, true);
539 + ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev, false);
540 + ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev, true);
543 * Input width and height are irrelevant as they will be defined
544 @@ -2209,13 +2286,130 @@ static const struct v4l2_m2m_ops m2m_ops
545 .job_abort = job_abort,
548 +/* Size of the array to provide to the VPU when asking for the list of supported
550 + * The ISP component currently advertises 33 input formats, so add a small
551 + * overhead on that.
553 +#define MAX_SUPPORTED_ENCODINGS 40
555 +/* Populate dev->supported_fmts with the formats supported by those ports. */
556 +static int bcm2835_codec_get_supported_fmts(struct bcm2835_codec_dev *dev)
558 + struct bcm2835_codec_fmt *list;
559 + struct vchiq_mmal_component *component;
560 + u32 fourccs[MAX_SUPPORTED_ENCODINGS];
561 + u32 param_size = sizeof(fourccs);
562 + unsigned int i, j, num_encodings;
565 + ret = vchiq_mmal_component_init(dev->instance,
567 + "ril.video_decode" :
568 + "ril.video_encode",
571 + v4l2_err(&dev->v4l2_dev, "%s: failed to create component\n",
576 + ret = vchiq_mmal_port_parameter_get(dev->instance,
577 + &component->input[0],
578 + MMAL_PARAMETER_SUPPORTED_ENCODINGS,
583 + if (ret == MMAL_MSG_STATUS_ENOSPC) {
584 + v4l2_err(&dev->v4l2_dev, "%s: port has more encoding than we provided space for. Some are dropped.\n",
586 + num_encodings = MAX_SUPPORTED_ENCODINGS;
588 + v4l2_err(&dev->v4l2_dev, "%s: get_param ret %u.\n",
591 + goto destroy_component;
594 + num_encodings = param_size / sizeof(u32);
597 + /* Assume at this stage that all encodings will be supported in V4L2.
598 + * Any that aren't supported will waste a very small amount of memory.
600 + list = devm_kzalloc(&dev->pdev->dev,
601 + sizeof(struct bcm2835_codec_fmt) * num_encodings,
605 + goto destroy_component;
607 + dev->supported_fmts[0].list = list;
609 + for (i = 0, j = 0; i < num_encodings; i++) {
610 + const struct bcm2835_codec_fmt *fmt = get_fmt(fourccs[i]);
617 + dev->supported_fmts[0].num_entries = j;
619 + param_size = sizeof(fourccs);
620 + ret = vchiq_mmal_port_parameter_get(dev->instance,
621 + &component->output[0],
622 + MMAL_PARAMETER_SUPPORTED_ENCODINGS,
627 + if (ret == MMAL_MSG_STATUS_ENOSPC) {
628 + v4l2_err(&dev->v4l2_dev, "%s: port has more encoding than we provided space for. Some are dropped.\n",
630 + num_encodings = MAX_SUPPORTED_ENCODINGS;
633 + goto destroy_component;
636 + num_encodings = param_size / sizeof(u32);
638 + /* Assume at this stage that all encodings will be supported in V4L2. */
639 + list = devm_kzalloc(&dev->pdev->dev,
640 + sizeof(struct bcm2835_codec_fmt) * num_encodings,
644 + goto destroy_component;
646 + dev->supported_fmts[1].list = list;
648 + for (i = 0, j = 0; i < num_encodings; i++) {
649 + const struct bcm2835_codec_fmt *fmt = get_fmt(fourccs[i]);
656 + dev->supported_fmts[1].num_entries = j;
661 + vchiq_mmal_component_finalise(dev->instance, component);
666 static int bcm2835_codec_create(struct platform_device *pdev,
667 struct bcm2835_codec_dev **new_dev,
670 struct bcm2835_codec_dev *dev;
671 struct video_device *vfd;
672 - struct vchiq_mmal_instance *instance = NULL;
676 @@ -2227,10 +2421,18 @@ static int bcm2835_codec_create(struct p
678 dev->decode = decode;
680 - ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
681 + ret = vchiq_mmal_init(&dev->instance);
685 + ret = bcm2835_codec_get_supported_fmts(dev);
687 + goto vchiq_finalise;
689 + ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
691 + goto vchiq_finalise;
693 atomic_set(&dev->num_inst, 0);
694 mutex_init(&dev->dev_mutex);
696 @@ -2270,12 +2472,7 @@ static int bcm2835_codec_create(struct p
700 - ret = vchiq_mmal_init(&instance);
703 - dev->instance = instance;
705 - v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s codec\n",
706 + v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s\n",
707 dev->decode ? "decode" : "encode");
710 @@ -2284,7 +2481,8 @@ err_m2m:
711 video_unregister_device(&dev->vfd);
713 v4l2_device_unregister(&dev->v4l2_dev);
716 + vchiq_mmal_finalise(dev->instance);
720 @@ -2297,6 +2495,7 @@ static int bcm2835_codec_destroy(struct
721 v4l2_m2m_release(dev->m2m_dev);
722 video_unregister_device(&dev->vfd);
723 v4l2_device_unregister(&dev->v4l2_dev);
724 + vchiq_mmal_finalise(dev->instance);