]>
Commit | Line | Data |
---|---|---|
57b2c062 JCT |
1 | /* |
2 | * Copyright (C) STMicroelectronics SA 2015 | |
3 | * Authors: Yannick Fertre <yannick.fertre@st.com> | |
4 | * Hugues Fruchet <hugues.fruchet@st.com> | |
5 | * License terms: GNU General Public License (GPL), version 2 | |
6 | */ | |
7 | ||
8 | #include <linux/module.h> | |
9 | #include <linux/platform_device.h> | |
10 | #include <linux/slab.h> | |
11 | #include <media/v4l2-event.h> | |
12 | #include <media/v4l2-ioctl.h> | |
13 | #include <media/videobuf2-dma-contig.h> | |
14 | ||
15 | #include "hva.h" | |
16 | #include "hva-hw.h" | |
17 | ||
18 | #define HVA_NAME "st-hva" | |
19 | ||
20 | #define MIN_FRAMES 1 | |
21 | #define MIN_STREAMS 1 | |
22 | ||
23 | #define HVA_MIN_WIDTH 32 | |
24 | #define HVA_MAX_WIDTH 1920 | |
25 | #define HVA_MIN_HEIGHT 32 | |
26 | #define HVA_MAX_HEIGHT 1920 | |
27 | ||
28 | /* HVA requires a 16x16 pixels alignment for frames */ | |
29 | #define HVA_WIDTH_ALIGNMENT 16 | |
30 | #define HVA_HEIGHT_ALIGNMENT 16 | |
31 | ||
32 | #define HVA_DEFAULT_WIDTH HVA_MIN_WIDTH | |
33 | #define HVA_DEFAULT_HEIGHT HVA_MIN_HEIGHT | |
34 | #define HVA_DEFAULT_FRAME_NUM 1 | |
35 | #define HVA_DEFAULT_FRAME_DEN 30 | |
36 | ||
37 | #define to_type_str(type) (type == V4L2_BUF_TYPE_VIDEO_OUTPUT ? \ | |
38 | "frame" : "stream") | |
39 | ||
40 | #define fh_to_ctx(f) (container_of(f, struct hva_ctx, fh)) | |
41 | ||
42 | /* registry of available encoders */ | |
19de16c0 | 43 | static const struct hva_enc *hva_encoders[] = { |
ba4616b7 JCT |
44 | &nv12h264enc, |
45 | &nv21h264enc, | |
57b2c062 JCT |
46 | }; |
47 | ||
48 | static inline int frame_size(u32 w, u32 h, u32 fmt) | |
49 | { | |
50 | switch (fmt) { | |
51 | case V4L2_PIX_FMT_NV12: | |
52 | case V4L2_PIX_FMT_NV21: | |
53 | return (w * h * 3) / 2; | |
54 | default: | |
55 | return 0; | |
56 | } | |
57 | } | |
58 | ||
59 | static inline int frame_stride(u32 w, u32 fmt) | |
60 | { | |
61 | switch (fmt) { | |
62 | case V4L2_PIX_FMT_NV12: | |
63 | case V4L2_PIX_FMT_NV21: | |
64 | return w; | |
65 | default: | |
66 | return 0; | |
67 | } | |
68 | } | |
69 | ||
70 | static inline int frame_alignment(u32 fmt) | |
71 | { | |
72 | switch (fmt) { | |
73 | case V4L2_PIX_FMT_NV12: | |
74 | case V4L2_PIX_FMT_NV21: | |
75 | /* multiple of 2 */ | |
76 | return 2; | |
77 | default: | |
78 | return 1; | |
79 | } | |
80 | } | |
81 | ||
82 | static inline int estimated_stream_size(u32 w, u32 h) | |
83 | { | |
84 | /* | |
85 | * HVA only encodes in YUV420 format, whatever the frame format. | |
86 | * A compression ratio of 2 is assumed: thus, the maximum size | |
87 | * of a stream is estimated to ((width x height x 3 / 2) / 2) | |
88 | */ | |
89 | return (w * h * 3) / 4; | |
90 | } | |
91 | ||
92 | static void set_default_params(struct hva_ctx *ctx) | |
93 | { | |
94 | struct hva_frameinfo *frameinfo = &ctx->frameinfo; | |
95 | struct hva_streaminfo *streaminfo = &ctx->streaminfo; | |
96 | ||
97 | frameinfo->pixelformat = V4L2_PIX_FMT_NV12; | |
98 | frameinfo->width = HVA_DEFAULT_WIDTH; | |
99 | frameinfo->height = HVA_DEFAULT_HEIGHT; | |
100 | frameinfo->aligned_width = ALIGN(frameinfo->width, | |
101 | HVA_WIDTH_ALIGNMENT); | |
102 | frameinfo->aligned_height = ALIGN(frameinfo->height, | |
103 | HVA_HEIGHT_ALIGNMENT); | |
104 | frameinfo->size = frame_size(frameinfo->aligned_width, | |
105 | frameinfo->aligned_height, | |
106 | frameinfo->pixelformat); | |
107 | ||
108 | streaminfo->streamformat = V4L2_PIX_FMT_H264; | |
109 | streaminfo->width = HVA_DEFAULT_WIDTH; | |
110 | streaminfo->height = HVA_DEFAULT_HEIGHT; | |
111 | ||
112 | ctx->colorspace = V4L2_COLORSPACE_REC709; | |
113 | ctx->xfer_func = V4L2_XFER_FUNC_DEFAULT; | |
114 | ctx->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; | |
115 | ctx->quantization = V4L2_QUANTIZATION_DEFAULT; | |
116 | ||
117 | ctx->max_stream_size = estimated_stream_size(streaminfo->width, | |
118 | streaminfo->height); | |
119 | } | |
120 | ||
121 | static const struct hva_enc *hva_find_encoder(struct hva_ctx *ctx, | |
122 | u32 pixelformat, | |
123 | u32 streamformat) | |
124 | { | |
125 | struct hva_dev *hva = ctx_to_hdev(ctx); | |
126 | const struct hva_enc *enc; | |
127 | unsigned int i; | |
128 | ||
129 | for (i = 0; i < hva->nb_of_encoders; i++) { | |
130 | enc = hva->encoders[i]; | |
131 | if ((enc->pixelformat == pixelformat) && | |
132 | (enc->streamformat == streamformat)) | |
133 | return enc; | |
134 | } | |
135 | ||
136 | return NULL; | |
137 | } | |
138 | ||
139 | static void register_format(u32 format, u32 formats[], u32 *nb_of_formats) | |
140 | { | |
141 | u32 i; | |
142 | bool found = false; | |
143 | ||
144 | for (i = 0; i < *nb_of_formats; i++) { | |
145 | if (format == formats[i]) { | |
146 | found = true; | |
147 | break; | |
148 | } | |
149 | } | |
150 | ||
151 | if (!found) | |
152 | formats[(*nb_of_formats)++] = format; | |
153 | } | |
154 | ||
155 | static void register_formats(struct hva_dev *hva) | |
156 | { | |
157 | unsigned int i; | |
158 | ||
159 | for (i = 0; i < hva->nb_of_encoders; i++) { | |
160 | register_format(hva->encoders[i]->pixelformat, | |
161 | hva->pixelformats, | |
162 | &hva->nb_of_pixelformats); | |
163 | ||
164 | register_format(hva->encoders[i]->streamformat, | |
165 | hva->streamformats, | |
166 | &hva->nb_of_streamformats); | |
167 | } | |
168 | } | |
169 | ||
170 | static void register_encoders(struct hva_dev *hva) | |
171 | { | |
172 | struct device *dev = hva_to_dev(hva); | |
173 | unsigned int i; | |
174 | ||
175 | for (i = 0; i < ARRAY_SIZE(hva_encoders); i++) { | |
176 | if (hva->nb_of_encoders >= HVA_MAX_ENCODERS) { | |
177 | dev_dbg(dev, | |
178 | "%s failed to register %s encoder (%d maximum reached)\n", | |
179 | HVA_PREFIX, hva_encoders[i]->name, | |
180 | HVA_MAX_ENCODERS); | |
181 | return; | |
182 | } | |
183 | ||
184 | hva->encoders[hva->nb_of_encoders++] = hva_encoders[i]; | |
185 | dev_info(dev, "%s %s encoder registered\n", HVA_PREFIX, | |
186 | hva_encoders[i]->name); | |
187 | } | |
188 | } | |
189 | ||
190 | static int hva_open_encoder(struct hva_ctx *ctx, u32 streamformat, | |
191 | u32 pixelformat, struct hva_enc **penc) | |
192 | { | |
193 | struct hva_dev *hva = ctx_to_hdev(ctx); | |
194 | struct device *dev = ctx_to_dev(ctx); | |
195 | struct hva_enc *enc; | |
196 | int ret; | |
197 | ||
198 | /* find an encoder which can deal with these formats */ | |
199 | enc = (struct hva_enc *)hva_find_encoder(ctx, pixelformat, | |
200 | streamformat); | |
201 | if (!enc) { | |
202 | dev_err(dev, "%s no encoder found matching %4.4s => %4.4s\n", | |
203 | ctx->name, (char *)&pixelformat, (char *)&streamformat); | |
204 | return -EINVAL; | |
205 | } | |
206 | ||
207 | dev_dbg(dev, "%s one encoder matching %4.4s => %4.4s\n", | |
208 | ctx->name, (char *)&pixelformat, (char *)&streamformat); | |
209 | ||
210 | /* update instance name */ | |
211 | snprintf(ctx->name, sizeof(ctx->name), "[%3d:%4.4s]", | |
212 | hva->instance_id, (char *)&streamformat); | |
213 | ||
214 | /* open encoder instance */ | |
215 | ret = enc->open(ctx); | |
216 | if (ret) { | |
217 | dev_err(dev, "%s failed to open encoder instance (%d)\n", | |
218 | ctx->name, ret); | |
219 | return ret; | |
220 | } | |
221 | ||
222 | dev_dbg(dev, "%s %s encoder opened\n", ctx->name, enc->name); | |
223 | ||
224 | *penc = enc; | |
225 | ||
226 | return ret; | |
227 | } | |
228 | ||
229 | /* | |
230 | * V4L2 ioctl operations | |
231 | */ | |
232 | ||
233 | static int hva_querycap(struct file *file, void *priv, | |
234 | struct v4l2_capability *cap) | |
235 | { | |
236 | struct hva_ctx *ctx = fh_to_ctx(file->private_data); | |
237 | struct hva_dev *hva = ctx_to_hdev(ctx); | |
238 | ||
239 | strlcpy(cap->driver, HVA_NAME, sizeof(cap->driver)); | |
240 | strlcpy(cap->card, hva->vdev->name, sizeof(cap->card)); | |
241 | snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", | |
242 | hva->pdev->name); | |
243 | ||
244 | return 0; | |
245 | } | |
246 | ||
247 | static int hva_enum_fmt_stream(struct file *file, void *priv, | |
248 | struct v4l2_fmtdesc *f) | |
249 | { | |
250 | struct hva_ctx *ctx = fh_to_ctx(file->private_data); | |
251 | struct hva_dev *hva = ctx_to_hdev(ctx); | |
252 | ||
253 | if (unlikely(f->index >= hva->nb_of_streamformats)) | |
254 | return -EINVAL; | |
255 | ||
256 | f->pixelformat = hva->streamformats[f->index]; | |
257 | ||
258 | return 0; | |
259 | } | |
260 | ||
261 | static int hva_enum_fmt_frame(struct file *file, void *priv, | |
262 | struct v4l2_fmtdesc *f) | |
263 | { | |
264 | struct hva_ctx *ctx = fh_to_ctx(file->private_data); | |
265 | struct hva_dev *hva = ctx_to_hdev(ctx); | |
266 | ||
267 | if (unlikely(f->index >= hva->nb_of_pixelformats)) | |
268 | return -EINVAL; | |
269 | ||
270 | f->pixelformat = hva->pixelformats[f->index]; | |
271 | ||
272 | return 0; | |
273 | } | |
274 | ||
275 | static int hva_g_fmt_stream(struct file *file, void *fh, struct v4l2_format *f) | |
276 | { | |
277 | struct hva_ctx *ctx = fh_to_ctx(file->private_data); | |
278 | struct hva_streaminfo *streaminfo = &ctx->streaminfo; | |
279 | ||
280 | f->fmt.pix.width = streaminfo->width; | |
281 | f->fmt.pix.height = streaminfo->height; | |
282 | f->fmt.pix.field = V4L2_FIELD_NONE; | |
283 | f->fmt.pix.colorspace = ctx->colorspace; | |
284 | f->fmt.pix.xfer_func = ctx->xfer_func; | |
285 | f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc; | |
286 | f->fmt.pix.quantization = ctx->quantization; | |
287 | f->fmt.pix.pixelformat = streaminfo->streamformat; | |
288 | f->fmt.pix.bytesperline = 0; | |
289 | f->fmt.pix.sizeimage = ctx->max_stream_size; | |
290 | ||
291 | return 0; | |
292 | } | |
293 | ||
294 | static int hva_g_fmt_frame(struct file *file, void *fh, struct v4l2_format *f) | |
295 | { | |
296 | struct hva_ctx *ctx = fh_to_ctx(file->private_data); | |
297 | struct hva_frameinfo *frameinfo = &ctx->frameinfo; | |
298 | ||
299 | f->fmt.pix.width = frameinfo->width; | |
300 | f->fmt.pix.height = frameinfo->height; | |
301 | f->fmt.pix.field = V4L2_FIELD_NONE; | |
302 | f->fmt.pix.colorspace = ctx->colorspace; | |
303 | f->fmt.pix.xfer_func = ctx->xfer_func; | |
304 | f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc; | |
305 | f->fmt.pix.quantization = ctx->quantization; | |
306 | f->fmt.pix.pixelformat = frameinfo->pixelformat; | |
307 | f->fmt.pix.bytesperline = frame_stride(frameinfo->aligned_width, | |
308 | frameinfo->pixelformat); | |
309 | f->fmt.pix.sizeimage = frameinfo->size; | |
310 | ||
311 | return 0; | |
312 | } | |
313 | ||
314 | static int hva_try_fmt_stream(struct file *file, void *priv, | |
315 | struct v4l2_format *f) | |
316 | { | |
317 | struct hva_ctx *ctx = fh_to_ctx(file->private_data); | |
318 | struct device *dev = ctx_to_dev(ctx); | |
319 | struct v4l2_pix_format *pix = &f->fmt.pix; | |
320 | u32 streamformat = pix->pixelformat; | |
321 | const struct hva_enc *enc; | |
322 | u32 width, height; | |
323 | u32 stream_size; | |
324 | ||
325 | enc = hva_find_encoder(ctx, ctx->frameinfo.pixelformat, streamformat); | |
326 | if (!enc) { | |
327 | dev_dbg(dev, | |
328 | "%s V4L2 TRY_FMT (CAPTURE): unsupported format %.4s\n", | |
329 | ctx->name, (char *)&pix->pixelformat); | |
330 | return -EINVAL; | |
331 | } | |
332 | ||
333 | width = pix->width; | |
334 | height = pix->height; | |
335 | if (ctx->flags & HVA_FLAG_FRAMEINFO) { | |
336 | /* | |
337 | * if the frame resolution is already fixed, only allow the | |
338 | * same stream resolution | |
339 | */ | |
340 | pix->width = ctx->frameinfo.width; | |
341 | pix->height = ctx->frameinfo.height; | |
342 | if ((pix->width != width) || (pix->height != height)) | |
343 | dev_dbg(dev, | |
344 | "%s V4L2 TRY_FMT (CAPTURE): resolution updated %dx%d -> %dx%d to fit frame resolution\n", | |
345 | ctx->name, width, height, | |
346 | pix->width, pix->height); | |
347 | } else { | |
348 | /* adjust width & height */ | |
349 | v4l_bound_align_image(&pix->width, | |
350 | HVA_MIN_WIDTH, enc->max_width, | |
351 | 0, | |
352 | &pix->height, | |
353 | HVA_MIN_HEIGHT, enc->max_height, | |
354 | 0, | |
355 | 0); | |
356 | ||
357 | if ((pix->width != width) || (pix->height != height)) | |
358 | dev_dbg(dev, | |
359 | "%s V4L2 TRY_FMT (CAPTURE): resolution updated %dx%d -> %dx%d to fit min/max/alignment\n", | |
360 | ctx->name, width, height, | |
361 | pix->width, pix->height); | |
362 | } | |
363 | ||
364 | stream_size = estimated_stream_size(pix->width, pix->height); | |
365 | if (pix->sizeimage < stream_size) | |
366 | pix->sizeimage = stream_size; | |
367 | ||
368 | pix->bytesperline = 0; | |
369 | pix->colorspace = ctx->colorspace; | |
370 | pix->xfer_func = ctx->xfer_func; | |
371 | pix->ycbcr_enc = ctx->ycbcr_enc; | |
372 | pix->quantization = ctx->quantization; | |
373 | pix->field = V4L2_FIELD_NONE; | |
374 | ||
375 | return 0; | |
376 | } | |
377 | ||
378 | static int hva_try_fmt_frame(struct file *file, void *priv, | |
379 | struct v4l2_format *f) | |
380 | { | |
381 | struct hva_ctx *ctx = fh_to_ctx(file->private_data); | |
382 | struct device *dev = ctx_to_dev(ctx); | |
383 | struct v4l2_pix_format *pix = &f->fmt.pix; | |
384 | u32 pixelformat = pix->pixelformat; | |
385 | const struct hva_enc *enc; | |
386 | u32 width, height; | |
387 | ||
388 | enc = hva_find_encoder(ctx, pixelformat, ctx->streaminfo.streamformat); | |
389 | if (!enc) { | |
390 | dev_dbg(dev, | |
391 | "%s V4L2 TRY_FMT (OUTPUT): unsupported format %.4s\n", | |
392 | ctx->name, (char *)&pixelformat); | |
393 | return -EINVAL; | |
394 | } | |
395 | ||
396 | /* adjust width & height */ | |
397 | width = pix->width; | |
398 | height = pix->height; | |
399 | v4l_bound_align_image(&pix->width, | |
400 | HVA_MIN_WIDTH, HVA_MAX_WIDTH, | |
401 | frame_alignment(pixelformat) - 1, | |
402 | &pix->height, | |
403 | HVA_MIN_HEIGHT, HVA_MAX_HEIGHT, | |
404 | frame_alignment(pixelformat) - 1, | |
405 | 0); | |
406 | ||
407 | if ((pix->width != width) || (pix->height != height)) | |
408 | dev_dbg(dev, | |
409 | "%s V4L2 TRY_FMT (OUTPUT): resolution updated %dx%d -> %dx%d to fit min/max/alignment\n", | |
410 | ctx->name, width, height, pix->width, pix->height); | |
411 | ||
412 | width = ALIGN(pix->width, HVA_WIDTH_ALIGNMENT); | |
413 | height = ALIGN(pix->height, HVA_HEIGHT_ALIGNMENT); | |
414 | ||
415 | if (!pix->colorspace) { | |
416 | pix->colorspace = V4L2_COLORSPACE_REC709; | |
417 | pix->xfer_func = V4L2_XFER_FUNC_DEFAULT; | |
418 | pix->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; | |
419 | pix->quantization = V4L2_QUANTIZATION_DEFAULT; | |
420 | } | |
421 | ||
422 | pix->bytesperline = frame_stride(width, pixelformat); | |
423 | pix->sizeimage = frame_size(width, height, pixelformat); | |
424 | pix->field = V4L2_FIELD_NONE; | |
425 | ||
426 | return 0; | |
427 | } | |
428 | ||
429 | static int hva_s_fmt_stream(struct file *file, void *fh, struct v4l2_format *f) | |
430 | { | |
431 | struct hva_ctx *ctx = fh_to_ctx(file->private_data); | |
432 | struct device *dev = ctx_to_dev(ctx); | |
433 | struct vb2_queue *vq; | |
434 | int ret; | |
435 | ||
436 | ret = hva_try_fmt_stream(file, fh, f); | |
437 | if (ret) { | |
438 | dev_dbg(dev, "%s V4L2 S_FMT (CAPTURE): unsupported format %.4s\n", | |
439 | ctx->name, (char *)&f->fmt.pix.pixelformat); | |
440 | return ret; | |
441 | } | |
442 | ||
443 | vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); | |
444 | if (vb2_is_streaming(vq)) { | |
445 | dev_dbg(dev, "%s V4L2 S_FMT (CAPTURE): queue busy\n", | |
446 | ctx->name); | |
447 | return -EBUSY; | |
448 | } | |
449 | ||
450 | ctx->max_stream_size = f->fmt.pix.sizeimage; | |
451 | ctx->streaminfo.width = f->fmt.pix.width; | |
452 | ctx->streaminfo.height = f->fmt.pix.height; | |
453 | ctx->streaminfo.streamformat = f->fmt.pix.pixelformat; | |
454 | ctx->flags |= HVA_FLAG_STREAMINFO; | |
455 | ||
456 | return 0; | |
457 | } | |
458 | ||
459 | static int hva_s_fmt_frame(struct file *file, void *fh, struct v4l2_format *f) | |
460 | { | |
461 | struct hva_ctx *ctx = fh_to_ctx(file->private_data); | |
462 | struct device *dev = ctx_to_dev(ctx); | |
463 | struct v4l2_pix_format *pix = &f->fmt.pix; | |
464 | struct vb2_queue *vq; | |
465 | int ret; | |
466 | ||
467 | ret = hva_try_fmt_frame(file, fh, f); | |
468 | if (ret) { | |
469 | dev_dbg(dev, "%s V4L2 S_FMT (OUTPUT): unsupported format %.4s\n", | |
470 | ctx->name, (char *)&pix->pixelformat); | |
471 | return ret; | |
472 | } | |
473 | ||
474 | vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); | |
475 | if (vb2_is_streaming(vq)) { | |
476 | dev_dbg(dev, "%s V4L2 S_FMT (OUTPUT): queue busy\n", ctx->name); | |
477 | return -EBUSY; | |
478 | } | |
479 | ||
480 | ctx->colorspace = pix->colorspace; | |
481 | ctx->xfer_func = pix->xfer_func; | |
482 | ctx->ycbcr_enc = pix->ycbcr_enc; | |
483 | ctx->quantization = pix->quantization; | |
484 | ||
485 | ctx->frameinfo.aligned_width = ALIGN(pix->width, HVA_WIDTH_ALIGNMENT); | |
486 | ctx->frameinfo.aligned_height = ALIGN(pix->height, | |
487 | HVA_HEIGHT_ALIGNMENT); | |
488 | ctx->frameinfo.size = pix->sizeimage; | |
489 | ctx->frameinfo.pixelformat = pix->pixelformat; | |
490 | ctx->frameinfo.width = pix->width; | |
491 | ctx->frameinfo.height = pix->height; | |
492 | ctx->flags |= HVA_FLAG_FRAMEINFO; | |
493 | ||
494 | return 0; | |
495 | } | |
496 | ||
497 | static int hva_g_parm(struct file *file, void *fh, struct v4l2_streamparm *sp) | |
498 | { | |
499 | struct hva_ctx *ctx = fh_to_ctx(file->private_data); | |
500 | struct v4l2_fract *time_per_frame = &ctx->ctrls.time_per_frame; | |
501 | ||
502 | if (sp->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) | |
503 | return -EINVAL; | |
504 | ||
505 | sp->parm.output.capability = V4L2_CAP_TIMEPERFRAME; | |
506 | sp->parm.output.timeperframe.numerator = time_per_frame->numerator; | |
507 | sp->parm.output.timeperframe.denominator = | |
508 | time_per_frame->denominator; | |
509 | ||
510 | return 0; | |
511 | } | |
512 | ||
513 | static int hva_s_parm(struct file *file, void *fh, struct v4l2_streamparm *sp) | |
514 | { | |
515 | struct hva_ctx *ctx = fh_to_ctx(file->private_data); | |
516 | struct v4l2_fract *time_per_frame = &ctx->ctrls.time_per_frame; | |
517 | ||
518 | if (sp->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) | |
519 | return -EINVAL; | |
520 | ||
521 | if (!sp->parm.output.timeperframe.numerator || | |
522 | !sp->parm.output.timeperframe.denominator) | |
523 | return hva_g_parm(file, fh, sp); | |
524 | ||
525 | sp->parm.output.capability = V4L2_CAP_TIMEPERFRAME; | |
526 | time_per_frame->numerator = sp->parm.output.timeperframe.numerator; | |
527 | time_per_frame->denominator = | |
528 | sp->parm.output.timeperframe.denominator; | |
529 | ||
530 | return 0; | |
531 | } | |
532 | ||
533 | static int hva_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | |
534 | { | |
535 | struct hva_ctx *ctx = fh_to_ctx(file->private_data); | |
536 | struct device *dev = ctx_to_dev(ctx); | |
537 | ||
538 | if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { | |
539 | /* | |
540 | * depending on the targeted compressed video format, the | |
541 | * capture buffer might contain headers (e.g. H.264 SPS/PPS) | |
542 | * filled in by the driver client; the size of these data is | |
543 | * copied from the bytesused field of the V4L2 buffer in the | |
544 | * payload field of the hva stream buffer | |
545 | */ | |
546 | struct vb2_queue *vq; | |
547 | struct hva_stream *stream; | |
548 | ||
549 | vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, buf->type); | |
550 | ||
551 | if (buf->index >= vq->num_buffers) { | |
552 | dev_dbg(dev, "%s buffer index %d out of range (%d)\n", | |
553 | ctx->name, buf->index, vq->num_buffers); | |
554 | return -EINVAL; | |
555 | } | |
556 | ||
557 | stream = (struct hva_stream *)vq->bufs[buf->index]; | |
558 | stream->bytesused = buf->bytesused; | |
559 | } | |
560 | ||
561 | return v4l2_m2m_qbuf(file, ctx->fh.m2m_ctx, buf); | |
562 | } | |
563 | ||
564 | /* V4L2 ioctl ops */ | |
565 | static const struct v4l2_ioctl_ops hva_ioctl_ops = { | |
566 | .vidioc_querycap = hva_querycap, | |
567 | .vidioc_enum_fmt_vid_cap = hva_enum_fmt_stream, | |
568 | .vidioc_enum_fmt_vid_out = hva_enum_fmt_frame, | |
569 | .vidioc_g_fmt_vid_cap = hva_g_fmt_stream, | |
570 | .vidioc_g_fmt_vid_out = hva_g_fmt_frame, | |
571 | .vidioc_try_fmt_vid_cap = hva_try_fmt_stream, | |
572 | .vidioc_try_fmt_vid_out = hva_try_fmt_frame, | |
573 | .vidioc_s_fmt_vid_cap = hva_s_fmt_stream, | |
574 | .vidioc_s_fmt_vid_out = hva_s_fmt_frame, | |
575 | .vidioc_g_parm = hva_g_parm, | |
576 | .vidioc_s_parm = hva_s_parm, | |
577 | .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, | |
578 | .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, | |
579 | .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, | |
580 | .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, | |
581 | .vidioc_qbuf = hva_qbuf, | |
582 | .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, | |
583 | .vidioc_streamon = v4l2_m2m_ioctl_streamon, | |
584 | .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, | |
585 | .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, | |
586 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, | |
587 | }; | |
588 | ||
589 | /* | |
590 | * V4L2 control operations | |
591 | */ | |
592 | ||
593 | static int hva_s_ctrl(struct v4l2_ctrl *ctrl) | |
594 | { | |
595 | struct hva_ctx *ctx = container_of(ctrl->handler, struct hva_ctx, | |
596 | ctrl_handler); | |
597 | struct device *dev = ctx_to_dev(ctx); | |
598 | ||
599 | dev_dbg(dev, "%s S_CTRL: id = %d, val = %d\n", ctx->name, | |
600 | ctrl->id, ctrl->val); | |
601 | ||
602 | switch (ctrl->id) { | |
603 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: | |
604 | ctx->ctrls.bitrate_mode = ctrl->val; | |
605 | break; | |
606 | case V4L2_CID_MPEG_VIDEO_GOP_SIZE: | |
607 | ctx->ctrls.gop_size = ctrl->val; | |
608 | break; | |
609 | case V4L2_CID_MPEG_VIDEO_BITRATE: | |
610 | ctx->ctrls.bitrate = ctrl->val; | |
611 | break; | |
612 | case V4L2_CID_MPEG_VIDEO_ASPECT: | |
613 | ctx->ctrls.aspect = ctrl->val; | |
614 | break; | |
ba4616b7 JCT |
615 | case V4L2_CID_MPEG_VIDEO_H264_PROFILE: |
616 | ctx->ctrls.profile = ctrl->val; | |
617 | if (ctx->flags & HVA_FLAG_STREAMINFO) | |
618 | snprintf(ctx->streaminfo.profile, | |
619 | sizeof(ctx->streaminfo.profile), | |
620 | "%s profile", | |
621 | v4l2_ctrl_get_menu(ctrl->id)[ctrl->val]); | |
622 | break; | |
623 | case V4L2_CID_MPEG_VIDEO_H264_LEVEL: | |
624 | ctx->ctrls.level = ctrl->val; | |
625 | if (ctx->flags & HVA_FLAG_STREAMINFO) | |
626 | snprintf(ctx->streaminfo.level, | |
627 | sizeof(ctx->streaminfo.level), | |
628 | "level %s", | |
629 | v4l2_ctrl_get_menu(ctrl->id)[ctrl->val]); | |
630 | break; | |
631 | case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE: | |
632 | ctx->ctrls.entropy_mode = ctrl->val; | |
633 | break; | |
634 | case V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE: | |
635 | ctx->ctrls.cpb_size = ctrl->val; | |
636 | break; | |
637 | case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM: | |
638 | ctx->ctrls.dct8x8 = ctrl->val; | |
639 | break; | |
640 | case V4L2_CID_MPEG_VIDEO_H264_MIN_QP: | |
641 | ctx->ctrls.qpmin = ctrl->val; | |
642 | break; | |
643 | case V4L2_CID_MPEG_VIDEO_H264_MAX_QP: | |
644 | ctx->ctrls.qpmax = ctrl->val; | |
645 | break; | |
646 | case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE: | |
647 | ctx->ctrls.vui_sar = ctrl->val; | |
648 | break; | |
649 | case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC: | |
650 | ctx->ctrls.vui_sar_idc = ctrl->val; | |
651 | break; | |
652 | case V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING: | |
653 | ctx->ctrls.sei_fp = ctrl->val; | |
654 | break; | |
655 | case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE: | |
656 | ctx->ctrls.sei_fp_type = ctrl->val; | |
657 | break; | |
57b2c062 JCT |
658 | default: |
659 | dev_dbg(dev, "%s S_CTRL: invalid control (id = %d)\n", | |
660 | ctx->name, ctrl->id); | |
661 | return -EINVAL; | |
662 | } | |
663 | ||
664 | return 0; | |
665 | } | |
666 | ||
667 | /* V4L2 control ops */ | |
668 | static const struct v4l2_ctrl_ops hva_ctrl_ops = { | |
669 | .s_ctrl = hva_s_ctrl, | |
670 | }; | |
671 | ||
672 | static int hva_ctrls_setup(struct hva_ctx *ctx) | |
673 | { | |
674 | struct device *dev = ctx_to_dev(ctx); | |
675 | u64 mask; | |
ba4616b7 JCT |
676 | enum v4l2_mpeg_video_h264_sei_fp_arrangement_type sei_fp_type = |
677 | V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_TOP_BOTTOM; | |
57b2c062 | 678 | |
ba4616b7 | 679 | v4l2_ctrl_handler_init(&ctx->ctrl_handler, 15); |
57b2c062 JCT |
680 | |
681 | v4l2_ctrl_new_std_menu(&ctx->ctrl_handler, &hva_ctrl_ops, | |
682 | V4L2_CID_MPEG_VIDEO_BITRATE_MODE, | |
683 | V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, | |
684 | 0, | |
685 | V4L2_MPEG_VIDEO_BITRATE_MODE_CBR); | |
686 | ||
687 | v4l2_ctrl_new_std(&ctx->ctrl_handler, &hva_ctrl_ops, | |
688 | V4L2_CID_MPEG_VIDEO_GOP_SIZE, | |
689 | 1, 60, 1, 16); | |
690 | ||
691 | v4l2_ctrl_new_std(&ctx->ctrl_handler, &hva_ctrl_ops, | |
692 | V4L2_CID_MPEG_VIDEO_BITRATE, | |
693 | 1000, 60000000, 1000, 20000000); | |
694 | ||
695 | mask = ~(1 << V4L2_MPEG_VIDEO_ASPECT_1x1); | |
696 | v4l2_ctrl_new_std_menu(&ctx->ctrl_handler, &hva_ctrl_ops, | |
697 | V4L2_CID_MPEG_VIDEO_ASPECT, | |
698 | V4L2_MPEG_VIDEO_ASPECT_1x1, | |
699 | mask, | |
700 | V4L2_MPEG_VIDEO_ASPECT_1x1); | |
701 | ||
ba4616b7 JCT |
702 | mask = ~((1 << V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) | |
703 | (1 << V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) | | |
704 | (1 << V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) | | |
705 | (1 << V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH)); | |
706 | v4l2_ctrl_new_std_menu(&ctx->ctrl_handler, &hva_ctrl_ops, | |
707 | V4L2_CID_MPEG_VIDEO_H264_PROFILE, | |
708 | V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH, | |
709 | mask, | |
710 | V4L2_MPEG_VIDEO_H264_PROFILE_HIGH); | |
711 | ||
712 | v4l2_ctrl_new_std_menu(&ctx->ctrl_handler, &hva_ctrl_ops, | |
713 | V4L2_CID_MPEG_VIDEO_H264_LEVEL, | |
714 | V4L2_MPEG_VIDEO_H264_LEVEL_4_2, | |
715 | 0, | |
716 | V4L2_MPEG_VIDEO_H264_LEVEL_4_0); | |
717 | ||
718 | v4l2_ctrl_new_std_menu(&ctx->ctrl_handler, &hva_ctrl_ops, | |
719 | V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE, | |
720 | V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC, | |
721 | 0, | |
722 | V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC); | |
723 | ||
724 | v4l2_ctrl_new_std(&ctx->ctrl_handler, &hva_ctrl_ops, | |
725 | V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE, | |
726 | 1, 10000, 1, 3000); | |
727 | ||
728 | v4l2_ctrl_new_std(&ctx->ctrl_handler, &hva_ctrl_ops, | |
729 | V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM, | |
730 | 0, 1, 1, 0); | |
731 | ||
732 | v4l2_ctrl_new_std(&ctx->ctrl_handler, &hva_ctrl_ops, | |
733 | V4L2_CID_MPEG_VIDEO_H264_MIN_QP, | |
734 | 0, 51, 1, 5); | |
735 | ||
736 | v4l2_ctrl_new_std(&ctx->ctrl_handler, &hva_ctrl_ops, | |
737 | V4L2_CID_MPEG_VIDEO_H264_MAX_QP, | |
738 | 0, 51, 1, 51); | |
739 | ||
740 | v4l2_ctrl_new_std(&ctx->ctrl_handler, &hva_ctrl_ops, | |
741 | V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE, | |
742 | 0, 1, 1, 1); | |
743 | ||
744 | mask = ~(1 << V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_1x1); | |
745 | v4l2_ctrl_new_std_menu(&ctx->ctrl_handler, &hva_ctrl_ops, | |
746 | V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC, | |
747 | V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_1x1, | |
748 | mask, | |
749 | V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_1x1); | |
750 | ||
751 | v4l2_ctrl_new_std(&ctx->ctrl_handler, &hva_ctrl_ops, | |
752 | V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING, | |
753 | 0, 1, 1, 0); | |
754 | ||
755 | mask = ~(1 << sei_fp_type); | |
756 | v4l2_ctrl_new_std_menu(&ctx->ctrl_handler, &hva_ctrl_ops, | |
757 | V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE, | |
758 | sei_fp_type, | |
759 | mask, | |
760 | sei_fp_type); | |
761 | ||
57b2c062 JCT |
762 | if (ctx->ctrl_handler.error) { |
763 | int err = ctx->ctrl_handler.error; | |
764 | ||
765 | dev_dbg(dev, "%s controls setup failed (%d)\n", | |
766 | ctx->name, err); | |
767 | v4l2_ctrl_handler_free(&ctx->ctrl_handler); | |
768 | return err; | |
769 | } | |
770 | ||
771 | v4l2_ctrl_handler_setup(&ctx->ctrl_handler); | |
772 | ||
773 | /* set default time per frame */ | |
774 | ctx->ctrls.time_per_frame.numerator = HVA_DEFAULT_FRAME_NUM; | |
775 | ctx->ctrls.time_per_frame.denominator = HVA_DEFAULT_FRAME_DEN; | |
776 | ||
777 | return 0; | |
778 | } | |
779 | ||
780 | /* | |
781 | * mem-to-mem operations | |
782 | */ | |
783 | ||
784 | static void hva_run_work(struct work_struct *work) | |
785 | { | |
786 | struct hva_ctx *ctx = container_of(work, struct hva_ctx, run_work); | |
787 | struct vb2_v4l2_buffer *src_buf, *dst_buf; | |
788 | const struct hva_enc *enc = ctx->enc; | |
789 | struct hva_frame *frame; | |
790 | struct hva_stream *stream; | |
791 | int ret; | |
792 | ||
793 | /* protect instance against reentrancy */ | |
794 | mutex_lock(&ctx->lock); | |
795 | ||
796 | src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); | |
797 | dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); | |
798 | ||
799 | frame = to_hva_frame(src_buf); | |
800 | stream = to_hva_stream(dst_buf); | |
801 | frame->vbuf.sequence = ctx->frame_num++; | |
802 | ||
803 | ret = enc->encode(ctx, frame, stream); | |
804 | ||
805 | vb2_set_plane_payload(&dst_buf->vb2_buf, 0, stream->bytesused); | |
806 | if (ret) { | |
807 | v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); | |
808 | v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR); | |
809 | } else { | |
810 | /* propagate frame timestamp */ | |
811 | dst_buf->vb2_buf.timestamp = src_buf->vb2_buf.timestamp; | |
812 | dst_buf->field = V4L2_FIELD_NONE; | |
813 | dst_buf->sequence = ctx->stream_num - 1; | |
814 | ||
815 | v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); | |
816 | v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); | |
817 | } | |
818 | ||
819 | mutex_unlock(&ctx->lock); | |
820 | ||
821 | v4l2_m2m_job_finish(ctx->hva_dev->m2m_dev, ctx->fh.m2m_ctx); | |
822 | } | |
823 | ||
824 | static void hva_device_run(void *priv) | |
825 | { | |
826 | struct hva_ctx *ctx = priv; | |
827 | struct hva_dev *hva = ctx_to_hdev(ctx); | |
828 | ||
829 | queue_work(hva->work_queue, &ctx->run_work); | |
830 | } | |
831 | ||
832 | static void hva_job_abort(void *priv) | |
833 | { | |
834 | struct hva_ctx *ctx = priv; | |
835 | struct device *dev = ctx_to_dev(ctx); | |
836 | ||
837 | dev_dbg(dev, "%s aborting job\n", ctx->name); | |
838 | ||
839 | ctx->aborting = true; | |
840 | } | |
841 | ||
842 | static int hva_job_ready(void *priv) | |
843 | { | |
844 | struct hva_ctx *ctx = priv; | |
845 | struct device *dev = ctx_to_dev(ctx); | |
846 | ||
847 | if (!v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx)) { | |
848 | dev_dbg(dev, "%s job not ready: no frame buffers\n", | |
849 | ctx->name); | |
850 | return 0; | |
851 | } | |
852 | ||
853 | if (!v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx)) { | |
854 | dev_dbg(dev, "%s job not ready: no stream buffers\n", | |
855 | ctx->name); | |
856 | return 0; | |
857 | } | |
858 | ||
859 | if (ctx->aborting) { | |
860 | dev_dbg(dev, "%s job not ready: aborting\n", ctx->name); | |
861 | return 0; | |
862 | } | |
863 | ||
864 | return 1; | |
865 | } | |
866 | ||
867 | /* mem-to-mem ops */ | |
868 | static const struct v4l2_m2m_ops hva_m2m_ops = { | |
869 | .device_run = hva_device_run, | |
870 | .job_abort = hva_job_abort, | |
871 | .job_ready = hva_job_ready, | |
872 | }; | |
873 | ||
874 | /* | |
875 | * VB2 queue operations | |
876 | */ | |
877 | ||
878 | static int hva_queue_setup(struct vb2_queue *vq, | |
879 | unsigned int *num_buffers, unsigned int *num_planes, | |
880 | unsigned int sizes[], struct device *alloc_devs[]) | |
881 | { | |
882 | struct hva_ctx *ctx = vb2_get_drv_priv(vq); | |
883 | struct device *dev = ctx_to_dev(ctx); | |
884 | unsigned int size; | |
885 | ||
886 | dev_dbg(dev, "%s %s queue setup: num_buffers %d\n", ctx->name, | |
887 | to_type_str(vq->type), *num_buffers); | |
888 | ||
889 | size = vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT ? | |
890 | ctx->frameinfo.size : ctx->max_stream_size; | |
891 | ||
892 | if (*num_planes) | |
893 | return sizes[0] < size ? -EINVAL : 0; | |
894 | ||
895 | /* only one plane supported */ | |
896 | *num_planes = 1; | |
897 | sizes[0] = size; | |
898 | ||
899 | return 0; | |
900 | } | |
901 | ||
902 | static int hva_buf_prepare(struct vb2_buffer *vb) | |
903 | { | |
904 | struct hva_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); | |
905 | struct device *dev = ctx_to_dev(ctx); | |
906 | struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); | |
907 | ||
908 | if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { | |
909 | struct hva_frame *frame = to_hva_frame(vbuf); | |
910 | ||
911 | if (vbuf->field == V4L2_FIELD_ANY) | |
912 | vbuf->field = V4L2_FIELD_NONE; | |
913 | if (vbuf->field != V4L2_FIELD_NONE) { | |
914 | dev_dbg(dev, | |
915 | "%s frame[%d] prepare: %d field not supported\n", | |
916 | ctx->name, vb->index, vbuf->field); | |
917 | return -EINVAL; | |
918 | } | |
919 | ||
920 | if (!frame->prepared) { | |
921 | /* get memory addresses */ | |
922 | frame->vaddr = vb2_plane_vaddr(&vbuf->vb2_buf, 0); | |
923 | frame->paddr = vb2_dma_contig_plane_dma_addr( | |
924 | &vbuf->vb2_buf, 0); | |
925 | frame->info = ctx->frameinfo; | |
926 | frame->prepared = true; | |
927 | ||
928 | dev_dbg(dev, | |
929 | "%s frame[%d] prepared; virt=%p, phy=%pad\n", | |
930 | ctx->name, vb->index, | |
931 | frame->vaddr, &frame->paddr); | |
932 | } | |
933 | } else { | |
934 | struct hva_stream *stream = to_hva_stream(vbuf); | |
935 | ||
936 | if (!stream->prepared) { | |
937 | /* get memory addresses */ | |
938 | stream->vaddr = vb2_plane_vaddr(&vbuf->vb2_buf, 0); | |
939 | stream->paddr = vb2_dma_contig_plane_dma_addr( | |
940 | &vbuf->vb2_buf, 0); | |
941 | stream->size = vb2_plane_size(&vbuf->vb2_buf, 0); | |
942 | stream->prepared = true; | |
943 | ||
944 | dev_dbg(dev, | |
945 | "%s stream[%d] prepared; virt=%p, phy=%pad\n", | |
946 | ctx->name, vb->index, | |
947 | stream->vaddr, &stream->paddr); | |
948 | } | |
949 | } | |
950 | ||
951 | return 0; | |
952 | } | |
953 | ||
954 | static void hva_buf_queue(struct vb2_buffer *vb) | |
955 | { | |
956 | struct hva_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); | |
957 | struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); | |
958 | ||
959 | if (ctx->fh.m2m_ctx) | |
960 | v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); | |
961 | } | |
962 | ||
963 | static int hva_start_streaming(struct vb2_queue *vq, unsigned int count) | |
964 | { | |
965 | struct hva_ctx *ctx = vb2_get_drv_priv(vq); | |
966 | struct hva_dev *hva = ctx_to_hdev(ctx); | |
967 | struct device *dev = ctx_to_dev(ctx); | |
968 | struct vb2_v4l2_buffer *vbuf; | |
969 | int ret; | |
970 | unsigned int i; | |
971 | bool found = false; | |
972 | ||
973 | dev_dbg(dev, "%s %s start streaming\n", ctx->name, | |
974 | to_type_str(vq->type)); | |
975 | ||
976 | /* open encoder when both start_streaming have been called */ | |
977 | if (V4L2_TYPE_IS_OUTPUT(vq->type)) { | |
978 | if (!vb2_start_streaming_called(&ctx->fh.m2m_ctx->cap_q_ctx.q)) | |
979 | return 0; | |
980 | } else { | |
981 | if (!vb2_start_streaming_called(&ctx->fh.m2m_ctx->out_q_ctx.q)) | |
982 | return 0; | |
983 | } | |
984 | ||
985 | /* store the instance context in the instances array */ | |
986 | for (i = 0; i < HVA_MAX_INSTANCES; i++) { | |
987 | if (!hva->instances[i]) { | |
988 | hva->instances[i] = ctx; | |
989 | /* save the context identifier in the context */ | |
990 | ctx->id = i; | |
991 | found = true; | |
992 | break; | |
993 | } | |
994 | } | |
995 | ||
996 | if (!found) { | |
997 | dev_err(dev, "%s maximum instances reached\n", ctx->name); | |
998 | ret = -ENOMEM; | |
999 | goto err; | |
1000 | } | |
1001 | ||
1002 | hva->nb_of_instances++; | |
1003 | ||
1004 | if (!ctx->enc) { | |
1005 | ret = hva_open_encoder(ctx, | |
1006 | ctx->streaminfo.streamformat, | |
1007 | ctx->frameinfo.pixelformat, | |
1008 | &ctx->enc); | |
1009 | if (ret < 0) | |
1010 | goto err_ctx; | |
1011 | } | |
1012 | ||
1013 | return 0; | |
1014 | ||
1015 | err_ctx: | |
1016 | hva->instances[ctx->id] = NULL; | |
1017 | hva->nb_of_instances--; | |
1018 | err: | |
1019 | if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { | |
1020 | /* return of all pending buffers to vb2 (in queued state) */ | |
1021 | while ((vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx))) | |
1022 | v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_QUEUED); | |
1023 | } else { | |
1024 | /* return of all pending buffers to vb2 (in queued state) */ | |
1025 | while ((vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx))) | |
1026 | v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_QUEUED); | |
1027 | } | |
1028 | ||
1029 | return ret; | |
1030 | } | |
1031 | ||
1032 | static void hva_stop_streaming(struct vb2_queue *vq) | |
1033 | { | |
1034 | struct hva_ctx *ctx = vb2_get_drv_priv(vq); | |
1035 | struct hva_dev *hva = ctx_to_hdev(ctx); | |
1036 | struct device *dev = ctx_to_dev(ctx); | |
1037 | const struct hva_enc *enc = ctx->enc; | |
1038 | struct vb2_v4l2_buffer *vbuf; | |
1039 | ||
1040 | dev_dbg(dev, "%s %s stop streaming\n", ctx->name, | |
1041 | to_type_str(vq->type)); | |
1042 | ||
1043 | if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { | |
1044 | /* return of all pending buffers to vb2 (in error state) */ | |
1045 | ctx->frame_num = 0; | |
1046 | while ((vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx))) | |
1047 | v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); | |
1048 | } else { | |
1049 | /* return of all pending buffers to vb2 (in error state) */ | |
1050 | ctx->stream_num = 0; | |
1051 | while ((vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx))) | |
1052 | v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); | |
1053 | } | |
1054 | ||
1055 | if ((V4L2_TYPE_IS_OUTPUT(vq->type) && | |
1056 | vb2_is_streaming(&ctx->fh.m2m_ctx->cap_q_ctx.q)) || | |
1057 | (!V4L2_TYPE_IS_OUTPUT(vq->type) && | |
1058 | vb2_is_streaming(&ctx->fh.m2m_ctx->out_q_ctx.q))) { | |
1059 | dev_dbg(dev, "%s %s out=%d cap=%d\n", | |
1060 | ctx->name, to_type_str(vq->type), | |
1061 | vb2_is_streaming(&ctx->fh.m2m_ctx->out_q_ctx.q), | |
1062 | vb2_is_streaming(&ctx->fh.m2m_ctx->cap_q_ctx.q)); | |
1063 | return; | |
1064 | } | |
1065 | ||
1066 | /* close encoder when both stop_streaming have been called */ | |
1067 | if (enc) { | |
1068 | dev_dbg(dev, "%s %s encoder closed\n", ctx->name, enc->name); | |
1069 | enc->close(ctx); | |
1070 | ctx->enc = NULL; | |
1071 | ||
1072 | /* clear instance context in instances array */ | |
1073 | hva->instances[ctx->id] = NULL; | |
1074 | hva->nb_of_instances--; | |
1075 | } | |
1076 | ||
1077 | ctx->aborting = false; | |
1078 | } | |
1079 | ||
1080 | /* VB2 queue ops */ | |
1081 | static const struct vb2_ops hva_qops = { | |
1082 | .queue_setup = hva_queue_setup, | |
1083 | .buf_prepare = hva_buf_prepare, | |
1084 | .buf_queue = hva_buf_queue, | |
1085 | .start_streaming = hva_start_streaming, | |
1086 | .stop_streaming = hva_stop_streaming, | |
1087 | .wait_prepare = vb2_ops_wait_prepare, | |
1088 | .wait_finish = vb2_ops_wait_finish, | |
1089 | }; | |
1090 | ||
1091 | /* | |
1092 | * V4L2 file operations | |
1093 | */ | |
1094 | ||
1095 | static int queue_init(struct hva_ctx *ctx, struct vb2_queue *vq) | |
1096 | { | |
1097 | vq->io_modes = VB2_MMAP | VB2_DMABUF; | |
1098 | vq->drv_priv = ctx; | |
1099 | vq->ops = &hva_qops; | |
1100 | vq->mem_ops = &vb2_dma_contig_memops; | |
1101 | vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; | |
1102 | vq->lock = &ctx->hva_dev->lock; | |
1103 | ||
1104 | return vb2_queue_init(vq); | |
1105 | } | |
1106 | ||
1107 | static int hva_queue_init(void *priv, struct vb2_queue *src_vq, | |
1108 | struct vb2_queue *dst_vq) | |
1109 | { | |
1110 | struct hva_ctx *ctx = priv; | |
1111 | int ret; | |
1112 | ||
1113 | src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; | |
1114 | src_vq->buf_struct_size = sizeof(struct hva_frame); | |
1115 | src_vq->min_buffers_needed = MIN_FRAMES; | |
1116 | src_vq->dev = ctx->hva_dev->dev; | |
1117 | ||
1118 | ret = queue_init(ctx, src_vq); | |
1119 | if (ret) | |
1120 | return ret; | |
1121 | ||
1122 | dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
1123 | dst_vq->buf_struct_size = sizeof(struct hva_stream); | |
1124 | dst_vq->min_buffers_needed = MIN_STREAMS; | |
1125 | dst_vq->dev = ctx->hva_dev->dev; | |
1126 | ||
1127 | return queue_init(ctx, dst_vq); | |
1128 | } | |
1129 | ||
1130 | static int hva_open(struct file *file) | |
1131 | { | |
1132 | struct hva_dev *hva = video_drvdata(file); | |
1133 | struct device *dev = hva_to_dev(hva); | |
1134 | struct hva_ctx *ctx; | |
1135 | int ret; | |
1136 | ||
1137 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); | |
1138 | if (!ctx) { | |
1139 | ret = -ENOMEM; | |
1140 | goto out; | |
1141 | } | |
1142 | ctx->hva_dev = hva; | |
1143 | ||
1144 | INIT_WORK(&ctx->run_work, hva_run_work); | |
1145 | v4l2_fh_init(&ctx->fh, video_devdata(file)); | |
1146 | file->private_data = &ctx->fh; | |
1147 | v4l2_fh_add(&ctx->fh); | |
1148 | ||
1149 | ret = hva_ctrls_setup(ctx); | |
1150 | if (ret) { | |
1151 | dev_err(dev, "%s [x:x] failed to setup controls\n", | |
1152 | HVA_PREFIX); | |
1153 | goto err_fh; | |
1154 | } | |
1155 | ctx->fh.ctrl_handler = &ctx->ctrl_handler; | |
1156 | ||
1157 | mutex_init(&ctx->lock); | |
1158 | ||
1159 | ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(hva->m2m_dev, ctx, | |
1160 | &hva_queue_init); | |
1161 | if (IS_ERR(ctx->fh.m2m_ctx)) { | |
1162 | ret = PTR_ERR(ctx->fh.m2m_ctx); | |
1163 | dev_err(dev, "%s failed to initialize m2m context (%d)\n", | |
1164 | HVA_PREFIX, ret); | |
1165 | goto err_ctrls; | |
1166 | } | |
1167 | ||
1168 | /* set the instance name */ | |
1169 | mutex_lock(&hva->lock); | |
1170 | hva->instance_id++; | |
1171 | snprintf(ctx->name, sizeof(ctx->name), "[%3d:----]", | |
1172 | hva->instance_id); | |
1173 | mutex_unlock(&hva->lock); | |
1174 | ||
1175 | /* default parameters for frame and stream */ | |
1176 | set_default_params(ctx); | |
1177 | ||
1178 | dev_info(dev, "%s encoder instance created\n", ctx->name); | |
1179 | ||
1180 | return 0; | |
1181 | ||
1182 | err_ctrls: | |
1183 | v4l2_ctrl_handler_free(&ctx->ctrl_handler); | |
1184 | err_fh: | |
1185 | v4l2_fh_del(&ctx->fh); | |
1186 | v4l2_fh_exit(&ctx->fh); | |
1187 | kfree(ctx); | |
1188 | out: | |
1189 | return ret; | |
1190 | } | |
1191 | ||
1192 | static int hva_release(struct file *file) | |
1193 | { | |
1194 | struct hva_ctx *ctx = fh_to_ctx(file->private_data); | |
1195 | struct hva_dev *hva = ctx_to_hdev(ctx); | |
1196 | struct device *dev = ctx_to_dev(ctx); | |
1197 | const struct hva_enc *enc = ctx->enc; | |
1198 | ||
1199 | if (enc) { | |
1200 | dev_dbg(dev, "%s %s encoder closed\n", ctx->name, enc->name); | |
1201 | enc->close(ctx); | |
1202 | ctx->enc = NULL; | |
1203 | ||
1204 | /* clear instance context in instances array */ | |
1205 | hva->instances[ctx->id] = NULL; | |
1206 | hva->nb_of_instances--; | |
1207 | } | |
1208 | ||
1209 | v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); | |
1210 | ||
1211 | v4l2_ctrl_handler_free(&ctx->ctrl_handler); | |
1212 | ||
1213 | v4l2_fh_del(&ctx->fh); | |
1214 | v4l2_fh_exit(&ctx->fh); | |
1215 | ||
1216 | dev_info(dev, "%s encoder instance released\n", ctx->name); | |
1217 | ||
1218 | kfree(ctx); | |
1219 | ||
1220 | return 0; | |
1221 | } | |
1222 | ||
1223 | /* V4L2 file ops */ | |
1224 | static const struct v4l2_file_operations hva_fops = { | |
1225 | .owner = THIS_MODULE, | |
1226 | .open = hva_open, | |
1227 | .release = hva_release, | |
1228 | .unlocked_ioctl = video_ioctl2, | |
1229 | .mmap = v4l2_m2m_fop_mmap, | |
1230 | .poll = v4l2_m2m_fop_poll, | |
1231 | }; | |
1232 | ||
1233 | /* | |
1234 | * Platform device operations | |
1235 | */ | |
1236 | ||
1237 | static int hva_register_device(struct hva_dev *hva) | |
1238 | { | |
1239 | int ret; | |
1240 | struct video_device *vdev; | |
1241 | struct device *dev; | |
1242 | ||
1243 | if (!hva) | |
1244 | return -ENODEV; | |
1245 | dev = hva_to_dev(hva); | |
1246 | ||
1247 | hva->m2m_dev = v4l2_m2m_init(&hva_m2m_ops); | |
1248 | if (IS_ERR(hva->m2m_dev)) { | |
1249 | dev_err(dev, "%s failed to initialize v4l2-m2m device\n", | |
1250 | HVA_PREFIX); | |
1251 | ret = PTR_ERR(hva->m2m_dev); | |
1252 | goto err; | |
1253 | } | |
1254 | ||
1255 | vdev = video_device_alloc(); | |
1256 | if (!vdev) { | |
1257 | dev_err(dev, "%s failed to allocate video device\n", | |
1258 | HVA_PREFIX); | |
1259 | ret = -ENOMEM; | |
1260 | goto err_m2m_release; | |
1261 | } | |
1262 | ||
1263 | vdev->fops = &hva_fops; | |
1264 | vdev->ioctl_ops = &hva_ioctl_ops; | |
1265 | vdev->release = video_device_release; | |
1266 | vdev->lock = &hva->lock; | |
1267 | vdev->vfl_dir = VFL_DIR_M2M; | |
1268 | vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M; | |
1269 | vdev->v4l2_dev = &hva->v4l2_dev; | |
1270 | snprintf(vdev->name, sizeof(vdev->name), "%s%lx", HVA_NAME, | |
1271 | hva->ip_version); | |
1272 | ||
1273 | ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); | |
1274 | if (ret) { | |
1275 | dev_err(dev, "%s failed to register video device\n", | |
1276 | HVA_PREFIX); | |
1277 | goto err_vdev_release; | |
1278 | } | |
1279 | ||
1280 | hva->vdev = vdev; | |
1281 | video_set_drvdata(vdev, hva); | |
1282 | return 0; | |
1283 | ||
1284 | err_vdev_release: | |
1285 | video_device_release(vdev); | |
1286 | err_m2m_release: | |
1287 | v4l2_m2m_release(hva->m2m_dev); | |
1288 | err: | |
1289 | return ret; | |
1290 | } | |
1291 | ||
1292 | static void hva_unregister_device(struct hva_dev *hva) | |
1293 | { | |
1294 | if (!hva) | |
1295 | return; | |
1296 | ||
1297 | if (hva->m2m_dev) | |
1298 | v4l2_m2m_release(hva->m2m_dev); | |
1299 | ||
1300 | video_unregister_device(hva->vdev); | |
1301 | } | |
1302 | ||
1303 | static int hva_probe(struct platform_device *pdev) | |
1304 | { | |
1305 | struct hva_dev *hva; | |
1306 | struct device *dev = &pdev->dev; | |
1307 | int ret; | |
1308 | ||
1309 | hva = devm_kzalloc(dev, sizeof(*hva), GFP_KERNEL); | |
1310 | if (!hva) { | |
1311 | ret = -ENOMEM; | |
1312 | goto err; | |
1313 | } | |
1314 | ||
1315 | hva->dev = dev; | |
1316 | hva->pdev = pdev; | |
1317 | platform_set_drvdata(pdev, hva); | |
1318 | ||
1319 | mutex_init(&hva->lock); | |
1320 | ||
1321 | /* probe hardware */ | |
1322 | ret = hva_hw_probe(pdev, hva); | |
1323 | if (ret) | |
1324 | goto err; | |
1325 | ||
1326 | /* register all available encoders */ | |
1327 | register_encoders(hva); | |
1328 | ||
1329 | /* register all supported formats */ | |
1330 | register_formats(hva); | |
1331 | ||
1332 | /* register on V4L2 */ | |
1333 | ret = v4l2_device_register(dev, &hva->v4l2_dev); | |
1334 | if (ret) { | |
1335 | dev_err(dev, "%s %s failed to register V4L2 device\n", | |
1336 | HVA_PREFIX, HVA_NAME); | |
1337 | goto err_hw; | |
1338 | } | |
1339 | ||
1340 | hva->work_queue = create_workqueue(HVA_NAME); | |
1341 | if (!hva->work_queue) { | |
1342 | dev_err(dev, "%s %s failed to allocate work queue\n", | |
1343 | HVA_PREFIX, HVA_NAME); | |
1344 | ret = -ENOMEM; | |
1345 | goto err_v4l2; | |
1346 | } | |
1347 | ||
1348 | /* register device */ | |
1349 | ret = hva_register_device(hva); | |
1350 | if (ret) | |
1351 | goto err_work_queue; | |
1352 | ||
1353 | dev_info(dev, "%s %s registered as /dev/video%d\n", HVA_PREFIX, | |
1354 | HVA_NAME, hva->vdev->num); | |
1355 | ||
1356 | return 0; | |
1357 | ||
1358 | err_work_queue: | |
1359 | destroy_workqueue(hva->work_queue); | |
1360 | err_v4l2: | |
1361 | v4l2_device_unregister(&hva->v4l2_dev); | |
1362 | err_hw: | |
1363 | hva_hw_remove(hva); | |
1364 | err: | |
1365 | return ret; | |
1366 | } | |
1367 | ||
1368 | static int hva_remove(struct platform_device *pdev) | |
1369 | { | |
1370 | struct hva_dev *hva = platform_get_drvdata(pdev); | |
1371 | struct device *dev = hva_to_dev(hva); | |
1372 | ||
1373 | hva_unregister_device(hva); | |
1374 | ||
1375 | destroy_workqueue(hva->work_queue); | |
1376 | ||
1377 | hva_hw_remove(hva); | |
1378 | ||
1379 | v4l2_device_unregister(&hva->v4l2_dev); | |
1380 | ||
1381 | dev_info(dev, "%s %s removed\n", HVA_PREFIX, pdev->name); | |
1382 | ||
1383 | return 0; | |
1384 | } | |
1385 | ||
1386 | /* PM ops */ | |
1387 | static const struct dev_pm_ops hva_pm_ops = { | |
1388 | .runtime_suspend = hva_hw_runtime_suspend, | |
1389 | .runtime_resume = hva_hw_runtime_resume, | |
1390 | }; | |
1391 | ||
1392 | static const struct of_device_id hva_match_types[] = { | |
1393 | { | |
1394 | .compatible = "st,st-hva", | |
1395 | }, | |
1396 | { /* end node */ } | |
1397 | }; | |
1398 | ||
1399 | MODULE_DEVICE_TABLE(of, hva_match_types); | |
1400 | ||
19de16c0 | 1401 | static struct platform_driver hva_driver = { |
57b2c062 JCT |
1402 | .probe = hva_probe, |
1403 | .remove = hva_remove, | |
1404 | .driver = { | |
1405 | .name = HVA_NAME, | |
1406 | .of_match_table = hva_match_types, | |
1407 | .pm = &hva_pm_ops, | |
1408 | }, | |
1409 | }; | |
1410 | ||
1411 | module_platform_driver(hva_driver); | |
1412 | ||
1413 | MODULE_LICENSE("GPL"); | |
1414 | MODULE_AUTHOR("Yannick Fertre <yannick.fertre@st.com>"); | |
1415 | MODULE_DESCRIPTION("STMicroelectronics HVA video encoder V4L2 driver"); |