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