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");