media: venus: venc: Use pmruntime autosuspend
authorStanimir Varbanov <stanimir.varbanov@linaro.org>
Wed, 31 Mar 2021 11:05:42 +0000 (12:05 +0100)
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Thu, 21 Oct 2021 13:18:52 +0000 (14:18 +0100)
Migrate encoder to pm-runtime autosuspend.

Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>
Tested-by: Vikash Garodia <vgarodia@codeaurora.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
drivers/media/platform/qcom/venus/venc.c

index bc1c42d..472f2cf 100644 (file)
@@ -538,6 +538,64 @@ static const struct v4l2_ioctl_ops venc_ioctl_ops = {
        .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 };
 
+static int venc_pm_get(struct venus_inst *inst)
+{
+       struct venus_core *core = inst->core;
+       struct device *dev = core->dev_enc;
+       int ret;
+
+       mutex_lock(&core->pm_lock);
+       ret = pm_runtime_resume_and_get(dev);
+       mutex_unlock(&core->pm_lock);
+
+       return ret < 0 ? ret : 0;
+}
+
+static int venc_pm_put(struct venus_inst *inst, bool autosuspend)
+{
+       struct venus_core *core = inst->core;
+       struct device *dev = core->dev_enc;
+       int ret;
+
+       mutex_lock(&core->pm_lock);
+
+       if (autosuspend)
+               ret = pm_runtime_put_autosuspend(dev);
+       else
+               ret = pm_runtime_put_sync(dev);
+
+       mutex_unlock(&core->pm_lock);
+
+       return ret < 0 ? ret : 0;
+}
+
+static int venc_pm_get_put(struct venus_inst *inst)
+{
+       struct venus_core *core = inst->core;
+       struct device *dev = core->dev_enc;
+       int ret = 0;
+
+       mutex_lock(&core->pm_lock);
+
+       if (pm_runtime_suspended(dev)) {
+               ret = pm_runtime_resume_and_get(dev);
+               if (ret < 0)
+                       goto error;
+
+               ret = pm_runtime_put_autosuspend(dev);
+       }
+
+error:
+       mutex_unlock(&core->pm_lock);
+
+       return ret < 0 ? ret : 0;
+}
+
+static void venc_pm_touch(struct venus_inst *inst)
+{
+       pm_runtime_mark_last_busy(inst->core->dev_enc);
+}
+
 static int venc_set_properties(struct venus_inst *inst)
 {
        struct venc_controls *ctr = &inst->controls.enc;
@@ -931,11 +989,19 @@ static int venc_queue_setup(struct vb2_queue *q,
                return 0;
        }
 
+       ret = venc_pm_get(inst);
+       if (ret)
+               return ret;
+
        mutex_lock(&inst->lock);
        ret = venc_init_session(inst);
        mutex_unlock(&inst->lock);
 
        if (ret)
+               goto put_power;
+
+       ret = venc_pm_put(inst, false);
+       if (ret)
                return ret;
 
        switch (q->type) {
@@ -971,6 +1037,9 @@ static int venc_queue_setup(struct vb2_queue *q,
        }
 
        return ret;
+put_power:
+       venc_pm_put(inst, false);
+       return ret;
 }
 
 static int venc_buf_init(struct vb2_buffer *vb)
@@ -986,6 +1055,8 @@ static void venc_release_session(struct venus_inst *inst)
 {
        int ret;
 
+       venc_pm_get(inst);
+
        mutex_lock(&inst->lock);
 
        ret = hfi_session_deinit(inst);
@@ -997,6 +1068,8 @@ static void venc_release_session(struct venus_inst *inst)
        venus_pm_load_scale(inst);
        INIT_LIST_HEAD(&inst->registeredbufs);
        venus_pm_release_core(inst);
+
+       venc_pm_put(inst, false);
 }
 
 static void venc_buf_cleanup(struct vb2_buffer *vb)
@@ -1066,8 +1139,16 @@ static int venc_start_streaming(struct vb2_queue *q, unsigned int count)
        inst->sequence_cap = 0;
        inst->sequence_out = 0;
 
+       ret = venc_pm_get(inst);
+       if (ret)
+               goto error;
+
        ret = venus_pm_acquire_core(inst);
        if (ret)
+               goto put_power;
+
+       ret = venc_pm_put(inst, true);
+       if (ret)
                goto error;
 
        ret = venc_set_properties(inst);
@@ -1091,6 +1172,8 @@ static int venc_start_streaming(struct vb2_queue *q, unsigned int count)
 
        return 0;
 
+put_power:
+       venc_pm_put(inst, false);
 error:
        venus_helper_buffers_done(inst, q->type, VB2_BUF_STATE_QUEUED);
        if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
@@ -1105,6 +1188,8 @@ static void venc_vb2_buf_queue(struct vb2_buffer *vb)
 {
        struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
 
+       venc_pm_get_put(inst);
+
        mutex_lock(&inst->lock);
        venus_helper_vb2_buf_queue(vb);
        mutex_unlock(&inst->lock);
@@ -1128,6 +1213,8 @@ static void venc_buf_done(struct venus_inst *inst, unsigned int buf_type,
        struct vb2_buffer *vb;
        unsigned int type;
 
+       venc_pm_touch(inst);
+
        if (buf_type == HFI_BUFFER_INPUT)
                type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
        else
@@ -1157,6 +1244,8 @@ static void venc_event_notify(struct venus_inst *inst, u32 event,
 {
        struct device *dev = inst->core->dev_enc;
 
+       venc_pm_touch(inst);
+
        if (event == EVT_SESSION_ERROR) {
                inst->session_error = true;
                dev_err(dev, "enc: event session error %x\n", inst->error);
@@ -1245,13 +1334,9 @@ static int venc_open(struct file *file)
 
        venus_helper_init_instance(inst);
 
-       ret = pm_runtime_resume_and_get(core->dev_enc);
-       if (ret < 0)
-               goto err_free;
-
        ret = venc_ctrl_init(inst);
        if (ret)
-               goto err_put_sync;
+               goto err_free;
 
        ret = hfi_session_create(inst, &venc_hfi_ops);
        if (ret)
@@ -1290,8 +1375,6 @@ err_session_destroy:
        hfi_session_destroy(inst);
 err_ctrl_deinit:
        venc_ctrl_deinit(inst);
-err_put_sync:
-       pm_runtime_put_sync(core->dev_enc);
 err_free:
        kfree(inst);
        return ret;
@@ -1301,6 +1384,8 @@ static int venc_close(struct file *file)
 {
        struct venus_inst *inst = to_inst(file);
 
+       venc_pm_get(inst);
+
        v4l2_m2m_ctx_release(inst->m2m_ctx);
        v4l2_m2m_release(inst->m2m_dev);
        venc_ctrl_deinit(inst);
@@ -1309,7 +1394,7 @@ static int venc_close(struct file *file)
        v4l2_fh_del(&inst->fh);
        v4l2_fh_exit(&inst->fh);
 
-       pm_runtime_put_sync(inst->core->dev_enc);
+       venc_pm_put(inst, false);
 
        kfree(inst);
        return 0;
@@ -1366,6 +1451,8 @@ static int venc_probe(struct platform_device *pdev)
        core->dev_enc = dev;
 
        video_set_drvdata(vdev, core);
+       pm_runtime_set_autosuspend_delay(dev, 2000);
+       pm_runtime_use_autosuspend(dev);
        pm_runtime_enable(dev);
 
        return 0;