Commit | Line | Data |
---|---|---|
af935746 | 1 | /* |
2c3fb08b | 2 | * linux/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c |
af935746 KD |
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> | |
af935746 KD |
21 | #include <linux/videodev2.h> |
22 | #include <linux/workqueue.h> | |
23 | #include <media/v4l2-ctrls.h> | |
a34026e7 | 24 | #include <media/v4l2-event.h> |
c139990e | 25 | #include <media/videobuf2-v4l2.h> |
af935746 | 26 | #include "s5p_mfc_common.h" |
818cd91a | 27 | #include "s5p_mfc_ctrl.h" |
af935746 KD |
28 | #include "s5p_mfc_debug.h" |
29 | #include "s5p_mfc_dec.h" | |
30 | #include "s5p_mfc_intr.h" | |
43a1ea1f | 31 | #include "s5p_mfc_opr.h" |
af935746 | 32 | #include "s5p_mfc_pm.h" |
af935746 KD |
33 | |
34 | static struct s5p_mfc_fmt formats[] = { | |
f96f3cfa JP |
35 | { |
36 | .name = "4:2:0 2 Planes 16x16 Tiles", | |
37 | .fourcc = V4L2_PIX_FMT_NV12MT_16X16, | |
38 | .codec_mode = S5P_MFC_CODEC_NONE, | |
39 | .type = MFC_FMT_RAW, | |
40 | .num_planes = 2, | |
9aa5f008 | 41 | .versions = MFC_V6_BIT | MFC_V7_BIT, |
f96f3cfa | 42 | }, |
af935746 KD |
43 | { |
44 | .name = "4:2:0 2 Planes 64x32 Tiles", | |
45 | .fourcc = V4L2_PIX_FMT_NV12MT, | |
43a1ea1f | 46 | .codec_mode = S5P_MFC_CODEC_NONE, |
af935746 KD |
47 | .type = MFC_FMT_RAW, |
48 | .num_planes = 2, | |
9aa5f008 | 49 | .versions = MFC_V5_BIT, |
43a1ea1f | 50 | }, |
af935746 | 51 | { |
f96f3cfa JP |
52 | .name = "4:2:0 2 Planes Y/CbCr", |
53 | .fourcc = V4L2_PIX_FMT_NV12M, | |
54 | .codec_mode = S5P_MFC_CODEC_NONE, | |
55 | .type = MFC_FMT_RAW, | |
56 | .num_planes = 2, | |
b1394dc1 | 57 | .versions = MFC_V6PLUS_BITS, |
f96f3cfa JP |
58 | }, |
59 | { | |
60 | .name = "4:2:0 2 Planes Y/CrCb", | |
61 | .fourcc = V4L2_PIX_FMT_NV21M, | |
62 | .codec_mode = S5P_MFC_CODEC_NONE, | |
63 | .type = MFC_FMT_RAW, | |
64 | .num_planes = 2, | |
b1394dc1 | 65 | .versions = MFC_V6PLUS_BITS, |
f96f3cfa JP |
66 | }, |
67 | { | |
68 | .name = "H264 Encoded Stream", | |
69 | .fourcc = V4L2_PIX_FMT_H264, | |
70 | .codec_mode = S5P_MFC_CODEC_H264_DEC, | |
71 | .type = MFC_FMT_DEC, | |
72 | .num_planes = 1, | |
b1394dc1 | 73 | .versions = MFC_V5PLUS_BITS, |
af935746 KD |
74 | }, |
75 | { | |
f96f3cfa JP |
76 | .name = "H264/MVC Encoded Stream", |
77 | .fourcc = V4L2_PIX_FMT_H264_MVC, | |
78 | .codec_mode = S5P_MFC_CODEC_H264_MVC_DEC, | |
79 | .type = MFC_FMT_DEC, | |
80 | .num_planes = 1, | |
b1394dc1 | 81 | .versions = MFC_V6PLUS_BITS, |
af935746 KD |
82 | }, |
83 | { | |
f96f3cfa JP |
84 | .name = "H263 Encoded Stream", |
85 | .fourcc = V4L2_PIX_FMT_H263, | |
86 | .codec_mode = S5P_MFC_CODEC_H263_DEC, | |
87 | .type = MFC_FMT_DEC, | |
88 | .num_planes = 1, | |
b1394dc1 | 89 | .versions = MFC_V5PLUS_BITS, |
af935746 KD |
90 | }, |
91 | { | |
f96f3cfa JP |
92 | .name = "MPEG1 Encoded Stream", |
93 | .fourcc = V4L2_PIX_FMT_MPEG1, | |
94 | .codec_mode = S5P_MFC_CODEC_MPEG2_DEC, | |
95 | .type = MFC_FMT_DEC, | |
96 | .num_planes = 1, | |
b1394dc1 | 97 | .versions = MFC_V5PLUS_BITS, |
af935746 KD |
98 | }, |
99 | { | |
f96f3cfa JP |
100 | .name = "MPEG2 Encoded Stream", |
101 | .fourcc = V4L2_PIX_FMT_MPEG2, | |
102 | .codec_mode = S5P_MFC_CODEC_MPEG2_DEC, | |
103 | .type = MFC_FMT_DEC, | |
104 | .num_planes = 1, | |
b1394dc1 | 105 | .versions = MFC_V5PLUS_BITS, |
af935746 KD |
106 | }, |
107 | { | |
f96f3cfa JP |
108 | .name = "MPEG4 Encoded Stream", |
109 | .fourcc = V4L2_PIX_FMT_MPEG4, | |
110 | .codec_mode = S5P_MFC_CODEC_MPEG4_DEC, | |
111 | .type = MFC_FMT_DEC, | |
112 | .num_planes = 1, | |
b1394dc1 | 113 | .versions = MFC_V5PLUS_BITS, |
af935746 KD |
114 | }, |
115 | { | |
f96f3cfa JP |
116 | .name = "XviD Encoded Stream", |
117 | .fourcc = V4L2_PIX_FMT_XVID, | |
118 | .codec_mode = S5P_MFC_CODEC_MPEG4_DEC, | |
119 | .type = MFC_FMT_DEC, | |
120 | .num_planes = 1, | |
b1394dc1 | 121 | .versions = MFC_V5PLUS_BITS, |
af935746 KD |
122 | }, |
123 | { | |
f96f3cfa JP |
124 | .name = "VC1 Encoded Stream", |
125 | .fourcc = V4L2_PIX_FMT_VC1_ANNEX_G, | |
126 | .codec_mode = S5P_MFC_CODEC_VC1_DEC, | |
127 | .type = MFC_FMT_DEC, | |
128 | .num_planes = 1, | |
b1394dc1 | 129 | .versions = MFC_V5PLUS_BITS, |
af935746 KD |
130 | }, |
131 | { | |
f96f3cfa JP |
132 | .name = "VC1 RCV Encoded Stream", |
133 | .fourcc = V4L2_PIX_FMT_VC1_ANNEX_L, | |
134 | .codec_mode = S5P_MFC_CODEC_VC1RCV_DEC, | |
135 | .type = MFC_FMT_DEC, | |
136 | .num_planes = 1, | |
b1394dc1 | 137 | .versions = MFC_V5PLUS_BITS, |
f96f3cfa JP |
138 | }, |
139 | { | |
140 | .name = "VP8 Encoded Stream", | |
141 | .fourcc = V4L2_PIX_FMT_VP8, | |
142 | .codec_mode = S5P_MFC_CODEC_VP8_DEC, | |
143 | .type = MFC_FMT_DEC, | |
144 | .num_planes = 1, | |
b1394dc1 | 145 | .versions = MFC_V6PLUS_BITS, |
af935746 | 146 | }, |
c9fcd51c SM |
147 | { |
148 | .fourcc = V4L2_PIX_FMT_HEVC, | |
149 | .codec_mode = S5P_FIMV_CODEC_HEVC_DEC, | |
150 | .type = MFC_FMT_DEC, | |
151 | .num_planes = 1, | |
152 | .versions = MFC_V10_BIT, | |
153 | }, | |
fc92b92a SM |
154 | { |
155 | .fourcc = V4L2_PIX_FMT_VP9, | |
156 | .codec_mode = S5P_FIMV_CODEC_VP9_DEC, | |
157 | .type = MFC_FMT_DEC, | |
158 | .num_planes = 1, | |
159 | .versions = MFC_V10_BIT, | |
160 | }, | |
af935746 KD |
161 | }; |
162 | ||
163 | #define NUM_FORMATS ARRAY_SIZE(formats) | |
164 | ||
165 | /* Find selected format description */ | |
166 | static struct s5p_mfc_fmt *find_format(struct v4l2_format *f, unsigned int t) | |
167 | { | |
168 | unsigned int i; | |
169 | ||
170 | for (i = 0; i < NUM_FORMATS; i++) { | |
171 | if (formats[i].fourcc == f->fmt.pix_mp.pixelformat && | |
172 | formats[i].type == t) | |
173 | return &formats[i]; | |
174 | } | |
175 | return NULL; | |
176 | } | |
177 | ||
178 | static struct mfc_control controls[] = { | |
179 | { | |
180 | .id = V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY, | |
181 | .type = V4L2_CTRL_TYPE_INTEGER, | |
182 | .name = "H264 Display Delay", | |
183 | .minimum = 0, | |
184 | .maximum = 16383, | |
185 | .step = 1, | |
186 | .default_value = 0, | |
187 | }, | |
188 | { | |
189 | .id = V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE, | |
190 | .type = V4L2_CTRL_TYPE_BOOLEAN, | |
191 | .name = "H264 Display Delay Enable", | |
192 | .minimum = 0, | |
193 | .maximum = 1, | |
194 | .step = 1, | |
195 | .default_value = 0, | |
196 | }, | |
197 | { | |
198 | .id = V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER, | |
199 | .type = V4L2_CTRL_TYPE_BOOLEAN, | |
200 | .name = "Mpeg4 Loop Filter Enable", | |
201 | .minimum = 0, | |
202 | .maximum = 1, | |
203 | .step = 1, | |
204 | .default_value = 0, | |
205 | }, | |
206 | { | |
207 | .id = V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE, | |
208 | .type = V4L2_CTRL_TYPE_BOOLEAN, | |
209 | .name = "Slice Interface Enable", | |
210 | .minimum = 0, | |
211 | .maximum = 1, | |
212 | .step = 1, | |
213 | .default_value = 0, | |
214 | }, | |
215 | { | |
216 | .id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, | |
217 | .type = V4L2_CTRL_TYPE_INTEGER, | |
218 | .name = "Minimum number of cap bufs", | |
219 | .minimum = 1, | |
220 | .maximum = 32, | |
221 | .step = 1, | |
222 | .default_value = 1, | |
0da0a783 | 223 | .is_volatile = 1, |
af935746 KD |
224 | }, |
225 | }; | |
226 | ||
227 | #define NUM_CTRLS ARRAY_SIZE(controls) | |
228 | ||
229 | /* Check whether a context should be run on hardware */ | |
230 | static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx) | |
231 | { | |
232 | /* Context is to parse header */ | |
233 | if (ctx->src_queue_cnt >= 1 && ctx->state == MFCINST_GOT_INST) | |
234 | return 1; | |
235 | /* Context is to decode a frame */ | |
236 | if (ctx->src_queue_cnt >= 1 && | |
237 | ctx->state == MFCINST_RUNNING && | |
e9d98ddc | 238 | ctx->dst_queue_cnt >= ctx->pb_count) |
af935746 KD |
239 | return 1; |
240 | /* Context is to return last frame */ | |
241 | if (ctx->state == MFCINST_FINISHING && | |
e9d98ddc | 242 | ctx->dst_queue_cnt >= ctx->pb_count) |
af935746 KD |
243 | return 1; |
244 | /* Context is to set buffers */ | |
245 | if (ctx->src_queue_cnt >= 1 && | |
246 | ctx->state == MFCINST_HEAD_PARSED && | |
247 | ctx->capture_state == QUEUE_BUFS_MMAPED) | |
248 | return 1; | |
249 | /* Resolution change */ | |
250 | if ((ctx->state == MFCINST_RES_CHANGE_INIT || | |
251 | ctx->state == MFCINST_RES_CHANGE_FLUSH) && | |
e9d98ddc | 252 | ctx->dst_queue_cnt >= ctx->pb_count) |
af935746 KD |
253 | return 1; |
254 | if (ctx->state == MFCINST_RES_CHANGE_END && | |
255 | ctx->src_queue_cnt >= 1) | |
256 | return 1; | |
257 | mfc_debug(2, "ctx is not ready\n"); | |
258 | return 0; | |
259 | } | |
260 | ||
4e9691aa | 261 | static const struct s5p_mfc_codec_ops decoder_codec_ops = { |
af935746 KD |
262 | .pre_seq_start = NULL, |
263 | .post_seq_start = NULL, | |
264 | .pre_frame_start = NULL, | |
265 | .post_frame_start = NULL, | |
266 | }; | |
267 | ||
268 | /* Query capabilities of the device */ | |
269 | static int vidioc_querycap(struct file *file, void *priv, | |
270 | struct v4l2_capability *cap) | |
271 | { | |
272 | struct s5p_mfc_dev *dev = video_drvdata(file); | |
273 | ||
c0decac1 MCC |
274 | strscpy(cap->driver, S5P_MFC_NAME, sizeof(cap->driver)); |
275 | strscpy(cap->card, dev->vfd_dec->name, sizeof(cap->card)); | |
4759bb46 JMC |
276 | snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", |
277 | dev_name(&dev->plat_dev->dev)); | |
f0476a83 SN |
278 | /* |
279 | * This is only a mem-to-mem video device. The capture and output | |
280 | * device capability flags are left only for backward compatibility | |
281 | * and are scheduled for removal. | |
282 | */ | |
8c17e5e3 HV |
283 | cap->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; |
284 | cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; | |
af935746 KD |
285 | return 0; |
286 | } | |
287 | ||
288 | /* Enumerate format */ | |
9aa5f008 | 289 | static int vidioc_enum_fmt(struct file *file, struct v4l2_fmtdesc *f, |
7e8fe13d | 290 | bool out) |
af935746 | 291 | { |
9aa5f008 | 292 | struct s5p_mfc_dev *dev = video_drvdata(file); |
af935746 KD |
293 | struct s5p_mfc_fmt *fmt; |
294 | int i, j = 0; | |
295 | ||
296 | for (i = 0; i < ARRAY_SIZE(formats); ++i) { | |
af935746 KD |
297 | if (out && formats[i].type != MFC_FMT_DEC) |
298 | continue; | |
299 | else if (!out && formats[i].type != MFC_FMT_RAW) | |
300 | continue; | |
9aa5f008 KD |
301 | else if ((dev->variant->version_bit & formats[i].versions) == 0) |
302 | continue; | |
af935746 KD |
303 | |
304 | if (j == f->index) | |
305 | break; | |
306 | ++j; | |
307 | } | |
308 | if (i == ARRAY_SIZE(formats)) | |
309 | return -EINVAL; | |
310 | fmt = &formats[i]; | |
c0decac1 | 311 | strscpy(f->description, fmt->name, sizeof(f->description)); |
af935746 KD |
312 | f->pixelformat = fmt->fourcc; |
313 | return 0; | |
314 | } | |
315 | ||
af935746 KD |
316 | static int vidioc_enum_fmt_vid_cap_mplane(struct file *file, void *pirv, |
317 | struct v4l2_fmtdesc *f) | |
318 | { | |
7e8fe13d | 319 | return vidioc_enum_fmt(file, f, false); |
af935746 KD |
320 | } |
321 | ||
9aa5f008 | 322 | static int vidioc_enum_fmt_vid_out_mplane(struct file *file, void *priv, |
af935746 KD |
323 | struct v4l2_fmtdesc *f) |
324 | { | |
7e8fe13d | 325 | return vidioc_enum_fmt(file, f, true); |
af935746 KD |
326 | } |
327 | ||
328 | /* Get format */ | |
329 | static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) | |
330 | { | |
331 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | |
332 | struct v4l2_pix_format_mplane *pix_mp; | |
333 | ||
334 | mfc_debug_enter(); | |
335 | pix_mp = &f->fmt.pix_mp; | |
336 | if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && | |
337 | (ctx->state == MFCINST_GOT_INST || ctx->state == | |
338 | MFCINST_RES_CHANGE_END)) { | |
339 | /* If the MFC is parsing the header, | |
340 | * so wait until it is finished */ | |
43a1ea1f | 341 | s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_SEQ_DONE_RET, |
af935746 KD |
342 | 0); |
343 | } | |
344 | if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && | |
345 | ctx->state >= MFCINST_HEAD_PARSED && | |
346 | ctx->state < MFCINST_ABORT) { | |
347 | /* This is run on CAPTURE (decode output) */ | |
348 | /* Width and height are set to the dimensions | |
349 | of the movie, the buffer is bigger and | |
350 | further processing stages should crop to this | |
351 | rectangle. */ | |
352 | pix_mp->width = ctx->buf_width; | |
353 | pix_mp->height = ctx->buf_height; | |
354 | pix_mp->field = V4L2_FIELD_NONE; | |
355 | pix_mp->num_planes = 2; | |
356 | /* Set pixelformat to the format in which MFC | |
357 | outputs the decoded frame */ | |
b2634562 | 358 | pix_mp->pixelformat = ctx->dst_fmt->fourcc; |
af935746 KD |
359 | pix_mp->plane_fmt[0].bytesperline = ctx->buf_width; |
360 | pix_mp->plane_fmt[0].sizeimage = ctx->luma_size; | |
361 | pix_mp->plane_fmt[1].bytesperline = ctx->buf_width; | |
362 | pix_mp->plane_fmt[1].sizeimage = ctx->chroma_size; | |
363 | } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | |
364 | /* This is run on OUTPUT | |
365 | The buffer contains compressed image | |
366 | so width and height have no meaning */ | |
367 | pix_mp->width = 0; | |
368 | pix_mp->height = 0; | |
369 | pix_mp->field = V4L2_FIELD_NONE; | |
370 | pix_mp->plane_fmt[0].bytesperline = ctx->dec_src_buf_size; | |
371 | pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size; | |
372 | pix_mp->pixelformat = ctx->src_fmt->fourcc; | |
373 | pix_mp->num_planes = ctx->src_fmt->num_planes; | |
374 | } else { | |
375 | mfc_err("Format could not be read\n"); | |
376 | mfc_debug(2, "%s-- with error\n", __func__); | |
377 | return -EINVAL; | |
378 | } | |
379 | mfc_debug_leave(); | |
380 | return 0; | |
381 | } | |
382 | ||
383 | /* Try format */ | |
384 | static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) | |
385 | { | |
f96f3cfa | 386 | struct s5p_mfc_dev *dev = video_drvdata(file); |
af935746 KD |
387 | struct s5p_mfc_fmt *fmt; |
388 | ||
f96f3cfa JP |
389 | mfc_debug(2, "Type is %d\n", f->type); |
390 | if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | |
391 | fmt = find_format(f, MFC_FMT_DEC); | |
392 | if (!fmt) { | |
393 | mfc_err("Unsupported format for source.\n"); | |
394 | return -EINVAL; | |
395 | } | |
b2634562 JS |
396 | if (fmt->codec_mode == S5P_FIMV_CODEC_NONE) { |
397 | mfc_err("Unknown codec\n"); | |
f96f3cfa JP |
398 | return -EINVAL; |
399 | } | |
9aa5f008 KD |
400 | if ((dev->variant->version_bit & fmt->versions) == 0) { |
401 | mfc_err("Unsupported format by this MFC version.\n"); | |
402 | return -EINVAL; | |
b2634562 | 403 | } |
f96f3cfa JP |
404 | } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { |
405 | fmt = find_format(f, MFC_FMT_RAW); | |
406 | if (!fmt) { | |
407 | mfc_err("Unsupported format for destination.\n"); | |
408 | return -EINVAL; | |
409 | } | |
9aa5f008 KD |
410 | if ((dev->variant->version_bit & fmt->versions) == 0) { |
411 | mfc_err("Unsupported format by this MFC version.\n"); | |
f96f3cfa JP |
412 | return -EINVAL; |
413 | } | |
af935746 | 414 | } |
f96f3cfa | 415 | |
af935746 KD |
416 | return 0; |
417 | } | |
418 | ||
419 | /* Set format */ | |
420 | static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) | |
421 | { | |
422 | struct s5p_mfc_dev *dev = video_drvdata(file); | |
423 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | |
424 | int ret = 0; | |
af935746 | 425 | struct v4l2_pix_format_mplane *pix_mp; |
f8600689 | 426 | struct s5p_mfc_buf_size *buf_size = dev->variant->buf_size; |
af935746 KD |
427 | |
428 | mfc_debug_enter(); | |
429 | ret = vidioc_try_fmt(file, priv, f); | |
430 | pix_mp = &f->fmt.pix_mp; | |
431 | if (ret) | |
432 | return ret; | |
6d2b7497 | 433 | if (vb2_is_streaming(&ctx->vq_src) || vb2_is_streaming(&ctx->vq_dst)) { |
af935746 KD |
434 | v4l2_err(&dev->v4l2_dev, "%s queue busy\n", __func__); |
435 | ret = -EBUSY; | |
436 | goto out; | |
437 | } | |
f96f3cfa | 438 | if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { |
b2634562 JS |
439 | /* dst_fmt is validated by call to vidioc_try_fmt */ |
440 | ctx->dst_fmt = find_format(f, MFC_FMT_RAW); | |
441 | ret = 0; | |
af935746 | 442 | goto out; |
b2634562 JS |
443 | } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { |
444 | /* src_fmt is validated by call to vidioc_try_fmt */ | |
445 | ctx->src_fmt = find_format(f, MFC_FMT_DEC); | |
446 | ctx->codec_mode = ctx->src_fmt->codec_mode; | |
447 | mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode); | |
448 | pix_mp->height = 0; | |
449 | pix_mp->width = 0; | |
f8600689 | 450 | if (pix_mp->plane_fmt[0].sizeimage == 0) |
b2634562 JS |
451 | pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size = |
452 | DEF_CPB_SIZE; | |
f8600689 | 453 | else if (pix_mp->plane_fmt[0].sizeimage > buf_size->cpb) |
454 | ctx->dec_src_buf_size = buf_size->cpb; | |
455 | else | |
456 | ctx->dec_src_buf_size = pix_mp->plane_fmt[0].sizeimage; | |
b2634562 JS |
457 | pix_mp->plane_fmt[0].bytesperline = 0; |
458 | ctx->state = MFCINST_INIT; | |
459 | ret = 0; | |
460 | goto out; | |
461 | } else { | |
462 | mfc_err("Wrong type error for S_FMT : %d", f->type); | |
af935746 KD |
463 | ret = -EINVAL; |
464 | goto out; | |
465 | } | |
b2634562 | 466 | |
af935746 KD |
467 | out: |
468 | mfc_debug_leave(); | |
469 | return ret; | |
470 | } | |
471 | ||
38beac65 PO |
472 | static int reqbufs_output(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx, |
473 | struct v4l2_requestbuffers *reqbufs) | |
af935746 | 474 | { |
af935746 | 475 | int ret = 0; |
af935746 | 476 | |
38beac65 PO |
477 | s5p_mfc_clock_on(); |
478 | ||
479 | if (reqbufs->count == 0) { | |
480 | mfc_debug(2, "Freeing buffers\n"); | |
481 | ret = vb2_reqbufs(&ctx->vq_src, reqbufs); | |
482 | if (ret) | |
483 | goto out; | |
484 | ctx->src_bufs_cnt = 0; | |
9d87e837 | 485 | ctx->output_state = QUEUE_FREE; |
38beac65 | 486 | } else if (ctx->output_state == QUEUE_FREE) { |
9d87e837 | 487 | /* Can only request buffers when we have a valid format set. */ |
38beac65 PO |
488 | WARN_ON(ctx->src_bufs_cnt != 0); |
489 | if (ctx->state != MFCINST_INIT) { | |
490 | mfc_err("Reqbufs called in an invalid state\n"); | |
491 | ret = -EINVAL; | |
492 | goto out; | |
af935746 | 493 | } |
38beac65 PO |
494 | |
495 | mfc_debug(2, "Allocating %d buffers for OUTPUT queue\n", | |
496 | reqbufs->count); | |
497 | ret = vb2_reqbufs(&ctx->vq_src, reqbufs); | |
498 | if (ret) | |
499 | goto out; | |
500 | ||
9d87e837 PO |
501 | ret = s5p_mfc_open_mfc_inst(dev, ctx); |
502 | if (ret) { | |
503 | reqbufs->count = 0; | |
504 | vb2_reqbufs(&ctx->vq_src, reqbufs); | |
505 | goto out; | |
506 | } | |
507 | ||
38beac65 PO |
508 | ctx->output_state = QUEUE_BUFS_REQUESTED; |
509 | } else { | |
510 | mfc_err("Buffers have already been requested\n"); | |
511 | ret = -EINVAL; | |
512 | } | |
513 | out: | |
514 | s5p_mfc_clock_off(); | |
515 | if (ret) | |
516 | mfc_err("Failed allocating buffers for OUTPUT queue\n"); | |
517 | return ret; | |
518 | } | |
519 | ||
520 | static int reqbufs_capture(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx, | |
521 | struct v4l2_requestbuffers *reqbufs) | |
522 | { | |
523 | int ret = 0; | |
524 | ||
525 | s5p_mfc_clock_on(); | |
526 | ||
527 | if (reqbufs->count == 0) { | |
528 | mfc_debug(2, "Freeing buffers\n"); | |
529 | ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); | |
530 | if (ret) | |
531 | goto out; | |
fdd1d4b0 | 532 | s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, ctx); |
af935746 | 533 | ctx->dst_bufs_cnt = 0; |
38beac65 PO |
534 | } else if (ctx->capture_state == QUEUE_FREE) { |
535 | WARN_ON(ctx->dst_bufs_cnt != 0); | |
536 | mfc_debug(2, "Allocating %d buffers for CAPTURE queue\n", | |
537 | reqbufs->count); | |
af935746 | 538 | ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); |
38beac65 PO |
539 | if (ret) |
540 | goto out; | |
541 | ||
542 | ctx->capture_state = QUEUE_BUFS_REQUESTED; | |
af935746 | 543 | ctx->total_dpb_count = reqbufs->count; |
38beac65 | 544 | |
43a1ea1f | 545 | ret = s5p_mfc_hw_call(dev->mfc_ops, alloc_codec_buffers, ctx); |
af935746 KD |
546 | if (ret) { |
547 | mfc_err("Failed to allocate decoding buffers\n"); | |
548 | reqbufs->count = 0; | |
38beac65 PO |
549 | vb2_reqbufs(&ctx->vq_dst, reqbufs); |
550 | ret = -ENOMEM; | |
551 | ctx->capture_state = QUEUE_FREE; | |
552 | goto out; | |
af935746 | 553 | } |
38beac65 PO |
554 | |
555 | WARN_ON(ctx->dst_bufs_cnt != ctx->total_dpb_count); | |
556 | ctx->capture_state = QUEUE_BUFS_MMAPED; | |
557 | ||
7fb89eca AH |
558 | if (s5p_mfc_ctx_ready(ctx)) |
559 | set_work_bit_irqsave(ctx); | |
fdd1d4b0 | 560 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
38beac65 PO |
561 | s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_INIT_BUFFERS_RET, |
562 | 0); | |
563 | } else { | |
564 | mfc_err("Buffers have already been requested\n"); | |
565 | ret = -EINVAL; | |
af935746 | 566 | } |
38beac65 PO |
567 | out: |
568 | s5p_mfc_clock_off(); | |
569 | if (ret) | |
570 | mfc_err("Failed allocating buffers for CAPTURE queue\n"); | |
af935746 KD |
571 | return ret; |
572 | } | |
573 | ||
e4be1253 | 574 | /* Request buffers */ |
38beac65 PO |
575 | static int vidioc_reqbufs(struct file *file, void *priv, |
576 | struct v4l2_requestbuffers *reqbufs) | |
577 | { | |
578 | struct s5p_mfc_dev *dev = video_drvdata(file); | |
579 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | |
580 | ||
581 | if (reqbufs->memory != V4L2_MEMORY_MMAP) { | |
c8e913e1 | 582 | mfc_debug(2, "Only V4L2_MEMORY_MMAP is supported\n"); |
38beac65 PO |
583 | return -EINVAL; |
584 | } | |
585 | ||
586 | if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | |
587 | return reqbufs_output(dev, ctx, reqbufs); | |
588 | } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { | |
589 | return reqbufs_capture(dev, ctx, reqbufs); | |
590 | } else { | |
591 | mfc_err("Invalid type requested\n"); | |
592 | return -EINVAL; | |
593 | } | |
594 | } | |
595 | ||
af935746 KD |
596 | /* Query buffer */ |
597 | static int vidioc_querybuf(struct file *file, void *priv, | |
598 | struct v4l2_buffer *buf) | |
599 | { | |
600 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | |
601 | int ret; | |
602 | int i; | |
603 | ||
604 | if (buf->memory != V4L2_MEMORY_MMAP) { | |
605 | mfc_err("Only mmaped buffers can be used\n"); | |
606 | return -EINVAL; | |
607 | } | |
608 | mfc_debug(2, "State: %d, buf->type: %d\n", ctx->state, buf->type); | |
9d87e837 | 609 | if (ctx->state == MFCINST_GOT_INST && |
af935746 KD |
610 | buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { |
611 | ret = vb2_querybuf(&ctx->vq_src, buf); | |
612 | } else if (ctx->state == MFCINST_RUNNING && | |
613 | buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { | |
614 | ret = vb2_querybuf(&ctx->vq_dst, buf); | |
615 | for (i = 0; i < buf->length; i++) | |
616 | buf->m.planes[i].m.mem_offset += DST_QUEUE_OFF_BASE; | |
617 | } else { | |
618 | mfc_err("vidioc_querybuf called in an inappropriate state\n"); | |
619 | ret = -EINVAL; | |
620 | } | |
621 | mfc_debug_leave(); | |
622 | return ret; | |
623 | } | |
624 | ||
625 | /* Queue a buffer */ | |
626 | static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | |
627 | { | |
628 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | |
629 | ||
630 | if (ctx->state == MFCINST_ERROR) { | |
631 | mfc_err("Call on QBUF after unrecoverable error\n"); | |
632 | return -EIO; | |
633 | } | |
634 | if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) | |
394dc588 | 635 | return vb2_qbuf(&ctx->vq_src, NULL, buf); |
af935746 | 636 | else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) |
394dc588 | 637 | return vb2_qbuf(&ctx->vq_dst, NULL, buf); |
af935746 KD |
638 | return -EINVAL; |
639 | } | |
640 | ||
641 | /* Dequeue a buffer */ | |
642 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | |
643 | { | |
a34026e7 KD |
644 | const struct v4l2_event ev = { |
645 | .type = V4L2_EVENT_EOS | |
646 | }; | |
af935746 | 647 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); |
a34026e7 | 648 | int ret; |
af935746 KD |
649 | |
650 | if (ctx->state == MFCINST_ERROR) { | |
0a79ef33 | 651 | mfc_err_limited("Call on DQBUF after unrecoverable error\n"); |
af935746 KD |
652 | return -EIO; |
653 | } | |
4d0b0ed6 AH |
654 | |
655 | switch (buf->type) { | |
656 | case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: | |
657 | return vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK); | |
658 | case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: | |
a34026e7 | 659 | ret = vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK); |
4d0b0ed6 AH |
660 | if (ret) |
661 | return ret; | |
662 | ||
663 | if (ctx->state == MFCINST_FINISHED && | |
664 | (ctx->dst_bufs[buf->index].flags & MFC_BUF_FLAG_EOS)) | |
a34026e7 | 665 | v4l2_event_queue_fh(&ctx->fh, &ev); |
4d0b0ed6 AH |
666 | return 0; |
667 | default: | |
668 | return -EINVAL; | |
a34026e7 | 669 | } |
af935746 KD |
670 | } |
671 | ||
6fa9dd06 TS |
672 | /* Export DMA buffer */ |
673 | static int vidioc_expbuf(struct file *file, void *priv, | |
674 | struct v4l2_exportbuffer *eb) | |
675 | { | |
676 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | |
677 | ||
678 | if (eb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) | |
679 | return vb2_expbuf(&ctx->vq_src, eb); | |
680 | if (eb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) | |
681 | return vb2_expbuf(&ctx->vq_dst, eb); | |
682 | return -EINVAL; | |
683 | } | |
684 | ||
af935746 KD |
685 | /* Stream on */ |
686 | static int vidioc_streamon(struct file *file, void *priv, | |
687 | enum v4l2_buf_type type) | |
688 | { | |
689 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | |
af935746 KD |
690 | int ret = -EINVAL; |
691 | ||
692 | mfc_debug_enter(); | |
9d87e837 | 693 | if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) |
af935746 | 694 | ret = vb2_streamon(&ctx->vq_src, type); |
9d87e837 | 695 | else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) |
af935746 KD |
696 | ret = vb2_streamon(&ctx->vq_dst, type); |
697 | mfc_debug_leave(); | |
698 | return ret; | |
699 | } | |
700 | ||
701 | /* Stream off, which equals to a pause */ | |
702 | static int vidioc_streamoff(struct file *file, void *priv, | |
703 | enum v4l2_buf_type type) | |
704 | { | |
705 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | |
706 | ||
707 | if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) | |
708 | return vb2_streamoff(&ctx->vq_src, type); | |
709 | else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) | |
710 | return vb2_streamoff(&ctx->vq_dst, type); | |
711 | return -EINVAL; | |
712 | } | |
713 | ||
714 | /* Set controls - v4l2 control framework */ | |
715 | static int s5p_mfc_dec_s_ctrl(struct v4l2_ctrl *ctrl) | |
716 | { | |
717 | struct s5p_mfc_ctx *ctx = ctrl_to_ctx(ctrl); | |
718 | ||
719 | switch (ctrl->id) { | |
720 | case V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY: | |
f60935c1 | 721 | ctx->display_delay = ctrl->val; |
af935746 KD |
722 | break; |
723 | case V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE: | |
724 | ctx->display_delay_enable = ctrl->val; | |
725 | break; | |
726 | case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER: | |
f60935c1 | 727 | ctx->loop_filter_mpeg4 = ctrl->val; |
af935746 KD |
728 | break; |
729 | case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE: | |
730 | ctx->slice_interface = ctrl->val; | |
731 | break; | |
732 | default: | |
733 | mfc_err("Invalid control 0x%08x\n", ctrl->id); | |
734 | return -EINVAL; | |
735 | } | |
736 | return 0; | |
737 | } | |
738 | ||
739 | static int s5p_mfc_dec_g_v_ctrl(struct v4l2_ctrl *ctrl) | |
740 | { | |
741 | struct s5p_mfc_ctx *ctx = ctrl_to_ctx(ctrl); | |
742 | struct s5p_mfc_dev *dev = ctx->dev; | |
743 | ||
744 | switch (ctrl->id) { | |
745 | case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: | |
746 | if (ctx->state >= MFCINST_HEAD_PARSED && | |
747 | ctx->state < MFCINST_ABORT) { | |
e9d98ddc | 748 | ctrl->val = ctx->pb_count; |
af935746 | 749 | break; |
9841dde5 PO |
750 | } else if (ctx->state != MFCINST_INIT && |
751 | ctx->state != MFCINST_RES_CHANGE_END) { | |
af935746 KD |
752 | v4l2_err(&dev->v4l2_dev, "Decoding not initialised\n"); |
753 | return -EINVAL; | |
754 | } | |
755 | /* Should wait for the header to be parsed */ | |
af935746 | 756 | s5p_mfc_wait_for_done_ctx(ctx, |
43a1ea1f | 757 | S5P_MFC_R2H_CMD_SEQ_DONE_RET, 0); |
af935746 KD |
758 | if (ctx->state >= MFCINST_HEAD_PARSED && |
759 | ctx->state < MFCINST_ABORT) { | |
e9d98ddc | 760 | ctrl->val = ctx->pb_count; |
af935746 KD |
761 | } else { |
762 | v4l2_err(&dev->v4l2_dev, "Decoding not initialised\n"); | |
763 | return -EINVAL; | |
764 | } | |
765 | break; | |
766 | } | |
767 | return 0; | |
768 | } | |
769 | ||
770 | ||
771 | static const struct v4l2_ctrl_ops s5p_mfc_dec_ctrl_ops = { | |
772 | .s_ctrl = s5p_mfc_dec_s_ctrl, | |
773 | .g_volatile_ctrl = s5p_mfc_dec_g_v_ctrl, | |
774 | }; | |
775 | ||
776 | /* Get cropping information */ | |
777 | static int vidioc_g_crop(struct file *file, void *priv, | |
778 | struct v4l2_crop *cr) | |
779 | { | |
780 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | |
43a1ea1f | 781 | struct s5p_mfc_dev *dev = ctx->dev; |
af935746 KD |
782 | u32 left, right, top, bottom; |
783 | ||
784 | if (ctx->state != MFCINST_HEAD_PARSED && | |
8fe47dca SK |
785 | ctx->state != MFCINST_RUNNING && |
786 | ctx->state != MFCINST_FINISHING && | |
787 | ctx->state != MFCINST_FINISHED) { | |
788 | mfc_err("Can not get crop information\n"); | |
789 | return -EINVAL; | |
790 | } | |
af935746 | 791 | if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_H264) { |
43a1ea1f | 792 | left = s5p_mfc_hw_call(dev->mfc_ops, get_crop_info_h, ctx); |
af935746 KD |
793 | right = left >> S5P_FIMV_SHARED_CROP_RIGHT_SHIFT; |
794 | left = left & S5P_FIMV_SHARED_CROP_LEFT_MASK; | |
43a1ea1f | 795 | top = s5p_mfc_hw_call(dev->mfc_ops, get_crop_info_v, ctx); |
af935746 KD |
796 | bottom = top >> S5P_FIMV_SHARED_CROP_BOTTOM_SHIFT; |
797 | top = top & S5P_FIMV_SHARED_CROP_TOP_MASK; | |
798 | cr->c.left = left; | |
799 | cr->c.top = top; | |
800 | cr->c.width = ctx->img_width - left - right; | |
801 | cr->c.height = ctx->img_height - top - bottom; | |
c12a5cc6 MCC |
802 | mfc_debug(2, "Cropping info [h264]: l=%d t=%d w=%d h=%d (r=%d b=%d fw=%d fh=%d\n", |
803 | left, top, cr->c.width, cr->c.height, right, bottom, | |
804 | ctx->buf_width, ctx->buf_height); | |
af935746 KD |
805 | } else { |
806 | cr->c.left = 0; | |
807 | cr->c.top = 0; | |
808 | cr->c.width = ctx->img_width; | |
809 | cr->c.height = ctx->img_height; | |
c12a5cc6 MCC |
810 | mfc_debug(2, "Cropping info: w=%d h=%d fw=%d fh=%d\n", |
811 | cr->c.width, cr->c.height, ctx->buf_width, | |
812 | ctx->buf_height); | |
af935746 KD |
813 | } |
814 | return 0; | |
815 | } | |
816 | ||
8492ec69 MCC |
817 | static int vidioc_decoder_cmd(struct file *file, void *priv, |
818 | struct v4l2_decoder_cmd *cmd) | |
a34026e7 KD |
819 | { |
820 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | |
821 | struct s5p_mfc_dev *dev = ctx->dev; | |
822 | struct s5p_mfc_buf *buf; | |
823 | unsigned long flags; | |
824 | ||
825 | switch (cmd->cmd) { | |
68e77d2e | 826 | case V4L2_DEC_CMD_STOP: |
a34026e7 KD |
827 | if (cmd->flags != 0) |
828 | return -EINVAL; | |
829 | ||
6d2b7497 | 830 | if (!vb2_is_streaming(&ctx->vq_src)) |
a34026e7 KD |
831 | return -EINVAL; |
832 | ||
833 | spin_lock_irqsave(&dev->irqlock, flags); | |
834 | if (list_empty(&ctx->src_queue)) { | |
835 | mfc_err("EOS: empty src queue, entering finishing state"); | |
836 | ctx->state = MFCINST_FINISHING; | |
837 | if (s5p_mfc_ctx_ready(ctx)) | |
838 | set_work_bit_irqsave(ctx); | |
839 | spin_unlock_irqrestore(&dev->irqlock, flags); | |
fdd1d4b0 | 840 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
a34026e7 KD |
841 | } else { |
842 | mfc_err("EOS: marking last buffer of stream"); | |
843 | buf = list_entry(ctx->src_queue.prev, | |
844 | struct s5p_mfc_buf, list); | |
845 | if (buf->flags & MFC_BUF_FLAG_USED) | |
846 | ctx->state = MFCINST_FINISHING; | |
847 | else | |
848 | buf->flags |= MFC_BUF_FLAG_EOS; | |
849 | spin_unlock_irqrestore(&dev->irqlock, flags); | |
850 | } | |
851 | break; | |
852 | default: | |
853 | return -EINVAL; | |
854 | } | |
855 | return 0; | |
856 | } | |
857 | ||
858 | static int vidioc_subscribe_event(struct v4l2_fh *fh, | |
859 | const struct v4l2_event_subscription *sub) | |
860 | { | |
861 | switch (sub->type) { | |
862 | case V4L2_EVENT_EOS: | |
863 | return v4l2_event_subscribe(fh, sub, 2, NULL); | |
0520e4cc PO |
864 | case V4L2_EVENT_SOURCE_CHANGE: |
865 | return v4l2_src_change_event_subscribe(fh, sub); | |
a34026e7 KD |
866 | default: |
867 | return -EINVAL; | |
868 | } | |
869 | } | |
870 | ||
871 | ||
af935746 KD |
872 | /* v4l2_ioctl_ops */ |
873 | static const struct v4l2_ioctl_ops s5p_mfc_dec_ioctl_ops = { | |
874 | .vidioc_querycap = vidioc_querycap, | |
af935746 | 875 | .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap_mplane, |
af935746 KD |
876 | .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out_mplane, |
877 | .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt, | |
878 | .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt, | |
879 | .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt, | |
880 | .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt, | |
881 | .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt, | |
882 | .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt, | |
883 | .vidioc_reqbufs = vidioc_reqbufs, | |
884 | .vidioc_querybuf = vidioc_querybuf, | |
885 | .vidioc_qbuf = vidioc_qbuf, | |
886 | .vidioc_dqbuf = vidioc_dqbuf, | |
6fa9dd06 | 887 | .vidioc_expbuf = vidioc_expbuf, |
af935746 KD |
888 | .vidioc_streamon = vidioc_streamon, |
889 | .vidioc_streamoff = vidioc_streamoff, | |
890 | .vidioc_g_crop = vidioc_g_crop, | |
a34026e7 KD |
891 | .vidioc_decoder_cmd = vidioc_decoder_cmd, |
892 | .vidioc_subscribe_event = vidioc_subscribe_event, | |
893 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, | |
af935746 KD |
894 | }; |
895 | ||
fc714e70 | 896 | static int s5p_mfc_queue_setup(struct vb2_queue *vq, |
df9ecb0c | 897 | unsigned int *buf_count, |
fc714e70 | 898 | unsigned int *plane_count, unsigned int psize[], |
36c0f8b3 | 899 | struct device *alloc_devs[]) |
af935746 KD |
900 | { |
901 | struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); | |
f96f3cfa | 902 | struct s5p_mfc_dev *dev = ctx->dev; |
af935746 KD |
903 | |
904 | /* Video output for decoding (source) | |
905 | * this can be set after getting an instance */ | |
906 | if (ctx->state == MFCINST_INIT && | |
907 | vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | |
908 | /* A single plane is required for input */ | |
909 | *plane_count = 1; | |
910 | if (*buf_count < 1) | |
911 | *buf_count = 1; | |
912 | if (*buf_count > MFC_MAX_BUFFERS) | |
913 | *buf_count = MFC_MAX_BUFFERS; | |
914 | /* Video capture for decoding (destination) | |
915 | * this can be set after the header was parsed */ | |
916 | } else if (ctx->state == MFCINST_HEAD_PARSED && | |
917 | vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { | |
918 | /* Output plane count is 2 - one for Y and one for CbCr */ | |
919 | *plane_count = 2; | |
920 | /* Setup buffer count */ | |
e9d98ddc AK |
921 | if (*buf_count < ctx->pb_count) |
922 | *buf_count = ctx->pb_count; | |
923 | if (*buf_count > ctx->pb_count + MFC_MAX_EXTRA_DPB) | |
924 | *buf_count = ctx->pb_count + MFC_MAX_EXTRA_DPB; | |
af935746 KD |
925 | if (*buf_count > MFC_MAX_BUFFERS) |
926 | *buf_count = MFC_MAX_BUFFERS; | |
927 | } else { | |
928 | mfc_err("State seems invalid. State = %d, vq->type = %d\n", | |
929 | ctx->state, vq->type); | |
930 | return -EINVAL; | |
931 | } | |
932 | mfc_debug(2, "Buffer count=%d, plane count=%d\n", | |
933 | *buf_count, *plane_count); | |
934 | if (ctx->state == MFCINST_HEAD_PARSED && | |
935 | vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { | |
936 | psize[0] = ctx->luma_size; | |
937 | psize[1] = ctx->chroma_size; | |
f96f3cfa | 938 | |
722b979e | 939 | if (IS_MFCV6_PLUS(dev)) |
5ea289fe | 940 | alloc_devs[0] = ctx->dev->mem_dev[BANK_L_CTX]; |
f96f3cfa | 941 | else |
5ea289fe MS |
942 | alloc_devs[0] = ctx->dev->mem_dev[BANK_R_CTX]; |
943 | alloc_devs[1] = ctx->dev->mem_dev[BANK_L_CTX]; | |
af935746 KD |
944 | } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && |
945 | ctx->state == MFCINST_INIT) { | |
946 | psize[0] = ctx->dec_src_buf_size; | |
5ea289fe | 947 | alloc_devs[0] = ctx->dev->mem_dev[BANK_L_CTX]; |
af935746 | 948 | } else { |
8b513d0c | 949 | mfc_err("This video node is dedicated to decoding. Decoding not initialized\n"); |
af935746 KD |
950 | return -EINVAL; |
951 | } | |
952 | return 0; | |
953 | } | |
954 | ||
af935746 KD |
955 | static int s5p_mfc_buf_init(struct vb2_buffer *vb) |
956 | { | |
2d700715 | 957 | struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); |
af935746 KD |
958 | struct vb2_queue *vq = vb->vb2_queue; |
959 | struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); | |
960 | unsigned int i; | |
961 | ||
962 | if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { | |
963 | if (ctx->capture_state == QUEUE_BUFS_MMAPED) | |
964 | return 0; | |
00684dab | 965 | for (i = 0; i < ctx->dst_fmt->num_planes; i++) { |
af935746 | 966 | if (IS_ERR_OR_NULL(ERR_PTR( |
ba7fcb0c | 967 | vb2_dma_contig_plane_dma_addr(vb, i)))) { |
af935746 KD |
968 | mfc_err("Plane mem not allocated\n"); |
969 | return -EINVAL; | |
970 | } | |
971 | } | |
972 | if (vb2_plane_size(vb, 0) < ctx->luma_size || | |
973 | vb2_plane_size(vb, 1) < ctx->chroma_size) { | |
974 | mfc_err("Plane buffer (CAPTURE) is too small\n"); | |
975 | return -EINVAL; | |
976 | } | |
2d700715 JS |
977 | i = vb->index; |
978 | ctx->dst_bufs[i].b = vbuf; | |
af935746 | 979 | ctx->dst_bufs[i].cookie.raw.luma = |
ba7fcb0c | 980 | vb2_dma_contig_plane_dma_addr(vb, 0); |
af935746 | 981 | ctx->dst_bufs[i].cookie.raw.chroma = |
ba7fcb0c | 982 | vb2_dma_contig_plane_dma_addr(vb, 1); |
af935746 KD |
983 | ctx->dst_bufs_cnt++; |
984 | } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | |
985 | if (IS_ERR_OR_NULL(ERR_PTR( | |
ba7fcb0c | 986 | vb2_dma_contig_plane_dma_addr(vb, 0)))) { |
af935746 KD |
987 | mfc_err("Plane memory not allocated\n"); |
988 | return -EINVAL; | |
989 | } | |
990 | if (vb2_plane_size(vb, 0) < ctx->dec_src_buf_size) { | |
991 | mfc_err("Plane buffer (OUTPUT) is too small\n"); | |
992 | return -EINVAL; | |
993 | } | |
994 | ||
2d700715 JS |
995 | i = vb->index; |
996 | ctx->src_bufs[i].b = vbuf; | |
af935746 | 997 | ctx->src_bufs[i].cookie.stream = |
ba7fcb0c | 998 | vb2_dma_contig_plane_dma_addr(vb, 0); |
af935746 KD |
999 | ctx->src_bufs_cnt++; |
1000 | } else { | |
1001 | mfc_err("s5p_mfc_buf_init: unknown queue type\n"); | |
1002 | return -EINVAL; | |
1003 | } | |
1004 | return 0; | |
1005 | } | |
1006 | ||
bd323e28 | 1007 | static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count) |
af935746 KD |
1008 | { |
1009 | struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); | |
1010 | struct s5p_mfc_dev *dev = ctx->dev; | |
af935746 KD |
1011 | |
1012 | v4l2_ctrl_handler_setup(&ctx->ctrl_handler); | |
1013 | if (ctx->state == MFCINST_FINISHING || | |
1014 | ctx->state == MFCINST_FINISHED) | |
1015 | ctx->state = MFCINST_RUNNING; | |
1016 | /* If context is ready then dev = work->data;schedule it to run */ | |
7fb89eca AH |
1017 | if (s5p_mfc_ctx_ready(ctx)) |
1018 | set_work_bit_irqsave(ctx); | |
fdd1d4b0 | 1019 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
af935746 KD |
1020 | return 0; |
1021 | } | |
1022 | ||
e37559b2 | 1023 | static void s5p_mfc_stop_streaming(struct vb2_queue *q) |
af935746 KD |
1024 | { |
1025 | unsigned long flags; | |
1026 | struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); | |
1027 | struct s5p_mfc_dev *dev = ctx->dev; | |
1028 | int aborted = 0; | |
1029 | ||
7969b125 | 1030 | spin_lock_irqsave(&dev->irqlock, flags); |
af935746 KD |
1031 | if ((ctx->state == MFCINST_FINISHING || |
1032 | ctx->state == MFCINST_RUNNING) && | |
1033 | dev->curr_ctx == ctx->num && dev->hw_lock) { | |
1034 | ctx->state = MFCINST_ABORT; | |
7969b125 | 1035 | spin_unlock_irqrestore(&dev->irqlock, flags); |
af935746 | 1036 | s5p_mfc_wait_for_done_ctx(ctx, |
43a1ea1f | 1037 | S5P_MFC_R2H_CMD_FRAME_DONE_RET, 0); |
af935746 | 1038 | aborted = 1; |
7969b125 | 1039 | spin_lock_irqsave(&dev->irqlock, flags); |
af935746 | 1040 | } |
af935746 | 1041 | if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { |
62bbd72b | 1042 | s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst); |
af935746 KD |
1043 | INIT_LIST_HEAD(&ctx->dst_queue); |
1044 | ctx->dst_queue_cnt = 0; | |
1045 | ctx->dpb_flush_flag = 1; | |
1046 | ctx->dec_dst_flag = 0; | |
722b979e | 1047 | if (IS_MFCV6_PLUS(dev) && (ctx->state == MFCINST_RUNNING)) { |
8f23cc02 AK |
1048 | ctx->state = MFCINST_FLUSH; |
1049 | set_work_bit_irqsave(ctx); | |
fdd1d4b0 | 1050 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
7969b125 | 1051 | spin_unlock_irqrestore(&dev->irqlock, flags); |
8f23cc02 AK |
1052 | if (s5p_mfc_wait_for_done_ctx(ctx, |
1053 | S5P_MFC_R2H_CMD_DPB_FLUSH_RET, 0)) | |
1054 | mfc_err("Err flushing buffers\n"); | |
7969b125 | 1055 | spin_lock_irqsave(&dev->irqlock, flags); |
8f23cc02 | 1056 | } |
7969b125 | 1057 | } else if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { |
62bbd72b | 1058 | s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src); |
af935746 KD |
1059 | INIT_LIST_HEAD(&ctx->src_queue); |
1060 | ctx->src_queue_cnt = 0; | |
1061 | } | |
1062 | if (aborted) | |
1063 | ctx->state = MFCINST_RUNNING; | |
7969b125 | 1064 | spin_unlock_irqrestore(&dev->irqlock, flags); |
af935746 KD |
1065 | } |
1066 | ||
1067 | ||
1068 | static void s5p_mfc_buf_queue(struct vb2_buffer *vb) | |
1069 | { | |
1070 | struct vb2_queue *vq = vb->vb2_queue; | |
1071 | struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); | |
1072 | struct s5p_mfc_dev *dev = ctx->dev; | |
1073 | unsigned long flags; | |
1074 | struct s5p_mfc_buf *mfc_buf; | |
1075 | ||
1076 | if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | |
2d700715 | 1077 | mfc_buf = &ctx->src_bufs[vb->index]; |
f9f715a9 | 1078 | mfc_buf->flags &= ~MFC_BUF_FLAG_USED; |
af935746 KD |
1079 | spin_lock_irqsave(&dev->irqlock, flags); |
1080 | list_add_tail(&mfc_buf->list, &ctx->src_queue); | |
1081 | ctx->src_queue_cnt++; | |
1082 | spin_unlock_irqrestore(&dev->irqlock, flags); | |
1083 | } else if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { | |
2d700715 | 1084 | mfc_buf = &ctx->dst_bufs[vb->index]; |
f9f715a9 | 1085 | mfc_buf->flags &= ~MFC_BUF_FLAG_USED; |
af935746 KD |
1086 | /* Mark destination as available for use by MFC */ |
1087 | spin_lock_irqsave(&dev->irqlock, flags); | |
2d700715 | 1088 | set_bit(vb->index, &ctx->dec_dst_flag); |
af935746 KD |
1089 | list_add_tail(&mfc_buf->list, &ctx->dst_queue); |
1090 | ctx->dst_queue_cnt++; | |
1091 | spin_unlock_irqrestore(&dev->irqlock, flags); | |
1092 | } else { | |
1093 | mfc_err("Unsupported buffer type (%d)\n", vq->type); | |
1094 | } | |
7fb89eca AH |
1095 | if (s5p_mfc_ctx_ready(ctx)) |
1096 | set_work_bit_irqsave(ctx); | |
fdd1d4b0 | 1097 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
af935746 KD |
1098 | } |
1099 | ||
1100 | static struct vb2_ops s5p_mfc_dec_qops = { | |
1101 | .queue_setup = s5p_mfc_queue_setup, | |
654a731b PL |
1102 | .wait_prepare = vb2_ops_wait_prepare, |
1103 | .wait_finish = vb2_ops_wait_finish, | |
af935746 KD |
1104 | .buf_init = s5p_mfc_buf_init, |
1105 | .start_streaming = s5p_mfc_start_streaming, | |
1106 | .stop_streaming = s5p_mfc_stop_streaming, | |
1107 | .buf_queue = s5p_mfc_buf_queue, | |
1108 | }; | |
1109 | ||
4e9691aa | 1110 | const struct s5p_mfc_codec_ops *get_dec_codec_ops(void) |
af935746 KD |
1111 | { |
1112 | return &decoder_codec_ops; | |
1113 | } | |
1114 | ||
1115 | struct vb2_ops *get_dec_queue_ops(void) | |
1116 | { | |
1117 | return &s5p_mfc_dec_qops; | |
1118 | } | |
1119 | ||
1120 | const struct v4l2_ioctl_ops *get_dec_v4l2_ioctl_ops(void) | |
1121 | { | |
1122 | return &s5p_mfc_dec_ioctl_ops; | |
1123 | } | |
1124 | ||
0f8017be | 1125 | #define IS_MFC51_PRIV(x) ((V4L2_CTRL_ID2WHICH(x) == V4L2_CTRL_CLASS_MPEG) \ |
af935746 KD |
1126 | && V4L2_CTRL_DRIVER_PRIV(x)) |
1127 | ||
1128 | int s5p_mfc_dec_ctrls_setup(struct s5p_mfc_ctx *ctx) | |
1129 | { | |
1130 | struct v4l2_ctrl_config cfg; | |
1131 | int i; | |
1132 | ||
1133 | v4l2_ctrl_handler_init(&ctx->ctrl_handler, NUM_CTRLS); | |
1134 | if (ctx->ctrl_handler.error) { | |
1135 | mfc_err("v4l2_ctrl_handler_init failed\n"); | |
1136 | return ctx->ctrl_handler.error; | |
1137 | } | |
1138 | ||
1139 | for (i = 0; i < NUM_CTRLS; i++) { | |
1140 | if (IS_MFC51_PRIV(controls[i].id)) { | |
a65c3262 | 1141 | memset(&cfg, 0, sizeof(struct v4l2_ctrl_config)); |
af935746 KD |
1142 | cfg.ops = &s5p_mfc_dec_ctrl_ops; |
1143 | cfg.id = controls[i].id; | |
1144 | cfg.min = controls[i].minimum; | |
1145 | cfg.max = controls[i].maximum; | |
1146 | cfg.def = controls[i].default_value; | |
1147 | cfg.name = controls[i].name; | |
1148 | cfg.type = controls[i].type; | |
1149 | ||
1150 | cfg.step = controls[i].step; | |
1151 | cfg.menu_skip_mask = 0; | |
1152 | ||
1153 | ctx->ctrls[i] = v4l2_ctrl_new_custom(&ctx->ctrl_handler, | |
1154 | &cfg, NULL); | |
1155 | } else { | |
1156 | ctx->ctrls[i] = v4l2_ctrl_new_std(&ctx->ctrl_handler, | |
1157 | &s5p_mfc_dec_ctrl_ops, | |
1158 | controls[i].id, controls[i].minimum, | |
1159 | controls[i].maximum, controls[i].step, | |
1160 | controls[i].default_value); | |
1161 | } | |
1162 | if (ctx->ctrl_handler.error) { | |
1163 | mfc_err("Adding control (%d) failed\n", i); | |
1164 | return ctx->ctrl_handler.error; | |
1165 | } | |
1166 | if (controls[i].is_volatile && ctx->ctrls[i]) | |
88365105 | 1167 | ctx->ctrls[i]->flags |= V4L2_CTRL_FLAG_VOLATILE; |
af935746 KD |
1168 | } |
1169 | return 0; | |
1170 | } | |
1171 | ||
1172 | void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx) | |
1173 | { | |
1174 | int i; | |
1175 | ||
1176 | v4l2_ctrl_handler_free(&ctx->ctrl_handler); | |
1177 | for (i = 0; i < NUM_CTRLS; i++) | |
1178 | ctx->ctrls[i] = NULL; | |
1179 | } | |
1180 | ||
43a1ea1f AK |
1181 | void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx) |
1182 | { | |
1183 | struct v4l2_format f; | |
264e5bac | 1184 | f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264; |
43a1ea1f | 1185 | ctx->src_fmt = find_format(&f, MFC_FMT_DEC); |
f1a355bf | 1186 | if (IS_MFCV8_PLUS(ctx->dev)) |
e2b9deb2 KA |
1187 | f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M; |
1188 | else if (IS_MFCV6_PLUS(ctx->dev)) | |
264e5bac KD |
1189 | f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT_16X16; |
1190 | else | |
1191 | f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT; | |
43a1ea1f | 1192 | ctx->dst_fmt = find_format(&f, MFC_FMT_RAW); |
03ce7816 MCC |
1193 | mfc_debug(2, "Default src_fmt is %p, dest_fmt is %p\n", |
1194 | ctx->src_fmt, ctx->dst_fmt); | |
43a1ea1f | 1195 | } |
a34026e7 | 1196 |