forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 6778948f9de86c3cfaf36725a7c87dcff9ba247f
kernel/drivers/media/platform/qcom/venus/vdec.c
....@@ -1,16 +1,7 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
34 * Copyright (C) 2017 Linaro Ltd.
4
- *
5
- * This program is free software; you can redistribute it and/or modify
6
- * it under the terms of the GNU General Public License version 2 and
7
- * only version 2 as published by the Free Software Foundation.
8
- *
9
- * This program is distributed in the hope that it will be useful,
10
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- * GNU General Public License for more details.
13
- *
145 */
156 #include <linux/clk.h>
167 #include <linux/module.h>
....@@ -29,6 +20,7 @@
2920 #include "core.h"
3021 #include "helpers.h"
3122 #include "vdec.h"
23
+#include "pm_helpers.h"
3224
3325 /*
3426 * Three resons to keep MPLANE formats (despite that the number of planes
....@@ -46,42 +38,52 @@
4638 .pixfmt = V4L2_PIX_FMT_MPEG4,
4739 .num_planes = 1,
4840 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
41
+ .flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
4942 }, {
5043 .pixfmt = V4L2_PIX_FMT_MPEG2,
5144 .num_planes = 1,
5245 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
46
+ .flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
5347 }, {
5448 .pixfmt = V4L2_PIX_FMT_H263,
5549 .num_planes = 1,
5650 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
51
+ .flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
5752 }, {
5853 .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_G,
5954 .num_planes = 1,
6055 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
56
+ .flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
6157 }, {
6258 .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_L,
6359 .num_planes = 1,
6460 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
61
+ .flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
6562 }, {
6663 .pixfmt = V4L2_PIX_FMT_H264,
6764 .num_planes = 1,
6865 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
66
+ .flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
6967 }, {
7068 .pixfmt = V4L2_PIX_FMT_VP8,
7169 .num_planes = 1,
7270 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
71
+ .flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
7372 }, {
7473 .pixfmt = V4L2_PIX_FMT_VP9,
7574 .num_planes = 1,
7675 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
76
+ .flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
7777 }, {
7878 .pixfmt = V4L2_PIX_FMT_XVID,
7979 .num_planes = 1,
8080 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
81
+ .flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
8182 }, {
8283 .pixfmt = V4L2_PIX_FMT_HEVC,
8384 .num_planes = 1,
8485 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
86
+ .flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
8587 },
8688 };
8789
....@@ -142,6 +144,7 @@
142144 struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
143145 struct v4l2_plane_pix_format *pfmt = pixmp->plane_fmt;
144146 const struct venus_format *fmt;
147
+ u32 szimage;
145148
146149 memset(pfmt[0].reserved, 0, sizeof(pfmt[0].reserved));
147150 memset(pixmp->reserved, 0, sizeof(pixmp->reserved));
....@@ -155,6 +158,8 @@
155158 else
156159 return NULL;
157160 fmt = find_format(inst, pixmp->pixelformat, f->type);
161
+ if (!fmt)
162
+ return NULL;
158163 }
159164
160165 pixmp->width = clamp(pixmp->width, frame_width_min(inst),
....@@ -170,14 +175,17 @@
170175 pixmp->num_planes = fmt->num_planes;
171176 pixmp->flags = 0;
172177
173
- pfmt[0].sizeimage = venus_helper_get_framesz(pixmp->pixelformat,
174
- pixmp->width,
175
- pixmp->height);
178
+ szimage = venus_helper_get_framesz(pixmp->pixelformat, pixmp->width,
179
+ pixmp->height);
176180
177
- if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
181
+ if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
182
+ pfmt[0].sizeimage = szimage;
178183 pfmt[0].bytesperline = ALIGN(pixmp->width, 128);
179
- else
184
+ } else {
185
+ pfmt[0].sizeimage = clamp_t(u32, pfmt[0].sizeimage, 0, SZ_8M);
186
+ pfmt[0].sizeimage = max(pfmt[0].sizeimage, szimage);
180187 pfmt[0].bytesperline = 0;
188
+ }
181189
182190 return fmt;
183191 }
....@@ -191,33 +199,56 @@
191199 return 0;
192200 }
193201
202
+static int vdec_check_src_change(struct venus_inst *inst)
203
+{
204
+ int ret;
205
+
206
+ if (inst->subscriptions & V4L2_EVENT_SOURCE_CHANGE &&
207
+ inst->codec_state == VENUS_DEC_STATE_INIT &&
208
+ !inst->reconfig)
209
+ return -EINVAL;
210
+
211
+ if (inst->subscriptions & V4L2_EVENT_SOURCE_CHANGE)
212
+ return 0;
213
+
214
+ /*
215
+ * The code snippet below is a workaround for backward compatibility
216
+ * with applications which doesn't support V4L2 events. It will be
217
+ * dropped in future once those applications are fixed.
218
+ */
219
+
220
+ if (inst->codec_state != VENUS_DEC_STATE_INIT)
221
+ goto done;
222
+
223
+ ret = wait_event_timeout(inst->reconf_wait, inst->reconfig,
224
+ msecs_to_jiffies(100));
225
+ if (!ret)
226
+ return -EINVAL;
227
+
228
+ if (!(inst->codec_state == VENUS_DEC_STATE_CAPTURE_SETUP) ||
229
+ !inst->reconfig)
230
+ dev_dbg(inst->core->dev, VDBGH "wrong state\n");
231
+
232
+done:
233
+ return 0;
234
+}
235
+
194236 static int vdec_g_fmt(struct file *file, void *fh, struct v4l2_format *f)
195237 {
196238 struct venus_inst *inst = to_inst(file);
197239 const struct venus_format *fmt = NULL;
198240 struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
241
+ int ret;
199242
200243 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
201244 fmt = inst->fmt_cap;
202245 else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
203246 fmt = inst->fmt_out;
204247
205
- if (inst->reconfig) {
206
- struct v4l2_format format = {};
207
-
208
- inst->out_width = inst->reconfig_width;
209
- inst->out_height = inst->reconfig_height;
210
- inst->reconfig = false;
211
-
212
- format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
213
- format.fmt.pix_mp.pixelformat = inst->fmt_cap->pixfmt;
214
- format.fmt.pix_mp.width = inst->out_width;
215
- format.fmt.pix_mp.height = inst->out_height;
216
-
217
- vdec_try_fmt_common(inst, &format);
218
-
219
- inst->width = format.fmt.pix_mp.width;
220
- inst->height = format.fmt.pix_mp.height;
248
+ if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
249
+ ret = vdec_check_src_change(inst);
250
+ if (ret)
251
+ return ret;
221252 }
222253
223254 pixmp->pixelformat = fmt->pixfmt;
....@@ -247,6 +278,14 @@
247278 const struct venus_format *fmt;
248279 struct v4l2_format format;
249280 u32 pixfmt_out = 0, pixfmt_cap = 0;
281
+ struct vb2_queue *q;
282
+
283
+ q = v4l2_m2m_get_vq(inst->m2m_ctx, f->type);
284
+ if (!q)
285
+ return -EINVAL;
286
+
287
+ if (vb2_is_busy(q))
288
+ return -EBUSY;
250289
251290 orig_pixmp = *pixmp;
252291
....@@ -275,6 +314,7 @@
275314 inst->ycbcr_enc = pixmp->ycbcr_enc;
276315 inst->quantization = pixmp->quantization;
277316 inst->xfer_func = pixmp->xfer_func;
317
+ inst->input_buf_size = pixmp->plane_fmt[0].sizeimage;
278318 }
279319
280320 memset(&format, 0, sizeof(format));
....@@ -341,9 +381,9 @@
341381 static int
342382 vdec_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
343383 {
344
- strlcpy(cap->driver, "qcom-venus", sizeof(cap->driver));
345
- strlcpy(cap->card, "Qualcomm Venus video decoder", sizeof(cap->card));
346
- strlcpy(cap->bus_info, "platform:qcom-venus", sizeof(cap->bus_info));
384
+ strscpy(cap->driver, "qcom-venus", sizeof(cap->driver));
385
+ strscpy(cap->card, "Qualcomm Venus video decoder", sizeof(cap->card));
386
+ strscpy(cap->bus_info, "platform:qcom-venus", sizeof(cap->bus_info));
347387
348388 return 0;
349389 }
....@@ -360,6 +400,7 @@
360400 return -EINVAL;
361401
362402 f->pixelformat = fmt->pixfmt;
403
+ f->flags = fmt->flags;
363404
364405 return 0;
365406 }
....@@ -431,31 +472,23 @@
431472 static int vdec_subscribe_event(struct v4l2_fh *fh,
432473 const struct v4l2_event_subscription *sub)
433474 {
475
+ struct venus_inst *inst = container_of(fh, struct venus_inst, fh);
476
+ int ret;
477
+
434478 switch (sub->type) {
435479 case V4L2_EVENT_EOS:
436480 return v4l2_event_subscribe(fh, sub, 2, NULL);
437481 case V4L2_EVENT_SOURCE_CHANGE:
438
- return v4l2_src_change_event_subscribe(fh, sub);
482
+ ret = v4l2_src_change_event_subscribe(fh, sub);
483
+ if (ret)
484
+ return ret;
485
+ inst->subscriptions |= V4L2_EVENT_SOURCE_CHANGE;
486
+ return 0;
439487 case V4L2_EVENT_CTRL:
440488 return v4l2_ctrl_subscribe_event(fh, sub);
441489 default:
442490 return -EINVAL;
443491 }
444
-}
445
-
446
-static int
447
-vdec_try_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd)
448
-{
449
- switch (cmd->cmd) {
450
- case V4L2_DEC_CMD_STOP:
451
- if (cmd->flags & V4L2_DEC_CMD_STOP_TO_BLACK)
452
- return -EINVAL;
453
- break;
454
- default:
455
- return -EINVAL;
456
- }
457
-
458
- return 0;
459492 }
460493
461494 static int
....@@ -465,24 +498,29 @@
465498 struct hfi_frame_data fdata = {0};
466499 int ret;
467500
468
- ret = vdec_try_decoder_cmd(file, fh, cmd);
501
+ ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, cmd);
469502 if (ret)
470503 return ret;
471504
472505 mutex_lock(&inst->lock);
473506
474
- /*
475
- * Implement V4L2_DEC_CMD_STOP by enqueue an empty buffer on decoder
476
- * input to signal EOS.
477
- */
478
- if (!(inst->streamon_out & inst->streamon_cap))
479
- goto unlock;
507
+ if (cmd->cmd == V4L2_DEC_CMD_STOP) {
508
+ /*
509
+ * Implement V4L2_DEC_CMD_STOP by enqueue an empty buffer on
510
+ * decoder input to signal EOS.
511
+ */
512
+ if (!(inst->streamon_out && inst->streamon_cap))
513
+ goto unlock;
480514
481
- fdata.buffer_type = HFI_BUFFER_INPUT;
482
- fdata.flags |= HFI_BUFFERFLAG_EOS;
483
- fdata.device_addr = 0xdeadbeef;
515
+ fdata.buffer_type = HFI_BUFFER_INPUT;
516
+ fdata.flags |= HFI_BUFFERFLAG_EOS;
517
+ fdata.device_addr = 0xdeadb000;
484518
485
- ret = hfi_session_process_buf(inst, &fdata);
519
+ ret = hfi_session_process_buf(inst, &fdata);
520
+
521
+ if (!ret && inst->codec_state == VENUS_DEC_STATE_DECODING)
522
+ inst->codec_state = VENUS_DEC_STATE_DRAIN;
523
+ }
486524
487525 unlock:
488526 mutex_unlock(&inst->lock);
....@@ -491,8 +529,8 @@
491529
492530 static const struct v4l2_ioctl_ops vdec_ioctl_ops = {
493531 .vidioc_querycap = vdec_querycap,
494
- .vidioc_enum_fmt_vid_cap_mplane = vdec_enum_fmt,
495
- .vidioc_enum_fmt_vid_out_mplane = vdec_enum_fmt,
532
+ .vidioc_enum_fmt_vid_cap = vdec_enum_fmt,
533
+ .vidioc_enum_fmt_vid_out = vdec_enum_fmt,
496534 .vidioc_s_fmt_vid_cap_mplane = vdec_s_fmt,
497535 .vidioc_s_fmt_vid_out_mplane = vdec_s_fmt,
498536 .vidioc_g_fmt_vid_cap_mplane = vdec_g_fmt,
....@@ -513,9 +551,67 @@
513551 .vidioc_enum_framesizes = vdec_enum_framesizes,
514552 .vidioc_subscribe_event = vdec_subscribe_event,
515553 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
516
- .vidioc_try_decoder_cmd = vdec_try_decoder_cmd,
554
+ .vidioc_try_decoder_cmd = v4l2_m2m_ioctl_try_decoder_cmd,
517555 .vidioc_decoder_cmd = vdec_decoder_cmd,
518556 };
557
+
558
+static int vdec_pm_get(struct venus_inst *inst)
559
+{
560
+ struct venus_core *core = inst->core;
561
+ struct device *dev = core->dev_dec;
562
+ int ret;
563
+
564
+ mutex_lock(&core->pm_lock);
565
+ ret = pm_runtime_get_sync(dev);
566
+ mutex_unlock(&core->pm_lock);
567
+
568
+ return ret < 0 ? ret : 0;
569
+}
570
+
571
+static int vdec_pm_put(struct venus_inst *inst, bool autosuspend)
572
+{
573
+ struct venus_core *core = inst->core;
574
+ struct device *dev = core->dev_dec;
575
+ int ret;
576
+
577
+ mutex_lock(&core->pm_lock);
578
+
579
+ if (autosuspend)
580
+ ret = pm_runtime_put_autosuspend(dev);
581
+ else
582
+ ret = pm_runtime_put_sync(dev);
583
+
584
+ mutex_unlock(&core->pm_lock);
585
+
586
+ return ret < 0 ? ret : 0;
587
+}
588
+
589
+static int vdec_pm_get_put(struct venus_inst *inst)
590
+{
591
+ struct venus_core *core = inst->core;
592
+ struct device *dev = core->dev_dec;
593
+ int ret = 0;
594
+
595
+ mutex_lock(&core->pm_lock);
596
+
597
+ if (pm_runtime_suspended(dev)) {
598
+ ret = pm_runtime_get_sync(dev);
599
+ if (ret < 0)
600
+ goto error;
601
+
602
+ ret = pm_runtime_put_autosuspend(dev);
603
+ }
604
+
605
+error:
606
+ mutex_unlock(&core->pm_lock);
607
+
608
+ return ret < 0 ? ret : 0;
609
+}
610
+
611
+static void vdec_pm_touch(struct venus_inst *inst)
612
+{
613
+ pm_runtime_mark_last_busy(inst->core->dev_dec);
614
+}
519615
520616 static int vdec_set_properties(struct venus_inst *inst)
521617 {
....@@ -548,10 +644,6 @@
548644 int ret;
549645
550646 ret = venus_helper_set_work_mode(inst, VIDC_WORK_MODE_2);
551
- if (ret)
552
- return ret;
553
-
554
- ret = venus_helper_set_core_usage(inst, VIDC_CORE_ID_1);
555647 if (ret)
556648 return ret;
557649
....@@ -643,20 +735,22 @@
643735 return 0;
644736 }
645737
646
-static int vdec_init_session(struct venus_inst *inst)
738
+static int vdec_session_init(struct venus_inst *inst)
647739 {
648740 int ret;
649741
650742 ret = hfi_session_init(inst, inst->fmt_out->pixfmt);
651
- if (ret)
743
+ if (ret == -EINVAL)
744
+ return 0;
745
+ else if (ret)
652746 return ret;
653747
654
- ret = venus_helper_set_input_resolution(inst, inst->out_width,
655
- inst->out_height);
748
+ ret = venus_helper_set_input_resolution(inst, frame_width_min(inst),
749
+ frame_height_min(inst));
656750 if (ret)
657751 goto deinit;
658752
659
- ret = venus_helper_set_color_format(inst, inst->fmt_cap->pixfmt);
753
+ ret = venus_helper_init_codec_freq_data(inst);
660754 if (ret)
661755 goto deinit;
662756
....@@ -675,26 +769,19 @@
675769
676770 *in_num = *out_num = 0;
677771
678
- ret = vdec_init_session(inst);
679
- if (ret)
680
- return ret;
681
-
682772 ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq);
683773 if (ret)
684
- goto deinit;
774
+ return ret;
685775
686776 *in_num = HFI_BUFREQ_COUNT_MIN(&bufreq, ver);
687777
688778 ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT, &bufreq);
689779 if (ret)
690
- goto deinit;
780
+ return ret;
691781
692782 *out_num = HFI_BUFREQ_COUNT_MIN(&bufreq, ver);
693783
694
-deinit:
695
- hfi_session_deinit(inst);
696
-
697
- return ret;
784
+ return 0;
698785 }
699786
700787 static int vdec_queue_setup(struct vb2_queue *q,
....@@ -727,7 +814,19 @@
727814 return 0;
728815 }
729816
817
+ ret = vdec_pm_get(inst);
818
+ if (ret)
819
+ return ret;
820
+
821
+ ret = vdec_session_init(inst);
822
+ if (ret)
823
+ goto put_power;
824
+
730825 ret = vdec_num_buffers(inst, &in_num, &out_num);
826
+ if (ret)
827
+ goto put_power;
828
+
829
+ ret = vdec_pm_put(inst, false);
731830 if (ret)
732831 return ret;
733832
....@@ -737,6 +836,7 @@
737836 sizes[0] = venus_helper_get_framesz(inst->fmt_out->pixfmt,
738837 inst->out_width,
739838 inst->out_height);
839
+ sizes[0] = max(sizes[0], inst->input_buf_size);
740840 inst->input_buf_size = sizes[0];
741841 *num_buffers = max(*num_buffers, in_num);
742842 inst->num_input_bufs = *num_buffers;
....@@ -750,12 +850,21 @@
750850 inst->output_buf_size = sizes[0];
751851 *num_buffers = max(*num_buffers, out_num);
752852 inst->num_output_bufs = *num_buffers;
853
+
854
+ mutex_lock(&inst->lock);
855
+ if (inst->codec_state == VENUS_DEC_STATE_CAPTURE_SETUP)
856
+ inst->codec_state = VENUS_DEC_STATE_STOPPED;
857
+ mutex_unlock(&inst->lock);
753858 break;
754859 default:
755860 ret = -EINVAL;
756861 break;
757862 }
758863
864
+ return ret;
865
+
866
+put_power:
867
+ vdec_pm_put(inst, false);
759868 return ret;
760869 }
761870
....@@ -786,6 +895,131 @@
786895 return 0;
787896 }
788897
898
+static int vdec_start_capture(struct venus_inst *inst)
899
+{
900
+ int ret;
901
+
902
+ if (!inst->streamon_out)
903
+ return 0;
904
+
905
+ if (inst->codec_state == VENUS_DEC_STATE_DECODING) {
906
+ if (inst->reconfig)
907
+ goto reconfigure;
908
+
909
+ venus_helper_queue_dpb_bufs(inst);
910
+ venus_helper_process_initial_cap_bufs(inst);
911
+ inst->streamon_cap = 1;
912
+ return 0;
913
+ }
914
+
915
+ if (inst->codec_state != VENUS_DEC_STATE_STOPPED)
916
+ return 0;
917
+
918
+reconfigure:
919
+ ret = hfi_session_flush(inst, HFI_FLUSH_OUTPUT, true);
920
+ if (ret)
921
+ return ret;
922
+
923
+ ret = vdec_output_conf(inst);
924
+ if (ret)
925
+ return ret;
926
+
927
+ ret = venus_helper_set_num_bufs(inst, inst->num_input_bufs,
928
+ VB2_MAX_FRAME, VB2_MAX_FRAME);
929
+ if (ret)
930
+ return ret;
931
+
932
+ ret = venus_helper_intbufs_realloc(inst);
933
+ if (ret)
934
+ goto err;
935
+
936
+ ret = venus_helper_alloc_dpb_bufs(inst);
937
+ if (ret)
938
+ goto err;
939
+
940
+ ret = venus_helper_queue_dpb_bufs(inst);
941
+ if (ret)
942
+ goto free_dpb_bufs;
943
+
944
+ ret = venus_helper_process_initial_cap_bufs(inst);
945
+ if (ret)
946
+ goto free_dpb_bufs;
947
+
948
+ venus_pm_load_scale(inst);
949
+
950
+ ret = hfi_session_continue(inst);
951
+ if (ret)
952
+ goto free_dpb_bufs;
953
+
954
+ inst->codec_state = VENUS_DEC_STATE_DECODING;
955
+
956
+ inst->streamon_cap = 1;
957
+ inst->sequence_cap = 0;
958
+ inst->reconfig = false;
959
+
960
+ return 0;
961
+
962
+free_dpb_bufs:
963
+ venus_helper_free_dpb_bufs(inst);
964
+err:
965
+ return ret;
966
+}
967
+
968
+static int vdec_start_output(struct venus_inst *inst)
969
+{
970
+ int ret;
971
+
972
+ if (inst->codec_state == VENUS_DEC_STATE_SEEK) {
973
+ ret = venus_helper_process_initial_out_bufs(inst);
974
+ inst->codec_state = VENUS_DEC_STATE_DECODING;
975
+ goto done;
976
+ }
977
+
978
+ if (inst->codec_state == VENUS_DEC_STATE_INIT ||
979
+ inst->codec_state == VENUS_DEC_STATE_CAPTURE_SETUP) {
980
+ ret = venus_helper_process_initial_out_bufs(inst);
981
+ goto done;
982
+ }
983
+
984
+ if (inst->codec_state != VENUS_DEC_STATE_DEINIT)
985
+ return -EINVAL;
986
+
987
+ venus_helper_init_instance(inst);
988
+ inst->sequence_out = 0;
989
+ inst->reconfig = false;
990
+
991
+ ret = vdec_set_properties(inst);
992
+ if (ret)
993
+ return ret;
994
+
995
+ ret = vdec_output_conf(inst);
996
+ if (ret)
997
+ return ret;
998
+
999
+ ret = vdec_verify_conf(inst);
1000
+ if (ret)
1001
+ return ret;
1002
+
1003
+ ret = venus_helper_set_num_bufs(inst, inst->num_input_bufs,
1004
+ VB2_MAX_FRAME, VB2_MAX_FRAME);
1005
+ if (ret)
1006
+ return ret;
1007
+
1008
+ ret = venus_helper_vb2_start_streaming(inst);
1009
+ if (ret)
1010
+ return ret;
1011
+
1012
+ ret = venus_helper_process_initial_out_bufs(inst);
1013
+ if (ret)
1014
+ return ret;
1015
+
1016
+ inst->codec_state = VENUS_DEC_STATE_INIT;
1017
+
1018
+done:
1019
+ inst->streamon_out = 1;
1020
+ return ret;
1021
+}
1022
+
7891023 static int vdec_start_streaming(struct vb2_queue *q, unsigned int count)
7901024 {
7911025 struct venus_inst *inst = vb2_get_drv_priv(q);
....@@ -793,74 +1027,199 @@
7931027
7941028 mutex_lock(&inst->lock);
7951029
796
- if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
797
- inst->streamon_out = 1;
798
- else
799
- inst->streamon_cap = 1;
1030
+ if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
1031
+ ret = vdec_start_capture(inst);
1032
+ } else {
1033
+ ret = vdec_pm_get(inst);
1034
+ if (ret)
1035
+ goto error;
8001036
801
- if (!(inst->streamon_out & inst->streamon_cap)) {
802
- mutex_unlock(&inst->lock);
803
- return 0;
1037
+ ret = venus_pm_acquire_core(inst);
1038
+ if (ret)
1039
+ goto put_power;
1040
+
1041
+ ret = vdec_pm_put(inst, true);
1042
+ if (ret)
1043
+ goto error;
1044
+
1045
+ ret = vdec_start_output(inst);
8041046 }
8051047
806
- venus_helper_init_instance(inst);
807
-
808
- inst->reconfig = false;
809
- inst->sequence_cap = 0;
810
- inst->sequence_out = 0;
811
-
812
- ret = vdec_init_session(inst);
8131048 if (ret)
814
- goto bufs_done;
815
-
816
- ret = vdec_set_properties(inst);
817
- if (ret)
818
- goto deinit_sess;
819
-
820
- ret = vdec_output_conf(inst);
821
- if (ret)
822
- goto deinit_sess;
823
-
824
- ret = vdec_verify_conf(inst);
825
- if (ret)
826
- goto deinit_sess;
827
-
828
- ret = venus_helper_set_num_bufs(inst, inst->num_input_bufs,
829
- VB2_MAX_FRAME, VB2_MAX_FRAME);
830
- if (ret)
831
- goto deinit_sess;
832
-
833
- ret = venus_helper_alloc_dpb_bufs(inst);
834
- if (ret)
835
- goto deinit_sess;
836
-
837
- ret = venus_helper_vb2_start_streaming(inst);
838
- if (ret)
839
- goto deinit_sess;
1049
+ goto error;
8401050
8411051 mutex_unlock(&inst->lock);
842
-
8431052 return 0;
8441053
845
-deinit_sess:
846
- hfi_session_deinit(inst);
847
-bufs_done:
848
- venus_helper_buffers_done(inst, VB2_BUF_STATE_QUEUED);
849
- if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
850
- inst->streamon_out = 0;
851
- else
852
- inst->streamon_cap = 0;
1054
+put_power:
1055
+ vdec_pm_put(inst, false);
1056
+error:
1057
+ venus_helper_buffers_done(inst, q->type, VB2_BUF_STATE_QUEUED);
8531058 mutex_unlock(&inst->lock);
8541059 return ret;
8551060 }
8561061
1062
+static void vdec_cancel_dst_buffers(struct venus_inst *inst)
1063
+{
1064
+ struct vb2_v4l2_buffer *buf;
1065
+
1066
+ while ((buf = v4l2_m2m_dst_buf_remove(inst->m2m_ctx)))
1067
+ v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR);
1068
+}
1069
+
1070
+static int vdec_stop_capture(struct venus_inst *inst)
1071
+{
1072
+ int ret = 0;
1073
+
1074
+ switch (inst->codec_state) {
1075
+ case VENUS_DEC_STATE_DECODING:
1076
+ ret = hfi_session_flush(inst, HFI_FLUSH_ALL, true);
1077
+ fallthrough;
1078
+ case VENUS_DEC_STATE_DRAIN:
1079
+ vdec_cancel_dst_buffers(inst);
1080
+ inst->codec_state = VENUS_DEC_STATE_STOPPED;
1081
+ break;
1082
+ case VENUS_DEC_STATE_DRC:
1083
+ WARN_ON(1);
1084
+ fallthrough;
1085
+ case VENUS_DEC_STATE_DRC_FLUSH_DONE:
1086
+ inst->codec_state = VENUS_DEC_STATE_CAPTURE_SETUP;
1087
+ venus_helper_free_dpb_bufs(inst);
1088
+ break;
1089
+ default:
1090
+ break;
1091
+ }
1092
+
1093
+ return ret;
1094
+}
1095
+
1096
+static int vdec_stop_output(struct venus_inst *inst)
1097
+{
1098
+ int ret = 0;
1099
+
1100
+ switch (inst->codec_state) {
1101
+ case VENUS_DEC_STATE_DECODING:
1102
+ case VENUS_DEC_STATE_DRAIN:
1103
+ case VENUS_DEC_STATE_STOPPED:
1104
+ ret = hfi_session_flush(inst, HFI_FLUSH_ALL, true);
1105
+ inst->codec_state = VENUS_DEC_STATE_SEEK;
1106
+ break;
1107
+ case VENUS_DEC_STATE_INIT:
1108
+ case VENUS_DEC_STATE_CAPTURE_SETUP:
1109
+ ret = hfi_session_flush(inst, HFI_FLUSH_INPUT, true);
1110
+ break;
1111
+ default:
1112
+ break;
1113
+ }
1114
+
1115
+ return ret;
1116
+}
1117
+
1118
+static void vdec_stop_streaming(struct vb2_queue *q)
1119
+{
1120
+ struct venus_inst *inst = vb2_get_drv_priv(q);
1121
+ int ret = -EINVAL;
1122
+
1123
+ mutex_lock(&inst->lock);
1124
+
1125
+ if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1126
+ ret = vdec_stop_capture(inst);
1127
+ else
1128
+ ret = vdec_stop_output(inst);
1129
+
1130
+ venus_helper_buffers_done(inst, q->type, VB2_BUF_STATE_ERROR);
1131
+
1132
+ if (ret)
1133
+ goto unlock;
1134
+
1135
+ if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1136
+ inst->streamon_out = 0;
1137
+ else
1138
+ inst->streamon_cap = 0;
1139
+
1140
+unlock:
1141
+ mutex_unlock(&inst->lock);
1142
+}
1143
+
1144
+static void vdec_session_release(struct venus_inst *inst)
1145
+{
1146
+ struct venus_core *core = inst->core;
1147
+ int ret, abort = 0;
1148
+
1149
+ vdec_pm_get(inst);
1150
+
1151
+ mutex_lock(&inst->lock);
1152
+ inst->codec_state = VENUS_DEC_STATE_DEINIT;
1153
+
1154
+ ret = hfi_session_stop(inst);
1155
+ abort = (ret && ret != -EINVAL) ? 1 : 0;
1156
+ ret = hfi_session_unload_res(inst);
1157
+ abort = (ret && ret != -EINVAL) ? 1 : 0;
1158
+ ret = venus_helper_unregister_bufs(inst);
1159
+ abort = (ret && ret != -EINVAL) ? 1 : 0;
1160
+ ret = venus_helper_intbufs_free(inst);
1161
+ abort = (ret && ret != -EINVAL) ? 1 : 0;
1162
+ ret = hfi_session_deinit(inst);
1163
+ abort = (ret && ret != -EINVAL) ? 1 : 0;
1164
+
1165
+ if (inst->session_error || core->sys_error)
1166
+ abort = 1;
1167
+
1168
+ if (abort)
1169
+ hfi_session_abort(inst);
1170
+
1171
+ venus_helper_free_dpb_bufs(inst);
1172
+ venus_pm_load_scale(inst);
1173
+ INIT_LIST_HEAD(&inst->registeredbufs);
1174
+ mutex_unlock(&inst->lock);
1175
+
1176
+ venus_pm_release_core(inst);
1177
+ vdec_pm_put(inst, false);
1178
+}
1179
+
1180
+static int vdec_buf_init(struct vb2_buffer *vb)
1181
+{
1182
+ struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
1183
+
1184
+ inst->buf_count++;
1185
+
1186
+ return venus_helper_vb2_buf_init(vb);
1187
+}
1188
+
1189
+static void vdec_buf_cleanup(struct vb2_buffer *vb)
1190
+{
1191
+ struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
1192
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1193
+ struct venus_buffer *buf = to_venus_buffer(vbuf);
1194
+
1195
+ mutex_lock(&inst->lock);
1196
+ if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1197
+ if (!list_empty(&inst->registeredbufs))
1198
+ list_del_init(&buf->reg_list);
1199
+ mutex_unlock(&inst->lock);
1200
+
1201
+ inst->buf_count--;
1202
+ if (!inst->buf_count)
1203
+ vdec_session_release(inst);
1204
+}
1205
+
1206
+static void vdec_vb2_buf_queue(struct vb2_buffer *vb)
1207
+{
1208
+ struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
1209
+
1210
+ vdec_pm_get_put(inst);
1211
+
1212
+ venus_helper_vb2_buf_queue(vb);
1213
+}
1214
+
8571215 static const struct vb2_ops vdec_vb2_ops = {
8581216 .queue_setup = vdec_queue_setup,
859
- .buf_init = venus_helper_vb2_buf_init,
1217
+ .buf_init = vdec_buf_init,
1218
+ .buf_cleanup = vdec_buf_cleanup,
8601219 .buf_prepare = venus_helper_vb2_buf_prepare,
8611220 .start_streaming = vdec_start_streaming,
862
- .stop_streaming = venus_helper_vb2_stop_streaming,
863
- .buf_queue = venus_helper_vb2_buf_queue,
1221
+ .stop_streaming = vdec_stop_streaming,
1222
+ .buf_queue = vdec_vb2_buf_queue,
8641223 };
8651224
8661225 static void vdec_buf_done(struct venus_inst *inst, unsigned int buf_type,
....@@ -871,6 +1230,8 @@
8711230 struct vb2_v4l2_buffer *vbuf;
8721231 struct vb2_buffer *vb;
8731232 unsigned int type;
1233
+
1234
+ vdec_pm_touch(inst);
8741235
8751236 if (buf_type == HFI_BUFFER_INPUT)
8761237 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
....@@ -883,24 +1244,37 @@
8831244
8841245 vbuf->flags = flags;
8851246 vbuf->field = V4L2_FIELD_NONE;
1247
+ vb = &vbuf->vb2_buf;
8861248
8871249 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
888
- unsigned int opb_sz = venus_helper_get_opb_size(inst);
889
-
890
- vb = &vbuf->vb2_buf;
891
- vb2_set_plane_payload(vb, 0, bytesused ? : opb_sz);
1250
+ vb2_set_plane_payload(vb, 0, bytesused);
8921251 vb->planes[0].data_offset = data_offset;
8931252 vb->timestamp = timestamp_us * NSEC_PER_USEC;
8941253 vbuf->sequence = inst->sequence_cap++;
1254
+
1255
+ if (inst->last_buf == vb) {
1256
+ inst->last_buf = NULL;
1257
+ vbuf->flags |= V4L2_BUF_FLAG_LAST;
1258
+ vb2_set_plane_payload(vb, 0, 0);
1259
+ vb->timestamp = 0;
1260
+ }
8951261
8961262 if (vbuf->flags & V4L2_BUF_FLAG_LAST) {
8971263 const struct v4l2_event ev = { .type = V4L2_EVENT_EOS };
8981264
8991265 v4l2_event_queue_fh(&inst->fh, &ev);
1266
+
1267
+ if (inst->codec_state == VENUS_DEC_STATE_DRAIN)
1268
+ inst->codec_state = VENUS_DEC_STATE_STOPPED;
9001269 }
1270
+
1271
+ if (!bytesused)
1272
+ state = VB2_BUF_STATE_ERROR;
9011273 } else {
9021274 vbuf->sequence = inst->sequence_out++;
9031275 }
1276
+
1277
+ venus_helper_get_ts_metadata(inst, timestamp_us, vbuf);
9041278
9051279 if (hfi_flags & HFI_BUFFERFLAG_READONLY)
9061280 venus_helper_acquire_buf_ref(vbuf);
....@@ -908,7 +1282,84 @@
9081282 if (hfi_flags & HFI_BUFFERFLAG_DATACORRUPT)
9091283 state = VB2_BUF_STATE_ERROR;
9101284
1285
+ if (hfi_flags & HFI_BUFFERFLAG_DROP_FRAME) {
1286
+ state = VB2_BUF_STATE_ERROR;
1287
+ vb2_set_plane_payload(vb, 0, 0);
1288
+ vb->timestamp = 0;
1289
+ }
1290
+
9111291 v4l2_m2m_buf_done(vbuf, state);
1292
+}
1293
+
1294
+static void vdec_event_change(struct venus_inst *inst,
1295
+ struct hfi_event_data *ev_data, bool sufficient)
1296
+{
1297
+ static const struct v4l2_event ev = {
1298
+ .type = V4L2_EVENT_SOURCE_CHANGE,
1299
+ .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION };
1300
+ struct device *dev = inst->core->dev_dec;
1301
+ struct v4l2_format format = {};
1302
+
1303
+ mutex_lock(&inst->lock);
1304
+
1305
+ format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1306
+ format.fmt.pix_mp.pixelformat = inst->fmt_cap->pixfmt;
1307
+ format.fmt.pix_mp.width = ev_data->width;
1308
+ format.fmt.pix_mp.height = ev_data->height;
1309
+
1310
+ vdec_try_fmt_common(inst, &format);
1311
+
1312
+ inst->width = format.fmt.pix_mp.width;
1313
+ inst->height = format.fmt.pix_mp.height;
1314
+
1315
+ inst->out_width = ev_data->width;
1316
+ inst->out_height = ev_data->height;
1317
+
1318
+ if (inst->bit_depth != ev_data->bit_depth)
1319
+ inst->bit_depth = ev_data->bit_depth;
1320
+
1321
+ dev_dbg(dev, VDBGM "event %s sufficient resources (%ux%u)\n",
1322
+ sufficient ? "" : "not", ev_data->width, ev_data->height);
1323
+
1324
+ if (sufficient) {
1325
+ hfi_session_continue(inst);
1326
+ } else {
1327
+ switch (inst->codec_state) {
1328
+ case VENUS_DEC_STATE_INIT:
1329
+ inst->codec_state = VENUS_DEC_STATE_CAPTURE_SETUP;
1330
+ break;
1331
+ case VENUS_DEC_STATE_DECODING:
1332
+ inst->codec_state = VENUS_DEC_STATE_DRC;
1333
+ break;
1334
+ default:
1335
+ break;
1336
+ }
1337
+ }
1338
+
1339
+ /*
1340
+ * The assumption is that the firmware have to return the last buffer
1341
+ * before this event is received in the v4l2 driver. Also the firmware
1342
+ * itself doesn't mark the last decoder output buffer with HFI EOS flag.
1343
+ */
1344
+
1345
+ if (!sufficient && inst->codec_state == VENUS_DEC_STATE_DRC) {
1346
+ struct vb2_v4l2_buffer *last;
1347
+ int ret;
1348
+
1349
+ last = v4l2_m2m_last_dst_buf(inst->m2m_ctx);
1350
+ if (last)
1351
+ inst->last_buf = &last->vb2_buf;
1352
+
1353
+ ret = hfi_session_flush(inst, HFI_FLUSH_OUTPUT, false);
1354
+ if (ret)
1355
+ dev_dbg(dev, VDBGH "flush output error %d\n", ret);
1356
+ }
1357
+
1358
+ inst->reconfig = true;
1359
+ v4l2_event_queue_fh(&inst->fh, &ev);
1360
+ wake_up(&inst->reconf_wait);
1361
+
1362
+ mutex_unlock(&inst->lock);
9121363 }
9131364
9141365 static void vdec_event_notify(struct venus_inst *inst, u32 event,
....@@ -916,9 +1367,8 @@
9161367 {
9171368 struct venus_core *core = inst->core;
9181369 struct device *dev = core->dev_dec;
919
- static const struct v4l2_event ev = {
920
- .type = V4L2_EVENT_SOURCE_CHANGE,
921
- .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION };
1370
+
1371
+ vdec_pm_touch(inst);
9221372
9231373 switch (event) {
9241374 case EVT_SESSION_ERROR:
....@@ -928,18 +1378,10 @@
9281378 case EVT_SYS_EVENT_CHANGE:
9291379 switch (data->event_type) {
9301380 case HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUF_RESOURCES:
931
- hfi_session_continue(inst);
932
- dev_dbg(dev, "event sufficient resources\n");
1381
+ vdec_event_change(inst, data, true);
9331382 break;
9341383 case HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUF_RESOURCES:
935
- inst->reconfig_height = data->height;
936
- inst->reconfig_width = data->width;
937
- inst->reconfig = true;
938
-
939
- v4l2_event_queue_fh(&inst->fh, &ev);
940
-
941
- dev_dbg(dev, "event not sufficient resources (%ux%u)\n",
942
- data->width, data->height);
1384
+ vdec_event_change(inst, data, false);
9431385 break;
9441386 case HFI_EVENT_RELEASE_BUFFER_REFERENCE:
9451387 venus_helper_release_buf_ref(inst, data->tag);
....@@ -953,27 +1395,39 @@
9531395 }
9541396 }
9551397
1398
+static void vdec_flush_done(struct venus_inst *inst)
1399
+{
1400
+ if (inst->codec_state == VENUS_DEC_STATE_DRC)
1401
+ inst->codec_state = VENUS_DEC_STATE_DRC_FLUSH_DONE;
1402
+}
1403
+
9561404 static const struct hfi_inst_ops vdec_hfi_ops = {
9571405 .buf_done = vdec_buf_done,
9581406 .event_notify = vdec_event_notify,
1407
+ .flush_done = vdec_flush_done,
9591408 };
9601409
9611410 static void vdec_inst_init(struct venus_inst *inst)
9621411 {
1412
+ inst->hfi_codec = HFI_VIDEO_CODEC_H264;
9631413 inst->fmt_out = &vdec_formats[6];
9641414 inst->fmt_cap = &vdec_formats[0];
965
- inst->width = 1280;
966
- inst->height = ALIGN(720, 32);
967
- inst->out_width = 1280;
968
- inst->out_height = 720;
1415
+ inst->width = frame_width_min(inst);
1416
+ inst->height = ALIGN(frame_height_min(inst), 32);
1417
+ inst->out_width = frame_width_min(inst);
1418
+ inst->out_height = frame_height_min(inst);
9691419 inst->fps = 30;
9701420 inst->timeperframe.numerator = 1;
9711421 inst->timeperframe.denominator = 30;
972
- inst->hfi_codec = HFI_VIDEO_CODEC_H264;
1422
+ inst->opb_buftype = HFI_BUFFER_OUTPUT;
1423
+}
1424
+
1425
+static void vdec_m2m_device_run(void *priv)
1426
+{
9731427 }
9741428
9751429 static const struct v4l2_m2m_ops vdec_m2m_ops = {
976
- .device_run = venus_helper_m2m_device_run,
1430
+ .device_run = vdec_m2m_device_run,
9771431 .job_abort = venus_helper_m2m_job_abort,
9781432 };
9791433
....@@ -991,7 +1445,7 @@
9911445 src_vq->drv_priv = inst;
9921446 src_vq->buf_struct_size = sizeof(struct venus_buffer);
9931447 src_vq->allow_zero_bytesused = 1;
994
- src_vq->min_buffers_needed = 1;
1448
+ src_vq->min_buffers_needed = 0;
9951449 src_vq->dev = inst->core->dev;
9961450 ret = vb2_queue_init(src_vq);
9971451 if (ret)
....@@ -1005,15 +1459,9 @@
10051459 dst_vq->drv_priv = inst;
10061460 dst_vq->buf_struct_size = sizeof(struct venus_buffer);
10071461 dst_vq->allow_zero_bytesused = 1;
1008
- dst_vq->min_buffers_needed = 1;
1462
+ dst_vq->min_buffers_needed = 0;
10091463 dst_vq->dev = inst->core->dev;
1010
- ret = vb2_queue_init(dst_vq);
1011
- if (ret) {
1012
- vb2_queue_release(src_vq);
1013
- return ret;
1014
- }
1015
-
1016
- return 0;
1464
+ return vb2_queue_init(dst_vq);
10171465 }
10181466
10191467 static int vdec_open(struct file *file)
....@@ -1035,16 +1483,17 @@
10351483 inst->core = core;
10361484 inst->session_type = VIDC_SESSION_TYPE_DEC;
10371485 inst->num_output_bufs = 1;
1038
-
1486
+ inst->codec_state = VENUS_DEC_STATE_DEINIT;
1487
+ inst->buf_count = 0;
1488
+ inst->clk_data.core_id = VIDC_CORE_ID_DEFAULT;
1489
+ inst->core_acquired = false;
1490
+ inst->bit_depth = VIDC_BITDEPTH_8;
1491
+ init_waitqueue_head(&inst->reconf_wait);
10391492 venus_helper_init_instance(inst);
1040
-
1041
- ret = pm_runtime_get_sync(core->dev_dec);
1042
- if (ret < 0)
1043
- goto err_free_inst;
10441493
10451494 ret = vdec_ctrl_init(inst);
10461495 if (ret)
1047
- goto err_put_sync;
1496
+ goto err_free;
10481497
10491498 ret = hfi_session_create(inst, &vdec_hfi_ops);
10501499 if (ret)
....@@ -1083,9 +1532,7 @@
10831532 hfi_session_destroy(inst);
10841533 err_ctrl_deinit:
10851534 vdec_ctrl_deinit(inst);
1086
-err_put_sync:
1087
- pm_runtime_put_sync(core->dev_dec);
1088
-err_free_inst:
1535
+err_free:
10891536 kfree(inst);
10901537 return ret;
10911538 }
....@@ -1093,6 +1540,8 @@
10931540 static int vdec_close(struct file *file)
10941541 {
10951542 struct venus_inst *inst = to_inst(file);
1543
+
1544
+ vdec_pm_get(inst);
10961545
10971546 v4l2_m2m_ctx_release(inst->m2m_ctx);
10981547 v4l2_m2m_release(inst->m2m_dev);
....@@ -1102,7 +1551,7 @@
11021551 v4l2_fh_del(&inst->fh);
11031552 v4l2_fh_exit(&inst->fh);
11041553
1105
- pm_runtime_put_sync(inst->core->dev_dec);
1554
+ vdec_pm_put(inst, false);
11061555
11071556 kfree(inst);
11081557 return 0;
....@@ -1131,25 +1580,19 @@
11311580 if (!core)
11321581 return -EPROBE_DEFER;
11331582
1134
- if (IS_V3(core) || IS_V4(core)) {
1135
- core->core0_clk = devm_clk_get(dev, "core");
1136
- if (IS_ERR(core->core0_clk))
1137
- return PTR_ERR(core->core0_clk);
1138
- }
1139
-
1140
- if (IS_V4(core)) {
1141
- core->core0_bus_clk = devm_clk_get(dev, "bus");
1142
- if (IS_ERR(core->core0_bus_clk))
1143
- return PTR_ERR(core->core0_bus_clk);
1144
- }
1145
-
11461583 platform_set_drvdata(pdev, core);
1584
+
1585
+ if (core->pm_ops->vdec_get) {
1586
+ ret = core->pm_ops->vdec_get(dev);
1587
+ if (ret)
1588
+ return ret;
1589
+ }
11471590
11481591 vdev = video_device_alloc();
11491592 if (!vdev)
11501593 return -ENOMEM;
11511594
1152
- strlcpy(vdev->name, "qcom-venus-decoder", sizeof(vdev->name));
1595
+ strscpy(vdev->name, "qcom-venus-decoder", sizeof(vdev->name));
11531596 vdev->release = video_device_release;
11541597 vdev->fops = &vdec_fops;
11551598 vdev->ioctl_ops = &vdec_ioctl_ops;
....@@ -1157,7 +1600,7 @@
11571600 vdev->v4l2_dev = &core->v4l2_dev;
11581601 vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
11591602
1160
- ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
1603
+ ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
11611604 if (ret)
11621605 goto err_vdev_release;
11631606
....@@ -1165,6 +1608,8 @@
11651608 core->dev_dec = dev;
11661609
11671610 video_set_drvdata(vdev, core);
1611
+ pm_runtime_set_autosuspend_delay(dev, 2000);
1612
+ pm_runtime_use_autosuspend(dev);
11681613 pm_runtime_enable(dev);
11691614
11701615 return 0;
....@@ -1181,57 +1626,33 @@
11811626 video_unregister_device(core->vdev_dec);
11821627 pm_runtime_disable(core->dev_dec);
11831628
1629
+ if (core->pm_ops->vdec_put)
1630
+ core->pm_ops->vdec_put(core->dev_dec);
1631
+
11841632 return 0;
11851633 }
11861634
11871635 static __maybe_unused int vdec_runtime_suspend(struct device *dev)
11881636 {
11891637 struct venus_core *core = dev_get_drvdata(dev);
1190
- int ret;
1638
+ const struct venus_pm_ops *pm_ops = core->pm_ops;
1639
+ int ret = 0;
11911640
1192
- if (IS_V1(core))
1193
- return 0;
1641
+ if (pm_ops->vdec_power)
1642
+ ret = pm_ops->vdec_power(dev, POWER_OFF);
11941643
1195
- ret = venus_helper_power_enable(core, VIDC_SESSION_TYPE_DEC, true);
1196
- if (ret)
1197
- return ret;
1198
-
1199
- if (IS_V4(core))
1200
- clk_disable_unprepare(core->core0_bus_clk);
1201
-
1202
- clk_disable_unprepare(core->core0_clk);
1203
-
1204
- return venus_helper_power_enable(core, VIDC_SESSION_TYPE_DEC, false);
1644
+ return ret;
12051645 }
12061646
12071647 static __maybe_unused int vdec_runtime_resume(struct device *dev)
12081648 {
12091649 struct venus_core *core = dev_get_drvdata(dev);
1210
- int ret;
1650
+ const struct venus_pm_ops *pm_ops = core->pm_ops;
1651
+ int ret = 0;
12111652
1212
- if (IS_V1(core))
1213
- return 0;
1653
+ if (pm_ops->vdec_power)
1654
+ ret = pm_ops->vdec_power(dev, POWER_ON);
12141655
1215
- ret = venus_helper_power_enable(core, VIDC_SESSION_TYPE_DEC, true);
1216
- if (ret)
1217
- return ret;
1218
-
1219
- ret = clk_prepare_enable(core->core0_clk);
1220
- if (ret)
1221
- goto err_power_disable;
1222
-
1223
- if (IS_V4(core))
1224
- ret = clk_prepare_enable(core->core0_bus_clk);
1225
-
1226
- if (ret)
1227
- goto err_unprepare_core0;
1228
-
1229
- return venus_helper_power_enable(core, VIDC_SESSION_TYPE_DEC, false);
1230
-
1231
-err_unprepare_core0:
1232
- clk_disable_unprepare(core->core0_clk);
1233
-err_power_disable:
1234
- venus_helper_power_enable(core, VIDC_SESSION_TYPE_DEC, false);
12351656 return ret;
12361657 }
12371658