lkml.org 
[lkml]   [2021]   [Aug]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v8 25/34] media: staging: tegra-vde: Support generic power domain and OPP
    Date
    Currently driver supports legacy power domain API, this patch adds generic
    power domain and OPP support. This allows us to utilize a modern GENPD API
    for newer device-trees and support DVFS of the video decoder hardware.

    Tested-by: Peter Geis <pgwipeout@gmail.com> # Ouya T30
    Tested-by: Paul Fertser <fercerpav@gmail.com> # PAZ00 T20
    Tested-by: Nicolas Chauvet <kwizart@gmail.com> # PAZ00 T20 and TK1 T124
    Tested-by: Matt Merhar <mattmerhar@protonmail.com> # Ouya T30
    Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
    ---
    drivers/staging/media/tegra-vde/vde.c | 65 ++++++++++++++++++++++-----
    1 file changed, 54 insertions(+), 11 deletions(-)

    diff --git a/drivers/staging/media/tegra-vde/vde.c b/drivers/staging/media/tegra-vde/vde.c
    index ed4c1250b303..9a3eee8e71e2 100644
    --- a/drivers/staging/media/tegra-vde/vde.c
    +++ b/drivers/staging/media/tegra-vde/vde.c
    @@ -15,11 +15,14 @@
    #include <linux/miscdevice.h>
    #include <linux/module.h>
    #include <linux/of_device.h>
    +#include <linux/pm_domain.h>
    +#include <linux/pm_opp.h>
    #include <linux/pm_runtime.h>
    #include <linux/reset.h>
    #include <linux/slab.h>
    #include <linux/uaccess.h>

    +#include <soc/tegra/common.h>
    #include <soc/tegra/pmc.h>

    #include "uapi.h"
    @@ -920,13 +923,17 @@ static __maybe_unused int tegra_vde_runtime_suspend(struct device *dev)
    struct tegra_vde *vde = dev_get_drvdata(dev);
    int err;

    - err = tegra_powergate_power_off(TEGRA_POWERGATE_VDEC);
    - if (err) {
    - dev_err(dev, "Failed to power down HW: %d\n", err);
    - return err;
    + if (!dev->pm_domain) {
    + err = tegra_powergate_power_off(TEGRA_POWERGATE_VDEC);
    + if (err) {
    + dev_err(dev, "Failed to power down HW: %d\n", err);
    + return err;
    + }
    }

    clk_disable_unprepare(vde->clk);
    + reset_control_release(vde->rst);
    + reset_control_release(vde->rst_mc);

    return 0;
    }
    @@ -936,14 +943,47 @@ static __maybe_unused int tegra_vde_runtime_resume(struct device *dev)
    struct tegra_vde *vde = dev_get_drvdata(dev);
    int err;

    - err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_VDEC,
    - vde->clk, vde->rst);
    + err = reset_control_acquire(vde->rst_mc);
    + if (err) {
    + dev_err(dev, "Failed to acquire mc reset: %d\n", err);
    + return err;
    + }
    +
    + err = reset_control_acquire(vde->rst);
    + if (err) {
    + dev_err(dev, "Failed to acquire reset: %d\n", err);
    + goto release_mc_reset;
    + }
    +
    + if (!dev->pm_domain) {
    + err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_VDEC,
    + vde->clk, vde->rst);
    + if (err) {
    + dev_err(dev, "Failed to power up HW : %d\n", err);
    + goto release_reset;
    + }
    + }
    +
    + err = dev_pm_opp_sync(dev);
    if (err) {
    - dev_err(dev, "Failed to power up HW : %d\n", err);
    + dev_err(dev, "failed to sync OPP: %d\n", err);
    return err;
    }

    + err = clk_prepare_enable(vde->clk);
    + if (err) {
    + dev_err(dev, "Failed to enable clock: %d\n", err);
    + goto release_reset;
    + }
    +
    return 0;
    +
    +release_reset:
    + reset_control_release(vde->rst);
    +release_mc_reset:
    + reset_control_release(vde->rst_mc);
    +
    + return err;
    }

    static int tegra_vde_probe(struct platform_device *pdev)
    @@ -1001,14 +1041,14 @@ static int tegra_vde_probe(struct platform_device *pdev)
    return err;
    }

    - vde->rst = devm_reset_control_get(dev, NULL);
    + vde->rst = devm_reset_control_get_exclusive_released(dev, NULL);
    if (IS_ERR(vde->rst)) {
    err = PTR_ERR(vde->rst);
    dev_err(dev, "Could not get VDE reset %d\n", err);
    return err;
    }

    - vde->rst_mc = devm_reset_control_get_optional(dev, "mc");
    + vde->rst_mc = devm_reset_control_get_optional_exclusive_released(dev, "mc");
    if (IS_ERR(vde->rst_mc)) {
    err = PTR_ERR(vde->rst_mc);
    dev_err(dev, "Could not get MC reset %d\n", err);
    @@ -1026,6 +1066,10 @@ static int tegra_vde_probe(struct platform_device *pdev)
    return err;
    }

    + err = devm_tegra_core_dev_init_opp_table_simple(dev);
    + if (err)
    + return err;
    +
    vde->iram_pool = of_gen_pool_get(dev->of_node, "iram", 0);
    if (!vde->iram_pool) {
    dev_err(dev, "Could not get IRAM pool\n");
    @@ -1133,8 +1177,7 @@ static void tegra_vde_shutdown(struct platform_device *pdev)
    * On some devices bootloader isn't ready to a power-gated VDE on
    * a warm-reboot, machine will hang in that case.
    */
    - if (pm_runtime_status_suspended(&pdev->dev))
    - tegra_vde_runtime_resume(&pdev->dev);
    + pm_runtime_get_sync(&pdev->dev);
    }

    static __maybe_unused int tegra_vde_pm_suspend(struct device *dev)
    --
    2.32.0
    \
     
     \ /
      Last update: 2021-08-17 03:32    [W:3.537 / U:0.504 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site