#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <media/cadence/cdns-csi2rx.h>
struct ti_csi2rx_dev *csi = ctx->csi;
struct ti_csi2rx_dma *dma = &ctx->dma;
unsigned long flags;
- int ret = 0;
+ int ret;
+
+ ret = pm_runtime_resume_and_get(csi->dev);
+ if (ret)
+ return ret;
spin_lock_irqsave(&dma->lock, flags);
if (list_empty(&dma->queue))
ret = -EIO;
spin_unlock_irqrestore(&dma->lock, flags);
if (ret)
- return ret;
+ goto err;
ret = video_device_pipeline_start(&ctx->vdev, &csi->pipe);
if (ret)
writel(0, csi->shim + SHIM_DMACNTX(ctx->idx));
err:
ti_csi2rx_cleanup_buffers(ctx, VB2_BUF_STATE_QUEUED);
+ pm_runtime_put(csi->dev);
+
return ret;
}
ti_csi2rx_stop_dma(ctx);
ti_csi2rx_cleanup_buffers(ctx, VB2_BUF_STATE_ERROR);
+ pm_runtime_put(csi->dev);
}
static const struct vb2_ops csi_vb2_qops = {
static void ti_csi2rx_cleanup_ctx(struct ti_csi2rx_ctx *ctx)
{
- dma_release_channel(ctx->dma.chan);
+ if (!pm_runtime_status_suspended(ctx->csi->dev))
+ dma_release_channel(ctx->dma.chan);
+
vb2_queue_release(&ctx->vidq);
video_unregister_device(&ctx->vdev);
return ret;
}
+static int ti_csi2rx_runtime_suspend(struct device *dev)
+{
+ struct ti_csi2rx_dev *csi = dev_get_drvdata(dev);
+
+ if (csi->enable_count != 0)
+ return -EBUSY;
+
+ for (unsigned int i = 0; i < csi->num_ctx; i++)
+ dma_release_channel(csi->ctx[i].dma.chan);
+
+ return 0;
+}
+
+static int ti_csi2rx_runtime_resume(struct device *dev)
+{
+ struct ti_csi2rx_dev *csi = dev_get_drvdata(dev);
+ int ret;
+
+ for (unsigned int i = 0; i < csi->num_ctx; i++) {
+ ret = ti_csi2rx_init_dma(&csi->ctx[i]);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct dev_pm_ops ti_csi2rx_pm_ops = {
+ RUNTIME_PM_OPS(ti_csi2rx_runtime_suspend, ti_csi2rx_runtime_resume,
+ NULL)
+};
+
static int ti_csi2rx_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
goto err_ctx;
}
+ pm_runtime_set_active(csi->dev);
+ pm_runtime_enable(csi->dev);
+
ret = ti_csi2rx_notifier_register(csi);
if (ret)
goto err_ctx;
struct ti_csi2rx_dev *csi = platform_get_drvdata(pdev);
unsigned int i;
+ if (!pm_runtime_status_suspended(&pdev->dev))
+ pm_runtime_set_suspended(&pdev->dev);
+
for (i = 0; i < csi->num_ctx; i++)
ti_csi2rx_cleanup_ctx(&csi->ctx[i]);
ti_csi2rx_cleanup_v4l2(csi);
dma_free_coherent(csi->dev, csi->drain.len, csi->drain.vaddr,
csi->drain.paddr);
+ pm_runtime_disable(&pdev->dev);
}
static const struct of_device_id ti_csi2rx_of_match[] = {
.driver = {
.name = TI_CSI2RX_MODULE_NAME,
.of_match_table = ti_csi2rx_of_match,
+ .pm = &ti_csi2rx_pm_ops,
},
};