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 <chinmays@codeaurora.org>
This commit is contained in:
Chinmay Sawarkar 2016-08-01 18:30:45 -07:00
parent e94b446eac
commit 050ef43ec7
4 changed files with 58 additions and 1 deletions

View file

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

View file

@ -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 {

View file

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

View file

@ -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 <linux/bitops.h>
#include <linux/clk.h>
#include <linux/clk/msm-clk.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@ -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");