diff options
author | Lu, Han <han.lu@intel.com> | 2015-03-12 01:53:00 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-03-12 15:18:14 -0400 |
commit | 76c07b8265c68d9a89fb4c0a634e373a087f11be (patch) | |
tree | d972cf3abd74d00193df8c22e4b0e7a1da51be20 | |
parent | e8e79ede44ec99e09f8604c23ee99dc25065a343 (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.c | 19 | ||||
-rw-r--r-- | sound/soc/intel/sst-haswell-ipc.h | 3 | ||||
-rw-r--r-- | sound/soc/intel/sst-haswell-pcm.c | 68 |
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 | ||
1993 | void sst_hsw_set_module_enabled_rtd3(struct sst_hsw *hsw, u32 module_id) | ||
1994 | { | ||
1995 | hsw->enabled_modules_rtd3 |= (1 << module_id); | ||
1996 | } | ||
1997 | |||
1998 | void sst_hsw_set_module_disabled_rtd3(struct sst_hsw *hsw, u32 module_id) | ||
1999 | { | ||
2000 | hsw->enabled_modules_rtd3 &= ~(1 << module_id); | ||
2001 | } | ||
2002 | |||
2003 | bool 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 | |||
1989 | int sst_hsw_module_load(struct sst_hsw *hsw, | 2008 | int 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); | |||
477 | void sst_hsw_init_module_state(struct sst_hsw *hsw); | 477 | void sst_hsw_init_module_state(struct sst_hsw *hsw); |
478 | bool sst_hsw_is_module_loaded(struct sst_hsw *hsw, u32 module_id); | 478 | bool sst_hsw_is_module_loaded(struct sst_hsw *hsw, u32 module_id); |
479 | bool sst_hsw_is_module_active(struct sst_hsw *hsw, u32 module_id); | 479 | bool sst_hsw_is_module_active(struct sst_hsw *hsw, u32 module_id); |
480 | void sst_hsw_set_module_enabled_rtd3(struct sst_hsw *hsw, u32 module_id); | ||
481 | void sst_hsw_set_module_disabled_rtd3(struct sst_hsw *hsw, u32 module_id); | ||
482 | bool sst_hsw_is_module_enabled_rtd3(struct sst_hsw *hsw, u32 module_id); | ||
480 | 483 | ||
481 | int sst_hsw_module_load(struct sst_hsw *hsw, | 484 | int 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 | ||
321 | static 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 | |||
335 | static 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 */ |
322 | static const DECLARE_TLV_DB_SCALE(hsw_vol_tlv, -9000, 300, 1); | 370 | static 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 | } |