df59acd249d9f865357bf11685587d2896d148c5
[oweals/openwrt.git] /
1 From 7afce6566802bcaa468f92b9e06da8b899161128 Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.org>
3 Date: Wed, 13 Feb 2019 14:07:52 +0000
4 Subject: [PATCH] staging: bcm2835_codec: Add support for the ISP as an
5  M2M device
6
7 The MMAL ISP component can also use this same V4L2 wrapper to
8 provide a M2M format conversion and resizer.
9 Instantiate 3 V4L2 devices now, one for each of decode, encode,
10 and isp.
11 The ISP currently doesn't expose any controls via V4L2, but this
12 can be extended in the future.
13
14 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
15 ---
16  .../bcm2835-codec/bcm2835-v4l2-codec.c        | 132 ++++++++++++------
17  1 file changed, 92 insertions(+), 40 deletions(-)
18
19 --- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
20 +++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
21 @@ -54,10 +54,26 @@ static int encode_video_nr = 11;
22  module_param(encode_video_nr, int, 0644);
23  MODULE_PARM_DESC(encode_video_nr, "encoder video device number");
24  
25 +static int isp_video_nr = 12;
26 +module_param(isp_video_nr, int, 0644);
27 +MODULE_PARM_DESC(isp_video_nr, "isp video device number");
28 +
29  static unsigned int debug;
30  module_param(debug, uint, 0644);
31  MODULE_PARM_DESC(debug, "activates debug info (0-3)");
32  
33 +enum bcm2835_codec_role {
34 +       DECODE,
35 +       ENCODE,
36 +       ISP,
37 +};
38 +
39 +static const char * const components[] = {
40 +       "ril.video_decode",
41 +       "ril.video_encode",
42 +       "ril.isp",
43 +};
44 +
45  #define MIN_W          32
46  #define MIN_H          32
47  #define MAX_W          1920
48 @@ -373,7 +389,7 @@ struct bcm2835_codec_dev {
49         atomic_t                num_inst;
50  
51         /* allocated mmal instance and components */
52 -       bool                    decode;  /* Is this instance a decoder? */
53 +       enum bcm2835_codec_role role;
54         /* The list of formats supported on input and output queues. */
55         struct bcm2835_codec_fmt_list   supported_fmts[2];
56  
57 @@ -558,7 +574,7 @@ static void setup_mmal_port_format(struc
58                 port->es.video.frame_rate.den = 1;
59         } else {
60                 /* Compressed format - leave resolution as 0 for decode */
61 -               if (ctx->dev->decode) {
62 +               if (ctx->dev->role == DECODE) {
63                         port->es.video.width = 0;
64                         port->es.video.height = 0;
65                         port->es.video.crop.width = 0;
66 @@ -1089,7 +1105,8 @@ static int vidioc_s_fmt(struct bcm2835_c
67         v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Calulated bpl as %u, size %u\n",
68                  q_data->bytesperline, q_data->sizeimage);
69  
70 -       if (ctx->dev->decode && q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED &&
71 +       if (ctx->dev->role == DECODE &&
72 +           q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED &&
73             f->fmt.pix.width && f->fmt.pix.height) {
74                 /*
75                  * On the decoder, if provided with a resolution on the input
76 @@ -1188,7 +1205,8 @@ static int vidioc_g_selection(struct fil
77         bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ?
78                                                                 true : false;
79  
80 -       if (capture_queue ^ ctx->dev->decode)
81 +       if ((ctx->dev->role == DECODE && !capture_queue) ||
82 +           (ctx->dev->role == ENCODE && capture_queue))
83                 /* OUTPUT on decoder and CAPTURE on encoder are not valid. */
84                 return -EINVAL;
85  
86 @@ -1196,7 +1214,8 @@ static int vidioc_g_selection(struct fil
87         if (!q_data)
88                 return -EINVAL;
89  
90 -       if (ctx->dev->decode) {
91 +       switch (ctx->dev->role) {
92 +       case DECODE:
93                 switch (s->target) {
94                 case V4L2_SEL_TGT_COMPOSE_DEFAULT:
95                 case V4L2_SEL_TGT_COMPOSE:
96 @@ -1214,7 +1233,8 @@ static int vidioc_g_selection(struct fil
97                 default:
98                         return -EINVAL;
99                 }
100 -       } else {
101 +               break;
102 +       case ENCODE:
103                 switch (s->target) {
104                 case V4L2_SEL_TGT_CROP_DEFAULT:
105                 case V4L2_SEL_TGT_CROP_BOUNDS:
106 @@ -1232,6 +1252,9 @@ static int vidioc_g_selection(struct fil
107                 default:
108                         return -EINVAL;
109                 }
110 +               break;
111 +       case ISP:
112 +               break;
113         }
114  
115         return 0;
116 @@ -1249,7 +1272,8 @@ static int vidioc_s_selection(struct fil
117                  __func__, ctx, s->type, q_data, s->target, s->r.left, s->r.top,
118                  s->r.width, s->r.height);
119  
120 -       if (capture_queue ^ ctx->dev->decode)
121 +       if ((ctx->dev->role == DECODE && !capture_queue) ||
122 +           (ctx->dev->role == ENCODE && capture_queue))
123                 /* OUTPUT on decoder and CAPTURE on encoder are not valid. */
124                 return -EINVAL;
125  
126 @@ -1257,7 +1281,8 @@ static int vidioc_s_selection(struct fil
127         if (!q_data)
128                 return -EINVAL;
129  
130 -       if (ctx->dev->decode) {
131 +       switch (ctx->dev->role) {
132 +       case DECODE:
133                 switch (s->target) {
134                 case V4L2_SEL_TGT_COMPOSE:
135                         /* Accept cropped image */
136 @@ -1272,7 +1297,8 @@ static int vidioc_s_selection(struct fil
137                 default:
138                         return -EINVAL;
139                 }
140 -       } else {
141 +               break;
142 +       case ENCODE:
143                 switch (s->target) {
144                 case V4L2_SEL_TGT_CROP:
145                         /* Only support crop from (0,0) */
146 @@ -1287,6 +1313,9 @@ static int vidioc_s_selection(struct fil
147                 default:
148                         return -EINVAL;
149                 }
150 +               break;
151 +       case ISP:
152 +               break;
153         }
154  
155         return 0;
156 @@ -1490,7 +1519,7 @@ static int vidioc_try_decoder_cmd(struct
157  {
158         struct bcm2835_codec_ctx *ctx = file2ctx(file);
159  
160 -       if (!ctx->dev->decode)
161 +       if (ctx->dev->role != DECODE)
162                 return -EINVAL;
163  
164         switch (cmd->cmd) {
165 @@ -1564,7 +1593,7 @@ static int vidioc_try_encoder_cmd(struct
166  {
167         struct bcm2835_codec_ctx *ctx = file2ctx(file);
168  
169 -       if (ctx->dev->decode)
170 +       if (ctx->dev->role != ENCODE)
171                 return -EINVAL;
172  
173         switch (cmd->cmd) {
174 @@ -1697,12 +1726,11 @@ static int bcm2835_codec_create_componen
175         unsigned int enable = 1;
176         int ret;
177  
178 -       ret = vchiq_mmal_component_init(dev->instance, dev->decode ?
179 -                                       "ril.video_decode" : "ril.video_encode",
180 +       ret = vchiq_mmal_component_init(dev->instance, components[dev->role],
181                                         &ctx->component);
182         if (ret < 0) {
183 -               v4l2_err(&dev->v4l2_dev, "%s: failed to create component for %s\n",
184 -                        __func__, dev->decode ? "decode" : "encode");
185 +               v4l2_err(&dev->v4l2_dev, "%s: failed to create component %s\n",
186 +                        __func__, components[dev->role]);
187                 return -ENOMEM;
188         }
189  
190 @@ -1729,13 +1757,7 @@ static int bcm2835_codec_create_componen
191         if (ret < 0)
192                 goto destroy_component;
193  
194 -       if (dev->decode) {
195 -               if (ctx->q_data[V4L2_M2M_DST].sizeimage <
196 -                       ctx->component->output[0].minimum_buffer.size)
197 -                       v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
198 -                                ctx->q_data[V4L2_M2M_DST].sizeimage,
199 -                                ctx->component->output[0].minimum_buffer.size);
200 -       } else {
201 +       if (dev->role == ENCODE) {
202                 if (ctx->q_data[V4L2_M2M_SRC].sizeimage <
203                         ctx->component->output[0].minimum_buffer.size)
204                         v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
205 @@ -1744,6 +1766,12 @@ static int bcm2835_codec_create_componen
206  
207                 /* Now we have a component we can set all the ctrls */
208                 bcm2835_codec_set_ctrls(ctx);
209 +       } else {
210 +               if (ctx->q_data[V4L2_M2M_DST].sizeimage <
211 +                       ctx->component->output[0].minimum_buffer.size)
212 +                       v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
213 +                                ctx->q_data[V4L2_M2M_DST].sizeimage,
214 +                                ctx->component->output[0].minimum_buffer.size);
215         }
216  
217         return 0;
218 @@ -2090,8 +2118,6 @@ static int bcm2835_codec_open(struct fil
219         struct v4l2_ctrl_handler *hdl;
220         int rc = 0;
221  
222 -       v4l2_dbg(1, debug, &dev->v4l2_dev, "Creating instance for %s\n",
223 -                dev->decode ? "decode" : "encode");
224         if (mutex_lock_interruptible(&dev->dev_mutex)) {
225                 v4l2_err(&dev->v4l2_dev, "Mutex fail\n");
226                 return -ERESTARTSYS;
227 @@ -2104,7 +2130,8 @@ static int bcm2835_codec_open(struct fil
228  
229         ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev, false);
230         ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev, true);
231 -       if (dev->decode) {
232 +       switch (dev->role) {
233 +       case DECODE:
234                 /*
235                  * Input width and height are irrelevant as they will be defined
236                  * by the bitstream not the format. Required by V4L2 though.
237 @@ -2126,7 +2153,8 @@ static int bcm2835_codec_open(struct fil
238                         get_sizeimage(ctx->q_data[V4L2_M2M_DST].bytesperline,
239                                       ctx->q_data[V4L2_M2M_DST].height,
240                                       ctx->q_data[V4L2_M2M_DST].fmt);
241 -       } else {
242 +               break;
243 +       case ENCODE:
244                 ctx->q_data[V4L2_M2M_SRC].crop_width = DEFAULT_WIDTH;
245                 ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
246                 ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
247 @@ -2144,6 +2172,9 @@ static int bcm2835_codec_open(struct fil
248                 ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
249                 ctx->q_data[V4L2_M2M_DST].sizeimage =
250                                                 DEF_COMP_BUF_SIZE_720P_OR_LESS;
251 +               break;
252 +       case ISP:
253 +               break;
254         }
255  
256         ctx->colorspace = V4L2_COLORSPACE_REC709;
257 @@ -2154,7 +2185,7 @@ static int bcm2835_codec_open(struct fil
258         file->private_data = &ctx->fh;
259         ctx->dev = dev;
260         hdl = &ctx->hdl;
261 -       if (!dev->decode) {
262 +       if (dev->role == ENCODE) {
263                 /* Encode controls */
264                 v4l2_ctrl_handler_init(hdl, 6);
265  
266 @@ -2303,14 +2334,11 @@ static int bcm2835_codec_get_supported_f
267         unsigned int i, j, num_encodings;
268         int ret;
269  
270 -       ret = vchiq_mmal_component_init(dev->instance,
271 -                                       dev->decode ?
272 -                                               "ril.video_decode" :
273 -                                               "ril.video_encode",
274 +       ret = vchiq_mmal_component_init(dev->instance, components[dev->role],
275                                         &component);
276         if (ret < 0) {
277 -               v4l2_err(&dev->v4l2_dev, "%s: failed to create component\n",
278 -                        __func__);
279 +               v4l2_err(&dev->v4l2_dev, "%s: failed to create component %s\n",
280 +                        __func__, components[dev->role]);
281                 return -ENOMEM;
282         }
283  
284 @@ -2406,12 +2434,13 @@ destroy_component:
285  
286  static int bcm2835_codec_create(struct platform_device *pdev,
287                                 struct bcm2835_codec_dev **new_dev,
288 -                               bool decode)
289 +                               enum bcm2835_codec_role role)
290  {
291         struct bcm2835_codec_dev *dev;
292         struct video_device *vfd;
293         int video_nr;
294         int ret;
295 +       const static char *roles[] = {"decode", "encode", "isp"};
296  
297         dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
298         if (!dev)
299 @@ -2419,7 +2448,7 @@ static int bcm2835_codec_create(struct p
300  
301         dev->pdev = pdev;
302  
303 -       dev->decode = decode;
304 +       dev->role = role;
305  
306         ret = vchiq_mmal_init(&dev->instance);
307         if (ret)
308 @@ -2441,14 +2470,27 @@ static int bcm2835_codec_create(struct p
309         vfd->lock = &dev->dev_mutex;
310         vfd->v4l2_dev = &dev->v4l2_dev;
311  
312 -       if (dev->decode) {
313 +       switch (role) {
314 +       case DECODE:
315                 v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
316                 v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
317                 video_nr = decode_video_nr;
318 -       } else {
319 +               break;
320 +       case ENCODE:
321                 v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
322                 v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
323                 video_nr = encode_video_nr;
324 +               break;
325 +       case ISP:
326 +               v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
327 +               v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
328 +               v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
329 +               v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
330 +               video_nr = isp_video_nr;
331 +               break;
332 +       default:
333 +               ret = -EINVAL;
334 +               goto unreg_dev;
335         }
336  
337         ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
338 @@ -2473,7 +2515,7 @@ static int bcm2835_codec_create(struct p
339         }
340  
341         v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s\n",
342 -                 dev->decode ? "decode" : "encode");
343 +                 roles[role]);
344         return 0;
345  
346  err_m2m:
347 @@ -2509,11 +2551,15 @@ static int bcm2835_codec_probe(struct pl
348         if (!drv)
349                 return -ENOMEM;
350  
351 -       ret = bcm2835_codec_create(pdev, &drv->encode, false);
352 +       ret = bcm2835_codec_create(pdev, &drv->decode, DECODE);
353         if (ret)
354                 goto out;
355  
356 -       ret = bcm2835_codec_create(pdev, &drv->decode, true);
357 +       ret = bcm2835_codec_create(pdev, &drv->encode, ENCODE);
358 +       if (ret)
359 +               goto out;
360 +
361 +       ret = bcm2835_codec_create(pdev, &drv->isp, ISP);
362         if (ret)
363                 goto out;
364  
365 @@ -2526,6 +2572,10 @@ out:
366                 bcm2835_codec_destroy(drv->encode);
367                 drv->encode = NULL;
368         }
369 +       if (drv->decode) {
370 +               bcm2835_codec_destroy(drv->decode);
371 +               drv->decode = NULL;
372 +       }
373         return ret;
374  }
375  
376 @@ -2533,6 +2583,8 @@ static int bcm2835_codec_remove(struct p
377  {
378         struct bcm2835_codec_driver *drv = platform_get_drvdata(pdev);
379  
380 +       bcm2835_codec_destroy(drv->isp);
381 +
382         bcm2835_codec_destroy(drv->encode);
383  
384         bcm2835_codec_destroy(drv->decode);