From 050ef43ec73e79355c6c693c97c5c367df788b4a Mon Sep 17 00:00:00 2001 From: Chinmay Sawarkar Date: Mon, 1 Aug 2016 18:30:45 -0700 Subject: [PATCH] msm: vidc: Set no memory retention for video clocks Currently, certain memories are set to retain their contents even after clocks are off. Here, we set the no memory retention flags for the associated clocks, to save power. CRs-Fixed: 1044381 Change-Id: I87c34fece6cb352ecef3aaeb8a02c1196fa8bcc3 Signed-off-by: Chinmay Sawarkar --- .../platform/msm/vidc/msm_vidc_res_parse.c | 6 ++++ .../platform/msm/vidc/msm_vidc_resources.h | 1 + drivers/media/platform/msm/vidc/venus_hfi.c | 16 +++++++++ drivers/media/platform/msm/vidc/vmem/vmem.c | 36 ++++++++++++++++++- 4 files changed, 58 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c index 2bb91ccc6c26..77d6e360c28b 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c @@ -25,6 +25,7 @@ enum clock_properties { CLOCK_PROP_HAS_SCALING = 1 << 0, + CLOCK_PROP_HAS_MEM_RETENTION = 1 << 1, }; static int msm_vidc_populate_legacy_context_bank( struct msm_vidc_platform_resources *res); @@ -943,6 +944,11 @@ static int msm_vidc_load_clock_table( vc->has_scaling = false; } + if (clock_props[c] & CLOCK_PROP_HAS_MEM_RETENTION) + vc->has_mem_retention = true; + else + vc->has_mem_retention = false; + dprintk(VIDC_DBG, "Found clock %s: scale-able = %s\n", vc->name, vc->count ? "yes" : "no"); } diff --git a/drivers/media/platform/msm/vidc/msm_vidc_resources.h b/drivers/media/platform/msm/vidc/msm_vidc_resources.h index c61605c7e405..734586a3f76c 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_resources.h +++ b/drivers/media/platform/msm/vidc/msm_vidc_resources.h @@ -104,6 +104,7 @@ struct clock_info { struct load_freq_table *load_freq_tbl; u32 count; bool has_scaling; + bool has_mem_retention; }; struct clock_set { diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c index 20e217cc0445..704ea94e42f1 100644 --- a/drivers/media/platform/msm/vidc/venus_hfi.c +++ b/drivers/media/platform/msm/vidc/venus_hfi.c @@ -3796,6 +3796,22 @@ static inline int __prepare_enable_clks(struct venus_hfi_device *device) if (cl->has_scaling) clk_set_rate(cl->clk, clk_round_rate(cl->clk, 0)); + if (cl->has_mem_retention) { + rc = clk_set_flags(cl->clk, CLKFLAG_NORETAIN_PERIPH); + if (rc) { + dprintk(VIDC_WARN, + "Failed set flag NORETAIN_PERIPH %s\n", + cl->name); + } + + rc = clk_set_flags(cl->clk, CLKFLAG_NORETAIN_MEM); + if (rc) { + dprintk(VIDC_WARN, + "Failed set flag NORETAIN_MEM %s\n", + cl->name); + } + } + rc = clk_prepare_enable(cl->clk); if (rc) { dprintk(VIDC_ERR, "Failed to enable clocks\n"); diff --git a/drivers/media/platform/msm/vidc/vmem/vmem.c b/drivers/media/platform/msm/vidc/vmem/vmem.c index 3a2ac31c6450..76fb84bc2daa 100644 --- a/drivers/media/platform/msm/vidc/vmem/vmem.c +++ b/drivers/media/platform/msm/vidc/vmem/vmem.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -111,6 +112,7 @@ struct vmem { struct { const char *name; struct clk *clk; + bool has_mem_retention; } *clocks; int num_clocks; struct { @@ -186,6 +188,21 @@ static inline int __power_on(struct vmem *v) pr_debug("Enabled regulator vdd\n"); for (c = 0; c < v->num_clocks; ++c) { + if (v->clocks[c].has_mem_retention) { + rc = clk_set_flags(v->clocks[c].clk, + CLKFLAG_NORETAIN_PERIPH); + if (rc) { + pr_warn("Failed set flag NORETAIN_PERIPH %s\n", + v->clocks[c].name); + } + rc = clk_set_flags(v->clocks[c].clk, + CLKFLAG_NORETAIN_MEM); + if (rc) { + pr_warn("Failed set flag NORETAIN_MEM %s\n", + v->clocks[c].name); + } + } + rc = clk_prepare_enable(v->clocks[c].clk); if (rc) { pr_err("Failed to enable %s clock (%d)\n", @@ -448,6 +465,7 @@ static inline int __init_resources(struct vmem *v, struct platform_device *pdev) { int rc = 0, c = 0; + int *clock_props = NULL; v->irq = platform_get_irq(pdev, 0); if (v->irq < 0) { @@ -504,6 +522,21 @@ static inline int __init_resources(struct vmem *v, goto exit; } + clock_props = devm_kzalloc(&pdev->dev, + v->num_clocks * sizeof(*clock_props), + GFP_KERNEL); + if (!clock_props) { + pr_err("Failed to allocate clock config table\n"); + goto exit; + } + + rc = of_property_read_u32_array(pdev->dev.of_node, "clock-config", + clock_props, v->num_clocks); + if (rc) { + pr_err("Failed to read clock config\n"); + goto exit; + } + for (c = 0; c < v->num_clocks; ++c) { const char *name = NULL; struct clk *temp = NULL; @@ -519,6 +552,7 @@ static inline int __init_resources(struct vmem *v, v->clocks[c].clk = temp; v->clocks[c].name = name; + v->clocks[c].has_mem_retention = clock_props[c]; } v->vdd = devm_regulator_get(&pdev->dev, "vdd");