mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-07-29 13:46:49 +00:00
Merge pull request #4492 from jernejsk/vp8
Allwinner: Add VP8 HW decoding support
This commit is contained in:
commit
986c2dd5e4
269
projects/Allwinner/patches/linux/0002-backport-from-next.patch
Normal file
269
projects/Allwinner/patches/linux/0002-backport-from-next.patch
Normal file
@ -0,0 +1,269 @@
|
||||
From d5aecd289babf3adcf5a837b067a5efddb097d99 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
Date: Sat, 9 May 2020 22:06:43 +0200
|
||||
Subject: [PATCH] media: cedrus: Implement runtime PM
|
||||
|
||||
This allows the VE clocks and PLL_VE to be disabled most of the time.
|
||||
A runtime PM reference is held while streaming.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
Signed-off-by: Samuel Holland <samuel@sholland.org>
|
||||
Reviewed-by: Ezequiel Garcia <ezequiel@collabora.com>
|
||||
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
|
||||
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
|
||||
---
|
||||
drivers/staging/media/sunxi/cedrus/cedrus.c | 7 ++
|
||||
.../staging/media/sunxi/cedrus/cedrus_hw.c | 106 ++++++++++++------
|
||||
.../staging/media/sunxi/cedrus/cedrus_hw.h | 3 +
|
||||
.../staging/media/sunxi/cedrus/cedrus_video.c | 33 ++++--
|
||||
4 files changed, 104 insertions(+), 45 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c
|
||||
index 05a85517ff60..bc27f9430eeb 100644
|
||||
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c
|
||||
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
+#include <linux/pm.h>
|
||||
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-ioctl.h>
|
||||
@@ -551,12 +552,18 @@ static const struct of_device_id cedrus_dt_match[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, cedrus_dt_match);
|
||||
|
||||
+static const struct dev_pm_ops cedrus_dev_pm_ops = {
|
||||
+ SET_RUNTIME_PM_OPS(cedrus_hw_suspend,
|
||||
+ cedrus_hw_resume, NULL)
|
||||
+};
|
||||
+
|
||||
static struct platform_driver cedrus_driver = {
|
||||
.probe = cedrus_probe,
|
||||
.remove = cedrus_remove,
|
||||
.driver = {
|
||||
.name = CEDRUS_NAME,
|
||||
.of_match_table = of_match_ptr(cedrus_dt_match),
|
||||
+ .pm = &cedrus_dev_pm_ops,
|
||||
},
|
||||
};
|
||||
module_platform_driver(cedrus_driver);
|
||||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
|
||||
index daf5f244f93b..1744e6fcc999 100644
|
||||
--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
|
||||
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/clk.h>
|
||||
+#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/soc/sunxi/sunxi_sram.h>
|
||||
@@ -140,6 +141,64 @@ static irqreturn_t cedrus_irq(int irq, void *data)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
+int cedrus_hw_suspend(struct device *device)
|
||||
+{
|
||||
+ struct cedrus_dev *dev = dev_get_drvdata(device);
|
||||
+
|
||||
+ reset_control_assert(dev->rstc);
|
||||
+
|
||||
+ clk_disable_unprepare(dev->ram_clk);
|
||||
+ clk_disable_unprepare(dev->mod_clk);
|
||||
+ clk_disable_unprepare(dev->ahb_clk);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int cedrus_hw_resume(struct device *device)
|
||||
+{
|
||||
+ struct cedrus_dev *dev = dev_get_drvdata(device);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = clk_prepare_enable(dev->ahb_clk);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev->dev, "Failed to enable AHB clock\n");
|
||||
+
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = clk_prepare_enable(dev->mod_clk);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev->dev, "Failed to enable MOD clock\n");
|
||||
+
|
||||
+ goto err_ahb_clk;
|
||||
+ }
|
||||
+
|
||||
+ ret = clk_prepare_enable(dev->ram_clk);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev->dev, "Failed to enable RAM clock\n");
|
||||
+
|
||||
+ goto err_mod_clk;
|
||||
+ }
|
||||
+
|
||||
+ ret = reset_control_reset(dev->rstc);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev->dev, "Failed to apply reset\n");
|
||||
+
|
||||
+ goto err_ram_clk;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err_ram_clk:
|
||||
+ clk_disable_unprepare(dev->ram_clk);
|
||||
+err_mod_clk:
|
||||
+ clk_disable_unprepare(dev->mod_clk);
|
||||
+err_ahb_clk:
|
||||
+ clk_disable_unprepare(dev->ahb_clk);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
int cedrus_hw_probe(struct cedrus_dev *dev)
|
||||
{
|
||||
const struct cedrus_variant *variant;
|
||||
@@ -236,42 +295,17 @@ int cedrus_hw_probe(struct cedrus_dev *dev)
|
||||
goto err_sram;
|
||||
}
|
||||
|
||||
- ret = clk_prepare_enable(dev->ahb_clk);
|
||||
- if (ret) {
|
||||
- dev_err(dev->dev, "Failed to enable AHB clock\n");
|
||||
-
|
||||
- goto err_sram;
|
||||
- }
|
||||
-
|
||||
- ret = clk_prepare_enable(dev->mod_clk);
|
||||
- if (ret) {
|
||||
- dev_err(dev->dev, "Failed to enable MOD clock\n");
|
||||
-
|
||||
- goto err_ahb_clk;
|
||||
- }
|
||||
-
|
||||
- ret = clk_prepare_enable(dev->ram_clk);
|
||||
- if (ret) {
|
||||
- dev_err(dev->dev, "Failed to enable RAM clock\n");
|
||||
-
|
||||
- goto err_mod_clk;
|
||||
- }
|
||||
-
|
||||
- ret = reset_control_reset(dev->rstc);
|
||||
- if (ret) {
|
||||
- dev_err(dev->dev, "Failed to apply reset\n");
|
||||
-
|
||||
- goto err_ram_clk;
|
||||
+ pm_runtime_enable(dev->dev);
|
||||
+ if (!pm_runtime_enabled(dev->dev)) {
|
||||
+ ret = cedrus_hw_resume(dev->dev);
|
||||
+ if (ret)
|
||||
+ goto err_pm;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
-err_ram_clk:
|
||||
- clk_disable_unprepare(dev->ram_clk);
|
||||
-err_mod_clk:
|
||||
- clk_disable_unprepare(dev->mod_clk);
|
||||
-err_ahb_clk:
|
||||
- clk_disable_unprepare(dev->ahb_clk);
|
||||
+err_pm:
|
||||
+ pm_runtime_disable(dev->dev);
|
||||
err_sram:
|
||||
sunxi_sram_release(dev->dev);
|
||||
err_mem:
|
||||
@@ -282,11 +316,9 @@ int cedrus_hw_probe(struct cedrus_dev *dev)
|
||||
|
||||
void cedrus_hw_remove(struct cedrus_dev *dev)
|
||||
{
|
||||
- reset_control_assert(dev->rstc);
|
||||
-
|
||||
- clk_disable_unprepare(dev->ram_clk);
|
||||
- clk_disable_unprepare(dev->mod_clk);
|
||||
- clk_disable_unprepare(dev->ahb_clk);
|
||||
+ pm_runtime_disable(dev->dev);
|
||||
+ if (!pm_runtime_status_suspended(dev->dev))
|
||||
+ cedrus_hw_suspend(dev->dev);
|
||||
|
||||
sunxi_sram_release(dev->dev);
|
||||
|
||||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.h b/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
|
||||
index 604ff932fbf5..45f641f0bfa2 100644
|
||||
--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
|
||||
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.h
|
||||
@@ -22,6 +22,9 @@ void cedrus_engine_disable(struct cedrus_dev *dev);
|
||||
void cedrus_dst_format_set(struct cedrus_dev *dev,
|
||||
struct v4l2_pix_format *fmt);
|
||||
|
||||
+int cedrus_hw_suspend(struct device *device);
|
||||
+int cedrus_hw_resume(struct device *device);
|
||||
+
|
||||
int cedrus_hw_probe(struct cedrus_dev *dev);
|
||||
void cedrus_hw_remove(struct cedrus_dev *dev);
|
||||
|
||||
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
|
||||
index ed3f511f066f..16d82309e7b6 100644
|
||||
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
|
||||
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
|
||||
@@ -13,6 +13,8 @@
|
||||
* Marek Szyprowski, <m.szyprowski@samsung.com>
|
||||
*/
|
||||
|
||||
+#include <linux/pm_runtime.h>
|
||||
+
|
||||
#include <media/videobuf2-dma-contig.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-ioctl.h>
|
||||
@@ -450,12 +452,24 @@ static int cedrus_start_streaming(struct vb2_queue *vq, unsigned int count)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- if (V4L2_TYPE_IS_OUTPUT(vq->type) &&
|
||||
- dev->dec_ops[ctx->current_codec]->start)
|
||||
- ret = dev->dec_ops[ctx->current_codec]->start(ctx);
|
||||
+ if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
|
||||
+ ret = pm_runtime_get_sync(dev->dev);
|
||||
+ if (ret < 0)
|
||||
+ goto err_cleanup;
|
||||
|
||||
- if (ret)
|
||||
- cedrus_queue_cleanup(vq, VB2_BUF_STATE_QUEUED);
|
||||
+ if (dev->dec_ops[ctx->current_codec]->start) {
|
||||
+ ret = dev->dec_ops[ctx->current_codec]->start(ctx);
|
||||
+ if (ret)
|
||||
+ goto err_pm;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err_pm:
|
||||
+ pm_runtime_put(dev->dev);
|
||||
+err_cleanup:
|
||||
+ cedrus_queue_cleanup(vq, VB2_BUF_STATE_QUEUED);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -465,9 +479,12 @@ static void cedrus_stop_streaming(struct vb2_queue *vq)
|
||||
struct cedrus_ctx *ctx = vb2_get_drv_priv(vq);
|
||||
struct cedrus_dev *dev = ctx->dev;
|
||||
|
||||
- if (V4L2_TYPE_IS_OUTPUT(vq->type) &&
|
||||
- dev->dec_ops[ctx->current_codec]->stop)
|
||||
- dev->dec_ops[ctx->current_codec]->stop(ctx);
|
||||
+ if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
|
||||
+ if (dev->dec_ops[ctx->current_codec]->stop)
|
||||
+ dev->dec_ops[ctx->current_codec]->stop(ctx);
|
||||
+
|
||||
+ pm_runtime_put(dev->dev);
|
||||
+ }
|
||||
|
||||
cedrus_queue_cleanup(vq, VB2_BUF_STATE_ERROR);
|
||||
}
|
||||
--
|
||||
2.27.0
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user