aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLu, Han <han.lu@intel.com>2015-03-12 01:53:02 -0400
committerMark Brown <broonie@kernel.org>2015-03-12 15:18:14 -0400
commit3814c204446822cd3c82ec4e8616600732c1f94e (patch)
tree40787c2f195684df7b6592296aab9406daf5bf75
parent201892268b8335ae8c9dc7cc9a0d4bf6e1336f0e (diff)
ASoC: Intel: add kcontrol to set parameter to sound effect module waves
Each kcontrol command includes a line of parameters up to 128 bytes. kcontrol command to set param: cset "name='Waves Set Param' <0x01,0xff,...>" or cset-bin-file "name='Waves Set Param' <path/to/binary/config/file>" The parameter lines are stored in a buffer array, so can be read back from buffer rather than from DSP, and be relaunched to DSP when resume from RTD3. The buffer size is 160 parameter lines. kcontrol command to reset the buffer: cset "name='Waves Set Param' 0xff" alsa-lib v1.0.29 or commit 6ea14c36 and f47480af are required to support the kcontrol commands. 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.c64
-rw-r--r--sound/soc/intel/sst-haswell-ipc.h6
-rw-r--r--sound/soc/intel/sst-haswell-pcm.c50
3 files changed, 120 insertions, 0 deletions
diff --git a/sound/soc/intel/sst-haswell-ipc.c b/sound/soc/intel/sst-haswell-ipc.c
index a97324dff8fa..43fb5f339168 100644
--- a/sound/soc/intel/sst-haswell-ipc.c
+++ b/sound/soc/intel/sst-haswell-ipc.c
@@ -341,6 +341,11 @@ struct sst_hsw {
341 /* flags bit field to track module state when resume from RTD3, 341 /* flags bit field to track module state when resume from RTD3,
342 * each bit represent state (enabled/disabled) of single module */ 342 * each bit represent state (enabled/disabled) of single module */
343 u32 enabled_modules_rtd3; 343 u32 enabled_modules_rtd3;
344
345 /* buffer to store parameter lines */
346 u32 param_idx_w; /* write index */
347 u32 param_idx_r; /* read index */
348 u8 param_buf[WAVES_PARAM_LINES][WAVES_PARAM_COUNT];
344}; 349};
345 350
346#define CREATE_TRACE_POINTS 351#define CREATE_TRACE_POINTS
@@ -2005,6 +2010,62 @@ bool sst_hsw_is_module_enabled_rtd3(struct sst_hsw *hsw, u32 module_id)
2005 return hsw->enabled_modules_rtd3 & (1 << module_id); 2010 return hsw->enabled_modules_rtd3 & (1 << module_id);
2006} 2011}
2007 2012
2013void sst_hsw_reset_param_buf(struct sst_hsw *hsw)
2014{
2015 hsw->param_idx_w = 0;
2016 hsw->param_idx_r = 0;
2017 memset((void *)hsw->param_buf, 0, sizeof(hsw->param_buf));
2018}
2019
2020int sst_hsw_store_param_line(struct sst_hsw *hsw, u8 *buf)
2021{
2022 /* save line to the first available position of param buffer */
2023 if (hsw->param_idx_w > WAVES_PARAM_LINES - 1) {
2024 dev_warn(hsw->dev, "warning: param buffer overflow!\n");
2025 return -EPERM;
2026 }
2027 memcpy(hsw->param_buf[hsw->param_idx_w], buf, WAVES_PARAM_COUNT);
2028 hsw->param_idx_w++;
2029 return 0;
2030}
2031
2032int sst_hsw_load_param_line(struct sst_hsw *hsw, u8 *buf)
2033{
2034 u8 id = 0;
2035
2036 /* read the first matching line from param buffer */
2037 while (hsw->param_idx_r < WAVES_PARAM_LINES) {
2038 id = hsw->param_buf[hsw->param_idx_r][0];
2039 hsw->param_idx_r++;
2040 if (buf[0] == id) {
2041 memcpy(buf, hsw->param_buf[hsw->param_idx_r],
2042 WAVES_PARAM_COUNT);
2043 break;
2044 }
2045 }
2046 if (hsw->param_idx_r > WAVES_PARAM_LINES - 1) {
2047 dev_dbg(hsw->dev, "end of buffer, roll to the beginning\n");
2048 hsw->param_idx_r = 0;
2049 return 0;
2050 }
2051 return 0;
2052}
2053
2054int sst_hsw_launch_param_buf(struct sst_hsw *hsw)
2055{
2056 int ret, idx;
2057
2058 /* put all param lines to DSP through ipc */
2059 for (idx = 0; idx < hsw->param_idx_w; idx++) {
2060 ret = sst_hsw_module_set_param(hsw,
2061 SST_HSW_MODULE_WAVES, 0, hsw->param_buf[idx][0],
2062 WAVES_PARAM_COUNT, hsw->param_buf[idx]);
2063 if (ret < 0)
2064 return ret;
2065 }
2066 return 0;
2067}
2068
2008int sst_hsw_module_load(struct sst_hsw *hsw, 2069int sst_hsw_module_load(struct sst_hsw *hsw,
2009 u32 module_id, u32 instance_id, char *name) 2070 u32 module_id, u32 instance_id, char *name)
2010{ 2071{
@@ -2299,6 +2360,9 @@ int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata)
2299 if (ret < 0) 2360 if (ret < 0)
2300 goto boot_err; 2361 goto boot_err;
2301 2362
2363 /* init param buffer */
2364 sst_hsw_reset_param_buf(hsw);
2365
2302 /* wait for DSP boot completion */ 2366 /* wait for DSP boot completion */
2303 sst_dsp_boot(hsw->dsp); 2367 sst_dsp_boot(hsw->dsp);
2304 ret = wait_event_timeout(hsw->boot_wait, hsw->boot_complete, 2368 ret = wait_event_timeout(hsw->boot_wait, hsw->boot_complete,
diff --git a/sound/soc/intel/sst-haswell-ipc.h b/sound/soc/intel/sst-haswell-ipc.h
index 16bec433265c..06d71aefa1fe 100644
--- a/sound/soc/intel/sst-haswell-ipc.h
+++ b/sound/soc/intel/sst-haswell-ipc.h
@@ -38,6 +38,8 @@
38#define SST_HSW_MAX_INFO_SIZE 64 38#define SST_HSW_MAX_INFO_SIZE 64
39#define SST_HSW_BUILD_HASH_LENGTH 40 39#define SST_HSW_BUILD_HASH_LENGTH 40
40#define SST_HSW_IPC_MAX_SHORT_PARAMETER_SIZE 500 40#define SST_HSW_IPC_MAX_SHORT_PARAMETER_SIZE 500
41#define WAVES_PARAM_COUNT 128
42#define WAVES_PARAM_LINES 160
41 43
42struct sst_hsw; 44struct sst_hsw;
43struct sst_hsw_stream; 45struct sst_hsw_stream;
@@ -503,6 +505,10 @@ bool sst_hsw_is_module_active(struct sst_hsw *hsw, u32 module_id);
503void sst_hsw_set_module_enabled_rtd3(struct sst_hsw *hsw, u32 module_id); 505void sst_hsw_set_module_enabled_rtd3(struct sst_hsw *hsw, u32 module_id);
504void sst_hsw_set_module_disabled_rtd3(struct sst_hsw *hsw, u32 module_id); 506void sst_hsw_set_module_disabled_rtd3(struct sst_hsw *hsw, u32 module_id);
505bool sst_hsw_is_module_enabled_rtd3(struct sst_hsw *hsw, u32 module_id); 507bool sst_hsw_is_module_enabled_rtd3(struct sst_hsw *hsw, u32 module_id);
508void sst_hsw_reset_param_buf(struct sst_hsw *hsw);
509int sst_hsw_store_param_line(struct sst_hsw *hsw, u8 *buf);
510int sst_hsw_load_param_line(struct sst_hsw *hsw, u8 *buf);
511int sst_hsw_launch_param_buf(struct sst_hsw *hsw);
506 512
507int sst_hsw_module_load(struct sst_hsw *hsw, 513int sst_hsw_module_load(struct sst_hsw *hsw,
508 u32 module_id, u32 instance_id, char *name); 514 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 b3de87aac373..b40ec746bc19 100644
--- a/sound/soc/intel/sst-haswell-pcm.c
+++ b/sound/soc/intel/sst-haswell-pcm.c
@@ -366,6 +366,49 @@ static int hsw_waves_switch_put(struct snd_kcontrol *kcontrol,
366 return ret; 366 return ret;
367} 367}
368 368
369static int hsw_waves_param_get(struct snd_kcontrol *kcontrol,
370 struct snd_ctl_elem_value *ucontrol)
371{
372 struct snd_soc_platform *platform = snd_soc_kcontrol_platform(kcontrol);
373 struct hsw_priv_data *pdata = snd_soc_platform_get_drvdata(platform);
374 struct sst_hsw *hsw = pdata->hsw;
375
376 /* return a matching line from param buffer */
377 return sst_hsw_load_param_line(hsw, ucontrol->value.bytes.data);
378}
379
380static int hsw_waves_param_put(struct snd_kcontrol *kcontrol,
381 struct snd_ctl_elem_value *ucontrol)
382{
383 struct snd_soc_platform *platform = snd_soc_kcontrol_platform(kcontrol);
384 struct hsw_priv_data *pdata = snd_soc_platform_get_drvdata(platform);
385 struct sst_hsw *hsw = pdata->hsw;
386 int ret;
387 enum sst_hsw_module_id id = SST_HSW_MODULE_WAVES;
388 int param_id = ucontrol->value.bytes.data[0];
389 int param_size = WAVES_PARAM_COUNT;
390
391 /* clear param buffer and reset buffer index */
392 if (param_id == 0xFF) {
393 sst_hsw_reset_param_buf(hsw);
394 return 0;
395 }
396
397 /* store params into buffer */
398 ret = sst_hsw_store_param_line(hsw, ucontrol->value.bytes.data);
399 if (ret < 0)
400 return ret;
401
402 if (sst_hsw_is_module_loaded(hsw, id)) {
403 if (!sst_hsw_is_module_active(hsw, id))
404 return 0;
405
406 ret = sst_hsw_module_set_param(hsw, id, 0, param_id,
407 param_size, ucontrol->value.bytes.data);
408 }
409 return ret;
410}
411
369/* TLV used by both global and stream volumes */ 412/* TLV used by both global and stream volumes */
370static const DECLARE_TLV_DB_SCALE(hsw_vol_tlv, -9000, 300, 1); 413static const DECLARE_TLV_DB_SCALE(hsw_vol_tlv, -9000, 300, 1);
371 414
@@ -390,6 +433,9 @@ static const struct snd_kcontrol_new hsw_volume_controls[] = {
390 /* enable/disable module waves */ 433 /* enable/disable module waves */
391 SOC_SINGLE_BOOL_EXT("Waves Switch", 0, 434 SOC_SINGLE_BOOL_EXT("Waves Switch", 0,
392 hsw_waves_switch_get, hsw_waves_switch_put), 435 hsw_waves_switch_get, hsw_waves_switch_put),
436 /* set parameters to module waves */
437 SND_SOC_BYTES_EXT("Waves Set Param", WAVES_PARAM_COUNT,
438 hsw_waves_param_get, hsw_waves_param_put),
393}; 439};
394 440
395/* Create DMA buffer page table for DSP */ 441/* Create DMA buffer page table for DSP */
@@ -1220,6 +1266,10 @@ static int hsw_pcm_runtime_resume(struct device *dev)
1220 ret = sst_hsw_module_enable(hsw, SST_HSW_MODULE_WAVES, 0); 1266 ret = sst_hsw_module_enable(hsw, SST_HSW_MODULE_WAVES, 0);
1221 if (ret < 0) 1267 if (ret < 0)
1222 return ret; 1268 return ret;
1269 /* put parameters from buffer to dsp */
1270 ret = sst_hsw_launch_param_buf(hsw);
1271 if (ret < 0)
1272 return ret;
1223 /* unset flag */ 1273 /* unset flag */
1224 sst_hsw_set_module_disabled_rtd3(hsw, SST_HSW_MODULE_WAVES); 1274 sst_hsw_set_module_disabled_rtd3(hsw, SST_HSW_MODULE_WAVES);
1225 } 1275 }