3bbe6814c3012e43e52740e06951b70751495cda
[openwrt/openwrt.git] /
1 From 6fe43df9941cbd4810c4fcd02e49156a85180c16 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);