5eec74e42ac789ed3a5b9badfbb47f81bb601089
[oweals/openwrt.git] /
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
5  the component
6
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.
12
13 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
14 ---
15  .../bcm2835-codec/bcm2835-v4l2-codec.c        | 455 +++++++++++++-----
16  1 file changed, 327 insertions(+), 128 deletions(-)
17
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;
22         u32     flags;
23         u32     mmal_fmt;
24 -       bool    decode_only;
25 -       bool    encode_only;
26         int     size_multiplier_x2;
27  };
28  
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).
32 - */
33 -static struct bcm2835_codec_fmt raw_formats[] = {
34 +static const struct bcm2835_codec_fmt supported_formats[] = {
35         {
36 +               /* YUV formats */
37                 .fourcc                 = V4L2_PIX_FMT_YUV420,
38                 .depth                  = 8,
39                 .bytesperline_align     = 32,
40 @@ -139,7 +134,6 @@ static struct bcm2835_codec_fmt raw_form
41                 .bytesperline_align     = 32,
42                 .flags                  = 0,
43                 .mmal_fmt               = MMAL_ENCODING_YUYV,
44 -               .encode_only            = true,
45                 .size_multiplier_x2     = 2,
46         }, {
47                 .fourcc                 = V4L2_PIX_FMT_UYVY,
48 @@ -147,7 +141,6 @@ static struct bcm2835_codec_fmt raw_form
49                 .bytesperline_align     = 32,
50                 .flags                  = 0,
51                 .mmal_fmt               = MMAL_ENCODING_UYVY,
52 -               .encode_only            = true,
53                 .size_multiplier_x2     = 2,
54         }, {
55                 .fourcc                 = V4L2_PIX_FMT_YVYU,
56 @@ -155,7 +148,6 @@ static struct bcm2835_codec_fmt raw_form
57                 .bytesperline_align     = 32,
58                 .flags                  = 0,
59                 .mmal_fmt               = MMAL_ENCODING_YVYU,
60 -               .encode_only            = true,
61                 .size_multiplier_x2     = 2,
62         }, {
63                 .fourcc                 = V4L2_PIX_FMT_VYUY,
64 @@ -163,15 +155,14 @@ static struct bcm2835_codec_fmt raw_form
65                 .bytesperline_align     = 32,
66                 .flags                  = 0,
67                 .mmal_fmt               = MMAL_ENCODING_VYUY,
68 -               .encode_only            = true,
69                 .size_multiplier_x2     = 2,
70         }, {
71 +               /* RGB formats */
72                 .fourcc                 = V4L2_PIX_FMT_RGB24,
73                 .depth                  = 24,
74                 .bytesperline_align     = 32,
75                 .flags                  = 0,
76                 .mmal_fmt               = MMAL_ENCODING_RGB24,
77 -               .encode_only            = true,
78                 .size_multiplier_x2     = 2,
79         }, {
80                 .fourcc                 = V4L2_PIX_FMT_BGR24,
81 @@ -179,7 +170,6 @@ static struct bcm2835_codec_fmt raw_form
82                 .bytesperline_align     = 32,
83                 .flags                  = 0,
84                 .mmal_fmt               = MMAL_ENCODING_BGR24,
85 -               .encode_only            = true,
86                 .size_multiplier_x2     = 2,
87         }, {
88                 .fourcc                 = V4L2_PIX_FMT_BGR32,
89 @@ -187,17 +177,126 @@ static struct bcm2835_codec_fmt raw_form
90                 .bytesperline_align     = 32,
91                 .flags                  = 0,
92                 .mmal_fmt               = MMAL_ENCODING_BGRA,
93 -               .encode_only            = true,
94                 .size_multiplier_x2     = 2,
95 -       },
96 -};
97 -
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).
101 - */
102 -static struct bcm2835_codec_fmt encoded_formats[] = {
103 -       {
104 +       }, {
105 +               /* Bayer formats */
106 +               /* 8 bit */
107 +               .fourcc                 = V4L2_PIX_FMT_SRGGB8,
108 +               .depth                  = 8,
109 +               .bytesperline_align     = 32,
110 +               .flags                  = 0,
111 +               .mmal_fmt               = MMAL_ENCODING_BAYER_SRGGB8,
112 +               .size_multiplier_x2     = 2,
113 +       }, {
114 +               .fourcc                 = V4L2_PIX_FMT_SBGGR8,
115 +               .depth                  = 8,
116 +               .bytesperline_align     = 32,
117 +               .flags                  = 0,
118 +               .mmal_fmt               = MMAL_ENCODING_BAYER_SBGGR8,
119 +               .size_multiplier_x2     = 2,
120 +       }, {
121 +               .fourcc                 = V4L2_PIX_FMT_SGRBG8,
122 +               .depth                  = 8,
123 +               .bytesperline_align     = 32,
124 +               .flags                  = 0,
125 +               .mmal_fmt               = MMAL_ENCODING_BAYER_SGRBG8,
126 +               .size_multiplier_x2     = 2,
127 +       }, {
128 +               .fourcc                 = V4L2_PIX_FMT_SGBRG8,
129 +               .depth                  = 8,
130 +               .bytesperline_align     = 32,
131 +               .flags                  = 0,
132 +               .mmal_fmt               = MMAL_ENCODING_BAYER_SGBRG8,
133 +               .size_multiplier_x2     = 2,
134 +       }, {
135 +               /* 10 bit */
136 +               .fourcc                 = V4L2_PIX_FMT_SRGGB10P,
137 +               .depth                  = 10,
138 +               .bytesperline_align     = 32,
139 +               .flags                  = 0,
140 +               .mmal_fmt               = MMAL_ENCODING_BAYER_SRGGB10P,
141 +               .size_multiplier_x2     = 2,
142 +       }, {
143 +               .fourcc                 = V4L2_PIX_FMT_SBGGR10P,
144 +               .depth                  = 10,
145 +               .bytesperline_align     = 32,
146 +               .flags                  = 0,
147 +               .mmal_fmt               = MMAL_ENCODING_BAYER_SBGGR10P,
148 +               .size_multiplier_x2     = 2,
149 +       }, {
150 +               .fourcc                 = V4L2_PIX_FMT_SGRBG10P,
151 +               .depth                  = 10,
152 +               .bytesperline_align     = 32,
153 +               .flags                  = 0,
154 +               .mmal_fmt               = MMAL_ENCODING_BAYER_SGRBG10P,
155 +               .size_multiplier_x2     = 2,
156 +       }, {
157 +               .fourcc                 = V4L2_PIX_FMT_SGBRG10P,
158 +               .depth                  = 10,
159 +               .bytesperline_align     = 32,
160 +               .flags                  = 0,
161 +               .mmal_fmt               = MMAL_ENCODING_BAYER_SGBRG10P,
162 +               .size_multiplier_x2     = 2,
163 +       }, {
164 +               /* 12 bit */
165 +               .fourcc                 = V4L2_PIX_FMT_SRGGB12P,
166 +               .depth                  = 12,
167 +               .bytesperline_align     = 32,
168 +               .flags                  = 0,
169 +               .mmal_fmt               = MMAL_ENCODING_BAYER_SRGGB12P,
170 +               .size_multiplier_x2     = 2,
171 +       }, {
172 +               .fourcc                 = V4L2_PIX_FMT_SBGGR12P,
173 +               .depth                  = 12,
174 +               .bytesperline_align     = 32,
175 +               .flags                  = 0,
176 +               .mmal_fmt               = MMAL_ENCODING_BAYER_SBGGR12P,
177 +               .size_multiplier_x2     = 2,
178 +       }, {
179 +               .fourcc                 = V4L2_PIX_FMT_SGRBG12P,
180 +               .depth                  = 12,
181 +               .bytesperline_align     = 32,
182 +               .flags                  = 0,
183 +               .mmal_fmt               = MMAL_ENCODING_BAYER_SGRBG12P,
184 +               .size_multiplier_x2     = 2,
185 +       }, {
186 +               .fourcc                 = V4L2_PIX_FMT_SGBRG12P,
187 +               .depth                  = 12,
188 +               .bytesperline_align     = 32,
189 +               .flags                  = 0,
190 +               .mmal_fmt               = MMAL_ENCODING_BAYER_SGBRG12P,
191 +               .size_multiplier_x2     = 2,
192 +       }, {
193 +               /* 16 bit */
194 +               .fourcc                 = V4L2_PIX_FMT_SRGGB16,
195 +               .depth                  = 16,
196 +               .bytesperline_align     = 32,
197 +               .flags                  = 0,
198 +               .mmal_fmt               = MMAL_ENCODING_BAYER_SRGGB16,
199 +               .size_multiplier_x2     = 2,
200 +       }, {
201 +               .fourcc                 = V4L2_PIX_FMT_SBGGR16,
202 +               .depth                  = 16,
203 +               .bytesperline_align     = 32,
204 +               .flags                  = 0,
205 +               .mmal_fmt               = MMAL_ENCODING_BAYER_SBGGR16,
206 +               .size_multiplier_x2     = 2,
207 +       }, {
208 +               .fourcc                 = V4L2_PIX_FMT_SGRBG16,
209 +               .depth                  = 16,
210 +               .bytesperline_align     = 32,
211 +               .flags                  = 0,
212 +               .mmal_fmt               = MMAL_ENCODING_BAYER_SGRBG16,
213 +               .size_multiplier_x2     = 2,
214 +       }, {
215 +               .fourcc                 = V4L2_PIX_FMT_SGBRG16,
216 +               .depth                  = 16,
217 +               .bytesperline_align     = 32,
218 +               .flags                  = 0,
219 +               .mmal_fmt               = MMAL_ENCODING_BAYER_SGBRG16,
220 +               .size_multiplier_x2     = 2,
221 +       }, {
222 +               /* Compressed formats */
223                 .fourcc                 = V4L2_PIX_FMT_H264,
224                 .depth                  = 0,
225                 .flags                  = V4L2_FMT_FLAG_COMPRESSED,
226 @@ -212,30 +311,22 @@ static struct bcm2835_codec_fmt encoded_
227                 .depth                  = 0,
228                 .flags                  = V4L2_FMT_FLAG_COMPRESSED,
229                 .mmal_fmt               = MMAL_ENCODING_MP4V,
230 -               .decode_only            = true,
231         }, {
232                 .fourcc                 = V4L2_PIX_FMT_H263,
233                 .depth                  = 0,
234                 .flags                  = V4L2_FMT_FLAG_COMPRESSED,
235                 .mmal_fmt               = MMAL_ENCODING_H263,
236 -               .decode_only            = true,
237         }, {
238                 .fourcc                 = V4L2_PIX_FMT_MPEG2,
239                 .depth                  = 0,
240                 .flags                  = V4L2_FMT_FLAG_COMPRESSED,
241                 .mmal_fmt               = MMAL_ENCODING_MP2V,
242 -               .decode_only            = true,
243         }, {
244                 .fourcc                 = V4L2_PIX_FMT_VP8,
245                 .depth                  = 0,
246                 .flags                  = V4L2_FMT_FLAG_COMPRESSED,
247                 .mmal_fmt               = MMAL_ENCODING_VP8,
248 -               .decode_only            = true,
249         },
250 -       /*
251 -        * This list couold include VP6 and Theorafor decode, but V4L2 doesn't
252 -        * support them.
253 -        */
254  };
255  
256  struct bcm2835_codec_fmt_list {
257 @@ -243,19 +334,6 @@ struct bcm2835_codec_fmt_list {
258         unsigned int num_entries;
259  };
260  
261 -#define RAW_LIST       0
262 -#define ENCODED_LIST   1
263 -
264 -struct bcm2835_codec_fmt_list formats[] = {
265 -       {
266 -               .list = raw_formats,
267 -               .num_entries = ARRAY_SIZE(raw_formats),
268 -       }, {
269 -               .list = encoded_formats,
270 -               .num_entries = ARRAY_SIZE(encoded_formats),
271 -       },
272 -};
273 -
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 */
279  };
280  
281 -enum {
282 -       V4L2_M2M_SRC = 0,
283 -       V4L2_M2M_DST = 1,
284 -};
285 -
286 -static inline struct bcm2835_codec_fmt_list *get_format_list(bool decode,
287 -                                                            bool capture)
288 -{
289 -       return decode ^ capture ? &formats[ENCODED_LIST] : &formats[RAW_LIST];
290 -}
291 -
292 -static struct bcm2835_codec_fmt *get_default_format(bool decode, bool capture)
293 -{
294 -       return &get_format_list(decode, capture)->list[0];
295 -}
296 -
297 -static struct bcm2835_codec_fmt *find_format(struct v4l2_format *f, bool decode,
298 -                                            bool capture)
299 -{
300 -       struct bcm2835_codec_fmt *fmt;
301 -       unsigned int k;
302 -       struct bcm2835_codec_fmt_list *fmts = get_format_list(decode, capture);
303 -
304 -       for (k = 0; k < fmts->num_entries; k++) {
305 -               fmt = &fmts->list[k];
306 -               if (fmt->fourcc == f->fmt.pix.pixelformat)
307 -                       break;
308 -       }
309 -
310 -       /*
311 -        * Some compressed formats are only supported for decoding, not
312 -        * encoding.
313 -        */
314 -       if (!decode && fmts->list[k].decode_only)
315 -               return NULL;
316 -
317 -       /* Some pixel formats are only supported for encoding, not decoding. */
318 -       if (decode && fmts->list[k].encode_only)
319 -               return NULL;
320 -
321 -       if (k == fmts->num_entries)
322 -               return NULL;
323 -
324 -       return &fmts->list[k];
325 -}
326 -
327  struct bcm2835_codec_dev {
328         struct platform_device *pdev;
329  
330 @@ -342,6 +374,9 @@ struct bcm2835_codec_dev {
331  
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];
336 +
337         struct vchiq_mmal_instance      *instance;
338  
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;
345 +};
346 +
347 +enum {
348 +       V4L2_M2M_SRC = 0,
349 +       V4L2_M2M_DST = 1,
350  };
351  
352 +static const struct bcm2835_codec_fmt *get_fmt(u32 mmal_fmt)
353 +{
354 +       unsigned int i;
355 +
356 +       for (i = 0; i < ARRAY_SIZE(supported_formats); i++) {
357 +               if (supported_formats[i].mmal_fmt == mmal_fmt)
358 +                       return &supported_formats[i];
359 +       }
360 +       return NULL;
361 +}
362 +
363 +static inline
364 +struct bcm2835_codec_fmt_list *get_format_list(struct bcm2835_codec_dev *dev,
365 +                                              bool capture)
366 +{
367 +       return &dev->supported_fmts[capture ? 1 : 0];
368 +}
369 +
370 +static
371 +struct bcm2835_codec_fmt *get_default_format(struct bcm2835_codec_dev *dev,
372 +                                            bool capture)
373 +{
374 +       return &dev->supported_fmts[capture ? 1 : 0].list[0];
375 +}
376 +
377 +static struct bcm2835_codec_fmt *find_format(struct v4l2_format *f,
378 +                                            struct bcm2835_codec_dev *dev,
379 +                                            bool capture)
380 +{
381 +       struct bcm2835_codec_fmt *fmt;
382 +       unsigned int k;
383 +       struct bcm2835_codec_fmt_list *fmts =
384 +                                       &dev->supported_fmts[capture ? 1 : 0];
385 +
386 +       for (k = 0; k < fmts->num_entries; k++) {
387 +               fmt = &fmts->list[k];
388 +               if (fmt->fourcc == f->fmt.pix.pixelformat)
389 +                       break;
390 +       }
391 +       if (k == fmts->num_entries)
392 +               return NULL;
393 +
394 +       return &fmts->list[k];
395 +}
396 +
397  static inline struct bcm2835_codec_ctx *file2ctx(struct file *file)
398  {
399         return container_of(file->private_data, struct bcm2835_codec_ctx, fh);
400 @@ -456,7 +542,6 @@ static inline unsigned int get_bytesperl
401  }
402  
403  static void setup_mmal_port_format(struct bcm2835_codec_ctx *ctx,
404 -                                  bool decode,
405                                    struct bcm2835_codec_q_data *q_data,
406                                    struct vchiq_mmal_port *port)
407  {
408 @@ -473,7 +558,7 @@ static void setup_mmal_port_format(struc
409                 port->es.video.frame_rate.den = 1;
410         } else {
411                 /* Compressed format - leave resolution as 0 for decode */
412 -               if (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 *
418         return 0;
419  }
420  
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,
423 +                   bool capture)
424  {
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);
429  
430         if (f->index < fmts->num_entries) {
431                 /* Format found */
432 -               /* Check format isn't a decode only format when encoding */
433 -               if (!decode &&
434 -                   fmts->list[f->index].decode_only)
435 -                       return -EINVAL;
436 -               /* Check format isn't a decode only format when encoding */
437 -               if (decode &&
438 -                   fmts->list[f->index].encode_only)
439 -                       return -EINVAL;
440 -
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
445  {
446         struct bcm2835_codec_ctx *ctx = file2ctx(file);
447  
448 -       return enum_fmt(f, ctx->dev->decode, true);
449 +       return enum_fmt(f, ctx, true);
450  }
451  
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
454  {
455         struct bcm2835_codec_ctx *ctx = file2ctx(file);
456  
457 -       return enum_fmt(f, ctx->dev->decode, false);
458 +       return enum_fmt(f, ctx, false);
459  }
460  
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);
465  
466 -       fmt = find_format(f, ctx->dev->decode, true);
467 +       fmt = find_format(f, ctx->dev, true);
468         if (!fmt) {
469 -               f->fmt.pix.pixelformat = get_default_format(ctx->dev->decode,
470 +               f->fmt.pix.pixelformat = get_default_format(ctx->dev,
471                                                             true)->fourcc;
472 -               fmt = find_format(f, ctx->dev->decode, true);
473 +               fmt = find_format(f, ctx->dev, true);
474         }
475  
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);
480  
481 -       fmt = find_format(f, ctx->dev->decode, false);
482 +       fmt = find_format(f, ctx->dev, false);
483         if (!fmt) {
484 -               f->fmt.pix.pixelformat = get_default_format(ctx->dev->decode,
485 +               f->fmt.pix.pixelformat = get_default_format(ctx->dev,
486                                                             false)->fourcc;
487 -               fmt = find_format(f, ctx->dev->decode, false);
488 +               fmt = find_format(f, ctx->dev, false);
489         }
490  
491         if (!f->fmt.pix.colorspace)
492 @@ -988,7 +1066,7 @@ static int vidioc_s_fmt(struct bcm2835_c
493                 return -EBUSY;
494         }
495  
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
502         if (!port)
503                 return 0;
504  
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);
508         if (ret) {
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];
513  
514 -               setup_mmal_port_format(ctx, ctx->dev->decode, q_data_dst,
515 -                                      port_dst);
516 +               setup_mmal_port_format(ctx, q_data_dst, port_dst);
517                 ret = vchiq_mmal_port_set_format(ctx->dev->instance, port_dst);
518                 if (ret) {
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,
522                                       sizeof(enable));
523  
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]);
527  
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]);
531  
532         ret = vchiq_mmal_port_set_format(dev->instance,
533 @@ -2025,8 +2102,8 @@ static int bcm2835_codec_open(struct fil
534                 goto open_unlock;
535         }
536  
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);
541         if (dev->decode) {
542                 /*
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,
546  };
547  
548 +/* Size of the array to provide to the VPU when asking for the list of supported
549 + * formats.
550 + * The ISP component currently advertises 33 input formats, so add a small
551 + * overhead on that.
552 + */
553 +#define MAX_SUPPORTED_ENCODINGS 40
554 +
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)
557 +{
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;
563 +       int ret;
564 +
565 +       ret = vchiq_mmal_component_init(dev->instance,
566 +                                       dev->decode ?
567 +                                               "ril.video_decode" :
568 +                                               "ril.video_encode",
569 +                                       &component);
570 +       if (ret < 0) {
571 +               v4l2_err(&dev->v4l2_dev, "%s: failed to create component\n",
572 +                        __func__);
573 +               return -ENOMEM;
574 +       }
575 +
576 +       ret = vchiq_mmal_port_parameter_get(dev->instance,
577 +                                           &component->input[0],
578 +                                           MMAL_PARAMETER_SUPPORTED_ENCODINGS,
579 +                                           &fourccs,
580 +                                           &param_size);
581 +
582 +       if (ret) {
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",
585 +                                __func__);
586 +                       num_encodings = MAX_SUPPORTED_ENCODINGS;
587 +               } else {
588 +                       v4l2_err(&dev->v4l2_dev, "%s: get_param ret %u.\n",
589 +                                __func__, ret);
590 +                       ret = -EINVAL;
591 +                       goto destroy_component;
592 +               }
593 +       } else {
594 +               num_encodings = param_size / sizeof(u32);
595 +       }
596 +
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.
599 +        */
600 +       list = devm_kzalloc(&dev->pdev->dev,
601 +                           sizeof(struct bcm2835_codec_fmt) * num_encodings,
602 +                           GFP_KERNEL);
603 +       if (!list) {
604 +               ret = -ENOMEM;
605 +               goto destroy_component;
606 +       }
607 +       dev->supported_fmts[0].list = list;
608 +
609 +       for (i = 0, j = 0; i < num_encodings; i++) {
610 +               const struct bcm2835_codec_fmt *fmt = get_fmt(fourccs[i]);
611 +
612 +               if (fmt) {
613 +                       list[j] = *fmt;
614 +                       j++;
615 +               }
616 +       }
617 +       dev->supported_fmts[0].num_entries = j;
618 +
619 +       param_size = sizeof(fourccs);
620 +       ret = vchiq_mmal_port_parameter_get(dev->instance,
621 +                                           &component->output[0],
622 +                                           MMAL_PARAMETER_SUPPORTED_ENCODINGS,
623 +                                           &fourccs,
624 +                                           &param_size);
625 +
626 +       if (ret) {
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",
629 +                                __func__);
630 +                       num_encodings = MAX_SUPPORTED_ENCODINGS;
631 +               } else {
632 +                       ret = -EINVAL;
633 +                       goto destroy_component;
634 +               }
635 +       } else {
636 +               num_encodings = param_size / sizeof(u32);
637 +       }
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,
641 +                           GFP_KERNEL);
642 +       if (!list) {
643 +               ret = -ENOMEM;
644 +               goto destroy_component;
645 +       }
646 +       dev->supported_fmts[1].list = list;
647 +
648 +       for (i = 0, j = 0; i < num_encodings; i++) {
649 +               const struct bcm2835_codec_fmt *fmt = get_fmt(fourccs[i]);
650 +
651 +               if (fmt) {
652 +                       list[j] = *fmt;
653 +                       j++;
654 +               }
655 +       }
656 +       dev->supported_fmts[1].num_entries = j;
657 +
658 +       ret = 0;
659 +
660 +destroy_component:
661 +       vchiq_mmal_component_finalise(dev->instance, component);
662 +
663 +       return ret;
664 +}
665 +
666  static int bcm2835_codec_create(struct platform_device *pdev,
667                                 struct bcm2835_codec_dev **new_dev,
668                                 bool decode)
669  {
670         struct bcm2835_codec_dev *dev;
671         struct video_device *vfd;
672 -       struct vchiq_mmal_instance *instance = NULL;
673         int video_nr;
674         int ret;
675  
676 @@ -2227,10 +2421,18 @@ static int bcm2835_codec_create(struct p
677  
678         dev->decode = decode;
679  
680 -       ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
681 +       ret = vchiq_mmal_init(&dev->instance);
682         if (ret)
683                 return ret;
684  
685 +       ret = bcm2835_codec_get_supported_fmts(dev);
686 +       if (ret)
687 +               goto vchiq_finalise;
688 +
689 +       ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
690 +       if (ret)
691 +               goto vchiq_finalise;
692 +
693         atomic_set(&dev->num_inst, 0);
694         mutex_init(&dev->dev_mutex);
695  
696 @@ -2270,12 +2472,7 @@ static int bcm2835_codec_create(struct p
697                 goto err_m2m;
698         }
699  
700 -       ret = vchiq_mmal_init(&instance);
701 -       if (ret < 0)
702 -               goto err_m2m;
703 -       dev->instance = instance;
704 -
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");
708         return 0;
709  
710 @@ -2284,7 +2481,8 @@ err_m2m:
711         video_unregister_device(&dev->vfd);
712  unreg_dev:
713         v4l2_device_unregister(&dev->v4l2_dev);
714 -
715 +vchiq_finalise:
716 +       vchiq_mmal_finalise(dev->instance);
717         return ret;
718  }
719  
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);
725  
726         return 0;
727  }