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 | ||
268 | strncpy(cap->driver, dev->plat_dev->name, sizeof(cap->driver) - 1); | |
269 | strncpy(cap->card, dev->plat_dev->name, sizeof(cap->card) - 1); | |
270 | cap->bus_info[0] = 0; | |
f0476a83 SN |
271 | /* |
272 | * This is only a mem-to-mem video device. The capture and output | |
273 | * device capability flags are left only for backward compatibility | |
274 | * and are scheduled for removal. | |
275 | */ | |
8c17e5e3 HV |
276 | cap->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; |
277 | cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; | |
af935746 KD |
278 | return 0; |
279 | } | |
280 | ||
281 | /* Enumerate format */ | |
9aa5f008 | 282 | static int vidioc_enum_fmt(struct file *file, struct v4l2_fmtdesc *f, |
7e8fe13d | 283 | bool out) |
af935746 | 284 | { |
9aa5f008 | 285 | struct s5p_mfc_dev *dev = video_drvdata(file); |
af935746 KD |
286 | struct s5p_mfc_fmt *fmt; |
287 | int i, j = 0; | |
288 | ||
289 | for (i = 0; i < ARRAY_SIZE(formats); ++i) { | |
af935746 KD |
290 | if (out && formats[i].type != MFC_FMT_DEC) |
291 | continue; | |
292 | else if (!out && formats[i].type != MFC_FMT_RAW) | |
293 | continue; | |
9aa5f008 KD |
294 | else if ((dev->variant->version_bit & formats[i].versions) == 0) |
295 | continue; | |
af935746 KD |
296 | |
297 | if (j == f->index) | |
298 | break; | |
299 | ++j; | |
300 | } | |
301 | if (i == ARRAY_SIZE(formats)) | |
302 | return -EINVAL; | |
303 | fmt = &formats[i]; | |
304 | strlcpy(f->description, fmt->name, sizeof(f->description)); | |
305 | f->pixelformat = fmt->fourcc; | |
306 | return 0; | |
307 | } | |
308 | ||
af935746 KD |
309 | static int vidioc_enum_fmt_vid_cap_mplane(struct file *file, void *pirv, |
310 | struct v4l2_fmtdesc *f) | |
311 | { | |
7e8fe13d | 312 | return vidioc_enum_fmt(file, f, false); |
af935746 KD |
313 | } |
314 | ||
9aa5f008 | 315 | static int vidioc_enum_fmt_vid_out_mplane(struct file *file, void *priv, |
af935746 KD |
316 | struct v4l2_fmtdesc *f) |
317 | { | |
7e8fe13d | 318 | return vidioc_enum_fmt(file, f, true); |
af935746 KD |
319 | } |
320 | ||
321 | /* Get format */ | |
322 | static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) | |
323 | { | |
324 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | |
325 | struct v4l2_pix_format_mplane *pix_mp; | |
326 | ||
327 | mfc_debug_enter(); | |
328 | pix_mp = &f->fmt.pix_mp; | |
329 | if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && | |
330 | (ctx->state == MFCINST_GOT_INST || ctx->state == | |
331 | MFCINST_RES_CHANGE_END)) { | |
332 | /* If the MFC is parsing the header, | |
333 | * so wait until it is finished */ | |
43a1ea1f | 334 | s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_SEQ_DONE_RET, |
af935746 KD |
335 | 0); |
336 | } | |
337 | if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && | |
338 | ctx->state >= MFCINST_HEAD_PARSED && | |
339 | ctx->state < MFCINST_ABORT) { | |
340 | /* This is run on CAPTURE (decode output) */ | |
341 | /* Width and height are set to the dimensions | |
342 | of the movie, the buffer is bigger and | |
343 | further processing stages should crop to this | |
344 | rectangle. */ | |
345 | pix_mp->width = ctx->buf_width; | |
346 | pix_mp->height = ctx->buf_height; | |
347 | pix_mp->field = V4L2_FIELD_NONE; | |
348 | pix_mp->num_planes = 2; | |
349 | /* Set pixelformat to the format in which MFC | |
350 | outputs the decoded frame */ | |
b2634562 | 351 | pix_mp->pixelformat = ctx->dst_fmt->fourcc; |
af935746 KD |
352 | pix_mp->plane_fmt[0].bytesperline = ctx->buf_width; |
353 | pix_mp->plane_fmt[0].sizeimage = ctx->luma_size; | |
354 | pix_mp->plane_fmt[1].bytesperline = ctx->buf_width; | |
355 | pix_mp->plane_fmt[1].sizeimage = ctx->chroma_size; | |
356 | } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | |
357 | /* This is run on OUTPUT | |
358 | The buffer contains compressed image | |
359 | so width and height have no meaning */ | |
360 | pix_mp->width = 0; | |
361 | pix_mp->height = 0; | |
362 | pix_mp->field = V4L2_FIELD_NONE; | |
363 | pix_mp->plane_fmt[0].bytesperline = ctx->dec_src_buf_size; | |
364 | pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size; | |
365 | pix_mp->pixelformat = ctx->src_fmt->fourcc; | |
366 | pix_mp->num_planes = ctx->src_fmt->num_planes; | |
367 | } else { | |
368 | mfc_err("Format could not be read\n"); | |
369 | mfc_debug(2, "%s-- with error\n", __func__); | |
370 | return -EINVAL; | |
371 | } | |
372 | mfc_debug_leave(); | |
373 | return 0; | |
374 | } | |
375 | ||
376 | /* Try format */ | |
377 | static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) | |
378 | { | |
f96f3cfa | 379 | struct s5p_mfc_dev *dev = video_drvdata(file); |
af935746 KD |
380 | struct s5p_mfc_fmt *fmt; |
381 | ||
f96f3cfa JP |
382 | mfc_debug(2, "Type is %d\n", f->type); |
383 | if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | |
384 | fmt = find_format(f, MFC_FMT_DEC); | |
385 | if (!fmt) { | |
386 | mfc_err("Unsupported format for source.\n"); | |
387 | return -EINVAL; | |
388 | } | |
b2634562 JS |
389 | if (fmt->codec_mode == S5P_FIMV_CODEC_NONE) { |
390 | mfc_err("Unknown codec\n"); | |
f96f3cfa JP |
391 | return -EINVAL; |
392 | } | |
9aa5f008 KD |
393 | if ((dev->variant->version_bit & fmt->versions) == 0) { |
394 | mfc_err("Unsupported format by this MFC version.\n"); | |
395 | return -EINVAL; | |
b2634562 | 396 | } |
f96f3cfa JP |
397 | } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { |
398 | fmt = find_format(f, MFC_FMT_RAW); | |
399 | if (!fmt) { | |
400 | mfc_err("Unsupported format for destination.\n"); | |
401 | return -EINVAL; | |
402 | } | |
9aa5f008 KD |
403 | if ((dev->variant->version_bit & fmt->versions) == 0) { |
404 | mfc_err("Unsupported format by this MFC version.\n"); | |
f96f3cfa JP |
405 | return -EINVAL; |
406 | } | |
af935746 | 407 | } |
f96f3cfa | 408 | |
af935746 KD |
409 | return 0; |
410 | } | |
411 | ||
412 | /* Set format */ | |
413 | static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) | |
414 | { | |
415 | struct s5p_mfc_dev *dev = video_drvdata(file); | |
416 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | |
417 | int ret = 0; | |
af935746 | 418 | struct v4l2_pix_format_mplane *pix_mp; |
f8600689 | 419 | struct s5p_mfc_buf_size *buf_size = dev->variant->buf_size; |
af935746 KD |
420 | |
421 | mfc_debug_enter(); | |
422 | ret = vidioc_try_fmt(file, priv, f); | |
423 | pix_mp = &f->fmt.pix_mp; | |
424 | if (ret) | |
425 | return ret; | |
426 | if (ctx->vq_src.streaming || ctx->vq_dst.streaming) { | |
427 | v4l2_err(&dev->v4l2_dev, "%s queue busy\n", __func__); | |
428 | ret = -EBUSY; | |
429 | goto out; | |
430 | } | |
f96f3cfa | 431 | if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { |
b2634562 JS |
432 | /* dst_fmt is validated by call to vidioc_try_fmt */ |
433 | ctx->dst_fmt = find_format(f, MFC_FMT_RAW); | |
434 | ret = 0; | |
af935746 | 435 | goto out; |
b2634562 JS |
436 | } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { |
437 | /* src_fmt is validated by call to vidioc_try_fmt */ | |
438 | ctx->src_fmt = find_format(f, MFC_FMT_DEC); | |
439 | ctx->codec_mode = ctx->src_fmt->codec_mode; | |
440 | mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode); | |
441 | pix_mp->height = 0; | |
442 | pix_mp->width = 0; | |
f8600689 | 443 | if (pix_mp->plane_fmt[0].sizeimage == 0) |
b2634562 JS |
444 | pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size = |
445 | DEF_CPB_SIZE; | |
f8600689 | 446 | else if (pix_mp->plane_fmt[0].sizeimage > buf_size->cpb) |
447 | ctx->dec_src_buf_size = buf_size->cpb; | |
448 | else | |
449 | ctx->dec_src_buf_size = pix_mp->plane_fmt[0].sizeimage; | |
b2634562 JS |
450 | pix_mp->plane_fmt[0].bytesperline = 0; |
451 | ctx->state = MFCINST_INIT; | |
452 | ret = 0; | |
453 | goto out; | |
454 | } else { | |
455 | mfc_err("Wrong type error for S_FMT : %d", f->type); | |
af935746 KD |
456 | ret = -EINVAL; |
457 | goto out; | |
458 | } | |
b2634562 | 459 | |
af935746 KD |
460 | out: |
461 | mfc_debug_leave(); | |
462 | return ret; | |
463 | } | |
464 | ||
38beac65 PO |
465 | static int reqbufs_output(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx, |
466 | struct v4l2_requestbuffers *reqbufs) | |
af935746 | 467 | { |
af935746 | 468 | int ret = 0; |
af935746 | 469 | |
38beac65 PO |
470 | s5p_mfc_clock_on(); |
471 | ||
472 | if (reqbufs->count == 0) { | |
473 | mfc_debug(2, "Freeing buffers\n"); | |
474 | ret = vb2_reqbufs(&ctx->vq_src, reqbufs); | |
475 | if (ret) | |
476 | goto out; | |
9d87e837 | 477 | s5p_mfc_close_mfc_inst(dev, ctx); |
38beac65 | 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 | ||
38beac65 PO |
568 | /* Reqeust buffers */ |
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) { | |
576 | mfc_err("Only V4L2_MEMORY_MAP is supported\n"); | |
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 && | |
779 | ctx->state != MFCINST_RUNNING && ctx->state != MFCINST_FINISHING | |
780 | && ctx->state != MFCINST_FINISHED) { | |
781 | mfc_err("Cannont set crop\n"); | |
782 | return -EINVAL; | |
783 | } | |
784 | if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_H264) { | |
43a1ea1f | 785 | left = s5p_mfc_hw_call(dev->mfc_ops, get_crop_info_h, ctx); |
af935746 KD |
786 | right = left >> S5P_FIMV_SHARED_CROP_RIGHT_SHIFT; |
787 | left = left & S5P_FIMV_SHARED_CROP_LEFT_MASK; | |
43a1ea1f | 788 | top = s5p_mfc_hw_call(dev->mfc_ops, get_crop_info_v, ctx); |
af935746 KD |
789 | bottom = top >> S5P_FIMV_SHARED_CROP_BOTTOM_SHIFT; |
790 | top = top & S5P_FIMV_SHARED_CROP_TOP_MASK; | |
791 | cr->c.left = left; | |
792 | cr->c.top = top; | |
793 | cr->c.width = ctx->img_width - left - right; | |
794 | cr->c.height = ctx->img_height - top - bottom; | |
795 | mfc_debug(2, "Cropping info [h264]: l=%d t=%d " | |
796 | "w=%d h=%d (r=%d b=%d fw=%d fh=%d\n", left, top, | |
797 | cr->c.width, cr->c.height, right, bottom, | |
798 | ctx->buf_width, ctx->buf_height); | |
799 | } else { | |
800 | cr->c.left = 0; | |
801 | cr->c.top = 0; | |
802 | cr->c.width = ctx->img_width; | |
803 | cr->c.height = ctx->img_height; | |
804 | mfc_debug(2, "Cropping info: w=%d h=%d fw=%d " | |
805 | "fh=%d\n", cr->c.width, cr->c.height, ctx->buf_width, | |
806 | ctx->buf_height); | |
807 | } | |
808 | return 0; | |
809 | } | |
810 | ||
8492ec69 MCC |
811 | static int vidioc_decoder_cmd(struct file *file, void *priv, |
812 | struct v4l2_decoder_cmd *cmd) | |
a34026e7 KD |
813 | { |
814 | struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); | |
815 | struct s5p_mfc_dev *dev = ctx->dev; | |
816 | struct s5p_mfc_buf *buf; | |
817 | unsigned long flags; | |
818 | ||
819 | switch (cmd->cmd) { | |
68e77d2e | 820 | case V4L2_DEC_CMD_STOP: |
a34026e7 KD |
821 | if (cmd->flags != 0) |
822 | return -EINVAL; | |
823 | ||
824 | if (!ctx->vq_src.streaming) | |
825 | return -EINVAL; | |
826 | ||
827 | spin_lock_irqsave(&dev->irqlock, flags); | |
828 | if (list_empty(&ctx->src_queue)) { | |
829 | mfc_err("EOS: empty src queue, entering finishing state"); | |
830 | ctx->state = MFCINST_FINISHING; | |
831 | if (s5p_mfc_ctx_ready(ctx)) | |
832 | set_work_bit_irqsave(ctx); | |
833 | spin_unlock_irqrestore(&dev->irqlock, flags); | |
fdd1d4b0 | 834 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
a34026e7 KD |
835 | } else { |
836 | mfc_err("EOS: marking last buffer of stream"); | |
837 | buf = list_entry(ctx->src_queue.prev, | |
838 | struct s5p_mfc_buf, list); | |
839 | if (buf->flags & MFC_BUF_FLAG_USED) | |
840 | ctx->state = MFCINST_FINISHING; | |
841 | else | |
842 | buf->flags |= MFC_BUF_FLAG_EOS; | |
843 | spin_unlock_irqrestore(&dev->irqlock, flags); | |
844 | } | |
845 | break; | |
846 | default: | |
847 | return -EINVAL; | |
848 | } | |
849 | return 0; | |
850 | } | |
851 | ||
852 | static int vidioc_subscribe_event(struct v4l2_fh *fh, | |
853 | const struct v4l2_event_subscription *sub) | |
854 | { | |
855 | switch (sub->type) { | |
856 | case V4L2_EVENT_EOS: | |
857 | return v4l2_event_subscribe(fh, sub, 2, NULL); | |
0520e4cc PO |
858 | case V4L2_EVENT_SOURCE_CHANGE: |
859 | return v4l2_src_change_event_subscribe(fh, sub); | |
a34026e7 KD |
860 | default: |
861 | return -EINVAL; | |
862 | } | |
863 | } | |
864 | ||
865 | ||
af935746 KD |
866 | /* v4l2_ioctl_ops */ |
867 | static const struct v4l2_ioctl_ops s5p_mfc_dec_ioctl_ops = { | |
868 | .vidioc_querycap = vidioc_querycap, | |
af935746 | 869 | .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap_mplane, |
af935746 KD |
870 | .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out_mplane, |
871 | .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt, | |
872 | .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt, | |
873 | .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt, | |
874 | .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt, | |
875 | .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt, | |
876 | .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt, | |
877 | .vidioc_reqbufs = vidioc_reqbufs, | |
878 | .vidioc_querybuf = vidioc_querybuf, | |
879 | .vidioc_qbuf = vidioc_qbuf, | |
880 | .vidioc_dqbuf = vidioc_dqbuf, | |
6fa9dd06 | 881 | .vidioc_expbuf = vidioc_expbuf, |
af935746 KD |
882 | .vidioc_streamon = vidioc_streamon, |
883 | .vidioc_streamoff = vidioc_streamoff, | |
884 | .vidioc_g_crop = vidioc_g_crop, | |
a34026e7 KD |
885 | .vidioc_decoder_cmd = vidioc_decoder_cmd, |
886 | .vidioc_subscribe_event = vidioc_subscribe_event, | |
887 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, | |
af935746 KD |
888 | }; |
889 | ||
fc714e70 | 890 | static int s5p_mfc_queue_setup(struct vb2_queue *vq, |
df9ecb0c | 891 | unsigned int *buf_count, |
fc714e70 GL |
892 | unsigned int *plane_count, unsigned int psize[], |
893 | void *allocators[]) | |
af935746 KD |
894 | { |
895 | struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); | |
f96f3cfa | 896 | struct s5p_mfc_dev *dev = ctx->dev; |
af935746 KD |
897 | |
898 | /* Video output for decoding (source) | |
899 | * this can be set after getting an instance */ | |
900 | if (ctx->state == MFCINST_INIT && | |
901 | vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | |
902 | /* A single plane is required for input */ | |
903 | *plane_count = 1; | |
904 | if (*buf_count < 1) | |
905 | *buf_count = 1; | |
906 | if (*buf_count > MFC_MAX_BUFFERS) | |
907 | *buf_count = MFC_MAX_BUFFERS; | |
908 | /* Video capture for decoding (destination) | |
909 | * this can be set after the header was parsed */ | |
910 | } else if (ctx->state == MFCINST_HEAD_PARSED && | |
911 | vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { | |
912 | /* Output plane count is 2 - one for Y and one for CbCr */ | |
913 | *plane_count = 2; | |
914 | /* Setup buffer count */ | |
e9d98ddc AK |
915 | if (*buf_count < ctx->pb_count) |
916 | *buf_count = ctx->pb_count; | |
917 | if (*buf_count > ctx->pb_count + MFC_MAX_EXTRA_DPB) | |
918 | *buf_count = ctx->pb_count + MFC_MAX_EXTRA_DPB; | |
af935746 KD |
919 | if (*buf_count > MFC_MAX_BUFFERS) |
920 | *buf_count = MFC_MAX_BUFFERS; | |
921 | } else { | |
922 | mfc_err("State seems invalid. State = %d, vq->type = %d\n", | |
923 | ctx->state, vq->type); | |
924 | return -EINVAL; | |
925 | } | |
926 | mfc_debug(2, "Buffer count=%d, plane count=%d\n", | |
927 | *buf_count, *plane_count); | |
928 | if (ctx->state == MFCINST_HEAD_PARSED && | |
929 | vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { | |
930 | psize[0] = ctx->luma_size; | |
931 | psize[1] = ctx->chroma_size; | |
f96f3cfa | 932 | |
722b979e | 933 | if (IS_MFCV6_PLUS(dev)) |
f96f3cfa JP |
934 | allocators[0] = |
935 | ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX]; | |
936 | else | |
937 | allocators[0] = | |
938 | ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX]; | |
af935746 KD |
939 | allocators[1] = ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX]; |
940 | } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && | |
941 | ctx->state == MFCINST_INIT) { | |
942 | psize[0] = ctx->dec_src_buf_size; | |
943 | allocators[0] = ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX]; | |
944 | } else { | |
8b513d0c | 945 | mfc_err("This video node is dedicated to decoding. Decoding not initialized\n"); |
af935746 KD |
946 | return -EINVAL; |
947 | } | |
948 | return 0; | |
949 | } | |
950 | ||
af935746 KD |
951 | static int s5p_mfc_buf_init(struct vb2_buffer *vb) |
952 | { | |
2d700715 | 953 | struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); |
af935746 KD |
954 | struct vb2_queue *vq = vb->vb2_queue; |
955 | struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); | |
956 | unsigned int i; | |
957 | ||
958 | if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { | |
959 | if (ctx->capture_state == QUEUE_BUFS_MMAPED) | |
960 | return 0; | |
00684dab | 961 | for (i = 0; i < ctx->dst_fmt->num_planes; i++) { |
af935746 | 962 | if (IS_ERR_OR_NULL(ERR_PTR( |
ba7fcb0c | 963 | vb2_dma_contig_plane_dma_addr(vb, i)))) { |
af935746 KD |
964 | mfc_err("Plane mem not allocated\n"); |
965 | return -EINVAL; | |
966 | } | |
967 | } | |
968 | if (vb2_plane_size(vb, 0) < ctx->luma_size || | |
969 | vb2_plane_size(vb, 1) < ctx->chroma_size) { | |
970 | mfc_err("Plane buffer (CAPTURE) is too small\n"); | |
971 | return -EINVAL; | |
972 | } | |
2d700715 JS |
973 | i = vb->index; |
974 | ctx->dst_bufs[i].b = vbuf; | |
af935746 | 975 | ctx->dst_bufs[i].cookie.raw.luma = |
ba7fcb0c | 976 | vb2_dma_contig_plane_dma_addr(vb, 0); |
af935746 | 977 | ctx->dst_bufs[i].cookie.raw.chroma = |
ba7fcb0c | 978 | vb2_dma_contig_plane_dma_addr(vb, 1); |
af935746 KD |
979 | ctx->dst_bufs_cnt++; |
980 | } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | |
981 | if (IS_ERR_OR_NULL(ERR_PTR( | |
ba7fcb0c | 982 | vb2_dma_contig_plane_dma_addr(vb, 0)))) { |
af935746 KD |
983 | mfc_err("Plane memory not allocated\n"); |
984 | return -EINVAL; | |
985 | } | |
986 | if (vb2_plane_size(vb, 0) < ctx->dec_src_buf_size) { | |
987 | mfc_err("Plane buffer (OUTPUT) is too small\n"); | |
988 | return -EINVAL; | |
989 | } | |
990 | ||
2d700715 JS |
991 | i = vb->index; |
992 | ctx->src_bufs[i].b = vbuf; | |
af935746 | 993 | ctx->src_bufs[i].cookie.stream = |
ba7fcb0c | 994 | vb2_dma_contig_plane_dma_addr(vb, 0); |
af935746 KD |
995 | ctx->src_bufs_cnt++; |
996 | } else { | |
997 | mfc_err("s5p_mfc_buf_init: unknown queue type\n"); | |
998 | return -EINVAL; | |
999 | } | |
1000 | return 0; | |
1001 | } | |
1002 | ||
bd323e28 | 1003 | static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count) |
af935746 KD |
1004 | { |
1005 | struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); | |
1006 | struct s5p_mfc_dev *dev = ctx->dev; | |
af935746 KD |
1007 | |
1008 | v4l2_ctrl_handler_setup(&ctx->ctrl_handler); | |
1009 | if (ctx->state == MFCINST_FINISHING || | |
1010 | ctx->state == MFCINST_FINISHED) | |
1011 | ctx->state = MFCINST_RUNNING; | |
1012 | /* If context is ready then dev = work->data;schedule it to run */ | |
7fb89eca AH |
1013 | if (s5p_mfc_ctx_ready(ctx)) |
1014 | set_work_bit_irqsave(ctx); | |
fdd1d4b0 | 1015 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
af935746 KD |
1016 | return 0; |
1017 | } | |
1018 | ||
e37559b2 | 1019 | static void s5p_mfc_stop_streaming(struct vb2_queue *q) |
af935746 KD |
1020 | { |
1021 | unsigned long flags; | |
1022 | struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); | |
1023 | struct s5p_mfc_dev *dev = ctx->dev; | |
1024 | int aborted = 0; | |
1025 | ||
7969b125 | 1026 | spin_lock_irqsave(&dev->irqlock, flags); |
af935746 KD |
1027 | if ((ctx->state == MFCINST_FINISHING || |
1028 | ctx->state == MFCINST_RUNNING) && | |
1029 | dev->curr_ctx == ctx->num && dev->hw_lock) { | |
1030 | ctx->state = MFCINST_ABORT; | |
7969b125 | 1031 | spin_unlock_irqrestore(&dev->irqlock, flags); |
af935746 | 1032 | s5p_mfc_wait_for_done_ctx(ctx, |
43a1ea1f | 1033 | S5P_MFC_R2H_CMD_FRAME_DONE_RET, 0); |
af935746 | 1034 | aborted = 1; |
7969b125 | 1035 | spin_lock_irqsave(&dev->irqlock, flags); |
af935746 | 1036 | } |
af935746 | 1037 | if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { |
62bbd72b | 1038 | s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst); |
af935746 KD |
1039 | INIT_LIST_HEAD(&ctx->dst_queue); |
1040 | ctx->dst_queue_cnt = 0; | |
1041 | ctx->dpb_flush_flag = 1; | |
1042 | ctx->dec_dst_flag = 0; | |
722b979e | 1043 | if (IS_MFCV6_PLUS(dev) && (ctx->state == MFCINST_RUNNING)) { |
8f23cc02 AK |
1044 | ctx->state = MFCINST_FLUSH; |
1045 | set_work_bit_irqsave(ctx); | |
fdd1d4b0 | 1046 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
7969b125 | 1047 | spin_unlock_irqrestore(&dev->irqlock, flags); |
8f23cc02 AK |
1048 | if (s5p_mfc_wait_for_done_ctx(ctx, |
1049 | S5P_MFC_R2H_CMD_DPB_FLUSH_RET, 0)) | |
1050 | mfc_err("Err flushing buffers\n"); | |
7969b125 | 1051 | spin_lock_irqsave(&dev->irqlock, flags); |
8f23cc02 | 1052 | } |
7969b125 | 1053 | } else if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { |
62bbd72b | 1054 | s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src); |
af935746 KD |
1055 | INIT_LIST_HEAD(&ctx->src_queue); |
1056 | ctx->src_queue_cnt = 0; | |
1057 | } | |
1058 | if (aborted) | |
1059 | ctx->state = MFCINST_RUNNING; | |
7969b125 | 1060 | spin_unlock_irqrestore(&dev->irqlock, flags); |
af935746 KD |
1061 | } |
1062 | ||
1063 | ||
1064 | static void s5p_mfc_buf_queue(struct vb2_buffer *vb) | |
1065 | { | |
1066 | struct vb2_queue *vq = vb->vb2_queue; | |
1067 | struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv); | |
1068 | struct s5p_mfc_dev *dev = ctx->dev; | |
1069 | unsigned long flags; | |
1070 | struct s5p_mfc_buf *mfc_buf; | |
1071 | ||
1072 | if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { | |
2d700715 | 1073 | mfc_buf = &ctx->src_bufs[vb->index]; |
f9f715a9 | 1074 | mfc_buf->flags &= ~MFC_BUF_FLAG_USED; |
af935746 KD |
1075 | spin_lock_irqsave(&dev->irqlock, flags); |
1076 | list_add_tail(&mfc_buf->list, &ctx->src_queue); | |
1077 | ctx->src_queue_cnt++; | |
1078 | spin_unlock_irqrestore(&dev->irqlock, flags); | |
1079 | } else if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { | |
2d700715 | 1080 | mfc_buf = &ctx->dst_bufs[vb->index]; |
f9f715a9 | 1081 | mfc_buf->flags &= ~MFC_BUF_FLAG_USED; |
af935746 KD |
1082 | /* Mark destination as available for use by MFC */ |
1083 | spin_lock_irqsave(&dev->irqlock, flags); | |
2d700715 | 1084 | set_bit(vb->index, &ctx->dec_dst_flag); |
af935746 KD |
1085 | list_add_tail(&mfc_buf->list, &ctx->dst_queue); |
1086 | ctx->dst_queue_cnt++; | |
1087 | spin_unlock_irqrestore(&dev->irqlock, flags); | |
1088 | } else { | |
1089 | mfc_err("Unsupported buffer type (%d)\n", vq->type); | |
1090 | } | |
7fb89eca AH |
1091 | if (s5p_mfc_ctx_ready(ctx)) |
1092 | set_work_bit_irqsave(ctx); | |
fdd1d4b0 | 1093 | s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); |
af935746 KD |
1094 | } |
1095 | ||
1096 | static struct vb2_ops s5p_mfc_dec_qops = { | |
1097 | .queue_setup = s5p_mfc_queue_setup, | |
654a731b PL |
1098 | .wait_prepare = vb2_ops_wait_prepare, |
1099 | .wait_finish = vb2_ops_wait_finish, | |
af935746 KD |
1100 | .buf_init = s5p_mfc_buf_init, |
1101 | .start_streaming = s5p_mfc_start_streaming, | |
1102 | .stop_streaming = s5p_mfc_stop_streaming, | |
1103 | .buf_queue = s5p_mfc_buf_queue, | |
1104 | }; | |
1105 | ||
4e9691aa | 1106 | const struct s5p_mfc_codec_ops *get_dec_codec_ops(void) |
af935746 KD |
1107 | { |
1108 | return &decoder_codec_ops; | |
1109 | } | |
1110 | ||
1111 | struct vb2_ops *get_dec_queue_ops(void) | |
1112 | { | |
1113 | return &s5p_mfc_dec_qops; | |
1114 | } | |
1115 | ||
1116 | const struct v4l2_ioctl_ops *get_dec_v4l2_ioctl_ops(void) | |
1117 | { | |
1118 | return &s5p_mfc_dec_ioctl_ops; | |
1119 | } | |
1120 | ||
0f8017be | 1121 | #define IS_MFC51_PRIV(x) ((V4L2_CTRL_ID2WHICH(x) == V4L2_CTRL_CLASS_MPEG) \ |
af935746 KD |
1122 | && V4L2_CTRL_DRIVER_PRIV(x)) |
1123 | ||
1124 | int s5p_mfc_dec_ctrls_setup(struct s5p_mfc_ctx *ctx) | |
1125 | { | |
1126 | struct v4l2_ctrl_config cfg; | |
1127 | int i; | |
1128 | ||
1129 | v4l2_ctrl_handler_init(&ctx->ctrl_handler, NUM_CTRLS); | |
1130 | if (ctx->ctrl_handler.error) { | |
1131 | mfc_err("v4l2_ctrl_handler_init failed\n"); | |
1132 | return ctx->ctrl_handler.error; | |
1133 | } | |
1134 | ||
1135 | for (i = 0; i < NUM_CTRLS; i++) { | |
1136 | if (IS_MFC51_PRIV(controls[i].id)) { | |
a65c3262 | 1137 | memset(&cfg, 0, sizeof(struct v4l2_ctrl_config)); |
af935746 KD |
1138 | cfg.ops = &s5p_mfc_dec_ctrl_ops; |
1139 | cfg.id = controls[i].id; | |
1140 | cfg.min = controls[i].minimum; | |
1141 | cfg.max = controls[i].maximum; | |
1142 | cfg.def = controls[i].default_value; | |
1143 | cfg.name = controls[i].name; | |
1144 | cfg.type = controls[i].type; | |
1145 | ||
1146 | cfg.step = controls[i].step; | |
1147 | cfg.menu_skip_mask = 0; | |
1148 | ||
1149 | ctx->ctrls[i] = v4l2_ctrl_new_custom(&ctx->ctrl_handler, | |
1150 | &cfg, NULL); | |
1151 | } else { | |
1152 | ctx->ctrls[i] = v4l2_ctrl_new_std(&ctx->ctrl_handler, | |
1153 | &s5p_mfc_dec_ctrl_ops, | |
1154 | controls[i].id, controls[i].minimum, | |
1155 | controls[i].maximum, controls[i].step, | |
1156 | controls[i].default_value); | |
1157 | } | |
1158 | if (ctx->ctrl_handler.error) { | |
1159 | mfc_err("Adding control (%d) failed\n", i); | |
1160 | return ctx->ctrl_handler.error; | |
1161 | } | |
1162 | if (controls[i].is_volatile && ctx->ctrls[i]) | |
88365105 | 1163 | ctx->ctrls[i]->flags |= V4L2_CTRL_FLAG_VOLATILE; |
af935746 KD |
1164 | } |
1165 | return 0; | |
1166 | } | |
1167 | ||
1168 | void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx) | |
1169 | { | |
1170 | int i; | |
1171 | ||
1172 | v4l2_ctrl_handler_free(&ctx->ctrl_handler); | |
1173 | for (i = 0; i < NUM_CTRLS; i++) | |
1174 | ctx->ctrls[i] = NULL; | |
1175 | } | |
1176 | ||
43a1ea1f AK |
1177 | void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx) |
1178 | { | |
1179 | struct v4l2_format f; | |
264e5bac | 1180 | f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264; |
43a1ea1f | 1181 | ctx->src_fmt = find_format(&f, MFC_FMT_DEC); |
e2b9deb2 KA |
1182 | if (IS_MFCV8(ctx->dev)) |
1183 | f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M; | |
1184 | else if (IS_MFCV6_PLUS(ctx->dev)) | |
264e5bac KD |
1185 | f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT_16X16; |
1186 | else | |
1187 | f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT; | |
43a1ea1f | 1188 | ctx->dst_fmt = find_format(&f, MFC_FMT_RAW); |
03ce7816 MCC |
1189 | mfc_debug(2, "Default src_fmt is %p, dest_fmt is %p\n", |
1190 | ctx->src_fmt, ctx->dst_fmt); | |
43a1ea1f | 1191 | } |
a34026e7 | 1192 |