aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLu, Han <han.lu@intel.com>2015-03-12 01:53:00 -0400
committerMark Brown <broonie@kernel.org>2015-03-12 15:18:14 -0400
commit76c07b8265c68d9a89fb4c0a634e373a087f11be (patch)
treed972cf3abd74d00193df8c22e4b0e7a1da51be20
parente8e79ede44ec99e09f8604c23ee99dc25065a343 (diff)
ASoC: Intel: add kcontrol to enable/disable sound effect module waves
Add kcontrol to enable/disable module waves. IPC is valid only when module is loaded. Also track module state over suspend so it's state can be restored on resume. Signed-off-by: Lu, Han <han.lu@intel.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/intel/sst-haswell-ipc.c19
-rw-r--r--sound/soc/intel/sst-haswell-ipc.h3
-rw-r--r--sound/soc/intel/sst-haswell-pcm.c68
3 files changed, 90 insertions, 0 deletions
diff --git a/sound/soc/intel/sst-haswell-ipc.c b/sound/soc/intel/sst-haswell-ipc.c
index 265d754a4090..ebca9035efce 100644
--- a/sound/soc/intel/sst-haswell-ipc.c
+++ b/sound/soc/intel/sst-haswell-ipc.c
@@ -337,6 +337,10 @@ struct sst_hsw {
337 337
338 /* FW log stream */ 338 /* FW log stream */
339 struct sst_hsw_log_stream log_stream; 339 struct sst_hsw_log_stream log_stream;
340
341 /* flags bit field to track module state when resume from RTD3,
342 * each bit represent state (enabled/disabled) of single module */
343 u32 enabled_modules_rtd3;
340}; 344};
341 345
342#define CREATE_TRACE_POINTS 346#define CREATE_TRACE_POINTS
@@ -1986,6 +1990,21 @@ bool sst_hsw_is_module_active(struct sst_hsw *hsw, u32 module_id)
1986 return false; 1990 return false;
1987} 1991}
1988 1992
1993void sst_hsw_set_module_enabled_rtd3(struct sst_hsw *hsw, u32 module_id)
1994{
1995 hsw->enabled_modules_rtd3 |= (1 << module_id);
1996}
1997
1998void sst_hsw_set_module_disabled_rtd3(struct sst_hsw *hsw, u32 module_id)
1999{
2000 hsw->enabled_modules_rtd3 &= ~(1 << module_id);
2001}
2002
2003bool sst_hsw_is_module_enabled_rtd3(struct sst_hsw *hsw, u32 module_id)
2004{
2005 return hsw->enabled_modules_rtd3 & (1 << module_id);
2006}
2007
1989int sst_hsw_module_load(struct sst_hsw *hsw, 2008int sst_hsw_module_load(struct sst_hsw *hsw,
1990 u32 module_id, u32 instance_id, char *name) 2009 u32 module_id, u32 instance_id, char *name)
1991{ 2010{
diff --git a/sound/soc/intel/sst-haswell-ipc.h b/sound/soc/intel/sst-haswell-ipc.h
index 30c65b28fa60..48290a1cfe5d 100644
--- a/sound/soc/intel/sst-haswell-ipc.h
+++ b/sound/soc/intel/sst-haswell-ipc.h
@@ -477,6 +477,9 @@ struct sst_dsp *sst_hsw_get_dsp(struct sst_hsw *hsw);
477void sst_hsw_init_module_state(struct sst_hsw *hsw); 477void sst_hsw_init_module_state(struct sst_hsw *hsw);
478bool sst_hsw_is_module_loaded(struct sst_hsw *hsw, u32 module_id); 478bool sst_hsw_is_module_loaded(struct sst_hsw *hsw, u32 module_id);
479bool sst_hsw_is_module_active(struct sst_hsw *hsw, u32 module_id); 479bool sst_hsw_is_module_active(struct sst_hsw *hsw, u32 module_id);
480void sst_hsw_set_module_enabled_rtd3(struct sst_hsw *hsw, u32 module_id);
481void sst_hsw_set_module_disabled_rtd3(struct sst_hsw *hsw, u32 module_id);
482bool sst_hsw_is_module_enabled_rtd3(struct sst_hsw *hsw, u32 module_id);
480 483
481int sst_hsw_module_load(struct sst_hsw *hsw, 484int sst_hsw_module_load(struct sst_hsw *hsw,
482 u32 module_id, u32 instance_id, char *name); 485 u32 module_id, u32 instance_id, char *name);
diff --git a/sound/soc/intel/sst-haswell-pcm.c b/sound/soc/intel/sst-haswell-pcm.c
index a604cc442111..b3de87aac373 100644
--- a/sound/soc/intel/sst-haswell-pcm.c
+++ b/sound/soc/intel/sst-haswell-pcm.c
@@ -318,6 +318,54 @@ static int hsw_volume_get(struct snd_kcontrol *kcontrol,
318 return 0; 318 return 0;
319} 319}
320 320
321static int hsw_waves_switch_get(struct snd_kcontrol *kcontrol,
322 struct snd_ctl_elem_value *ucontrol)
323{
324 struct snd_soc_platform *platform = snd_soc_kcontrol_platform(kcontrol);
325 struct hsw_priv_data *pdata = snd_soc_platform_get_drvdata(platform);
326 struct sst_hsw *hsw = pdata->hsw;
327 enum sst_hsw_module_id id = SST_HSW_MODULE_WAVES;
328
329 ucontrol->value.integer.value[0] =
330 (sst_hsw_is_module_active(hsw, id) ||
331 sst_hsw_is_module_enabled_rtd3(hsw, id));
332 return 0;
333}
334
335static int hsw_waves_switch_put(struct snd_kcontrol *kcontrol,
336 struct snd_ctl_elem_value *ucontrol)
337{
338 struct snd_soc_platform *platform = snd_soc_kcontrol_platform(kcontrol);
339 struct hsw_priv_data *pdata = snd_soc_platform_get_drvdata(platform);
340 struct sst_hsw *hsw = pdata->hsw;
341 int ret = 0;
342 enum sst_hsw_module_id id = SST_HSW_MODULE_WAVES;
343 bool switch_on = (bool)ucontrol->value.integer.value[0];
344
345 /* if module is in RAM on the DSP, apply user settings to module through
346 * ipc. If module is not in RAM on the DSP, store user setting for
347 * track */
348 if (sst_hsw_is_module_loaded(hsw, id)) {
349 if (switch_on == sst_hsw_is_module_active(hsw, id))
350 return 0;
351
352 if (switch_on)
353 ret = sst_hsw_module_enable(hsw, id, 0);
354 else
355 ret = sst_hsw_module_disable(hsw, id, 0);
356 } else {
357 if (switch_on == sst_hsw_is_module_enabled_rtd3(hsw, id))
358 return 0;
359
360 if (switch_on)
361 sst_hsw_set_module_enabled_rtd3(hsw, id);
362 else
363 sst_hsw_set_module_disabled_rtd3(hsw, id);
364 }
365
366 return ret;
367}
368
321/* TLV used by both global and stream volumes */ 369/* TLV used by both global and stream volumes */
322static const DECLARE_TLV_DB_SCALE(hsw_vol_tlv, -9000, 300, 1); 370static const DECLARE_TLV_DB_SCALE(hsw_vol_tlv, -9000, 300, 1);
323 371
@@ -339,6 +387,9 @@ static const struct snd_kcontrol_new hsw_volume_controls[] = {
339 SOC_DOUBLE_EXT_TLV("Mic Capture Volume", 4, 0, 8, 387 SOC_DOUBLE_EXT_TLV("Mic Capture Volume", 4, 0, 8,
340 ARRAY_SIZE(volume_map) - 1, 0, 388 ARRAY_SIZE(volume_map) - 1, 0,
341 hsw_stream_volume_get, hsw_stream_volume_put, hsw_vol_tlv), 389 hsw_stream_volume_get, hsw_stream_volume_put, hsw_vol_tlv),
390 /* enable/disable module waves */
391 SOC_SINGLE_BOOL_EXT("Waves Switch", 0,
392 hsw_waves_switch_get, hsw_waves_switch_put),
342}; 393};
343 394
344/* Create DMA buffer page table for DSP */ 395/* Create DMA buffer page table for DSP */
@@ -1118,10 +1169,18 @@ static int hsw_pcm_runtime_suspend(struct device *dev)
1118{ 1169{
1119 struct hsw_priv_data *pdata = dev_get_drvdata(dev); 1170 struct hsw_priv_data *pdata = dev_get_drvdata(dev);
1120 struct sst_hsw *hsw = pdata->hsw; 1171 struct sst_hsw *hsw = pdata->hsw;
1172 int ret;
1121 1173
1122 if (pdata->pm_state >= HSW_PM_STATE_RTD3) 1174 if (pdata->pm_state >= HSW_PM_STATE_RTD3)
1123 return 0; 1175 return 0;
1124 1176
1177 /* fw modules will be unloaded on RTD3, set flag to track */
1178 if (sst_hsw_is_module_active(hsw, SST_HSW_MODULE_WAVES)) {
1179 ret = sst_hsw_module_disable(hsw, SST_HSW_MODULE_WAVES, 0);
1180 if (ret < 0)
1181 return ret;
1182 sst_hsw_set_module_enabled_rtd3(hsw, SST_HSW_MODULE_WAVES);
1183 }
1125 sst_hsw_dsp_runtime_suspend(hsw); 1184 sst_hsw_dsp_runtime_suspend(hsw);
1126 sst_hsw_dsp_runtime_sleep(hsw); 1185 sst_hsw_dsp_runtime_sleep(hsw);
1127 pdata->pm_state = HSW_PM_STATE_RTD3; 1186 pdata->pm_state = HSW_PM_STATE_RTD3;
@@ -1156,6 +1215,15 @@ static int hsw_pcm_runtime_resume(struct device *dev)
1156 else if (ret == 1) /* no action required */ 1215 else if (ret == 1) /* no action required */
1157 return 0; 1216 return 0;
1158 1217
1218 /* check flag when resume */
1219 if (sst_hsw_is_module_enabled_rtd3(hsw, SST_HSW_MODULE_WAVES)) {
1220 ret = sst_hsw_module_enable(hsw, SST_HSW_MODULE_WAVES, 0);
1221 if (ret < 0)
1222 return ret;
1223 /* unset flag */
1224 sst_hsw_set_module_disabled_rtd3(hsw, SST_HSW_MODULE_WAVES);
1225 }
1226
1159 pdata->pm_state = HSW_PM_STATE_D0; 1227 pdata->pm_state = HSW_PM_STATE_D0;
1160 return ret; 1228 return ret;
1161} 1229}