1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright 2020-2021 NXP |
4 | */ |
5 | |
6 | #include <linux/init.h> |
7 | #include <linux/interconnect.h> |
8 | #include <linux/ioctl.h> |
9 | #include <linux/list.h> |
10 | #include <linux/kernel.h> |
11 | #include <linux/module.h> |
12 | #include <linux/vmalloc.h> |
13 | #include <linux/videodev2.h> |
14 | #include <media/v4l2-device.h> |
15 | #include <media/v4l2-event.h> |
16 | #include <media/v4l2-mem2mem.h> |
17 | #include <media/v4l2-ioctl.h> |
18 | #include <media/videobuf2-v4l2.h> |
19 | #include <media/videobuf2-dma-contig.h> |
20 | #include <media/videobuf2-vmalloc.h> |
21 | #include "vpu.h" |
22 | #include "vpu_defs.h" |
23 | #include "vpu_core.h" |
24 | #include "vpu_helpers.h" |
25 | #include "vpu_v4l2.h" |
26 | #include "vpu_cmds.h" |
27 | #include "vpu_rpc.h" |
28 | |
29 | #define VDEC_MIN_BUFFER_CAP 8 |
30 | #define VDEC_MIN_BUFFER_OUT 8 |
31 | |
32 | struct vdec_fs_info { |
33 | char name[8]; |
34 | u32 type; |
35 | u32 max_count; |
36 | u32 req_count; |
37 | u32 count; |
38 | u32 index; |
39 | u32 size; |
40 | struct vpu_buffer buffer[32]; |
41 | u32 tag; |
42 | }; |
43 | |
44 | struct vdec_t { |
45 | u32 seq_hdr_found; |
46 | struct vpu_buffer udata; |
47 | struct vpu_decode_params params; |
48 | struct vpu_dec_codec_info codec_info; |
49 | enum vpu_codec_state state; |
50 | |
51 | struct vpu_vb2_buffer *slots[VB2_MAX_FRAME]; |
52 | u32 req_frame_count; |
53 | struct vdec_fs_info mbi; |
54 | struct vdec_fs_info dcp; |
55 | u32 seq_tag; |
56 | |
57 | bool reset_codec; |
58 | bool fixed_fmt; |
59 | u32 decoded_frame_count; |
60 | u32 display_frame_count; |
61 | u32 sequence; |
62 | u32 eos_received; |
63 | bool is_source_changed; |
64 | u32 source_change; |
65 | u32 drain; |
66 | bool aborting; |
67 | }; |
68 | |
69 | static const struct vpu_format vdec_formats[] = { |
70 | { |
71 | .pixfmt = V4L2_PIX_FMT_NV12M_8L128, |
72 | .mem_planes = 2, |
73 | .comp_planes = 2, |
74 | .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, |
75 | .sibling = V4L2_PIX_FMT_NV12_8L128, |
76 | }, |
77 | { |
78 | .pixfmt = V4L2_PIX_FMT_NV12_8L128, |
79 | .mem_planes = 1, |
80 | .comp_planes = 2, |
81 | .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, |
82 | .sibling = V4L2_PIX_FMT_NV12M_8L128, |
83 | }, |
84 | { |
85 | .pixfmt = V4L2_PIX_FMT_NV12M_10BE_8L128, |
86 | .mem_planes = 2, |
87 | .comp_planes = 2, |
88 | .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, |
89 | .sibling = V4L2_PIX_FMT_NV12_10BE_8L128, |
90 | }, |
91 | { |
92 | .pixfmt = V4L2_PIX_FMT_NV12_10BE_8L128, |
93 | .mem_planes = 1, |
94 | .comp_planes = 2, |
95 | .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, |
96 | .sibling = V4L2_PIX_FMT_NV12M_10BE_8L128 |
97 | }, |
98 | { |
99 | .pixfmt = V4L2_PIX_FMT_H264, |
100 | .mem_planes = 1, |
101 | .comp_planes = 1, |
102 | .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, |
103 | .flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED |
104 | }, |
105 | { |
106 | .pixfmt = V4L2_PIX_FMT_H264_MVC, |
107 | .mem_planes = 1, |
108 | .comp_planes = 1, |
109 | .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, |
110 | .flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED |
111 | }, |
112 | { |
113 | .pixfmt = V4L2_PIX_FMT_HEVC, |
114 | .mem_planes = 1, |
115 | .comp_planes = 1, |
116 | .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, |
117 | .flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED |
118 | }, |
119 | { |
120 | .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_G, |
121 | .mem_planes = 1, |
122 | .comp_planes = 1, |
123 | .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, |
124 | .flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED |
125 | }, |
126 | { |
127 | .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_L, |
128 | .mem_planes = 1, |
129 | .comp_planes = 1, |
130 | .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, |
131 | .flags = V4L2_FMT_FLAG_COMPRESSED |
132 | }, |
133 | { |
134 | .pixfmt = V4L2_PIX_FMT_MPEG2, |
135 | .mem_planes = 1, |
136 | .comp_planes = 1, |
137 | .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, |
138 | .flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED |
139 | }, |
140 | { |
141 | .pixfmt = V4L2_PIX_FMT_MPEG4, |
142 | .mem_planes = 1, |
143 | .comp_planes = 1, |
144 | .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, |
145 | .flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED |
146 | }, |
147 | { |
148 | .pixfmt = V4L2_PIX_FMT_XVID, |
149 | .mem_planes = 1, |
150 | .comp_planes = 1, |
151 | .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, |
152 | .flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED |
153 | }, |
154 | { |
155 | .pixfmt = V4L2_PIX_FMT_VP8, |
156 | .mem_planes = 1, |
157 | .comp_planes = 1, |
158 | .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, |
159 | .flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED |
160 | }, |
161 | { |
162 | .pixfmt = V4L2_PIX_FMT_H263, |
163 | .mem_planes = 1, |
164 | .comp_planes = 1, |
165 | .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, |
166 | .flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED |
167 | }, |
168 | { |
169 | .pixfmt = V4L2_PIX_FMT_SPK, |
170 | .mem_planes = 1, |
171 | .comp_planes = 1, |
172 | .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, |
173 | .flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED |
174 | }, |
175 | { |
176 | .pixfmt = V4L2_PIX_FMT_RV30, |
177 | .mem_planes = 1, |
178 | .comp_planes = 1, |
179 | .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, |
180 | .flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED |
181 | }, |
182 | { |
183 | .pixfmt = V4L2_PIX_FMT_RV40, |
184 | .mem_planes = 1, |
185 | .comp_planes = 1, |
186 | .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, |
187 | .flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED |
188 | }, |
189 | {0, 0, 0, 0}, |
190 | }; |
191 | |
192 | static int vdec_op_s_ctrl(struct v4l2_ctrl *ctrl) |
193 | { |
194 | struct vpu_inst *inst = ctrl_to_inst(ctrl); |
195 | struct vdec_t *vdec = inst->priv; |
196 | int ret = 0; |
197 | |
198 | vpu_inst_lock(inst); |
199 | switch (ctrl->id) { |
200 | case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE: |
201 | vdec->params.display_delay_enable = ctrl->val; |
202 | break; |
203 | case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY: |
204 | vdec->params.display_delay = ctrl->val; |
205 | break; |
206 | default: |
207 | ret = -EINVAL; |
208 | break; |
209 | } |
210 | vpu_inst_unlock(inst); |
211 | |
212 | return ret; |
213 | } |
214 | |
215 | static const struct v4l2_ctrl_ops vdec_ctrl_ops = { |
216 | .s_ctrl = vdec_op_s_ctrl, |
217 | .g_volatile_ctrl = vpu_helper_g_volatile_ctrl, |
218 | }; |
219 | |
220 | static int vdec_ctrl_init(struct vpu_inst *inst) |
221 | { |
222 | struct v4l2_ctrl *ctrl; |
223 | int ret; |
224 | |
225 | ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, 20); |
226 | if (ret) |
227 | return ret; |
228 | |
229 | v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &vdec_ctrl_ops, |
230 | V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY, |
231 | min: 0, max: 0, step: 1, def: 0); |
232 | |
233 | v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &vdec_ctrl_ops, |
234 | V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE, |
235 | min: 0, max: 1, step: 1, def: 0); |
236 | |
237 | ctrl = v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &vdec_ctrl_ops, |
238 | V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, min: 1, max: 32, step: 1, def: 2); |
239 | if (ctrl) |
240 | ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; |
241 | |
242 | ctrl = v4l2_ctrl_new_std(hdl: &inst->ctrl_handler, ops: &vdec_ctrl_ops, |
243 | V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, min: 1, max: 32, step: 1, def: 2); |
244 | if (ctrl) |
245 | ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; |
246 | |
247 | if (inst->ctrl_handler.error) { |
248 | ret = inst->ctrl_handler.error; |
249 | v4l2_ctrl_handler_free(hdl: &inst->ctrl_handler); |
250 | return ret; |
251 | } |
252 | |
253 | ret = v4l2_ctrl_handler_setup(hdl: &inst->ctrl_handler); |
254 | if (ret) { |
255 | dev_err(inst->dev, "[%d] setup ctrls fail, ret = %d\n" , inst->id, ret); |
256 | v4l2_ctrl_handler_free(hdl: &inst->ctrl_handler); |
257 | return ret; |
258 | } |
259 | |
260 | return 0; |
261 | } |
262 | |
263 | static void vdec_handle_resolution_change(struct vpu_inst *inst) |
264 | { |
265 | struct vdec_t *vdec = inst->priv; |
266 | struct vb2_queue *q; |
267 | |
268 | if (!inst->fh.m2m_ctx) |
269 | return; |
270 | |
271 | if (inst->state != VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE) |
272 | return; |
273 | if (!vdec->source_change) |
274 | return; |
275 | |
276 | q = v4l2_m2m_get_dst_vq(m2m_ctx: inst->fh.m2m_ctx); |
277 | if (!list_empty(head: &q->done_list)) |
278 | return; |
279 | |
280 | vdec->source_change--; |
281 | vpu_notify_source_change(inst); |
282 | vpu_set_last_buffer_dequeued(inst, eos: false); |
283 | } |
284 | |
285 | static int vdec_update_state(struct vpu_inst *inst, enum vpu_codec_state state, u32 force) |
286 | { |
287 | struct vdec_t *vdec = inst->priv; |
288 | enum vpu_codec_state pre_state = inst->state; |
289 | |
290 | if (state == VPU_CODEC_STATE_SEEK) { |
291 | if (inst->state == VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE) |
292 | vdec->state = inst->state; |
293 | else |
294 | vdec->state = VPU_CODEC_STATE_ACTIVE; |
295 | } |
296 | if (inst->state != VPU_CODEC_STATE_SEEK || force) |
297 | inst->state = state; |
298 | else if (state == VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE) |
299 | vdec->state = VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE; |
300 | |
301 | if (inst->state != pre_state) |
302 | vpu_trace(inst->dev, "[%d] %s -> %s\n" , inst->id, |
303 | vpu_codec_state_name(pre_state), vpu_codec_state_name(inst->state)); |
304 | |
305 | if (inst->state == VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE) |
306 | vdec_handle_resolution_change(inst); |
307 | |
308 | return 0; |
309 | } |
310 | |
311 | static void vdec_set_last_buffer_dequeued(struct vpu_inst *inst) |
312 | { |
313 | struct vdec_t *vdec = inst->priv; |
314 | |
315 | if (inst->state == VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE) |
316 | return; |
317 | |
318 | if (vdec->eos_received) { |
319 | if (!vpu_set_last_buffer_dequeued(inst, eos: true)) { |
320 | vdec->eos_received--; |
321 | vdec_update_state(inst, state: VPU_CODEC_STATE_DRAIN, force: 0); |
322 | } |
323 | } |
324 | } |
325 | |
326 | static int vdec_querycap(struct file *file, void *fh, struct v4l2_capability *cap) |
327 | { |
328 | strscpy(cap->driver, "amphion-vpu" , sizeof(cap->driver)); |
329 | strscpy(cap->card, "amphion vpu decoder" , sizeof(cap->card)); |
330 | strscpy(cap->bus_info, "platform: amphion-vpu" , sizeof(cap->bus_info)); |
331 | |
332 | return 0; |
333 | } |
334 | |
335 | static int vdec_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f) |
336 | { |
337 | struct vpu_inst *inst = to_inst(filp: file); |
338 | struct vdec_t *vdec = inst->priv; |
339 | const struct vpu_format *fmt; |
340 | int ret = -EINVAL; |
341 | |
342 | vpu_inst_lock(inst); |
343 | if (V4L2_TYPE_IS_CAPTURE(f->type) && vdec->fixed_fmt) { |
344 | fmt = vpu_get_format(inst, type: f->type); |
345 | if (f->index == 1) |
346 | fmt = vpu_helper_find_sibling(inst, type: f->type, pixelfmt: fmt->pixfmt); |
347 | if (f->index > 1) |
348 | fmt = NULL; |
349 | } else { |
350 | fmt = vpu_helper_enum_format(inst, type: f->type, index: f->index); |
351 | } |
352 | if (!fmt) |
353 | goto exit; |
354 | |
355 | memset(f->reserved, 0, sizeof(f->reserved)); |
356 | f->pixelformat = fmt->pixfmt; |
357 | f->flags = fmt->flags; |
358 | ret = 0; |
359 | exit: |
360 | vpu_inst_unlock(inst); |
361 | return ret; |
362 | } |
363 | |
364 | static int vdec_g_fmt(struct file *file, void *fh, struct v4l2_format *f) |
365 | { |
366 | struct vpu_inst *inst = to_inst(filp: file); |
367 | struct vdec_t *vdec = inst->priv; |
368 | struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; |
369 | struct vpu_format *cur_fmt; |
370 | int i; |
371 | |
372 | vpu_inst_lock(inst); |
373 | cur_fmt = vpu_get_format(inst, type: f->type); |
374 | |
375 | pixmp->pixelformat = cur_fmt->pixfmt; |
376 | pixmp->num_planes = cur_fmt->mem_planes; |
377 | pixmp->width = cur_fmt->width; |
378 | pixmp->height = cur_fmt->height; |
379 | pixmp->field = cur_fmt->field; |
380 | pixmp->flags = cur_fmt->flags; |
381 | for (i = 0; i < pixmp->num_planes; i++) { |
382 | pixmp->plane_fmt[i].bytesperline = cur_fmt->bytesperline[i]; |
383 | pixmp->plane_fmt[i].sizeimage = vpu_get_fmt_plane_size(fmt: cur_fmt, plane_no: i); |
384 | } |
385 | |
386 | f->fmt.pix_mp.colorspace = vdec->codec_info.color_primaries; |
387 | f->fmt.pix_mp.xfer_func = vdec->codec_info.transfer_chars; |
388 | f->fmt.pix_mp.ycbcr_enc = vdec->codec_info.matrix_coeffs; |
389 | f->fmt.pix_mp.quantization = vdec->codec_info.full_range; |
390 | vpu_inst_unlock(inst); |
391 | |
392 | return 0; |
393 | } |
394 | |
395 | static int vdec_try_fmt(struct file *file, void *fh, struct v4l2_format *f) |
396 | { |
397 | struct vpu_inst *inst = to_inst(filp: file); |
398 | struct vdec_t *vdec = inst->priv; |
399 | struct vpu_format fmt; |
400 | |
401 | vpu_inst_lock(inst); |
402 | if (V4L2_TYPE_IS_CAPTURE(f->type) && vdec->fixed_fmt) { |
403 | struct vpu_format *cap_fmt = vpu_get_format(inst, type: f->type); |
404 | |
405 | if (!vpu_helper_match_format(inst, type: cap_fmt->type, fmta: cap_fmt->pixfmt, |
406 | fmtb: f->fmt.pix_mp.pixelformat)) |
407 | f->fmt.pix_mp.pixelformat = cap_fmt->pixfmt; |
408 | } |
409 | |
410 | vpu_try_fmt_common(inst, f, fmt: &fmt); |
411 | |
412 | if (vdec->fixed_fmt) { |
413 | f->fmt.pix_mp.colorspace = vdec->codec_info.color_primaries; |
414 | f->fmt.pix_mp.xfer_func = vdec->codec_info.transfer_chars; |
415 | f->fmt.pix_mp.ycbcr_enc = vdec->codec_info.matrix_coeffs; |
416 | f->fmt.pix_mp.quantization = vdec->codec_info.full_range; |
417 | } else { |
418 | f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT; |
419 | f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT; |
420 | f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; |
421 | f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT; |
422 | } |
423 | vpu_inst_unlock(inst); |
424 | |
425 | return 0; |
426 | } |
427 | |
428 | static int vdec_s_fmt_common(struct vpu_inst *inst, struct v4l2_format *f) |
429 | { |
430 | struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; |
431 | struct vpu_format fmt; |
432 | struct vpu_format *cur_fmt; |
433 | struct vb2_queue *q; |
434 | struct vdec_t *vdec = inst->priv; |
435 | int i; |
436 | |
437 | if (!inst->fh.m2m_ctx) |
438 | return -EINVAL; |
439 | |
440 | q = v4l2_m2m_get_vq(m2m_ctx: inst->fh.m2m_ctx, type: f->type); |
441 | if (!q) |
442 | return -EINVAL; |
443 | if (vb2_is_busy(q)) |
444 | return -EBUSY; |
445 | |
446 | if (vpu_try_fmt_common(inst, f, fmt: &fmt)) |
447 | return -EINVAL; |
448 | |
449 | cur_fmt = vpu_get_format(inst, type: f->type); |
450 | if (V4L2_TYPE_IS_OUTPUT(f->type) && inst->state != VPU_CODEC_STATE_DEINIT) { |
451 | if (cur_fmt->pixfmt != fmt.pixfmt) { |
452 | vdec->reset_codec = true; |
453 | vdec->fixed_fmt = false; |
454 | } |
455 | } |
456 | if (V4L2_TYPE_IS_OUTPUT(f->type) || !vdec->fixed_fmt) { |
457 | memcpy(cur_fmt, &fmt, sizeof(*cur_fmt)); |
458 | } else { |
459 | if (vpu_helper_match_format(inst, type: f->type, fmta: cur_fmt->pixfmt, fmtb: pixmp->pixelformat)) { |
460 | cur_fmt->pixfmt = fmt.pixfmt; |
461 | cur_fmt->mem_planes = fmt.mem_planes; |
462 | } |
463 | pixmp->pixelformat = cur_fmt->pixfmt; |
464 | pixmp->num_planes = cur_fmt->mem_planes; |
465 | pixmp->width = cur_fmt->width; |
466 | pixmp->height = cur_fmt->height; |
467 | for (i = 0; i < pixmp->num_planes; i++) { |
468 | pixmp->plane_fmt[i].bytesperline = cur_fmt->bytesperline[i]; |
469 | pixmp->plane_fmt[i].sizeimage = vpu_get_fmt_plane_size(fmt: cur_fmt, plane_no: i); |
470 | } |
471 | pixmp->field = cur_fmt->field; |
472 | } |
473 | |
474 | if (!vdec->fixed_fmt) { |
475 | if (V4L2_TYPE_IS_OUTPUT(f->type)) { |
476 | vdec->params.codec_format = cur_fmt->pixfmt; |
477 | vdec->codec_info.color_primaries = f->fmt.pix_mp.colorspace; |
478 | vdec->codec_info.transfer_chars = f->fmt.pix_mp.xfer_func; |
479 | vdec->codec_info.matrix_coeffs = f->fmt.pix_mp.ycbcr_enc; |
480 | vdec->codec_info.full_range = f->fmt.pix_mp.quantization; |
481 | } else { |
482 | vdec->params.output_format = cur_fmt->pixfmt; |
483 | inst->crop.left = 0; |
484 | inst->crop.top = 0; |
485 | inst->crop.width = cur_fmt->width; |
486 | inst->crop.height = cur_fmt->height; |
487 | } |
488 | } |
489 | |
490 | vpu_trace(inst->dev, "[%d] %c%c%c%c %dx%d\n" , inst->id, |
491 | f->fmt.pix_mp.pixelformat, |
492 | f->fmt.pix_mp.pixelformat >> 8, |
493 | f->fmt.pix_mp.pixelformat >> 16, |
494 | f->fmt.pix_mp.pixelformat >> 24, |
495 | f->fmt.pix_mp.width, |
496 | f->fmt.pix_mp.height); |
497 | |
498 | return 0; |
499 | } |
500 | |
501 | static int vdec_s_fmt(struct file *file, void *fh, struct v4l2_format *f) |
502 | { |
503 | struct vpu_inst *inst = to_inst(filp: file); |
504 | struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; |
505 | struct vdec_t *vdec = inst->priv; |
506 | int ret = 0; |
507 | |
508 | vpu_inst_lock(inst); |
509 | ret = vdec_s_fmt_common(inst, f); |
510 | if (ret) |
511 | goto exit; |
512 | |
513 | if (V4L2_TYPE_IS_OUTPUT(f->type) && !vdec->fixed_fmt) { |
514 | struct v4l2_format fc; |
515 | |
516 | memset(&fc, 0, sizeof(fc)); |
517 | fc.type = inst->cap_format.type; |
518 | fc.fmt.pix_mp.pixelformat = inst->cap_format.pixfmt; |
519 | fc.fmt.pix_mp.width = pixmp->width; |
520 | fc.fmt.pix_mp.height = pixmp->height; |
521 | vdec_s_fmt_common(inst, f: &fc); |
522 | } |
523 | |
524 | f->fmt.pix_mp.colorspace = vdec->codec_info.color_primaries; |
525 | f->fmt.pix_mp.xfer_func = vdec->codec_info.transfer_chars; |
526 | f->fmt.pix_mp.ycbcr_enc = vdec->codec_info.matrix_coeffs; |
527 | f->fmt.pix_mp.quantization = vdec->codec_info.full_range; |
528 | |
529 | exit: |
530 | vpu_inst_unlock(inst); |
531 | return ret; |
532 | } |
533 | |
534 | static int vdec_g_selection(struct file *file, void *fh, struct v4l2_selection *s) |
535 | { |
536 | struct vpu_inst *inst = to_inst(filp: file); |
537 | |
538 | if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) |
539 | return -EINVAL; |
540 | |
541 | switch (s->target) { |
542 | case V4L2_SEL_TGT_COMPOSE: |
543 | case V4L2_SEL_TGT_COMPOSE_DEFAULT: |
544 | case V4L2_SEL_TGT_COMPOSE_PADDED: |
545 | s->r = inst->crop; |
546 | break; |
547 | case V4L2_SEL_TGT_COMPOSE_BOUNDS: |
548 | s->r.left = 0; |
549 | s->r.top = 0; |
550 | s->r.width = inst->cap_format.width; |
551 | s->r.height = inst->cap_format.height; |
552 | break; |
553 | default: |
554 | return -EINVAL; |
555 | } |
556 | |
557 | return 0; |
558 | } |
559 | |
560 | static int vdec_drain(struct vpu_inst *inst) |
561 | { |
562 | struct vdec_t *vdec = inst->priv; |
563 | |
564 | if (!inst->fh.m2m_ctx) |
565 | return 0; |
566 | |
567 | if (!vdec->drain) |
568 | return 0; |
569 | |
570 | if (!vpu_is_source_empty(inst)) |
571 | return 0; |
572 | |
573 | if (!vdec->params.frame_count) { |
574 | vpu_set_last_buffer_dequeued(inst, eos: true); |
575 | return 0; |
576 | } |
577 | |
578 | vpu_iface_add_scode(inst, scode_type: SCODE_PADDING_EOS); |
579 | vdec->params.end_flag = 1; |
580 | vpu_iface_set_decode_params(inst, params: &vdec->params, update: 1); |
581 | vdec->drain = 0; |
582 | vpu_trace(inst->dev, "[%d] frame_count = %d\n" , inst->id, vdec->params.frame_count); |
583 | |
584 | return 0; |
585 | } |
586 | |
587 | static int vdec_cmd_start(struct vpu_inst *inst) |
588 | { |
589 | struct vdec_t *vdec = inst->priv; |
590 | |
591 | switch (inst->state) { |
592 | case VPU_CODEC_STATE_STARTED: |
593 | case VPU_CODEC_STATE_DRAIN: |
594 | case VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE: |
595 | vdec_update_state(inst, state: VPU_CODEC_STATE_ACTIVE, force: 0); |
596 | break; |
597 | default: |
598 | break; |
599 | } |
600 | vpu_process_capture_buffer(inst); |
601 | if (vdec->eos_received) |
602 | vdec_set_last_buffer_dequeued(inst); |
603 | return 0; |
604 | } |
605 | |
606 | static int vdec_cmd_stop(struct vpu_inst *inst) |
607 | { |
608 | struct vdec_t *vdec = inst->priv; |
609 | |
610 | vpu_trace(inst->dev, "[%d]\n" , inst->id); |
611 | |
612 | if (inst->state == VPU_CODEC_STATE_DEINIT) { |
613 | vpu_set_last_buffer_dequeued(inst, eos: true); |
614 | } else { |
615 | vdec->drain = 1; |
616 | vdec_drain(inst); |
617 | } |
618 | |
619 | return 0; |
620 | } |
621 | |
622 | static int vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd) |
623 | { |
624 | struct vpu_inst *inst = to_inst(filp: file); |
625 | int ret; |
626 | |
627 | ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, dc: cmd); |
628 | if (ret) |
629 | return ret; |
630 | |
631 | vpu_inst_lock(inst); |
632 | switch (cmd->cmd) { |
633 | case V4L2_DEC_CMD_START: |
634 | vdec_cmd_start(inst); |
635 | break; |
636 | case V4L2_DEC_CMD_STOP: |
637 | vdec_cmd_stop(inst); |
638 | break; |
639 | default: |
640 | break; |
641 | } |
642 | vpu_inst_unlock(inst); |
643 | |
644 | return 0; |
645 | } |
646 | |
647 | static int vdec_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub) |
648 | { |
649 | switch (sub->type) { |
650 | case V4L2_EVENT_EOS: |
651 | return v4l2_event_subscribe(fh, sub, elems: 0, NULL); |
652 | case V4L2_EVENT_SOURCE_CHANGE: |
653 | return v4l2_src_change_event_subscribe(fh, sub); |
654 | case V4L2_EVENT_CTRL: |
655 | return v4l2_ctrl_subscribe_event(fh, sub); |
656 | default: |
657 | return -EINVAL; |
658 | } |
659 | |
660 | return 0; |
661 | } |
662 | |
663 | static const struct v4l2_ioctl_ops vdec_ioctl_ops = { |
664 | .vidioc_querycap = vdec_querycap, |
665 | .vidioc_enum_fmt_vid_cap = vdec_enum_fmt, |
666 | .vidioc_enum_fmt_vid_out = vdec_enum_fmt, |
667 | .vidioc_g_fmt_vid_cap_mplane = vdec_g_fmt, |
668 | .vidioc_g_fmt_vid_out_mplane = vdec_g_fmt, |
669 | .vidioc_try_fmt_vid_cap_mplane = vdec_try_fmt, |
670 | .vidioc_try_fmt_vid_out_mplane = vdec_try_fmt, |
671 | .vidioc_s_fmt_vid_cap_mplane = vdec_s_fmt, |
672 | .vidioc_s_fmt_vid_out_mplane = vdec_s_fmt, |
673 | .vidioc_g_selection = vdec_g_selection, |
674 | .vidioc_try_decoder_cmd = v4l2_m2m_ioctl_try_decoder_cmd, |
675 | .vidioc_decoder_cmd = vdec_decoder_cmd, |
676 | .vidioc_subscribe_event = vdec_subscribe_event, |
677 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, |
678 | .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, |
679 | .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, |
680 | .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, |
681 | .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, |
682 | .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, |
683 | .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, |
684 | .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, |
685 | .vidioc_streamon = v4l2_m2m_ioctl_streamon, |
686 | .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, |
687 | }; |
688 | |
689 | static bool vdec_check_ready(struct vpu_inst *inst, unsigned int type) |
690 | { |
691 | struct vdec_t *vdec = inst->priv; |
692 | |
693 | if (V4L2_TYPE_IS_OUTPUT(type)) |
694 | return true; |
695 | |
696 | if (vdec->req_frame_count) |
697 | return true; |
698 | |
699 | return false; |
700 | } |
701 | |
702 | static struct vb2_v4l2_buffer *vdec_get_src_buffer(struct vpu_inst *inst, u32 count) |
703 | { |
704 | if (count > 1) |
705 | vpu_skip_frame(inst, count: count - 1); |
706 | |
707 | return vpu_next_src_buf(inst); |
708 | } |
709 | |
710 | static int vdec_frame_decoded(struct vpu_inst *inst, void *arg) |
711 | { |
712 | struct vdec_t *vdec = inst->priv; |
713 | struct vpu_dec_pic_info *info = arg; |
714 | struct vpu_vb2_buffer *vpu_buf; |
715 | struct vb2_v4l2_buffer *vbuf; |
716 | struct vb2_v4l2_buffer *src_buf; |
717 | int ret = 0; |
718 | |
719 | if (!info || info->id >= ARRAY_SIZE(vdec->slots)) |
720 | return -EINVAL; |
721 | |
722 | vpu_inst_lock(inst); |
723 | vpu_buf = vdec->slots[info->id]; |
724 | if (!vpu_buf) { |
725 | dev_err(inst->dev, "[%d] decoded invalid frame[%d]\n" , inst->id, info->id); |
726 | ret = -EINVAL; |
727 | goto exit; |
728 | } |
729 | vbuf = &vpu_buf->m2m_buf.vb; |
730 | src_buf = vdec_get_src_buffer(inst, count: info->consumed_count); |
731 | if (src_buf) { |
732 | v4l2_m2m_buf_copy_metadata(out_vb: src_buf, cap_vb: vbuf, copy_frame_flags: true); |
733 | if (info->consumed_count) { |
734 | v4l2_m2m_src_buf_remove(m2m_ctx: inst->fh.m2m_ctx); |
735 | vpu_set_buffer_state(vbuf: src_buf, state: VPU_BUF_STATE_IDLE); |
736 | v4l2_m2m_buf_done(buf: src_buf, state: VB2_BUF_STATE_DONE); |
737 | } else { |
738 | vpu_set_buffer_state(vbuf: src_buf, state: VPU_BUF_STATE_DECODED); |
739 | } |
740 | } |
741 | if (vpu_get_buffer_state(vbuf) == VPU_BUF_STATE_DECODED) |
742 | dev_info(inst->dev, "[%d] buf[%d] has been decoded\n" , inst->id, info->id); |
743 | vpu_set_buffer_state(vbuf, state: VPU_BUF_STATE_DECODED); |
744 | vdec->decoded_frame_count++; |
745 | if (vdec->params.display_delay_enable) { |
746 | struct vpu_format *cur_fmt; |
747 | |
748 | cur_fmt = vpu_get_format(inst, type: inst->cap_format.type); |
749 | vpu_set_buffer_state(vbuf, state: VPU_BUF_STATE_READY); |
750 | for (int i = 0; i < vbuf->vb2_buf.num_planes; i++) |
751 | vb2_set_plane_payload(vb: &vbuf->vb2_buf, |
752 | plane_no: i, size: vpu_get_fmt_plane_size(fmt: cur_fmt, plane_no: i)); |
753 | vbuf->field = cur_fmt->field; |
754 | vbuf->sequence = vdec->sequence++; |
755 | dev_dbg(inst->dev, "[%d][OUTPUT TS]%32lld\n" , inst->id, vbuf->vb2_buf.timestamp); |
756 | |
757 | v4l2_m2m_buf_done(buf: vbuf, state: VB2_BUF_STATE_DONE); |
758 | vdec->display_frame_count++; |
759 | } |
760 | exit: |
761 | vpu_inst_unlock(inst); |
762 | |
763 | return ret; |
764 | } |
765 | |
766 | static struct vpu_vb2_buffer *vdec_find_buffer(struct vpu_inst *inst, u32 luma) |
767 | { |
768 | struct vdec_t *vdec = inst->priv; |
769 | int i; |
770 | |
771 | for (i = 0; i < ARRAY_SIZE(vdec->slots); i++) { |
772 | if (!vdec->slots[i]) |
773 | continue; |
774 | if (luma == vdec->slots[i]->luma) |
775 | return vdec->slots[i]; |
776 | } |
777 | |
778 | return NULL; |
779 | } |
780 | |
781 | static void vdec_buf_done(struct vpu_inst *inst, struct vpu_frame_info *frame) |
782 | { |
783 | struct vdec_t *vdec = inst->priv; |
784 | struct vpu_format *cur_fmt; |
785 | struct vpu_vb2_buffer *vpu_buf; |
786 | struct vb2_v4l2_buffer *vbuf; |
787 | int i; |
788 | |
789 | if (!frame) |
790 | return; |
791 | |
792 | vpu_inst_lock(inst); |
793 | if (!vdec->params.display_delay_enable) |
794 | vdec->sequence++; |
795 | vpu_buf = vdec_find_buffer(inst, luma: frame->luma); |
796 | vpu_inst_unlock(inst); |
797 | if (!vpu_buf) { |
798 | dev_err(inst->dev, "[%d] can't find buffer, id = %d, addr = 0x%x\n" , |
799 | inst->id, frame->id, frame->luma); |
800 | return; |
801 | } |
802 | if (frame->skipped) { |
803 | dev_dbg(inst->dev, "[%d] frame skip\n" , inst->id); |
804 | return; |
805 | } |
806 | |
807 | cur_fmt = vpu_get_format(inst, type: inst->cap_format.type); |
808 | vbuf = &vpu_buf->m2m_buf.vb; |
809 | if (vbuf->vb2_buf.index != frame->id) |
810 | dev_err(inst->dev, "[%d] buffer id(%d, %d) dismatch\n" , |
811 | inst->id, vbuf->vb2_buf.index, frame->id); |
812 | |
813 | if (vpu_get_buffer_state(vbuf) == VPU_BUF_STATE_READY && vdec->params.display_delay_enable) |
814 | return; |
815 | |
816 | if (vpu_get_buffer_state(vbuf) != VPU_BUF_STATE_DECODED) |
817 | dev_err(inst->dev, "[%d] buffer(%d) ready without decoded\n" , inst->id, frame->id); |
818 | |
819 | vpu_set_buffer_state(vbuf, state: VPU_BUF_STATE_READY); |
820 | for (i = 0; i < vbuf->vb2_buf.num_planes; i++) |
821 | vb2_set_plane_payload(vb: &vbuf->vb2_buf, plane_no: i, size: vpu_get_fmt_plane_size(fmt: cur_fmt, plane_no: i)); |
822 | vbuf->field = cur_fmt->field; |
823 | vbuf->sequence = vdec->sequence; |
824 | dev_dbg(inst->dev, "[%d][OUTPUT TS]%32lld\n" , inst->id, vbuf->vb2_buf.timestamp); |
825 | |
826 | v4l2_m2m_buf_done(buf: vbuf, state: VB2_BUF_STATE_DONE); |
827 | vpu_inst_lock(inst); |
828 | vdec->display_frame_count++; |
829 | vpu_inst_unlock(inst); |
830 | dev_dbg(inst->dev, "[%d] decoded : %d, display : %d, sequence : %d\n" , |
831 | inst->id, vdec->decoded_frame_count, vdec->display_frame_count, vdec->sequence); |
832 | } |
833 | |
834 | static void vdec_stop_done(struct vpu_inst *inst) |
835 | { |
836 | struct vdec_t *vdec = inst->priv; |
837 | |
838 | vpu_inst_lock(inst); |
839 | vdec_update_state(inst, state: VPU_CODEC_STATE_DEINIT, force: 0); |
840 | vdec->seq_hdr_found = 0; |
841 | vdec->req_frame_count = 0; |
842 | vdec->reset_codec = false; |
843 | vdec->fixed_fmt = false; |
844 | vdec->params.end_flag = 0; |
845 | vdec->drain = 0; |
846 | vdec->params.frame_count = 0; |
847 | vdec->decoded_frame_count = 0; |
848 | vdec->display_frame_count = 0; |
849 | vdec->sequence = 0; |
850 | vdec->eos_received = 0; |
851 | vdec->is_source_changed = false; |
852 | vdec->source_change = 0; |
853 | inst->total_input_count = 0; |
854 | vpu_inst_unlock(inst); |
855 | } |
856 | |
857 | static bool vdec_check_source_change(struct vpu_inst *inst) |
858 | { |
859 | struct vdec_t *vdec = inst->priv; |
860 | const struct vpu_format *sibling; |
861 | |
862 | if (!inst->fh.m2m_ctx) |
863 | return false; |
864 | |
865 | if (vdec->reset_codec) |
866 | return false; |
867 | |
868 | sibling = vpu_helper_find_sibling(inst, type: inst->cap_format.type, pixelfmt: inst->cap_format.pixfmt); |
869 | if (sibling && vdec->codec_info.pixfmt == sibling->pixfmt) |
870 | vdec->codec_info.pixfmt = inst->cap_format.pixfmt; |
871 | |
872 | if (!vb2_is_streaming(q: v4l2_m2m_get_dst_vq(m2m_ctx: inst->fh.m2m_ctx))) |
873 | return true; |
874 | if (inst->cap_format.pixfmt != vdec->codec_info.pixfmt) |
875 | return true; |
876 | if (inst->cap_format.width != vdec->codec_info.decoded_width) |
877 | return true; |
878 | if (inst->cap_format.height != vdec->codec_info.decoded_height) |
879 | return true; |
880 | if (vpu_get_num_buffers(inst, type: inst->cap_format.type) < inst->min_buffer_cap) |
881 | return true; |
882 | if (inst->crop.left != vdec->codec_info.offset_x) |
883 | return true; |
884 | if (inst->crop.top != vdec->codec_info.offset_y) |
885 | return true; |
886 | if (inst->crop.width != vdec->codec_info.width) |
887 | return true; |
888 | if (inst->crop.height != vdec->codec_info.height) |
889 | return true; |
890 | |
891 | return false; |
892 | } |
893 | |
894 | static void vdec_init_fmt(struct vpu_inst *inst) |
895 | { |
896 | struct vdec_t *vdec = inst->priv; |
897 | struct v4l2_format f; |
898 | |
899 | memset(&f, 0, sizeof(f)); |
900 | f.type = inst->cap_format.type; |
901 | f.fmt.pix_mp.pixelformat = vdec->codec_info.pixfmt; |
902 | f.fmt.pix_mp.width = vdec->codec_info.decoded_width; |
903 | f.fmt.pix_mp.height = vdec->codec_info.decoded_height; |
904 | if (vdec->codec_info.progressive) |
905 | f.fmt.pix_mp.field = V4L2_FIELD_NONE; |
906 | else |
907 | f.fmt.pix_mp.field = V4L2_FIELD_SEQ_TB; |
908 | vpu_try_fmt_common(inst, f: &f, fmt: &inst->cap_format); |
909 | |
910 | inst->out_format.width = vdec->codec_info.width; |
911 | inst->out_format.height = vdec->codec_info.height; |
912 | } |
913 | |
914 | static void vdec_init_crop(struct vpu_inst *inst) |
915 | { |
916 | struct vdec_t *vdec = inst->priv; |
917 | |
918 | inst->crop.left = vdec->codec_info.offset_x; |
919 | inst->crop.top = vdec->codec_info.offset_y; |
920 | inst->crop.width = vdec->codec_info.width; |
921 | inst->crop.height = vdec->codec_info.height; |
922 | } |
923 | |
924 | static void vdec_init_mbi(struct vpu_inst *inst) |
925 | { |
926 | struct vdec_t *vdec = inst->priv; |
927 | |
928 | vdec->mbi.size = vdec->codec_info.mbi_size; |
929 | vdec->mbi.max_count = ARRAY_SIZE(vdec->mbi.buffer); |
930 | scnprintf(buf: vdec->mbi.name, size: sizeof(vdec->mbi.name), fmt: "mbi" ); |
931 | vdec->mbi.type = MEM_RES_MBI; |
932 | vdec->mbi.tag = vdec->seq_tag; |
933 | } |
934 | |
935 | static void vdec_init_dcp(struct vpu_inst *inst) |
936 | { |
937 | struct vdec_t *vdec = inst->priv; |
938 | |
939 | vdec->dcp.size = vdec->codec_info.dcp_size; |
940 | vdec->dcp.max_count = ARRAY_SIZE(vdec->dcp.buffer); |
941 | scnprintf(buf: vdec->dcp.name, size: sizeof(vdec->dcp.name), fmt: "dcp" ); |
942 | vdec->dcp.type = MEM_RES_DCP; |
943 | vdec->dcp.tag = vdec->seq_tag; |
944 | } |
945 | |
946 | static void vdec_request_one_fs(struct vdec_fs_info *fs) |
947 | { |
948 | fs->req_count++; |
949 | if (fs->req_count > fs->max_count) |
950 | fs->req_count = fs->max_count; |
951 | } |
952 | |
953 | static int vdec_alloc_fs_buffer(struct vpu_inst *inst, struct vdec_fs_info *fs) |
954 | { |
955 | struct vpu_buffer *buffer; |
956 | |
957 | if (!fs->size) |
958 | return -EINVAL; |
959 | |
960 | if (fs->count >= fs->req_count) |
961 | return -EINVAL; |
962 | |
963 | buffer = &fs->buffer[fs->count]; |
964 | if (buffer->virt && buffer->length >= fs->size) |
965 | return 0; |
966 | |
967 | vpu_free_dma(buf: buffer); |
968 | buffer->length = fs->size; |
969 | return vpu_alloc_dma(core: inst->core, buf: buffer); |
970 | } |
971 | |
972 | static void vdec_alloc_fs(struct vpu_inst *inst, struct vdec_fs_info *fs) |
973 | { |
974 | int ret; |
975 | |
976 | while (fs->count < fs->req_count) { |
977 | ret = vdec_alloc_fs_buffer(inst, fs); |
978 | if (ret) |
979 | break; |
980 | fs->count++; |
981 | } |
982 | } |
983 | |
984 | static void vdec_clear_fs(struct vdec_fs_info *fs) |
985 | { |
986 | u32 i; |
987 | |
988 | if (!fs) |
989 | return; |
990 | |
991 | for (i = 0; i < ARRAY_SIZE(fs->buffer); i++) |
992 | vpu_free_dma(buf: &fs->buffer[i]); |
993 | memset(fs, 0, sizeof(*fs)); |
994 | } |
995 | |
996 | static int vdec_response_fs(struct vpu_inst *inst, struct vdec_fs_info *fs) |
997 | { |
998 | struct vpu_fs_info info; |
999 | int ret; |
1000 | |
1001 | if (fs->index >= fs->count) |
1002 | return 0; |
1003 | |
1004 | memset(&info, 0, sizeof(info)); |
1005 | info.id = fs->index; |
1006 | info.type = fs->type; |
1007 | info.tag = fs->tag; |
1008 | info.luma_addr = fs->buffer[fs->index].phys; |
1009 | info.luma_size = fs->buffer[fs->index].length; |
1010 | ret = vpu_session_alloc_fs(inst, fs: &info); |
1011 | if (ret) |
1012 | return ret; |
1013 | |
1014 | fs->index++; |
1015 | return 0; |
1016 | } |
1017 | |
1018 | static int vdec_response_frame_abnormal(struct vpu_inst *inst) |
1019 | { |
1020 | struct vdec_t *vdec = inst->priv; |
1021 | struct vpu_fs_info info; |
1022 | int ret; |
1023 | |
1024 | if (!vdec->req_frame_count) |
1025 | return 0; |
1026 | |
1027 | memset(&info, 0, sizeof(info)); |
1028 | info.type = MEM_RES_FRAME; |
1029 | info.tag = vdec->seq_tag + 0xf0; |
1030 | ret = vpu_session_alloc_fs(inst, fs: &info); |
1031 | if (ret) |
1032 | return ret; |
1033 | vdec->req_frame_count--; |
1034 | |
1035 | return 0; |
1036 | } |
1037 | |
1038 | static int vdec_response_frame(struct vpu_inst *inst, struct vb2_v4l2_buffer *vbuf) |
1039 | { |
1040 | struct vdec_t *vdec = inst->priv; |
1041 | struct vpu_vb2_buffer *vpu_buf; |
1042 | struct vpu_fs_info info; |
1043 | int ret; |
1044 | |
1045 | if (inst->state != VPU_CODEC_STATE_ACTIVE) |
1046 | return -EINVAL; |
1047 | |
1048 | if (vdec->aborting) |
1049 | return -EINVAL; |
1050 | |
1051 | if (!vdec->req_frame_count) |
1052 | return -EINVAL; |
1053 | |
1054 | if (!vbuf) |
1055 | return -EINVAL; |
1056 | |
1057 | if (vdec->slots[vbuf->vb2_buf.index]) { |
1058 | dev_err(inst->dev, "[%d] repeat alloc fs %d\n" , |
1059 | inst->id, vbuf->vb2_buf.index); |
1060 | return -EINVAL; |
1061 | } |
1062 | |
1063 | dev_dbg(inst->dev, "[%d] state = %s, alloc fs %d, tag = 0x%x\n" , |
1064 | inst->id, vpu_codec_state_name(inst->state), vbuf->vb2_buf.index, vdec->seq_tag); |
1065 | vpu_buf = to_vpu_vb2_buffer(vbuf); |
1066 | |
1067 | memset(&info, 0, sizeof(info)); |
1068 | info.id = vbuf->vb2_buf.index; |
1069 | info.type = MEM_RES_FRAME; |
1070 | info.tag = vdec->seq_tag; |
1071 | info.luma_addr = vpu_get_vb_phy_addr(vb: &vbuf->vb2_buf, plane_no: 0); |
1072 | info.luma_size = inst->cap_format.sizeimage[0]; |
1073 | if (vbuf->vb2_buf.num_planes > 1) |
1074 | info.chroma_addr = vpu_get_vb_phy_addr(vb: &vbuf->vb2_buf, plane_no: 1); |
1075 | else |
1076 | info.chroma_addr = info.luma_addr + info.luma_size; |
1077 | info.chromau_size = inst->cap_format.sizeimage[1]; |
1078 | info.bytesperline = inst->cap_format.bytesperline[0]; |
1079 | ret = vpu_session_alloc_fs(inst, fs: &info); |
1080 | if (ret) |
1081 | return ret; |
1082 | |
1083 | vpu_buf->tag = info.tag; |
1084 | vpu_buf->luma = info.luma_addr; |
1085 | vpu_buf->chroma_u = info.chroma_addr; |
1086 | vpu_buf->chroma_v = 0; |
1087 | vpu_set_buffer_state(vbuf, state: VPU_BUF_STATE_INUSE); |
1088 | vdec->slots[info.id] = vpu_buf; |
1089 | vdec->req_frame_count--; |
1090 | |
1091 | return 0; |
1092 | } |
1093 | |
1094 | static void vdec_response_fs_request(struct vpu_inst *inst, bool force) |
1095 | { |
1096 | struct vdec_t *vdec = inst->priv; |
1097 | int i; |
1098 | int ret; |
1099 | |
1100 | if (force) { |
1101 | for (i = vdec->req_frame_count; i > 0; i--) |
1102 | vdec_response_frame_abnormal(inst); |
1103 | return; |
1104 | } |
1105 | |
1106 | for (i = vdec->req_frame_count; i > 0; i--) { |
1107 | ret = vpu_process_capture_buffer(inst); |
1108 | if (ret) |
1109 | break; |
1110 | if (vdec->eos_received) |
1111 | break; |
1112 | } |
1113 | |
1114 | for (i = vdec->mbi.index; i < vdec->mbi.count; i++) { |
1115 | if (vdec_response_fs(inst, fs: &vdec->mbi)) |
1116 | break; |
1117 | if (vdec->eos_received) |
1118 | break; |
1119 | } |
1120 | for (i = vdec->dcp.index; i < vdec->dcp.count; i++) { |
1121 | if (vdec_response_fs(inst, fs: &vdec->dcp)) |
1122 | break; |
1123 | if (vdec->eos_received) |
1124 | break; |
1125 | } |
1126 | } |
1127 | |
1128 | static void vdec_response_fs_release(struct vpu_inst *inst, u32 id, u32 tag) |
1129 | { |
1130 | struct vpu_fs_info info; |
1131 | |
1132 | memset(&info, 0, sizeof(info)); |
1133 | info.id = id; |
1134 | info.tag = tag; |
1135 | vpu_session_release_fs(inst, fs: &info); |
1136 | } |
1137 | |
1138 | static void vdec_recycle_buffer(struct vpu_inst *inst, struct vb2_v4l2_buffer *vbuf) |
1139 | { |
1140 | if (!inst->fh.m2m_ctx) |
1141 | return; |
1142 | if (vbuf->vb2_buf.state != VB2_BUF_STATE_ACTIVE) |
1143 | return; |
1144 | if (vpu_find_buf_by_idx(inst, type: vbuf->vb2_buf.type, idx: vbuf->vb2_buf.index)) |
1145 | return; |
1146 | v4l2_m2m_buf_queue(m2m_ctx: inst->fh.m2m_ctx, vbuf); |
1147 | } |
1148 | |
1149 | static void vdec_clear_slots(struct vpu_inst *inst) |
1150 | { |
1151 | struct vdec_t *vdec = inst->priv; |
1152 | struct vpu_vb2_buffer *vpu_buf; |
1153 | struct vb2_v4l2_buffer *vbuf; |
1154 | int i; |
1155 | |
1156 | for (i = 0; i < ARRAY_SIZE(vdec->slots); i++) { |
1157 | if (!vdec->slots[i]) |
1158 | continue; |
1159 | |
1160 | vpu_buf = vdec->slots[i]; |
1161 | vbuf = &vpu_buf->m2m_buf.vb; |
1162 | |
1163 | vpu_trace(inst->dev, "clear slot %d\n" , i); |
1164 | vdec_response_fs_release(inst, id: i, tag: vpu_buf->tag); |
1165 | vdec_recycle_buffer(inst, vbuf); |
1166 | vdec->slots[i]->state = VPU_BUF_STATE_IDLE; |
1167 | vdec->slots[i] = NULL; |
1168 | } |
1169 | } |
1170 | |
1171 | static void vdec_event_seq_hdr(struct vpu_inst *inst, struct vpu_dec_codec_info *hdr) |
1172 | { |
1173 | struct vdec_t *vdec = inst->priv; |
1174 | |
1175 | vpu_inst_lock(inst); |
1176 | memcpy(&vdec->codec_info, hdr, sizeof(vdec->codec_info)); |
1177 | |
1178 | vpu_trace(inst->dev, "[%d] %d x %d, crop : (%d, %d) %d x %d, %d, %d\n" , |
1179 | inst->id, |
1180 | vdec->codec_info.decoded_width, |
1181 | vdec->codec_info.decoded_height, |
1182 | vdec->codec_info.offset_x, |
1183 | vdec->codec_info.offset_y, |
1184 | vdec->codec_info.width, |
1185 | vdec->codec_info.height, |
1186 | hdr->num_ref_frms, |
1187 | hdr->num_dpb_frms); |
1188 | inst->min_buffer_cap = hdr->num_ref_frms + hdr->num_dpb_frms; |
1189 | vdec->is_source_changed = vdec_check_source_change(inst); |
1190 | vdec_init_fmt(inst); |
1191 | vdec_init_crop(inst); |
1192 | vdec_init_mbi(inst); |
1193 | vdec_init_dcp(inst); |
1194 | if (!vdec->seq_hdr_found) { |
1195 | vdec->seq_tag = vdec->codec_info.tag; |
1196 | if (vdec->is_source_changed) { |
1197 | vdec_update_state(inst, state: VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE, force: 0); |
1198 | vdec->source_change++; |
1199 | vdec_handle_resolution_change(inst); |
1200 | vdec->is_source_changed = false; |
1201 | } |
1202 | } |
1203 | if (vdec->seq_tag != vdec->codec_info.tag) { |
1204 | vdec_response_fs_request(inst, force: true); |
1205 | vpu_trace(inst->dev, "[%d] seq tag change: %d -> %d\n" , |
1206 | inst->id, vdec->seq_tag, vdec->codec_info.tag); |
1207 | } |
1208 | vdec->seq_hdr_found++; |
1209 | vdec->fixed_fmt = true; |
1210 | vpu_inst_unlock(inst); |
1211 | } |
1212 | |
1213 | static void vdec_event_resolution_change(struct vpu_inst *inst) |
1214 | { |
1215 | struct vdec_t *vdec = inst->priv; |
1216 | |
1217 | vpu_trace(inst->dev, "[%d]\n" , inst->id); |
1218 | vpu_inst_lock(inst); |
1219 | vdec->seq_tag = vdec->codec_info.tag; |
1220 | vdec_clear_fs(fs: &vdec->mbi); |
1221 | vdec_clear_fs(fs: &vdec->dcp); |
1222 | vdec_clear_slots(inst); |
1223 | vdec_init_mbi(inst); |
1224 | vdec_init_dcp(inst); |
1225 | if (vdec->is_source_changed) { |
1226 | vdec_update_state(inst, state: VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE, force: 0); |
1227 | vdec->source_change++; |
1228 | vdec_handle_resolution_change(inst); |
1229 | vdec->is_source_changed = false; |
1230 | } |
1231 | vpu_inst_unlock(inst); |
1232 | } |
1233 | |
1234 | static void vdec_event_req_fs(struct vpu_inst *inst, struct vpu_fs_info *fs) |
1235 | { |
1236 | struct vdec_t *vdec = inst->priv; |
1237 | |
1238 | if (!fs) |
1239 | return; |
1240 | |
1241 | vpu_inst_lock(inst); |
1242 | |
1243 | switch (fs->type) { |
1244 | case MEM_RES_FRAME: |
1245 | vdec->req_frame_count++; |
1246 | break; |
1247 | case MEM_RES_MBI: |
1248 | vdec_request_one_fs(fs: &vdec->mbi); |
1249 | break; |
1250 | case MEM_RES_DCP: |
1251 | vdec_request_one_fs(fs: &vdec->dcp); |
1252 | break; |
1253 | default: |
1254 | break; |
1255 | } |
1256 | |
1257 | vdec_alloc_fs(inst, fs: &vdec->mbi); |
1258 | vdec_alloc_fs(inst, fs: &vdec->dcp); |
1259 | |
1260 | vdec_response_fs_request(inst, force: false); |
1261 | |
1262 | vpu_inst_unlock(inst); |
1263 | } |
1264 | |
1265 | static void vdec_evnet_rel_fs(struct vpu_inst *inst, struct vpu_fs_info *fs) |
1266 | { |
1267 | struct vdec_t *vdec = inst->priv; |
1268 | struct vpu_vb2_buffer *vpu_buf; |
1269 | struct vb2_v4l2_buffer *vbuf; |
1270 | |
1271 | if (!fs || fs->id >= ARRAY_SIZE(vdec->slots)) |
1272 | return; |
1273 | if (fs->type != MEM_RES_FRAME) |
1274 | return; |
1275 | |
1276 | if (fs->id >= vpu_get_num_buffers(inst, type: inst->cap_format.type)) { |
1277 | dev_err(inst->dev, "[%d] invalid fs(%d) to release\n" , inst->id, fs->id); |
1278 | return; |
1279 | } |
1280 | |
1281 | vpu_inst_lock(inst); |
1282 | vpu_buf = vdec->slots[fs->id]; |
1283 | vdec->slots[fs->id] = NULL; |
1284 | |
1285 | if (!vpu_buf) { |
1286 | dev_dbg(inst->dev, "[%d] fs[%d] has bee released\n" , inst->id, fs->id); |
1287 | goto exit; |
1288 | } |
1289 | |
1290 | vbuf = &vpu_buf->m2m_buf.vb; |
1291 | if (vpu_get_buffer_state(vbuf) == VPU_BUF_STATE_DECODED) { |
1292 | dev_dbg(inst->dev, "[%d] frame skip\n" , inst->id); |
1293 | vdec->sequence++; |
1294 | } |
1295 | |
1296 | vdec_response_fs_release(inst, id: fs->id, tag: vpu_buf->tag); |
1297 | if (vpu_get_buffer_state(vbuf) != VPU_BUF_STATE_READY) |
1298 | vdec_recycle_buffer(inst, vbuf); |
1299 | |
1300 | vpu_set_buffer_state(vbuf, state: VPU_BUF_STATE_IDLE); |
1301 | vpu_process_capture_buffer(inst); |
1302 | |
1303 | exit: |
1304 | vpu_inst_unlock(inst); |
1305 | } |
1306 | |
1307 | static void vdec_event_eos(struct vpu_inst *inst) |
1308 | { |
1309 | struct vdec_t *vdec = inst->priv; |
1310 | |
1311 | vpu_trace(inst->dev, "[%d] input : %d, decoded : %d, display : %d, sequence : %d\n" , |
1312 | inst->id, |
1313 | vdec->params.frame_count, |
1314 | vdec->decoded_frame_count, |
1315 | vdec->display_frame_count, |
1316 | vdec->sequence); |
1317 | vpu_inst_lock(inst); |
1318 | vdec->eos_received++; |
1319 | vdec->fixed_fmt = false; |
1320 | inst->min_buffer_cap = VDEC_MIN_BUFFER_CAP; |
1321 | vdec_set_last_buffer_dequeued(inst); |
1322 | vpu_inst_unlock(inst); |
1323 | } |
1324 | |
1325 | static void vdec_event_notify(struct vpu_inst *inst, u32 event, void *data) |
1326 | { |
1327 | switch (event) { |
1328 | case VPU_MSG_ID_SEQ_HDR_FOUND: |
1329 | vdec_event_seq_hdr(inst, hdr: data); |
1330 | break; |
1331 | case VPU_MSG_ID_RES_CHANGE: |
1332 | vdec_event_resolution_change(inst); |
1333 | break; |
1334 | case VPU_MSG_ID_FRAME_REQ: |
1335 | vdec_event_req_fs(inst, fs: data); |
1336 | break; |
1337 | case VPU_MSG_ID_FRAME_RELEASE: |
1338 | vdec_evnet_rel_fs(inst, fs: data); |
1339 | break; |
1340 | case VPU_MSG_ID_PIC_EOS: |
1341 | vdec_event_eos(inst); |
1342 | break; |
1343 | default: |
1344 | break; |
1345 | } |
1346 | } |
1347 | |
1348 | static int vdec_process_output(struct vpu_inst *inst, struct vb2_buffer *vb) |
1349 | { |
1350 | struct vdec_t *vdec = inst->priv; |
1351 | struct vb2_v4l2_buffer *vbuf; |
1352 | struct vpu_rpc_buffer_desc desc; |
1353 | u32 free_space; |
1354 | int ret; |
1355 | |
1356 | vbuf = to_vb2_v4l2_buffer(vb); |
1357 | dev_dbg(inst->dev, "[%d] dec output [%d] %d : %ld\n" , |
1358 | inst->id, vbuf->sequence, vb->index, vb2_get_plane_payload(vb, 0)); |
1359 | |
1360 | if (inst->state == VPU_CODEC_STATE_DEINIT) |
1361 | return -EINVAL; |
1362 | if (vdec->reset_codec) |
1363 | return -EINVAL; |
1364 | |
1365 | if (inst->state == VPU_CODEC_STATE_STARTED) |
1366 | vdec_update_state(inst, state: VPU_CODEC_STATE_ACTIVE, force: 0); |
1367 | |
1368 | ret = vpu_iface_get_stream_buffer_desc(inst, desc: &desc); |
1369 | if (ret) |
1370 | return ret; |
1371 | |
1372 | free_space = vpu_helper_get_free_space(inst); |
1373 | if (free_space < vb2_get_plane_payload(vb, plane_no: 0) + 0x40000) |
1374 | return -ENOMEM; |
1375 | |
1376 | vpu_set_buffer_state(vbuf, state: VPU_BUF_STATE_INUSE); |
1377 | ret = vpu_iface_input_frame(inst, vb); |
1378 | if (ret < 0) |
1379 | return -ENOMEM; |
1380 | |
1381 | dev_dbg(inst->dev, "[%d][INPUT TS]%32lld\n" , inst->id, vb->timestamp); |
1382 | vdec->params.frame_count++; |
1383 | |
1384 | if (vdec->drain) |
1385 | vdec_drain(inst); |
1386 | |
1387 | return 0; |
1388 | } |
1389 | |
1390 | static int vdec_process_capture(struct vpu_inst *inst, struct vb2_buffer *vb) |
1391 | { |
1392 | struct vdec_t *vdec = inst->priv; |
1393 | struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); |
1394 | int ret; |
1395 | |
1396 | if (inst->state == VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE) |
1397 | return -EINVAL; |
1398 | if (vdec->reset_codec) |
1399 | return -EINVAL; |
1400 | |
1401 | ret = vdec_response_frame(inst, vbuf); |
1402 | if (ret) |
1403 | return ret; |
1404 | v4l2_m2m_dst_buf_remove_by_buf(m2m_ctx: inst->fh.m2m_ctx, vbuf); |
1405 | return 0; |
1406 | } |
1407 | |
1408 | static void vdec_on_queue_empty(struct vpu_inst *inst, u32 type) |
1409 | { |
1410 | struct vdec_t *vdec = inst->priv; |
1411 | |
1412 | if (V4L2_TYPE_IS_OUTPUT(type)) |
1413 | return; |
1414 | |
1415 | vdec_handle_resolution_change(inst); |
1416 | if (vdec->eos_received) |
1417 | vdec_set_last_buffer_dequeued(inst); |
1418 | } |
1419 | |
1420 | static void vdec_abort(struct vpu_inst *inst) |
1421 | { |
1422 | struct vdec_t *vdec = inst->priv; |
1423 | struct vpu_rpc_buffer_desc desc; |
1424 | int ret; |
1425 | |
1426 | vpu_trace(inst->dev, "[%d] state = %s\n" , inst->id, vpu_codec_state_name(inst->state)); |
1427 | |
1428 | vdec->aborting = true; |
1429 | vpu_iface_add_scode(inst, scode_type: SCODE_PADDING_ABORT); |
1430 | vdec->params.end_flag = 1; |
1431 | vpu_iface_set_decode_params(inst, params: &vdec->params, update: 1); |
1432 | |
1433 | vpu_session_abort(inst); |
1434 | |
1435 | ret = vpu_iface_get_stream_buffer_desc(inst, desc: &desc); |
1436 | if (!ret) |
1437 | vpu_iface_update_stream_buffer(inst, ptr: desc.rptr, write: 1); |
1438 | |
1439 | vpu_session_rst_buf(inst); |
1440 | vpu_trace(inst->dev, "[%d] input : %d, decoded : %d, display : %d, sequence : %d\n" , |
1441 | inst->id, |
1442 | vdec->params.frame_count, |
1443 | vdec->decoded_frame_count, |
1444 | vdec->display_frame_count, |
1445 | vdec->sequence); |
1446 | if (!vdec->seq_hdr_found) |
1447 | vdec->reset_codec = true; |
1448 | vdec->params.end_flag = 0; |
1449 | vdec->drain = 0; |
1450 | vdec->params.frame_count = 0; |
1451 | vdec->decoded_frame_count = 0; |
1452 | vdec->display_frame_count = 0; |
1453 | vdec->sequence = 0; |
1454 | vdec->aborting = false; |
1455 | inst->extra_size = 0; |
1456 | } |
1457 | |
1458 | static void vdec_stop(struct vpu_inst *inst, bool free) |
1459 | { |
1460 | struct vdec_t *vdec = inst->priv; |
1461 | |
1462 | vdec_clear_slots(inst); |
1463 | if (inst->state != VPU_CODEC_STATE_DEINIT) |
1464 | vpu_session_stop(inst); |
1465 | vdec_clear_fs(fs: &vdec->mbi); |
1466 | vdec_clear_fs(fs: &vdec->dcp); |
1467 | if (free) { |
1468 | vpu_free_dma(buf: &vdec->udata); |
1469 | vpu_free_dma(buf: &inst->stream_buffer); |
1470 | } |
1471 | vdec_update_state(inst, state: VPU_CODEC_STATE_DEINIT, force: 1); |
1472 | vdec->reset_codec = false; |
1473 | } |
1474 | |
1475 | static void vdec_release(struct vpu_inst *inst) |
1476 | { |
1477 | if (inst->id != VPU_INST_NULL_ID) |
1478 | vpu_trace(inst->dev, "[%d]\n" , inst->id); |
1479 | vdec_stop(inst, free: true); |
1480 | } |
1481 | |
1482 | static void vdec_cleanup(struct vpu_inst *inst) |
1483 | { |
1484 | struct vdec_t *vdec; |
1485 | |
1486 | if (!inst) |
1487 | return; |
1488 | |
1489 | vdec = inst->priv; |
1490 | vfree(addr: vdec); |
1491 | inst->priv = NULL; |
1492 | vfree(addr: inst); |
1493 | } |
1494 | |
1495 | static void vdec_init_params(struct vdec_t *vdec) |
1496 | { |
1497 | vdec->params.frame_count = 0; |
1498 | vdec->params.end_flag = 0; |
1499 | } |
1500 | |
1501 | static int vdec_start(struct vpu_inst *inst) |
1502 | { |
1503 | struct vdec_t *vdec = inst->priv; |
1504 | int stream_buffer_size; |
1505 | int ret; |
1506 | |
1507 | if (inst->state != VPU_CODEC_STATE_DEINIT) |
1508 | return 0; |
1509 | |
1510 | vpu_trace(inst->dev, "[%d]\n" , inst->id); |
1511 | if (!vdec->udata.virt) { |
1512 | vdec->udata.length = 0x1000; |
1513 | ret = vpu_alloc_dma(core: inst->core, buf: &vdec->udata); |
1514 | if (ret) { |
1515 | dev_err(inst->dev, "[%d] alloc udata fail\n" , inst->id); |
1516 | goto error; |
1517 | } |
1518 | } |
1519 | |
1520 | if (!inst->stream_buffer.virt) { |
1521 | stream_buffer_size = vpu_iface_get_stream_buffer_size(core: inst->core); |
1522 | if (stream_buffer_size > 0) { |
1523 | inst->stream_buffer.length = stream_buffer_size; |
1524 | ret = vpu_alloc_dma(core: inst->core, buf: &inst->stream_buffer); |
1525 | if (ret) { |
1526 | dev_err(inst->dev, "[%d] alloc stream buffer fail\n" , inst->id); |
1527 | goto error; |
1528 | } |
1529 | inst->use_stream_buffer = true; |
1530 | } |
1531 | } |
1532 | |
1533 | if (inst->use_stream_buffer) |
1534 | vpu_iface_config_stream_buffer(inst, buf: &inst->stream_buffer); |
1535 | vpu_iface_init_instance(inst); |
1536 | vdec->params.udata.base = vdec->udata.phys; |
1537 | vdec->params.udata.size = vdec->udata.length; |
1538 | ret = vpu_iface_set_decode_params(inst, params: &vdec->params, update: 0); |
1539 | if (ret) { |
1540 | dev_err(inst->dev, "[%d] set decode params fail\n" , inst->id); |
1541 | goto error; |
1542 | } |
1543 | |
1544 | vdec_init_params(vdec); |
1545 | ret = vpu_session_start(inst); |
1546 | if (ret) { |
1547 | dev_err(inst->dev, "[%d] start fail\n" , inst->id); |
1548 | goto error; |
1549 | } |
1550 | |
1551 | vdec_update_state(inst, state: VPU_CODEC_STATE_STARTED, force: 0); |
1552 | |
1553 | return 0; |
1554 | error: |
1555 | vpu_free_dma(buf: &vdec->udata); |
1556 | vpu_free_dma(buf: &inst->stream_buffer); |
1557 | return ret; |
1558 | } |
1559 | |
1560 | static int vdec_start_session(struct vpu_inst *inst, u32 type) |
1561 | { |
1562 | struct vdec_t *vdec = inst->priv; |
1563 | int ret = 0; |
1564 | |
1565 | if (V4L2_TYPE_IS_OUTPUT(type)) { |
1566 | if (vdec->reset_codec) |
1567 | vdec_stop(inst, free: false); |
1568 | if (inst->state == VPU_CODEC_STATE_DEINIT) { |
1569 | ret = vdec_start(inst); |
1570 | if (ret) |
1571 | return ret; |
1572 | } |
1573 | } |
1574 | |
1575 | if (V4L2_TYPE_IS_OUTPUT(type)) { |
1576 | vdec_update_state(inst, state: vdec->state, force: 1); |
1577 | vdec->eos_received = 0; |
1578 | vpu_process_output_buffer(inst); |
1579 | } else { |
1580 | vdec_cmd_start(inst); |
1581 | } |
1582 | if (inst->state == VPU_CODEC_STATE_ACTIVE) |
1583 | vdec_response_fs_request(inst, force: false); |
1584 | |
1585 | return ret; |
1586 | } |
1587 | |
1588 | static int vdec_stop_session(struct vpu_inst *inst, u32 type) |
1589 | { |
1590 | struct vdec_t *vdec = inst->priv; |
1591 | |
1592 | if (inst->state == VPU_CODEC_STATE_DEINIT) |
1593 | return 0; |
1594 | |
1595 | if (V4L2_TYPE_IS_OUTPUT(type)) { |
1596 | vdec_update_state(inst, state: VPU_CODEC_STATE_SEEK, force: 0); |
1597 | vdec->drain = 0; |
1598 | vdec_abort(inst); |
1599 | } else { |
1600 | if (inst->state != VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE) { |
1601 | if (vb2_is_streaming(q: v4l2_m2m_get_src_vq(m2m_ctx: inst->fh.m2m_ctx))) |
1602 | vdec_abort(inst); |
1603 | vdec->eos_received = 0; |
1604 | } |
1605 | vdec_clear_slots(inst); |
1606 | } |
1607 | |
1608 | return 0; |
1609 | } |
1610 | |
1611 | static int vdec_get_debug_info(struct vpu_inst *inst, char *str, u32 size, u32 i) |
1612 | { |
1613 | struct vdec_t *vdec = inst->priv; |
1614 | int num = -1; |
1615 | |
1616 | switch (i) { |
1617 | case 0: |
1618 | num = scnprintf(buf: str, size, |
1619 | fmt: "req_frame_count = %d\ninterlaced = %d\n" , |
1620 | vdec->req_frame_count, |
1621 | vdec->codec_info.progressive ? 0 : 1); |
1622 | break; |
1623 | case 1: |
1624 | num = scnprintf(buf: str, size, |
1625 | fmt: "mbi: size = 0x%x request = %d, alloc = %d, response = %d\n" , |
1626 | vdec->mbi.size, |
1627 | vdec->mbi.req_count, |
1628 | vdec->mbi.count, |
1629 | vdec->mbi.index); |
1630 | break; |
1631 | case 2: |
1632 | num = scnprintf(buf: str, size, |
1633 | fmt: "dcp: size = 0x%x request = %d, alloc = %d, response = %d\n" , |
1634 | vdec->dcp.size, |
1635 | vdec->dcp.req_count, |
1636 | vdec->dcp.count, |
1637 | vdec->dcp.index); |
1638 | break; |
1639 | case 3: |
1640 | num = scnprintf(buf: str, size, fmt: "input_frame_count = %d\n" , vdec->params.frame_count); |
1641 | break; |
1642 | case 4: |
1643 | num = scnprintf(buf: str, size, fmt: "decoded_frame_count = %d\n" , vdec->decoded_frame_count); |
1644 | break; |
1645 | case 5: |
1646 | num = scnprintf(buf: str, size, fmt: "display_frame_count = %d\n" , vdec->display_frame_count); |
1647 | break; |
1648 | case 6: |
1649 | num = scnprintf(buf: str, size, fmt: "sequence = %d\n" , vdec->sequence); |
1650 | break; |
1651 | case 7: |
1652 | num = scnprintf(buf: str, size, fmt: "drain = %d, eos = %d, source_change = %d\n" , |
1653 | vdec->drain, vdec->eos_received, vdec->source_change); |
1654 | break; |
1655 | case 8: |
1656 | num = scnprintf(buf: str, size, fmt: "fps = %d/%d\n" , |
1657 | vdec->codec_info.frame_rate.numerator, |
1658 | vdec->codec_info.frame_rate.denominator); |
1659 | break; |
1660 | case 9: |
1661 | num = scnprintf(buf: str, size, fmt: "colorspace: %d, %d, %d, %d (%d)\n" , |
1662 | vdec->codec_info.color_primaries, |
1663 | vdec->codec_info.transfer_chars, |
1664 | vdec->codec_info.matrix_coeffs, |
1665 | vdec->codec_info.full_range, |
1666 | vdec->codec_info.vui_present); |
1667 | break; |
1668 | default: |
1669 | break; |
1670 | } |
1671 | |
1672 | return num; |
1673 | } |
1674 | |
1675 | static struct vpu_inst_ops vdec_inst_ops = { |
1676 | .ctrl_init = vdec_ctrl_init, |
1677 | .check_ready = vdec_check_ready, |
1678 | .buf_done = vdec_buf_done, |
1679 | .get_one_frame = vdec_frame_decoded, |
1680 | .stop_done = vdec_stop_done, |
1681 | .event_notify = vdec_event_notify, |
1682 | .release = vdec_release, |
1683 | .cleanup = vdec_cleanup, |
1684 | .start = vdec_start_session, |
1685 | .stop = vdec_stop_session, |
1686 | .process_output = vdec_process_output, |
1687 | .process_capture = vdec_process_capture, |
1688 | .on_queue_empty = vdec_on_queue_empty, |
1689 | .get_debug_info = vdec_get_debug_info, |
1690 | .wait_prepare = vpu_inst_unlock, |
1691 | .wait_finish = vpu_inst_lock, |
1692 | }; |
1693 | |
1694 | static void vdec_init(struct file *file) |
1695 | { |
1696 | struct vpu_inst *inst = to_inst(filp: file); |
1697 | struct v4l2_format f; |
1698 | |
1699 | memset(&f, 0, sizeof(f)); |
1700 | f.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
1701 | f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264; |
1702 | f.fmt.pix_mp.width = 1280; |
1703 | f.fmt.pix_mp.height = 720; |
1704 | f.fmt.pix_mp.field = V4L2_FIELD_NONE; |
1705 | vdec_s_fmt(file, fh: &inst->fh, f: &f); |
1706 | |
1707 | memset(&f, 0, sizeof(f)); |
1708 | f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
1709 | f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M_8L128; |
1710 | f.fmt.pix_mp.width = 1280; |
1711 | f.fmt.pix_mp.height = 720; |
1712 | f.fmt.pix_mp.field = V4L2_FIELD_NONE; |
1713 | vdec_s_fmt(file, fh: &inst->fh, f: &f); |
1714 | } |
1715 | |
1716 | static int vdec_open(struct file *file) |
1717 | { |
1718 | struct vpu_inst *inst; |
1719 | struct vdec_t *vdec; |
1720 | int ret; |
1721 | |
1722 | inst = vzalloc(size: sizeof(*inst)); |
1723 | if (!inst) |
1724 | return -ENOMEM; |
1725 | |
1726 | vdec = vzalloc(size: sizeof(*vdec)); |
1727 | if (!vdec) { |
1728 | vfree(addr: inst); |
1729 | return -ENOMEM; |
1730 | } |
1731 | |
1732 | inst->ops = &vdec_inst_ops; |
1733 | inst->formats = vdec_formats; |
1734 | inst->type = VPU_CORE_TYPE_DEC; |
1735 | inst->priv = vdec; |
1736 | |
1737 | ret = vpu_v4l2_open(file, inst); |
1738 | if (ret) |
1739 | return ret; |
1740 | |
1741 | vdec->fixed_fmt = false; |
1742 | vdec->state = VPU_CODEC_STATE_ACTIVE; |
1743 | inst->min_buffer_cap = VDEC_MIN_BUFFER_CAP; |
1744 | inst->min_buffer_out = VDEC_MIN_BUFFER_OUT; |
1745 | vdec_init(file); |
1746 | |
1747 | return 0; |
1748 | } |
1749 | |
1750 | static const struct v4l2_file_operations vdec_fops = { |
1751 | .owner = THIS_MODULE, |
1752 | .open = vdec_open, |
1753 | .release = vpu_v4l2_close, |
1754 | .unlocked_ioctl = video_ioctl2, |
1755 | .poll = v4l2_m2m_fop_poll, |
1756 | .mmap = v4l2_m2m_fop_mmap, |
1757 | }; |
1758 | |
1759 | const struct v4l2_ioctl_ops *vdec_get_ioctl_ops(void) |
1760 | { |
1761 | return &vdec_ioctl_ops; |
1762 | } |
1763 | |
1764 | const struct v4l2_file_operations *vdec_get_fops(void) |
1765 | { |
1766 | return &vdec_fops; |
1767 | } |
1768 | |