summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBhalchandra Gajare <gajare@codeaurora.org>2016-10-18 13:18:15 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2016-10-25 17:47:18 -0700
commit0fa1d41b8aa97da6f5051091b2c77929095f9133 (patch)
tree619c16dcbde72ef1f5f61d341796e8915c5f04ca
parent46aa49c1188a77f52dc4969f82292c176d8f399b (diff)
ASoC: wcd934x-dsp-cntl: fix memory enable/disable sequence
Enabling only the required memory for codec DSP helps reduce power consumption with codec DSP is not used. Update the memory enable/ disable sequence such that the switchable memory domain is enabled only when the codec DSP is being used. CRs-Fixed: 1075303 Change-Id: I0552bf8a48c214b89e160fe4df145973f02c2788 Signed-off-by: Bhalchandra Gajare <gajare@codeaurora.org>
-rw-r--r--sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c168
1 files changed, 108 insertions, 60 deletions
diff --git a/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c b/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c
index 8d2247176607..7e4cd6ce55a7 100644
--- a/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c
+++ b/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c
@@ -46,6 +46,11 @@
mutex_unlock(&lock); \
}
+enum wcd_mem_type {
+ WCD_MEM_TYPE_ALWAYS_ON,
+ WCD_MEM_TYPE_SWITCHABLE,
+};
+
struct wcd_cntl_attribute {
struct attribute attr;
ssize_t (*show)(struct wcd_dsp_cntl *cntl, char *buf);
@@ -469,7 +474,8 @@ static void wcd_cntl_cpar_ctrl(struct wcd_dsp_cntl *cntl,
snd_soc_write(codec, WCD934X_CPE_SS_CPAR_CTL, 0x00);
}
-static int wcd_cntl_enable_memory(struct wcd_dsp_cntl *cntl)
+static int wcd_cntl_enable_memory(struct wcd_dsp_cntl *cntl,
+ enum wcd_mem_type mem_type)
{
struct snd_soc_codec *codec = cntl->codec;
struct wcd9xxx *wcd9xxx = dev_get_drvdata(codec->dev->parent);
@@ -477,77 +483,115 @@ static int wcd_cntl_enable_memory(struct wcd_dsp_cntl *cntl)
u8 status;
int ret = 0;
- snd_soc_update_bits(codec, WCD934X_CPE_SS_SOC_SW_COLLAPSE_CTL,
- 0x04, 0x00);
- snd_soc_update_bits(codec, WCD934X_TEST_DEBUG_MEM_CTRL,
- 0x80, 0x80);
- snd_soc_update_bits(codec, WCD934X_CPE_SS_SOC_SW_COLLAPSE_CTL,
- 0x01, 0x01);
- do {
- loop_cnt++;
- /* Time to enable the power domain for memory */
- usleep_range(100, 150);
- status = snd_soc_read(codec,
- WCD934X_CPE_SS_SOC_SW_COLLAPSE_CTL);
- } while ((status & 0x02) != 0x02 &&
- loop_cnt != WCD_MEM_ENABLE_MAX_RETRIES);
-
- if ((status & 0x02) != 0x02) {
- dev_err(cntl->codec->dev,
- "%s: power domain not enabled, status = 0x%02x\n",
- __func__, status);
- ret = -EIO;
- goto done;
- }
+ switch (mem_type) {
- /* 512KB of always on region */
- wcd9xxx_slim_write_repeat(wcd9xxx,
- WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_0,
- ARRAY_SIZE(mem_enable_values),
- mem_enable_values);
- wcd9xxx_slim_write_repeat(wcd9xxx,
- WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_1,
- ARRAY_SIZE(mem_enable_values),
- mem_enable_values);
-
- snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_DRAM1_SHUTDOWN, 0x05);
-
- /* Rest of the memory */
- wcd9xxx_slim_write_repeat(wcd9xxx,
- WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_2,
- ARRAY_SIZE(mem_enable_values),
- mem_enable_values);
- wcd9xxx_slim_write_repeat(wcd9xxx,
- WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_3,
- ARRAY_SIZE(mem_enable_values),
- mem_enable_values);
+ case WCD_MEM_TYPE_ALWAYS_ON:
+ /* 512KB of always on region */
+ wcd9xxx_slim_write_repeat(wcd9xxx,
+ WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_0,
+ ARRAY_SIZE(mem_enable_values),
+ mem_enable_values);
+ wcd9xxx_slim_write_repeat(wcd9xxx,
+ WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_1,
+ ARRAY_SIZE(mem_enable_values),
+ mem_enable_values);
+ break;
+
+ case WCD_MEM_TYPE_SWITCHABLE:
+
+ snd_soc_update_bits(codec, WCD934X_CPE_SS_SOC_SW_COLLAPSE_CTL,
+ 0x04, 0x00);
+ snd_soc_update_bits(codec, WCD934X_TEST_DEBUG_MEM_CTRL,
+ 0x80, 0x80);
+ snd_soc_update_bits(codec, WCD934X_CPE_SS_SOC_SW_COLLAPSE_CTL,
+ 0x01, 0x01);
+ do {
+ loop_cnt++;
+ /* Time to enable the power domain for memory */
+ usleep_range(100, 150);
+ status = snd_soc_read(codec,
+ WCD934X_CPE_SS_SOC_SW_COLLAPSE_CTL);
+ } while ((status & 0x02) != 0x02 &&
+ loop_cnt != WCD_MEM_ENABLE_MAX_RETRIES);
+
+ if ((status & 0x02) != 0x02) {
+ dev_err(cntl->codec->dev,
+ "%s: power domain not enabled, status = 0x%02x\n",
+ __func__, status);
+ ret = -EIO;
+ goto done;
+ }
+
+ /* Rest of the memory */
+ wcd9xxx_slim_write_repeat(wcd9xxx,
+ WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_2,
+ ARRAY_SIZE(mem_enable_values),
+ mem_enable_values);
+ wcd9xxx_slim_write_repeat(wcd9xxx,
+ WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_3,
+ ARRAY_SIZE(mem_enable_values),
+ mem_enable_values);
+
+ snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_DRAM1_SHUTDOWN,
+ 0x05);
+ break;
+
+ default:
+ dev_err(cntl->codec->dev, "%s: Invalid mem_type %d\n",
+ __func__, mem_type);
+ ret = -EINVAL;
+ break;
+ }
+done:
/* Make sure Deep sleep of memories is enabled for all banks */
snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_SYSMEM_DEEPSLP_0, 0xFF);
snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_SYSMEM_DEEPSLP_1, 0x0F);
-done:
+
return ret;
}
-static void wcd_cntl_disable_memory(struct wcd_dsp_cntl *cntl)
+static void wcd_cntl_disable_memory(struct wcd_dsp_cntl *cntl,
+ enum wcd_mem_type mem_type)
{
struct snd_soc_codec *codec = cntl->codec;
+ u8 val;
+
+ switch (mem_type) {
+ case WCD_MEM_TYPE_ALWAYS_ON:
+ snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_1,
+ 0xFF);
+ snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_0,
+ 0xFF);
+ break;
+ case WCD_MEM_TYPE_SWITCHABLE:
+ snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_3,
+ 0xFF);
+ snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_2,
+ 0xFF);
+ snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_DRAM1_SHUTDOWN,
+ 0x07);
+
+ snd_soc_update_bits(codec, WCD934X_CPE_SS_SOC_SW_COLLAPSE_CTL,
+ 0x01, 0x00);
+ val = snd_soc_read(codec, WCD934X_CPE_SS_SOC_SW_COLLAPSE_CTL);
+ if (val & 0x02)
+ dev_err(codec->dev,
+ "%s: Disable switchable failed, val = 0x%02x",
+ __func__, val);
+
+ snd_soc_update_bits(codec, WCD934X_TEST_DEBUG_MEM_CTRL,
+ 0x80, 0x00);
+ break;
+ default:
+ dev_err(cntl->codec->dev, "%s: Invalid mem_type %d\n",
+ __func__, mem_type);
+ break;
+ }
snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_SYSMEM_DEEPSLP_0, 0xFF);
snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_SYSMEM_DEEPSLP_1, 0x0F);
- snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_3, 0xFF);
- snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_2, 0xFF);
- snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_DRAM1_SHUTDOWN, 0x07);
- snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_1, 0xFF);
- snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_0, 0xFF);
-
- snd_soc_update_bits(codec, WCD934X_CPE_SS_SOC_SW_COLLAPSE_CTL,
- 0x01, 0x00);
- snd_soc_update_bits(codec, WCD934X_TEST_DEBUG_MEM_CTRL,
- 0x80, 0x00);
- snd_soc_update_bits(codec, WCD934X_CPE_SS_SOC_SW_COLLAPSE_CTL,
- 0x04, 0x04);
}
static void wcd_cntl_do_shutdown(struct wcd_dsp_cntl *cntl)
@@ -743,7 +787,9 @@ static int wcd_control_handler(struct device *dev, void *priv_data,
wcd_cntl_cpar_ctrl(cntl, true);
if (event == WDSP_EVENT_PRE_DLOAD_CODE)
- wcd_cntl_enable_memory(cntl);
+ wcd_cntl_enable_memory(cntl, WCD_MEM_TYPE_ALWAYS_ON);
+ else if (event == WDSP_EVENT_PRE_DLOAD_DATA)
+ wcd_cntl_enable_memory(cntl, WCD_MEM_TYPE_SWITCHABLE);
break;
case WDSP_EVENT_DO_BOOT:
@@ -758,6 +804,7 @@ static int wcd_control_handler(struct device *dev, void *priv_data,
case WDSP_EVENT_DO_SHUTDOWN:
wcd_cntl_do_shutdown(cntl);
+ wcd_cntl_disable_memory(cntl, WCD_MEM_TYPE_SWITCHABLE);
break;
default:
@@ -1188,7 +1235,8 @@ void wcd_dsp_cntl_deinit(struct wcd_dsp_cntl **cntl)
* irrespective of DSP was booted up or not.
*/
wcd_cntl_do_shutdown(control);
- wcd_cntl_disable_memory(control);
+ wcd_cntl_disable_memory(control, WCD_MEM_TYPE_SWITCHABLE);
+ wcd_cntl_disable_memory(control, WCD_MEM_TYPE_ALWAYS_ON);
component_del(codec->dev, &wcd_ctrl_component_ops);