* [PATCH] media: imagination: e5010: Enable autosuspend for runtime PM
@ 2026-07-22 21:08 Brandon Brnich
0 siblings, 0 replies; only message in thread
From: Brandon Brnich @ 2026-07-22 21:08 UTC (permalink / raw)
To: devarsht, mchehab, hverkuil, benjamin.gaignard, sebastian.fricke
Cc: linux-media, linux-kernel, b-brnich, k-willis
Current implementation only has one call to turn the device on -
start_streaming. This can waste power of device as the device can be in
STREAM_ON state, but no buffers are actually being submitted.
e5010_init_device needs to be moved to the resume hook to ensure
register state is correct during any power on. This also fixes an issue
when device was never powered on, but system resumes from deep sleep.
The PM framework skips the runtime resume hook since device was never on
in the first place. This causes e5010_init_device to be called for a
powered off device leading to invalid write and system crash.
Fixes: a1e2940458853 ("media: imagination: Add E5010 JPEG Encoder driver")
Signed-off-by: Brandon Brnich <b-brnich@ti.com>
---
.../platform/imagination/e5010-jpeg-enc.c | 47 +++++++++----------
1 file changed, 21 insertions(+), 26 deletions(-)
diff --git a/drivers/media/platform/imagination/e5010-jpeg-enc.c b/drivers/media/platform/imagination/e5010-jpeg-enc.c
index 42ad9ee3993b4..189c147cb9705 100644
--- a/drivers/media/platform/imagination/e5010-jpeg-enc.c
+++ b/drivers/media/platform/imagination/e5010-jpeg-enc.c
@@ -976,6 +976,8 @@ static irqreturn_t e5010_irq(int irq, void *data)
v4l2_m2m_job_finish(e5010->m2m_dev, ctx->fh.m2m_ctx);
dprintk(e5010, 3, "ctx: 0x%p Finish job\n", ctx);
+ pm_runtime_mark_last_busy(e5010->dev);
+ pm_runtime_put_autosuspend(e5010->dev);
job_unlock:
spin_unlock(&e5010->hw_lock);
@@ -1099,6 +1101,8 @@ static int e5010_probe(struct platform_device *pdev)
goto fail_after_v4l2_register;
}
+ pm_runtime_set_autosuspend_delay(dev, 100);
+ pm_runtime_use_autosuspend(dev);
pm_runtime_enable(dev);
ret = video_register_device(e5010->vdev, VFL_TYPE_VIDEO, 0);
@@ -1289,31 +1293,13 @@ static int e5010_encoder_cmd(struct file *file, void *priv,
static int e5010_start_streaming(struct vb2_queue *q, unsigned int count)
{
struct e5010_context *ctx = vb2_get_drv_priv(q);
- int ret;
struct e5010_q_data *queue = get_queue(ctx, q->type);
v4l2_m2m_update_start_streaming_state(ctx->fh.m2m_ctx, q);
queue->sequence = 0;
- ret = pm_runtime_resume_and_get(ctx->e5010->dev);
- if (ret < 0) {
- v4l2_err(&ctx->e5010->v4l2_dev, "failed to power up jpeg\n");
- goto fail;
- }
-
- ret = e5010_init_device(ctx->e5010);
- if (ret) {
- v4l2_err(&ctx->e5010->v4l2_dev, "failed to Enable e5010 device\n");
- goto fail;
- }
-
return 0;
-
-fail:
- e5010_vb2_buffers_return(q, VB2_BUF_STATE_QUEUED);
-
- return ret;
}
static void e5010_stop_streaming(struct vb2_queue *q)
@@ -1329,8 +1315,6 @@ static void e5010_stop_streaming(struct vb2_queue *q)
v4l2_m2m_has_stopped(ctx->fh.m2m_ctx)) {
v4l2_event_queue_fh(&ctx->fh, &e5010_eos_event);
}
-
- pm_runtime_put_sync(ctx->e5010->dev);
}
static void e5010_device_run(void *priv)
@@ -1343,7 +1327,15 @@ static void e5010_device_run(void *priv)
unsigned long flags;
int num_planes = ctx->out_queue.fmt->num_planes;
+ ret = pm_runtime_resume_and_get(e5010->dev);
+ if (ret < 0) {
+ dev_err(e5010->dev, "Device failed to turn on\n");
+ v4l2_m2m_job_finish(e5010->m2m_dev, ctx->fh.m2m_ctx);
+ return;
+ }
+
spin_lock_irqsave(&e5010->hw_lock, flags);
+
s_vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
WARN_ON(!s_vb);
d_vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
@@ -1474,6 +1466,8 @@ static void e5010_device_run(void *priv)
e5010_reset(e5010->dev, e5010->core_base, e5010->mmu_base);
no_ready_buf_err:
+ pm_runtime_mark_last_busy(e5010->dev);
+ pm_runtime_put_autosuspend(e5010->dev);
if (s_vb) {
v4l2_m2m_src_buf_remove_by_buf(ctx->fh.m2m_ctx, s_vb);
v4l2_m2m_buf_done(s_vb, VB2_BUF_STATE_ERROR);
@@ -1501,6 +1495,13 @@ static int e5010_runtime_resume(struct device *dev)
return ret;
}
+ ret = e5010_init_device(e5010);
+ if (ret) {
+ dev_err(dev, "Failed to re-enable e5010 device\n");
+ clk_disable_unprepare(e5010->clk);
+ return ret;
+ }
+
return 0;
}
@@ -1533,12 +1534,6 @@ static int e5010_resume(struct device *dev)
if (ret < 0)
return ret;
- ret = e5010_init_device(e5010);
- if (ret) {
- dev_err(dev, "Failed to re-enable e5010 device\n");
- return ret;
- }
-
v4l2_m2m_resume(e5010->m2m_dev);
return ret;
--
2.43.0
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-07-22 21:09 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-22 21:08 [PATCH] media: imagination: e5010: Enable autosuspend for runtime PM Brandon Brnich
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox