diff options
Diffstat (limited to 'drivers/media/video/s5p-mfc/s5p_mfc_dec.c')
-rw-r--r-- | drivers/media/video/s5p-mfc/s5p_mfc_dec.c | 1036 |
1 files changed, 1036 insertions, 0 deletions
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_dec.c b/drivers/media/video/s5p-mfc/s5p_mfc_dec.c new file mode 100644 index 000000000000..b2c5052a9c41 --- /dev/null +++ b/drivers/media/video/s5p-mfc/s5p_mfc_dec.c | |||
@@ -0,0 +1,1036 @@ | |||
1 | /* | ||
2 | * linux/drivers/media/video/s5p-mfc/s5p_mfc_dec.c | ||
3 | * | ||
4 | * Copyright (C) 2011 Samsung Electronics Co., Ltd. | ||
5 | * http://www.samsung.com/ | ||
6 | * Kamil Debski, <k.debski@samsung.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/clk.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/version.h> | ||
22 | #include <linux/videodev2.h> | ||
23 | #include <linux/workqueue.h> | ||
24 | #include <media/v4l2-ctrls.h> | ||
25 | #include <media/videobuf2-core.h> | ||
26 | #include "regs-mfc.h" | ||
27 | #include "s5p_mfc_common.h" | ||
28 | #include "s5p_mfc_debug.h" | ||
29 | #include "s5p_mfc_dec.h" | ||
30 | #include "s5p_mfc_intr.h" | ||
31 | #include "s5p_mfc_opr.h" | ||
32 | #include "s5p_mfc_pm.h" | ||
33 | #include "s5p_mfc_shm.h" | ||
34 | |||
35 | static struct s5p_mfc_fmt formats[] = { | ||
36 | { | ||
37 | .name = "4:2:0 2 Planes 64x32 Tiles", | ||
38 | .fourcc = V4L2_PIX_FMT_NV12MT, | ||
39 | .codec_mode = S5P_FIMV_CODEC_NONE, | ||
40 | .type = MFC_FMT_RAW, | ||
41 | .num_planes = 2, | ||
42 | }, | ||
43 | { | ||
44 | .name = "4:2:0 2 Planes", | ||
45 | .fourcc = V4L2_PIX_FMT_NV12M, | ||
46 | .codec_mode = S5P_FIMV_CODEC_NONE, | ||
47 | .type = MFC_FMT_RAW, | ||
48 | .num_planes = 2, | ||
49 | }, | ||
50 | { | ||
51 | .name = "H264 Encoded Stream", | ||
52 | .fourcc = V4L2_PIX_FMT_H264, | ||
53 | .codec_mode = S5P_FIMV_CODEC_H264_DEC, | ||
54 | .type = MFC_FMT_DEC, | ||
55 | .num_planes = 1, | ||
56 | }, | ||
57 | { | ||
58 | .name = "H263 Encoded Stream", | ||
59 | .fourcc = V4L2_PIX_FMT_H263, | ||
60 | .codec_mode = S5P_FIMV_CODEC_H263_DEC, | ||
61 | .type = MFC_FMT_DEC, | ||
62 | .num_planes = 1, | ||
63 | }, | ||
64 | { | ||
65 | .name = "MPEG1 Encoded Stream", | ||
66 | .fourcc = V4L2_PIX_FMT_MPEG1, | ||
67 | .codec_mode = S5P_FIMV_CODEC_MPEG2_DEC, | ||
68 | .type = MFC_FMT_DEC, | ||
69 | .num_planes = 1, | ||
70 | }, | ||
71 | { | ||
72 | .name = "MPEG2 Encoded Stream", | ||
73 | .fourcc = V4L2_PIX_FMT_MPEG2, | ||
74 | .codec_mode = S5P_FIMV_CODEC_MPEG2_DEC, | ||
75 | .type = MFC_FMT_DEC, | ||
76 | .num_planes = 1, | ||
77 | }, | ||
78 | { | ||
79 | .name = "MPEG4 Encoded Stream", | ||
80 | .fourcc = V4L2_PIX_FMT_MPEG4, | ||
81 | .codec_mode = S5P_FIMV_CODEC_MPEG4_DEC, | ||
82 | .type = MFC_FMT_DEC, | ||
83 | .num_planes = 1, | ||
84 | }, | ||
85 | { | ||
86 | .name = "XviD Encoded Stream", | ||
87 | .fourcc = V4L2_PIX_FMT_XVID, | ||
88 | .codec_mode = S5P_FIMV_CODEC_MPEG4_DEC, | ||
89 | .type = MFC_FMT_DEC, | ||
90 | .num_planes = 1, | ||
91 | }, | ||
92 | { | ||
93 | .name = "VC1 Encoded Stream", | ||
94 | .fourcc = V4L2_PIX_FMT_VC1_ANNEX_G, | ||
95 | .codec_mode = S5P_FIMV_CODEC_VC1_DEC, | ||
96 | .type = MFC_FMT_DEC, | ||
97 | .num_planes = 1, | ||
98 | }, | ||
99 | { | ||
100 | .name = "VC1 RCV Encoded Stream", | ||
101 | .fourcc = V4L2_PIX_FMT_VC1_ANNEX_L, | ||
102 | .codec_mode = S5P_FIMV_CODEC_VC1RCV_DEC, | ||
103 | .type = MFC_FMT_DEC, | ||
104 | .num_planes = 1, | ||
105 | }, | ||
106 | }; | ||
107 | |||
108 | #define NUM_FORMATS ARRAY_SIZE(formats) | ||
109 | |||
110 | /* Find selected format description */ | ||
111 | static struct s5p_mfc_fmt *find_format(struct v4l2_format *f, unsigned int t) | ||
112 | { | ||
113 | unsigned int i; | ||
114 | |||
115 | for (i = 0; i < NUM_FORMATS; i++) { | ||
116 | if (formats[i].fourcc == f->fmt.pix_mp.pixelformat && | ||
117 | formats[i].type == t) | ||
118 | return &formats[i]; | ||
119 | } | ||
120 | return NULL; | ||
121 | } | ||
122 | |||
123 | static struct mfc_control controls[] = { | ||
124 | { | ||
125 | .id = V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY, | ||
126 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
127 | .name = "H264 Display Delay", | ||
128 | .minimum = 0, | ||
129 | .maximum = 16383, | ||
130 | .step = 1, | ||
131 | .default_value = 0, | ||
132 | }, | ||
133 | { | ||
134 | .id = V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE, | ||
135 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
136 | .name = "H264 Display Delay Enable", | ||
137 | .minimum = 0, | ||
138 | .maximum = 1, | ||
139 | .step = 1, | ||
140 | .default_value = 0, | ||
141 | }, | ||
142 | { | ||
143 | .id = V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER, | ||
144 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
145 | .name = "Mpeg4 Loop Filter Enable", | ||
146 | .minimum = 0, | ||
147 | .maximum = 1, | ||
148 | .step = 1, | ||
149 | .default_value = 0, | ||
150 | }, | ||
151 | { | ||
152 | .id = V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE, | ||
153 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
154 | .name = "Slice Interface Enable", | ||
155 | .minimum = 0, | ||
156 | .maximum = 1, | ||
157 | .step = 1, | ||
158 | .default_value = 0, | ||
159 | }, | ||
160 | { | ||
161 | .id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, | ||
162 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
163 | .name = "Minimum number of cap bufs", | ||
164 | .minimum = 1, | ||
165 | .maximum = 32, | ||
166 | .step = 1, | ||
167 | .default_value = 1, | ||
168 | .is_volatile = 1, | ||
169 | }, | ||
170 | }; | ||
171 | |||
172 | #define NUM_CTRLS ARRAY_SIZE(controls) | ||
173 | |||
174 | /* Check whether a context should be run on hardware */ | ||
175 | static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx) | ||
176 | { | ||
177 | /* Context is to parse header */ | ||
178 | if (ctx->src_queue_cnt >= 1 && ctx->state == MFCINST_GOT_INST) | ||
179 | return 1; | ||
180 | /* Context is to decode a frame */ | ||
181 | if (ctx->src_queue_cnt >= 1 && | ||
182 | ctx->state == MFCINST_RUNNING && | ||
183 | ctx->dst_queue_cnt >= ctx->dpb_count) | ||
184 | return 1; | ||
185 | /* Context is to return last frame */ | ||
186 | if (ctx->state == MFCINST_FINISHING && | ||
187 | ctx->dst_queue_cnt >= ctx->dpb_count) | ||
188 | return 1; | ||
189 | /* Context is to set buffers */ | ||
190 | if (ctx->src_queue_cnt >= 1 && | ||
191 | ctx->state == MFCINST_HEAD_PARSED && | ||
192 | ctx->capture_state == QUEUE_BUFS_MMAPED) | ||
193 | return 1; | ||
194 | /* Resolution change */ | ||
195 | if ((ctx->state == MFCINST_RES_CHANGE_INIT || | ||
196 | ctx->state == MFCINST_RES_CHANGE_FLUSH) && | ||
197 | ctx->dst_queue_cnt >= ctx->dpb_count) | ||
198 | return 1; | ||
199 | if (ctx->state == MFCINST_RES_CHANGE_END && | ||
200 | ctx->src_queue_cnt >= 1) | ||
201 | return 1; | ||
202 | mfc_debug(2, "ctx is not ready\n"); | ||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | static struct s5p_mfc_codec_ops decoder_codec_ops = { | ||
207 | .pre_seq_start = NULL, | ||
208 | .post_seq_start = NULL, | ||
209 | .pre_frame_start = NULL, | ||
210 | .post_frame_start = NULL, | ||
211 | }; | ||
212 | |||
213 | /* Query capabilities of the device */ | ||
214 | static int vidioc_querycap(struct file *file, void *priv, | ||
215 | struct v4l2_capability *cap) | ||
216 | { | ||
217 | struct s5p_mfc_dev *dev = video_drvdata(file); | ||
218 | |||
219 | strncpy(cap->driver, dev->plat_dev->name, sizeof(cap->driver) - 1); | ||
220 | strncpy(cap->card, dev->plat_dev->name, sizeof(cap->card) - 1); | ||
221 | cap->bus_info[0] = 0; | ||
222 | cap->version = KERNEL_VERSION(1, 0, 0); | ||
223 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT | ||
224 | | V4L2_CAP_STREAMING; | ||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | /* Enumerate format */ | ||
229 | static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool mplane, bool out) | ||
230 | { | ||
231 | struct s5p_mfc_fmt *fmt; | ||
232 | int i, j = 0; | ||
233 | |||
234 | for (i = 0; i < ARRAY_SIZE(formats); ++i) { | ||
235 | if (mplane && formats[i].num_planes == 1) | ||
236 | continue; | ||
237 | else if (!mplane && formats[i].num_planes > 1) | ||
238 | continue; | ||
239 | if (out && formats[i].type != MFC_FMT_DEC) | ||
240 | continue; | ||
241 | else if (!out && formats[i].type != MFC_FMT_RAW) | ||
242 | continue; | ||
243 | |||
244 | if (j == f->index) | ||
245 | break; | ||
246 | ++j; | ||
247 | } | ||
248 | if (i == ARRAY_SIZE(formats)) | ||
249 | return -EINVAL; | ||
250 | fmt = &formats[i]; | ||
251 | strlcpy(f->description, fmt->name, sizeof(f->description)); | ||
252 | f->pixelformat = fmt->fourcc; | ||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | static int vidioc_enum_fmt_vid_cap(struct file *file, void *pirv, | ||
257 | struct v4l2_fmtdesc *f) | ||
258 | { | ||
259 | return vidioc_enum_fmt(f, false, false); | ||
260 | } | ||
261 | |||
262 | static int vidioc_enum_fmt_vid_cap_mplane(struct file *file, void *pirv, | ||
263 | struct v4l2_fmtdesc *f) | ||
264 | { | ||
265 | return vidioc_enum_fmt(f, true, false); | ||
266 | } | ||
267 | |||
268 | static int vidioc_enum_fmt_vid_out(struct file *file, void *prov, | ||
269 | struct v4l2_fmtdesc *f) | ||
270 | { | ||
271 | return vidioc_enum_fmt(f, false, true); | ||
272 | } | ||
273 | |||
274 | static int vidioc_enum_fmt_vid_out_mplane(struct file *file, void *prov, | ||
275 | struct v4l2_fmtdesc *f) | ||
276 | { | ||
277 | return vidioc_enum_fmt(f, true, true); | ||
278 | } | ||
279 | |||
280 | /* Get format */ | ||
281 | static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) | ||
282 | { | ||
283 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | ||
284 | struct v4l2_pix_format_mplane *pix_mp; | ||
285 | |||
286 | mfc_debug_enter(); | ||
287 | pix_mp = &f->fmt.pix_mp; | ||
288 | if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && | ||
289 | (ctx->state == MFCINST_GOT_INST || ctx->state == | ||
290 | MFCINST_RES_CHANGE_END)) { | ||
291 | /* If the MFC is parsing the header, | ||
292 | * so wait until it is finished */ | ||
293 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
294 | s5p_mfc_wait_for_done_ctx(ctx, S5P_FIMV_R2H_CMD_SEQ_DONE_RET, | ||
295 | 0); | ||
296 | } | ||
297 | if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && | ||
298 | ctx->state >= MFCINST_HEAD_PARSED && | ||
299 | ctx->state < MFCINST_ABORT) { | ||
300 | /* This is run on CAPTURE (decode output) */ | ||
301 | /* Width and height are set to the dimensions | ||
302 | of the movie, the buffer is bigger and | ||
303 | further processing stages should crop to this | ||
304 | rectangle. */ | ||
305 | pix_mp->width = ctx->buf_width; | ||
306 | pix_mp->height = ctx->buf_height; | ||
307 | pix_mp->field = V4L2_FIELD_NONE; | ||
308 | pix_mp->num_planes = 2; | ||
309 | /* Set pixelformat to the format in which MFC | ||
310 | outputs the decoded frame */ | ||
311 | pix_mp->pixelformat = V4L2_PIX_FMT_NV12MT; | ||
312 | pix_mp->plane_fmt[0].bytesperline = ctx->buf_width; | ||
313 | pix_mp->plane_fmt[0].sizeimage = ctx->luma_size; | ||
314 | pix_mp->plane_fmt[1].bytesperline = ctx->buf_width; | ||
315 | pix_mp->plane_fmt[1].sizeimage = ctx->chroma_size; | ||
316 | } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | ||
317 | /* This is run on OUTPUT | ||
318 | The buffer contains compressed image | ||
319 | so width and height have no meaning */ | ||
320 | pix_mp->width = 0; | ||
321 | pix_mp->height = 0; | ||
322 | pix_mp->field = V4L2_FIELD_NONE; | ||
323 | pix_mp->plane_fmt[0].bytesperline = ctx->dec_src_buf_size; | ||
324 | pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size; | ||
325 | pix_mp->pixelformat = ctx->src_fmt->fourcc; | ||
326 | pix_mp->num_planes = ctx->src_fmt->num_planes; | ||
327 | } else { | ||
328 | mfc_err("Format could not be read\n"); | ||
329 | mfc_debug(2, "%s-- with error\n", __func__); | ||
330 | return -EINVAL; | ||
331 | } | ||
332 | mfc_debug_leave(); | ||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | /* Try format */ | ||
337 | static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) | ||
338 | { | ||
339 | struct s5p_mfc_fmt *fmt; | ||
340 | |||
341 | if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | ||
342 | mfc_err("This node supports decoding only\n"); | ||
343 | return -EINVAL; | ||
344 | } | ||
345 | fmt = find_format(f, MFC_FMT_DEC); | ||
346 | if (!fmt) { | ||
347 | mfc_err("Unsupported format\n"); | ||
348 | return -EINVAL; | ||
349 | } | ||
350 | if (fmt->type != MFC_FMT_DEC) { | ||
351 | mfc_err("\n"); | ||
352 | return -EINVAL; | ||
353 | } | ||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | /* Set format */ | ||
358 | static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) | ||
359 | { | ||
360 | struct s5p_mfc_dev *dev = video_drvdata(file); | ||
361 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | ||
362 | int ret = 0; | ||
363 | struct s5p_mfc_fmt *fmt; | ||
364 | struct v4l2_pix_format_mplane *pix_mp; | ||
365 | |||
366 | mfc_debug_enter(); | ||
367 | ret = vidioc_try_fmt(file, priv, f); | ||
368 | pix_mp = &f->fmt.pix_mp; | ||
369 | if (ret) | ||
370 | return ret; | ||
371 | if (ctx->vq_src.streaming || ctx->vq_dst.streaming) { | ||
372 | v4l2_err(&dev->v4l2_dev, "%s queue busy\n", __func__); | ||
373 | ret = -EBUSY; | ||
374 | goto out; | ||
375 | } | ||
376 | fmt = find_format(f, MFC_FMT_DEC); | ||
377 | if (!fmt || fmt->codec_mode == S5P_FIMV_CODEC_NONE) { | ||
378 | mfc_err("Unknown codec\n"); | ||
379 | ret = -EINVAL; | ||
380 | goto out; | ||
381 | } | ||
382 | if (fmt->type != MFC_FMT_DEC) { | ||
383 | mfc_err("Wrong format selected, you should choose " | ||
384 | "format for decoding\n"); | ||
385 | ret = -EINVAL; | ||
386 | goto out; | ||
387 | } | ||
388 | ctx->src_fmt = fmt; | ||
389 | ctx->codec_mode = fmt->codec_mode; | ||
390 | mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode); | ||
391 | pix_mp->height = 0; | ||
392 | pix_mp->width = 0; | ||
393 | if (pix_mp->plane_fmt[0].sizeimage) | ||
394 | ctx->dec_src_buf_size = pix_mp->plane_fmt[0].sizeimage; | ||
395 | else | ||
396 | pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size = | ||
397 | DEF_CPB_SIZE; | ||
398 | pix_mp->plane_fmt[0].bytesperline = 0; | ||
399 | ctx->state = MFCINST_INIT; | ||
400 | out: | ||
401 | mfc_debug_leave(); | ||
402 | return ret; | ||
403 | } | ||
404 | |||
405 | /* Reqeust buffers */ | ||
406 | static int vidioc_reqbufs(struct file *file, void *priv, | ||
407 | struct v4l2_requestbuffers *reqbufs) | ||
408 | { | ||
409 | struct s5p_mfc_dev *dev = video_drvdata(file); | ||
410 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | ||
411 | int ret = 0; | ||
412 | unsigned long flags; | ||
413 | |||
414 | if (reqbufs->memory != V4L2_MEMORY_MMAP) { | ||
415 | mfc_err("Only V4L2_MEMORY_MAP is supported\n"); | ||
416 | return -EINVAL; | ||
417 | } | ||
418 | if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | ||
419 | /* Can only request buffers after an instance has been opened.*/ | ||
420 | if (ctx->state == MFCINST_INIT) { | ||
421 | ctx->src_bufs_cnt = 0; | ||
422 | if (reqbufs->count == 0) { | ||
423 | mfc_debug(2, "Freeing buffers\n"); | ||
424 | s5p_mfc_clock_on(); | ||
425 | ret = vb2_reqbufs(&ctx->vq_src, reqbufs); | ||
426 | s5p_mfc_clock_off(); | ||
427 | return ret; | ||
428 | } | ||
429 | /* Decoding */ | ||
430 | if (ctx->output_state != QUEUE_FREE) { | ||
431 | mfc_err("Bufs have already been requested\n"); | ||
432 | return -EINVAL; | ||
433 | } | ||
434 | s5p_mfc_clock_on(); | ||
435 | ret = vb2_reqbufs(&ctx->vq_src, reqbufs); | ||
436 | s5p_mfc_clock_off(); | ||
437 | if (ret) { | ||
438 | mfc_err("vb2_reqbufs on output failed\n"); | ||
439 | return ret; | ||
440 | } | ||
441 | mfc_debug(2, "vb2_reqbufs: %d\n", ret); | ||
442 | ctx->output_state = QUEUE_BUFS_REQUESTED; | ||
443 | } | ||
444 | } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { | ||
445 | ctx->dst_bufs_cnt = 0; | ||
446 | if (reqbufs->count == 0) { | ||
447 | mfc_debug(2, "Freeing buffers\n"); | ||
448 | s5p_mfc_clock_on(); | ||
449 | ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); | ||
450 | s5p_mfc_clock_off(); | ||
451 | return ret; | ||
452 | } | ||
453 | if (ctx->capture_state != QUEUE_FREE) { | ||
454 | mfc_err("Bufs have already been requested\n"); | ||
455 | return -EINVAL; | ||
456 | } | ||
457 | ctx->capture_state = QUEUE_BUFS_REQUESTED; | ||
458 | s5p_mfc_clock_on(); | ||
459 | ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); | ||
460 | s5p_mfc_clock_off(); | ||
461 | if (ret) { | ||
462 | mfc_err("vb2_reqbufs on capture failed\n"); | ||
463 | return ret; | ||
464 | } | ||
465 | if (reqbufs->count < ctx->dpb_count) { | ||
466 | mfc_err("Not enough buffers allocated\n"); | ||
467 | reqbufs->count = 0; | ||
468 | s5p_mfc_clock_on(); | ||
469 | ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); | ||
470 | s5p_mfc_clock_off(); | ||
471 | return -ENOMEM; | ||
472 | } | ||
473 | ctx->total_dpb_count = reqbufs->count; | ||
474 | ret = s5p_mfc_alloc_codec_buffers(ctx); | ||
475 | if (ret) { | ||
476 | mfc_err("Failed to allocate decoding buffers\n"); | ||
477 | reqbufs->count = 0; | ||
478 | s5p_mfc_clock_on(); | ||
479 | ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); | ||
480 | s5p_mfc_clock_off(); | ||
481 | return -ENOMEM; | ||
482 | } | ||
483 | if (ctx->dst_bufs_cnt == ctx->total_dpb_count) { | ||
484 | ctx->capture_state = QUEUE_BUFS_MMAPED; | ||
485 | } else { | ||
486 | mfc_err("Not all buffers passed to buf_init\n"); | ||
487 | reqbufs->count = 0; | ||
488 | s5p_mfc_clock_on(); | ||
489 | ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); | ||
490 | s5p_mfc_release_codec_buffers(ctx); | ||
491 | s5p_mfc_clock_off(); | ||
492 | return -ENOMEM; | ||
493 | } | ||
494 | if (s5p_mfc_ctx_ready(ctx)) { | ||
495 | spin_lock_irqsave(&dev->condlock, flags); | ||
496 | set_bit(ctx->num, &dev->ctx_work_bits); | ||
497 | spin_unlock_irqrestore(&dev->condlock, flags); | ||
498 | } | ||
499 | s5p_mfc_try_run(dev); | ||
500 | s5p_mfc_wait_for_done_ctx(ctx, | ||
501 | S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET, 0); | ||
502 | } | ||
503 | return ret; | ||
504 | } | ||
505 | |||
506 | /* Query buffer */ | ||
507 | static int vidioc_querybuf(struct file *file, void *priv, | ||
508 | struct v4l2_buffer *buf) | ||
509 | { | ||
510 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | ||
511 | int ret; | ||
512 | int i; | ||
513 | |||
514 | if (buf->memory != V4L2_MEMORY_MMAP) { | ||
515 | mfc_err("Only mmaped buffers can be used\n"); | ||
516 | return -EINVAL; | ||
517 | } | ||
518 | mfc_debug(2, "State: %d, buf->type: %d\n", ctx->state, buf->type); | ||
519 | if (ctx->state == MFCINST_INIT && | ||
520 | buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | ||
521 | ret = vb2_querybuf(&ctx->vq_src, buf); | ||
522 | } else if (ctx->state == MFCINST_RUNNING && | ||
523 | buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { | ||
524 | ret = vb2_querybuf(&ctx->vq_dst, buf); | ||
525 | for (i = 0; i < buf->length; i++) | ||
526 | buf->m.planes[i].m.mem_offset += DST_QUEUE_OFF_BASE; | ||
527 | } else { | ||
528 | mfc_err("vidioc_querybuf called in an inappropriate state\n"); | ||
529 | ret = -EINVAL; | ||
530 | } | ||
531 | mfc_debug_leave(); | ||
532 | return ret; | ||
533 | } | ||
534 | |||
535 | /* Queue a buffer */ | ||
536 | static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | ||
537 | { | ||
538 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | ||
539 | |||
540 | if (ctx->state == MFCINST_ERROR) { | ||
541 | mfc_err("Call on QBUF after unrecoverable error\n"); | ||
542 | return -EIO; | ||
543 | } | ||
544 | if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) | ||
545 | return vb2_qbuf(&ctx->vq_src, buf); | ||
546 | else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) | ||
547 | return vb2_qbuf(&ctx->vq_dst, buf); | ||
548 | return -EINVAL; | ||
549 | } | ||
550 | |||
551 | /* Dequeue a buffer */ | ||
552 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | ||
553 | { | ||
554 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | ||
555 | |||
556 | if (ctx->state == MFCINST_ERROR) { | ||
557 | mfc_err("Call on DQBUF after unrecoverable error\n"); | ||
558 | return -EIO; | ||
559 | } | ||
560 | if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) | ||
561 | return vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK); | ||
562 | else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) | ||
563 | return vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK); | ||
564 | return -EINVAL; | ||
565 | } | ||
566 | |||
567 | /* Stream on */ | ||
568 | static int vidioc_streamon(struct file *file, void *priv, | ||
569 | enum v4l2_buf_type type) | ||
570 | { | ||
571 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | ||
572 | struct s5p_mfc_dev *dev = ctx->dev; | ||
573 | unsigned long flags; | ||
574 | int ret = -EINVAL; | ||
575 | |||
576 | mfc_debug_enter(); | ||
577 | if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | ||
578 | |||
579 | if (ctx->state == MFCINST_INIT) { | ||
580 | ctx->dst_bufs_cnt = 0; | ||
581 | ctx->src_bufs_cnt = 0; | ||
582 | ctx->capture_state = QUEUE_FREE; | ||
583 | ctx->output_state = QUEUE_FREE; | ||
584 | s5p_mfc_alloc_instance_buffer(ctx); | ||
585 | s5p_mfc_alloc_dec_temp_buffers(ctx); | ||
586 | spin_lock_irqsave(&dev->condlock, flags); | ||
587 | set_bit(ctx->num, &dev->ctx_work_bits); | ||
588 | spin_unlock_irqrestore(&dev->condlock, flags); | ||
589 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
590 | s5p_mfc_try_run(dev); | ||
591 | |||
592 | if (s5p_mfc_wait_for_done_ctx(ctx, | ||
593 | S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET, 0)) { | ||
594 | /* Error or timeout */ | ||
595 | mfc_err("Error getting instance from hardware\n"); | ||
596 | s5p_mfc_release_instance_buffer(ctx); | ||
597 | s5p_mfc_release_dec_desc_buffer(ctx); | ||
598 | return -EIO; | ||
599 | } | ||
600 | mfc_debug(2, "Got instance number: %d\n", ctx->inst_no); | ||
601 | } | ||
602 | ret = vb2_streamon(&ctx->vq_src, type); | ||
603 | } | ||
604 | else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) | ||
605 | ret = vb2_streamon(&ctx->vq_dst, type); | ||
606 | mfc_debug_leave(); | ||
607 | return ret; | ||
608 | } | ||
609 | |||
610 | /* Stream off, which equals to a pause */ | ||
611 | static int vidioc_streamoff(struct file *file, void *priv, | ||
612 | enum v4l2_buf_type type) | ||
613 | { | ||
614 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | ||
615 | |||
616 | if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) | ||
617 | return vb2_streamoff(&ctx->vq_src, type); | ||
618 | else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) | ||
619 | return vb2_streamoff(&ctx->vq_dst, type); | ||
620 | return -EINVAL; | ||
621 | } | ||
622 | |||
623 | /* Set controls - v4l2 control framework */ | ||
624 | static int s5p_mfc_dec_s_ctrl(struct v4l2_ctrl *ctrl) | ||
625 | { | ||
626 | struct s5p_mfc_ctx *ctx = ctrl_to_ctx(ctrl); | ||
627 | |||
628 | switch (ctrl->id) { | ||
629 | case V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY: | ||
630 | ctx->loop_filter_mpeg4 = ctrl->val; | ||
631 | break; | ||
632 | case V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE: | ||
633 | ctx->display_delay_enable = ctrl->val; | ||
634 | break; | ||
635 | case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER: | ||
636 | ctx->display_delay = ctrl->val; | ||
637 | break; | ||
638 | case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE: | ||
639 | ctx->slice_interface = ctrl->val; | ||
640 | break; | ||
641 | default: | ||
642 | mfc_err("Invalid control 0x%08x\n", ctrl->id); | ||
643 | return -EINVAL; | ||
644 | } | ||
645 | return 0; | ||
646 | } | ||
647 | |||
648 | static int s5p_mfc_dec_g_v_ctrl(struct v4l2_ctrl *ctrl) | ||
649 | { | ||
650 | struct s5p_mfc_ctx *ctx = ctrl_to_ctx(ctrl); | ||
651 | struct s5p_mfc_dev *dev = ctx->dev; | ||
652 | |||
653 | switch (ctrl->id) { | ||
654 | case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: | ||
655 | if (ctx->state >= MFCINST_HEAD_PARSED && | ||
656 | ctx->state < MFCINST_ABORT) { | ||
657 | ctrl->val = ctx->dpb_count; | ||
658 | break; | ||
659 | } else if (ctx->state != MFCINST_INIT) { | ||
660 | v4l2_err(&dev->v4l2_dev, "Decoding not initialised\n"); | ||
661 | return -EINVAL; | ||
662 | } | ||
663 | /* Should wait for the header to be parsed */ | ||
664 | s5p_mfc_clean_ctx_int_flags(ctx); | ||
665 | s5p_mfc_wait_for_done_ctx(ctx, | ||
666 | S5P_FIMV_R2H_CMD_SEQ_DONE_RET, 0); | ||
667 | if (ctx->state >= MFCINST_HEAD_PARSED && | ||
668 | ctx->state < MFCINST_ABORT) { | ||
669 | ctrl->val = ctx->dpb_count; | ||
670 | } else { | ||
671 | v4l2_err(&dev->v4l2_dev, "Decoding not initialised\n"); | ||
672 | return -EINVAL; | ||
673 | } | ||
674 | break; | ||
675 | } | ||
676 | return 0; | ||
677 | } | ||
678 | |||
679 | |||
680 | static const struct v4l2_ctrl_ops s5p_mfc_dec_ctrl_ops = { | ||
681 | .s_ctrl = s5p_mfc_dec_s_ctrl, | ||
682 | .g_volatile_ctrl = s5p_mfc_dec_g_v_ctrl, | ||
683 | }; | ||
684 | |||
685 | /* Get cropping information */ | ||
686 | static int vidioc_g_crop(struct file *file, void *priv, | ||
687 | struct v4l2_crop *cr) | ||
688 | { | ||
689 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | ||
690 | u32 left, right, top, bottom; | ||
691 | |||
692 | if (ctx->state != MFCINST_HEAD_PARSED && | ||
693 | ctx->state != MFCINST_RUNNING && ctx->state != MFCINST_FINISHING | ||
694 | && ctx->state != MFCINST_FINISHED) { | ||
695 | mfc_err("Cannont set crop\n"); | ||
696 | return -EINVAL; | ||
697 | } | ||
698 | if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_H264) { | ||
699 | left = s5p_mfc_read_shm(ctx, CROP_INFO_H); | ||
700 | right = left >> S5P_FIMV_SHARED_CROP_RIGHT_SHIFT; | ||
701 | left = left & S5P_FIMV_SHARED_CROP_LEFT_MASK; | ||
702 | top = s5p_mfc_read_shm(ctx, CROP_INFO_V); | ||
703 | bottom = top >> S5P_FIMV_SHARED_CROP_BOTTOM_SHIFT; | ||
704 | top = top & S5P_FIMV_SHARED_CROP_TOP_MASK; | ||
705 | cr->c.left = left; | ||
706 | cr->c.top = top; | ||
707 | cr->c.width = ctx->img_width - left - right; | ||
708 | cr->c.height = ctx->img_height - top - bottom; | ||
709 | mfc_debug(2, "Cropping info [h264]: l=%d t=%d " | ||
710 | "w=%d h=%d (r=%d b=%d fw=%d fh=%d\n", left, top, | ||
711 | cr->c.width, cr->c.height, right, bottom, | ||
712 | ctx->buf_width, ctx->buf_height); | ||
713 | } else { | ||
714 | cr->c.left = 0; | ||
715 | cr->c.top = 0; | ||
716 | cr->c.width = ctx->img_width; | ||
717 | cr->c.height = ctx->img_height; | ||
718 | mfc_debug(2, "Cropping info: w=%d h=%d fw=%d " | ||
719 | "fh=%d\n", cr->c.width, cr->c.height, ctx->buf_width, | ||
720 | ctx->buf_height); | ||
721 | } | ||
722 | return 0; | ||
723 | } | ||
724 | |||
725 | /* v4l2_ioctl_ops */ | ||
726 | static const struct v4l2_ioctl_ops s5p_mfc_dec_ioctl_ops = { | ||
727 | .vidioc_querycap = vidioc_querycap, | ||
728 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||
729 | .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap_mplane, | ||
730 | .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out, | ||
731 | .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out_mplane, | ||
732 | .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt, | ||
733 | .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt, | ||
734 | .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt, | ||
735 | .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt, | ||
736 | .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt, | ||
737 | .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt, | ||
738 | .vidioc_reqbufs = vidioc_reqbufs, | ||
739 | .vidioc_querybuf = vidioc_querybuf, | ||
740 | .vidioc_qbuf = vidioc_qbuf, | ||
741 | .vidioc_dqbuf = vidioc_dqbuf, | ||
742 | .vidioc_streamon = vidioc_streamon, | ||
743 | .vidioc_streamoff = vidioc_streamoff, | ||
744 | .vidioc_g_crop = vidioc_g_crop, | ||
745 | }; | ||
746 | |||
747 | static int s5p_mfc_queue_setup(struct vb2_queue *vq, unsigned int *buf_count, | ||
748 | unsigned int *plane_count, unsigned long psize[], | ||
749 | void *allocators[]) | ||
750 | { | ||
751 | struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); | ||
752 | |||
753 | /* Video output for decoding (source) | ||
754 | * this can be set after getting an instance */ | ||
755 | if (ctx->state == MFCINST_INIT && | ||
756 | vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | ||
757 | /* A single plane is required for input */ | ||
758 | *plane_count = 1; | ||
759 | if (*buf_count < 1) | ||
760 | *buf_count = 1; | ||
761 | if (*buf_count > MFC_MAX_BUFFERS) | ||
762 | *buf_count = MFC_MAX_BUFFERS; | ||
763 | /* Video capture for decoding (destination) | ||
764 | * this can be set after the header was parsed */ | ||
765 | } else if (ctx->state == MFCINST_HEAD_PARSED && | ||
766 | vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { | ||
767 | /* Output plane count is 2 - one for Y and one for CbCr */ | ||
768 | *plane_count = 2; | ||
769 | /* Setup buffer count */ | ||
770 | if (*buf_count < ctx->dpb_count) | ||
771 | *buf_count = ctx->dpb_count; | ||
772 | if (*buf_count > ctx->dpb_count + MFC_MAX_EXTRA_DPB) | ||
773 | *buf_count = ctx->dpb_count + MFC_MAX_EXTRA_DPB; | ||
774 | if (*buf_count > MFC_MAX_BUFFERS) | ||
775 | *buf_count = MFC_MAX_BUFFERS; | ||
776 | } else { | ||
777 | mfc_err("State seems invalid. State = %d, vq->type = %d\n", | ||
778 | ctx->state, vq->type); | ||
779 | return -EINVAL; | ||
780 | } | ||
781 | mfc_debug(2, "Buffer count=%d, plane count=%d\n", | ||
782 | *buf_count, *plane_count); | ||
783 | if (ctx->state == MFCINST_HEAD_PARSED && | ||
784 | vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { | ||
785 | psize[0] = ctx->luma_size; | ||
786 | psize[1] = ctx->chroma_size; | ||
787 | allocators[0] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX]; | ||
788 | allocators[1] = ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX]; | ||
789 | } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && | ||
790 | ctx->state == MFCINST_INIT) { | ||
791 | psize[0] = ctx->dec_src_buf_size; | ||
792 | allocators[0] = ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX]; | ||
793 | } else { | ||
794 | mfc_err("This video node is dedicated to decoding. Decoding not initalised\n"); | ||
795 | return -EINVAL; | ||
796 | } | ||
797 | return 0; | ||
798 | } | ||
799 | |||
800 | static void s5p_mfc_unlock(struct vb2_queue *q) | ||
801 | { | ||
802 | struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); | ||
803 | struct s5p_mfc_dev *dev = ctx->dev; | ||
804 | |||
805 | mutex_unlock(&dev->mfc_mutex); | ||
806 | } | ||
807 | |||
808 | static void s5p_mfc_lock(struct vb2_queue *q) | ||
809 | { | ||
810 | struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); | ||
811 | struct s5p_mfc_dev *dev = ctx->dev; | ||
812 | |||
813 | mutex_lock(&dev->mfc_mutex); | ||
814 | } | ||
815 | |||
816 | static int s5p_mfc_buf_init(struct vb2_buffer *vb) | ||
817 | { | ||
818 | struct vb2_queue *vq = vb->vb2_queue; | ||
819 | struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); | ||
820 | unsigned int i; | ||
821 | |||
822 | if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { | ||
823 | if (ctx->capture_state == QUEUE_BUFS_MMAPED) | ||
824 | return 0; | ||
825 | for (i = 0; i <= ctx->src_fmt->num_planes ; i++) { | ||
826 | if (IS_ERR_OR_NULL(ERR_PTR( | ||
827 | vb2_dma_contig_plane_paddr(vb, i)))) { | ||
828 | mfc_err("Plane mem not allocated\n"); | ||
829 | return -EINVAL; | ||
830 | } | ||
831 | } | ||
832 | if (vb2_plane_size(vb, 0) < ctx->luma_size || | ||
833 | vb2_plane_size(vb, 1) < ctx->chroma_size) { | ||
834 | mfc_err("Plane buffer (CAPTURE) is too small\n"); | ||
835 | return -EINVAL; | ||
836 | } | ||
837 | i = vb->v4l2_buf.index; | ||
838 | ctx->dst_bufs[i].b = vb; | ||
839 | ctx->dst_bufs[i].cookie.raw.luma = | ||
840 | vb2_dma_contig_plane_paddr(vb, 0); | ||
841 | ctx->dst_bufs[i].cookie.raw.chroma = | ||
842 | vb2_dma_contig_plane_paddr(vb, 1); | ||
843 | ctx->dst_bufs_cnt++; | ||
844 | } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | ||
845 | if (IS_ERR_OR_NULL(ERR_PTR( | ||
846 | vb2_dma_contig_plane_paddr(vb, 0)))) { | ||
847 | mfc_err("Plane memory not allocated\n"); | ||
848 | return -EINVAL; | ||
849 | } | ||
850 | if (vb2_plane_size(vb, 0) < ctx->dec_src_buf_size) { | ||
851 | mfc_err("Plane buffer (OUTPUT) is too small\n"); | ||
852 | return -EINVAL; | ||
853 | } | ||
854 | |||
855 | i = vb->v4l2_buf.index; | ||
856 | ctx->src_bufs[i].b = vb; | ||
857 | ctx->src_bufs[i].cookie.stream = | ||
858 | vb2_dma_contig_plane_paddr(vb, 0); | ||
859 | ctx->src_bufs_cnt++; | ||
860 | } else { | ||
861 | mfc_err("s5p_mfc_buf_init: unknown queue type\n"); | ||
862 | return -EINVAL; | ||
863 | } | ||
864 | return 0; | ||
865 | } | ||
866 | |||
867 | static int s5p_mfc_start_streaming(struct vb2_queue *q) | ||
868 | { | ||
869 | struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); | ||
870 | struct s5p_mfc_dev *dev = ctx->dev; | ||
871 | unsigned long flags; | ||
872 | |||
873 | v4l2_ctrl_handler_setup(&ctx->ctrl_handler); | ||
874 | if (ctx->state == MFCINST_FINISHING || | ||
875 | ctx->state == MFCINST_FINISHED) | ||
876 | ctx->state = MFCINST_RUNNING; | ||
877 | /* If context is ready then dev = work->data;schedule it to run */ | ||
878 | if (s5p_mfc_ctx_ready(ctx)) { | ||
879 | spin_lock_irqsave(&dev->condlock, flags); | ||
880 | set_bit(ctx->num, &dev->ctx_work_bits); | ||
881 | spin_unlock_irqrestore(&dev->condlock, flags); | ||
882 | } | ||
883 | s5p_mfc_try_run(dev); | ||
884 | return 0; | ||
885 | } | ||
886 | |||
887 | static int s5p_mfc_stop_streaming(struct vb2_queue *q) | ||
888 | { | ||
889 | unsigned long flags; | ||
890 | struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); | ||
891 | struct s5p_mfc_dev *dev = ctx->dev; | ||
892 | int aborted = 0; | ||
893 | |||
894 | if ((ctx->state == MFCINST_FINISHING || | ||
895 | ctx->state == MFCINST_RUNNING) && | ||
896 | dev->curr_ctx == ctx->num && dev->hw_lock) { | ||
897 | ctx->state = MFCINST_ABORT; | ||
898 | s5p_mfc_wait_for_done_ctx(ctx, | ||
899 | S5P_FIMV_R2H_CMD_FRAME_DONE_RET, 0); | ||
900 | aborted = 1; | ||
901 | } | ||
902 | spin_lock_irqsave(&dev->irqlock, flags); | ||
903 | if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { | ||
904 | s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst); | ||
905 | INIT_LIST_HEAD(&ctx->dst_queue); | ||
906 | ctx->dst_queue_cnt = 0; | ||
907 | ctx->dpb_flush_flag = 1; | ||
908 | ctx->dec_dst_flag = 0; | ||
909 | } | ||
910 | if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | ||
911 | s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src); | ||
912 | INIT_LIST_HEAD(&ctx->src_queue); | ||
913 | ctx->src_queue_cnt = 0; | ||
914 | } | ||
915 | if (aborted) | ||
916 | ctx->state = MFCINST_RUNNING; | ||
917 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
918 | return 0; | ||
919 | } | ||
920 | |||
921 | |||
922 | static void s5p_mfc_buf_queue(struct vb2_buffer *vb) | ||
923 | { | ||
924 | struct vb2_queue *vq = vb->vb2_queue; | ||
925 | struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); | ||
926 | struct s5p_mfc_dev *dev = ctx->dev; | ||
927 | unsigned long flags; | ||
928 | struct s5p_mfc_buf *mfc_buf; | ||
929 | |||
930 | if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | ||
931 | mfc_buf = &ctx->src_bufs[vb->v4l2_buf.index]; | ||
932 | mfc_buf->used = 0; | ||
933 | spin_lock_irqsave(&dev->irqlock, flags); | ||
934 | list_add_tail(&mfc_buf->list, &ctx->src_queue); | ||
935 | ctx->src_queue_cnt++; | ||
936 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
937 | } else if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { | ||
938 | mfc_buf = &ctx->dst_bufs[vb->v4l2_buf.index]; | ||
939 | mfc_buf->used = 0; | ||
940 | /* Mark destination as available for use by MFC */ | ||
941 | spin_lock_irqsave(&dev->irqlock, flags); | ||
942 | set_bit(vb->v4l2_buf.index, &ctx->dec_dst_flag); | ||
943 | list_add_tail(&mfc_buf->list, &ctx->dst_queue); | ||
944 | ctx->dst_queue_cnt++; | ||
945 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
946 | } else { | ||
947 | mfc_err("Unsupported buffer type (%d)\n", vq->type); | ||
948 | } | ||
949 | if (s5p_mfc_ctx_ready(ctx)) { | ||
950 | spin_lock_irqsave(&dev->condlock, flags); | ||
951 | set_bit(ctx->num, &dev->ctx_work_bits); | ||
952 | spin_unlock_irqrestore(&dev->condlock, flags); | ||
953 | } | ||
954 | s5p_mfc_try_run(dev); | ||
955 | } | ||
956 | |||
957 | static struct vb2_ops s5p_mfc_dec_qops = { | ||
958 | .queue_setup = s5p_mfc_queue_setup, | ||
959 | .wait_prepare = s5p_mfc_unlock, | ||
960 | .wait_finish = s5p_mfc_lock, | ||
961 | .buf_init = s5p_mfc_buf_init, | ||
962 | .start_streaming = s5p_mfc_start_streaming, | ||
963 | .stop_streaming = s5p_mfc_stop_streaming, | ||
964 | .buf_queue = s5p_mfc_buf_queue, | ||
965 | }; | ||
966 | |||
967 | struct s5p_mfc_codec_ops *get_dec_codec_ops(void) | ||
968 | { | ||
969 | return &decoder_codec_ops; | ||
970 | } | ||
971 | |||
972 | struct vb2_ops *get_dec_queue_ops(void) | ||
973 | { | ||
974 | return &s5p_mfc_dec_qops; | ||
975 | } | ||
976 | |||
977 | const struct v4l2_ioctl_ops *get_dec_v4l2_ioctl_ops(void) | ||
978 | { | ||
979 | return &s5p_mfc_dec_ioctl_ops; | ||
980 | } | ||
981 | |||
982 | #define IS_MFC51_PRIV(x) ((V4L2_CTRL_ID2CLASS(x) == V4L2_CTRL_CLASS_MPEG) \ | ||
983 | && V4L2_CTRL_DRIVER_PRIV(x)) | ||
984 | |||
985 | int s5p_mfc_dec_ctrls_setup(struct s5p_mfc_ctx *ctx) | ||
986 | { | ||
987 | struct v4l2_ctrl_config cfg; | ||
988 | int i; | ||
989 | |||
990 | v4l2_ctrl_handler_init(&ctx->ctrl_handler, NUM_CTRLS); | ||
991 | if (ctx->ctrl_handler.error) { | ||
992 | mfc_err("v4l2_ctrl_handler_init failed\n"); | ||
993 | return ctx->ctrl_handler.error; | ||
994 | } | ||
995 | |||
996 | for (i = 0; i < NUM_CTRLS; i++) { | ||
997 | if (IS_MFC51_PRIV(controls[i].id)) { | ||
998 | cfg.ops = &s5p_mfc_dec_ctrl_ops; | ||
999 | cfg.id = controls[i].id; | ||
1000 | cfg.min = controls[i].minimum; | ||
1001 | cfg.max = controls[i].maximum; | ||
1002 | cfg.def = controls[i].default_value; | ||
1003 | cfg.name = controls[i].name; | ||
1004 | cfg.type = controls[i].type; | ||
1005 | |||
1006 | cfg.step = controls[i].step; | ||
1007 | cfg.menu_skip_mask = 0; | ||
1008 | |||
1009 | ctx->ctrls[i] = v4l2_ctrl_new_custom(&ctx->ctrl_handler, | ||
1010 | &cfg, NULL); | ||
1011 | } else { | ||
1012 | ctx->ctrls[i] = v4l2_ctrl_new_std(&ctx->ctrl_handler, | ||
1013 | &s5p_mfc_dec_ctrl_ops, | ||
1014 | controls[i].id, controls[i].minimum, | ||
1015 | controls[i].maximum, controls[i].step, | ||
1016 | controls[i].default_value); | ||
1017 | } | ||
1018 | if (ctx->ctrl_handler.error) { | ||
1019 | mfc_err("Adding control (%d) failed\n", i); | ||
1020 | return ctx->ctrl_handler.error; | ||
1021 | } | ||
1022 | if (controls[i].is_volatile && ctx->ctrls[i]) | ||
1023 | ctx->ctrls[i]->is_volatile = 1; | ||
1024 | } | ||
1025 | return 0; | ||
1026 | } | ||
1027 | |||
1028 | void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx) | ||
1029 | { | ||
1030 | int i; | ||
1031 | |||
1032 | v4l2_ctrl_handler_free(&ctx->ctrl_handler); | ||
1033 | for (i = 0; i < NUM_CTRLS; i++) | ||
1034 | ctx->ctrls[i] = NULL; | ||
1035 | } | ||
1036 | |||