aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2015-04-12 14:48:33 -0400
committerMark Brown <broonie@kernel.org>2015-04-12 14:48:33 -0400
commitaab0bb17ef2440ef5f68dcde5f1a6b32dcdfa9fb (patch)
tree6e14e997a1424e189d47ec04f4b1e1b8e6d85491
parent77b62fa5d23988155132cf7fee44f2c209e3dc4c (diff)
parenta5e5e12bd4ed5cd1123ace4300b5c07230fbf21e (diff)
Merge remote-tracking branch 'asoc/topic/intel' into asoc-next
-rw-r--r--include/sound/rt5670.h1
-rw-r--r--sound/soc/codecs/rt5670.c213
-rw-r--r--sound/soc/codecs/rt5670.h7
-rw-r--r--sound/soc/intel/Makefile42
-rw-r--r--sound/soc/intel/atom/Makefile7
-rw-r--r--sound/soc/intel/atom/sst-atom-controls.c (renamed from sound/soc/intel/sst-atom-controls.c)0
-rw-r--r--sound/soc/intel/atom/sst-atom-controls.h (renamed from sound/soc/intel/sst-atom-controls.h)0
-rw-r--r--sound/soc/intel/atom/sst-mfld-dsp.h (renamed from sound/soc/intel/sst-mfld-dsp.h)0
-rw-r--r--sound/soc/intel/atom/sst-mfld-platform-compress.c (renamed from sound/soc/intel/sst-mfld-platform-compress.c)0
-rw-r--r--sound/soc/intel/atom/sst-mfld-platform-pcm.c (renamed from sound/soc/intel/sst-mfld-platform-pcm.c)0
-rw-r--r--sound/soc/intel/atom/sst-mfld-platform.h (renamed from sound/soc/intel/sst-mfld-platform.h)0
-rw-r--r--sound/soc/intel/atom/sst/Makefile (renamed from sound/soc/intel/sst/Makefile)0
-rw-r--r--sound/soc/intel/atom/sst/sst.c (renamed from sound/soc/intel/sst/sst.c)2
-rw-r--r--sound/soc/intel/atom/sst/sst.h (renamed from sound/soc/intel/sst/sst.h)0
-rw-r--r--sound/soc/intel/atom/sst/sst_acpi.c (renamed from sound/soc/intel/sst/sst_acpi.c)2
-rw-r--r--sound/soc/intel/atom/sst/sst_drv_interface.c (renamed from sound/soc/intel/sst/sst_drv_interface.c)4
-rw-r--r--sound/soc/intel/atom/sst/sst_ipc.c (renamed from sound/soc/intel/sst/sst_ipc.c)2
-rw-r--r--sound/soc/intel/atom/sst/sst_loader.c (renamed from sound/soc/intel/sst/sst_loader.c)2
-rw-r--r--sound/soc/intel/atom/sst/sst_pci.c (renamed from sound/soc/intel/sst/sst_pci.c)0
-rw-r--r--sound/soc/intel/atom/sst/sst_pvt.c (renamed from sound/soc/intel/sst/sst_pvt.c)26
-rw-r--r--sound/soc/intel/atom/sst/sst_stream.c (renamed from sound/soc/intel/sst/sst_stream.c)2
-rw-r--r--sound/soc/intel/baytrail/Makefile4
-rw-r--r--sound/soc/intel/baytrail/sst-baytrail-dsp.c (renamed from sound/soc/intel/sst-baytrail-dsp.c)4
-rw-r--r--sound/soc/intel/baytrail/sst-baytrail-ipc.c (renamed from sound/soc/intel/sst-baytrail-ipc.c)364
-rw-r--r--sound/soc/intel/baytrail/sst-baytrail-ipc.h (renamed from sound/soc/intel/sst-baytrail-ipc.h)0
-rw-r--r--sound/soc/intel/baytrail/sst-baytrail-pcm.c (renamed from sound/soc/intel/sst-baytrail-pcm.c)4
-rw-r--r--sound/soc/intel/boards/Makefile15
-rw-r--r--sound/soc/intel/boards/broadwell.c (renamed from sound/soc/intel/broadwell.c)34
-rw-r--r--sound/soc/intel/boards/byt-max98090.c (renamed from sound/soc/intel/byt-max98090.c)2
-rw-r--r--sound/soc/intel/boards/byt-rt5640.c (renamed from sound/soc/intel/byt-rt5640.c)4
-rw-r--r--sound/soc/intel/boards/bytcr_rt5640.c (renamed from sound/soc/intel/bytcr_dpcm_rt5640.c)4
-rw-r--r--sound/soc/intel/boards/cht_bsw_rt5645.c (renamed from sound/soc/intel/cht_bsw_rt5645.c)4
-rw-r--r--sound/soc/intel/boards/cht_bsw_rt5672.c (renamed from sound/soc/intel/cht_bsw_rt5672.c)99
-rw-r--r--sound/soc/intel/boards/haswell.c (renamed from sound/soc/intel/haswell.c)6
-rw-r--r--sound/soc/intel/boards/mfld_machine.c (renamed from sound/soc/intel/mfld_machine.c)0
-rw-r--r--sound/soc/intel/common/Makefile7
-rw-r--r--sound/soc/intel/common/sst-acpi.c (renamed from sound/soc/intel/sst-acpi.c)0
-rw-r--r--sound/soc/intel/common/sst-dsp-priv.h (renamed from sound/soc/intel/sst-dsp-priv.h)13
-rw-r--r--sound/soc/intel/common/sst-dsp.c (renamed from sound/soc/intel/sst-dsp.c)0
-rw-r--r--sound/soc/intel/common/sst-dsp.h (renamed from sound/soc/intel/sst-dsp.h)1
-rw-r--r--sound/soc/intel/common/sst-firmware.c (renamed from sound/soc/intel/sst-firmware.c)6
-rw-r--r--sound/soc/intel/common/sst-ipc.c294
-rw-r--r--sound/soc/intel/common/sst-ipc.h91
-rw-r--r--sound/soc/intel/haswell/Makefile4
-rw-r--r--sound/soc/intel/haswell/sst-haswell-dsp.c (renamed from sound/soc/intel/sst-haswell-dsp.c)9
-rw-r--r--sound/soc/intel/haswell/sst-haswell-ipc.c (renamed from sound/soc/intel/sst-haswell-ipc.c)794
-rw-r--r--sound/soc/intel/haswell/sst-haswell-ipc.h (renamed from sound/soc/intel/sst-haswell-ipc.h)53
-rw-r--r--sound/soc/intel/haswell/sst-haswell-pcm.c (renamed from sound/soc/intel/sst-haswell-pcm.c)140
48 files changed, 1554 insertions, 712 deletions
diff --git a/include/sound/rt5670.h b/include/sound/rt5670.h
index bd311197a3b5..b7d60510819b 100644
--- a/include/sound/rt5670.h
+++ b/include/sound/rt5670.h
@@ -14,6 +14,7 @@
14struct rt5670_platform_data { 14struct rt5670_platform_data {
15 int jd_mode; 15 int jd_mode;
16 bool in2_diff; 16 bool in2_diff;
17 bool dev_gpio;
17 18
18 bool dmic_en; 19 bool dmic_en;
19 unsigned int dmic1_data_pin; 20 unsigned int dmic1_data_pin;
diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c
index fd102613d20d..cc7f84a150a7 100644
--- a/sound/soc/codecs/rt5670.c
+++ b/sound/soc/codecs/rt5670.c
@@ -403,6 +403,189 @@ static bool rt5670_readable_register(struct device *dev, unsigned int reg)
403 } 403 }
404} 404}
405 405
406/**
407 * rt5670_headset_detect - Detect headset.
408 * @codec: SoC audio codec device.
409 * @jack_insert: Jack insert or not.
410 *
411 * Detect whether is headset or not when jack inserted.
412 *
413 * Returns detect status.
414 */
415
416static int rt5670_headset_detect(struct snd_soc_codec *codec, int jack_insert)
417{
418 int val;
419 struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
420
421 if (jack_insert) {
422 snd_soc_dapm_force_enable_pin(&codec->dapm,
423 "Mic Det Power");
424 snd_soc_dapm_sync(&codec->dapm);
425 snd_soc_update_bits(codec, RT5670_GEN_CTRL3, 0x4, 0x0);
426 snd_soc_update_bits(codec, RT5670_CJ_CTRL2,
427 RT5670_CBJ_DET_MODE | RT5670_CBJ_MN_JD,
428 RT5670_CBJ_MN_JD);
429 snd_soc_write(codec, RT5670_GPIO_CTRL2, 0x0004);
430 snd_soc_update_bits(codec, RT5670_GPIO_CTRL1,
431 RT5670_GP1_PIN_MASK, RT5670_GP1_PIN_IRQ);
432 snd_soc_update_bits(codec, RT5670_CJ_CTRL1,
433 RT5670_CBJ_BST1_EN, RT5670_CBJ_BST1_EN);
434 snd_soc_write(codec, RT5670_JD_CTRL3, 0x00f0);
435 snd_soc_update_bits(codec, RT5670_CJ_CTRL2,
436 RT5670_CBJ_MN_JD, RT5670_CBJ_MN_JD);
437 snd_soc_update_bits(codec, RT5670_CJ_CTRL2,
438 RT5670_CBJ_MN_JD, 0);
439 msleep(300);
440 val = snd_soc_read(codec, RT5670_CJ_CTRL3) & 0x7;
441 if (val == 0x1 || val == 0x2) {
442 rt5670->jack_type = SND_JACK_HEADSET;
443 /* for push button */
444 snd_soc_update_bits(codec, RT5670_INT_IRQ_ST, 0x8, 0x8);
445 snd_soc_update_bits(codec, RT5670_IL_CMD, 0x40, 0x40);
446 snd_soc_read(codec, RT5670_IL_CMD);
447 } else {
448 snd_soc_update_bits(codec, RT5670_GEN_CTRL3, 0x4, 0x4);
449 rt5670->jack_type = SND_JACK_HEADPHONE;
450 snd_soc_dapm_disable_pin(&codec->dapm, "Mic Det Power");
451 snd_soc_dapm_sync(&codec->dapm);
452 }
453 } else {
454 snd_soc_update_bits(codec, RT5670_INT_IRQ_ST, 0x8, 0x0);
455 snd_soc_update_bits(codec, RT5670_GEN_CTRL3, 0x4, 0x4);
456 rt5670->jack_type = 0;
457 snd_soc_dapm_disable_pin(&codec->dapm, "Mic Det Power");
458 snd_soc_dapm_sync(&codec->dapm);
459 }
460
461 return rt5670->jack_type;
462}
463
464void rt5670_jack_suspend(struct snd_soc_codec *codec)
465{
466 struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
467
468 rt5670->jack_type_saved = rt5670->jack_type;
469 rt5670_headset_detect(codec, 0);
470}
471EXPORT_SYMBOL_GPL(rt5670_jack_suspend);
472
473void rt5670_jack_resume(struct snd_soc_codec *codec)
474{
475 struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
476
477 if (rt5670->jack_type_saved)
478 rt5670_headset_detect(codec, 1);
479}
480EXPORT_SYMBOL_GPL(rt5670_jack_resume);
481
482static int rt5670_button_detect(struct snd_soc_codec *codec)
483{
484 int btn_type, val;
485
486 val = snd_soc_read(codec, RT5670_IL_CMD);
487 btn_type = val & 0xff80;
488 snd_soc_write(codec, RT5670_IL_CMD, val);
489 if (btn_type != 0) {
490 msleep(20);
491 val = snd_soc_read(codec, RT5670_IL_CMD);
492 snd_soc_write(codec, RT5670_IL_CMD, val);
493 }
494
495 return btn_type;
496}
497
498static int rt5670_irq_detection(void *data)
499{
500 struct rt5670_priv *rt5670 = (struct rt5670_priv *)data;
501 struct snd_soc_jack_gpio *gpio = &rt5670->hp_gpio;
502 struct snd_soc_jack *jack = rt5670->jack;
503 int val, btn_type, report = jack->status;
504
505 if (rt5670->pdata.jd_mode == 1) /* 2 port */
506 val = snd_soc_read(rt5670->codec, RT5670_A_JD_CTRL1) & 0x0070;
507 else
508 val = snd_soc_read(rt5670->codec, RT5670_A_JD_CTRL1) & 0x0020;
509
510 switch (val) {
511 /* jack in */
512 case 0x30: /* 2 port */
513 case 0x0: /* 1 port or 2 port */
514 if (rt5670->jack_type == 0) {
515 report = rt5670_headset_detect(rt5670->codec, 1);
516 /* for push button and jack out */
517 gpio->debounce_time = 25;
518 break;
519 }
520 btn_type = 0;
521 if (snd_soc_read(rt5670->codec, RT5670_INT_IRQ_ST) & 0x4) {
522 /* button pressed */
523 report = SND_JACK_HEADSET;
524 btn_type = rt5670_button_detect(rt5670->codec);
525 switch (btn_type) {
526 case 0x2000: /* up */
527 report |= SND_JACK_BTN_1;
528 break;
529 case 0x0400: /* center */
530 report |= SND_JACK_BTN_0;
531 break;
532 case 0x0080: /* down */
533 report |= SND_JACK_BTN_2;
534 break;
535 default:
536 dev_err(rt5670->codec->dev,
537 "Unexpected button code 0x%04x\n",
538 btn_type);
539 break;
540 }
541 }
542 if (btn_type == 0)/* button release */
543 report = rt5670->jack_type;
544
545 break;
546 /* jack out */
547 case 0x70: /* 2 port */
548 case 0x10: /* 2 port */
549 case 0x20: /* 1 port */
550 report = 0;
551 snd_soc_update_bits(rt5670->codec, RT5670_INT_IRQ_ST, 0x1, 0x0);
552 rt5670_headset_detect(rt5670->codec, 0);
553 gpio->debounce_time = 150; /* for jack in */
554 break;
555 default:
556 break;
557 }
558
559 return report;
560}
561
562int rt5670_set_jack_detect(struct snd_soc_codec *codec,
563 struct snd_soc_jack *jack)
564{
565 struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
566 int ret;
567
568 rt5670->jack = jack;
569 rt5670->hp_gpio.gpiod_dev = codec->dev;
570 rt5670->hp_gpio.name = "headphone detect";
571 rt5670->hp_gpio.report = SND_JACK_HEADSET |
572 SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2;
573 rt5670->hp_gpio.debounce_time = 150;
574 rt5670->hp_gpio.wake = true;
575 rt5670->hp_gpio.data = (struct rt5670_priv *)rt5670;
576 rt5670->hp_gpio.jack_status_check = rt5670_irq_detection;
577
578 ret = snd_soc_jack_add_gpios(rt5670->jack, 1,
579 &rt5670->hp_gpio);
580 if (ret) {
581 dev_err(codec->dev, "Adding jack GPIO failed\n");
582 return ret;
583 }
584
585 return 0;
586}
587EXPORT_SYMBOL_GPL(rt5670_set_jack_detect);
588
406static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0); 589static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0);
407static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0); 590static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0);
408static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0); 591static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0);
@@ -517,11 +700,9 @@ static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
517 struct snd_soc_dapm_widget *sink) 700 struct snd_soc_dapm_widget *sink)
518{ 701{
519 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); 702 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
520 unsigned int val; 703 struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
521 704
522 val = snd_soc_read(codec, RT5670_GLB_CLK); 705 if (rt5670->sysclk_src == RT5670_SCLK_S_PLL1)
523 val &= RT5670_SCLK_SRC_MASK;
524 if (val == RT5670_SCLK_SRC_PLL1)
525 return 1; 706 return 1;
526 else 707 else
527 return 0; 708 return 0;
@@ -2271,16 +2452,6 @@ static int rt5670_set_dai_sysclk(struct snd_soc_dai *dai,
2271 struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); 2452 struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
2272 unsigned int reg_val = 0; 2453 unsigned int reg_val = 0;
2273 2454
2274 if (freq == rt5670->sysclk && clk_id == rt5670->sysclk_src)
2275 return 0;
2276
2277 if (rt5670->pdata.jd_mode) {
2278 if (clk_id == RT5670_SCLK_S_PLL1)
2279 snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1");
2280 else
2281 snd_soc_dapm_disable_pin(&codec->dapm, "PLL1");
2282 snd_soc_dapm_sync(&codec->dapm);
2283 }
2284 switch (clk_id) { 2455 switch (clk_id) {
2285 case RT5670_SCLK_S_MCLK: 2456 case RT5670_SCLK_S_MCLK:
2286 reg_val |= RT5670_SCLK_SRC_MCLK; 2457 reg_val |= RT5670_SCLK_SRC_MCLK;
@@ -2298,7 +2469,8 @@ static int rt5670_set_dai_sysclk(struct snd_soc_dai *dai,
2298 snd_soc_update_bits(codec, RT5670_GLB_CLK, 2469 snd_soc_update_bits(codec, RT5670_GLB_CLK,
2299 RT5670_SCLK_SRC_MASK, reg_val); 2470 RT5670_SCLK_SRC_MASK, reg_val);
2300 rt5670->sysclk = freq; 2471 rt5670->sysclk = freq;
2301 rt5670->sysclk_src = clk_id; 2472 if (clk_id != RT5670_SCLK_S_RCCLK)
2473 rt5670->sysclk_src = clk_id;
2302 2474
2303 dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id); 2475 dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id);
2304 2476
@@ -2517,6 +2689,7 @@ static int rt5670_remove(struct snd_soc_codec *codec)
2517 struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec); 2689 struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
2518 2690
2519 regmap_write(rt5670->regmap, RT5670_RESET, 0); 2691 regmap_write(rt5670->regmap, RT5670_RESET, 0);
2692 snd_soc_jack_free_gpios(rt5670->jack, 1, &rt5670->hp_gpio);
2520 return 0; 2693 return 0;
2521} 2694}
2522 2695
@@ -2676,6 +2849,7 @@ static int rt5670_i2c_probe(struct i2c_client *i2c,
2676 if (dmi_check_system(dmi_platform_intel_braswell)) { 2849 if (dmi_check_system(dmi_platform_intel_braswell)) {
2677 rt5670->pdata.dmic_en = true; 2850 rt5670->pdata.dmic_en = true;
2678 rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P; 2851 rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P;
2852 rt5670->pdata.dev_gpio = true;
2679 rt5670->pdata.jd_mode = 1; 2853 rt5670->pdata.jd_mode = 1;
2680 } 2854 }
2681 2855
@@ -2717,12 +2891,17 @@ static int rt5670_i2c_probe(struct i2c_client *i2c,
2717 regmap_update_bits(rt5670->regmap, RT5670_IN2, 2891 regmap_update_bits(rt5670->regmap, RT5670_IN2,
2718 RT5670_IN_DF2, RT5670_IN_DF2); 2892 RT5670_IN_DF2, RT5670_IN_DF2);
2719 2893
2720 if (i2c->irq) { 2894 if (rt5670->pdata.dev_gpio) {
2895 /* for push button */
2896 regmap_write(rt5670->regmap, RT5670_IL_CMD, 0x0000);
2897 regmap_write(rt5670->regmap, RT5670_IL_CMD2, 0x0010);
2898 regmap_write(rt5670->regmap, RT5670_IL_CMD3, 0x0014);
2899 /* for irq */
2721 regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL1, 2900 regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL1,
2722 RT5670_GP1_PIN_MASK, RT5670_GP1_PIN_IRQ); 2901 RT5670_GP1_PIN_MASK, RT5670_GP1_PIN_IRQ);
2723 regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL2, 2902 regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL2,
2724 RT5670_GP1_PF_MASK, RT5670_GP1_PF_OUT); 2903 RT5670_GP1_PF_MASK, RT5670_GP1_PF_OUT);
2725 2904 regmap_update_bits(rt5670->regmap, RT5670_DIG_MISC, 0x8, 0x8);
2726 } 2905 }
2727 2906
2728 if (rt5670->pdata.jd_mode) { 2907 if (rt5670->pdata.jd_mode) {
diff --git a/sound/soc/codecs/rt5670.h b/sound/soc/codecs/rt5670.h
index 0a67adbcfbc3..dc2b46236c5c 100644
--- a/sound/soc/codecs/rt5670.h
+++ b/sound/soc/codecs/rt5670.h
@@ -1988,6 +1988,8 @@ struct rt5670_priv {
1988 struct snd_soc_codec *codec; 1988 struct snd_soc_codec *codec;
1989 struct rt5670_platform_data pdata; 1989 struct rt5670_platform_data pdata;
1990 struct regmap *regmap; 1990 struct regmap *regmap;
1991 struct snd_soc_jack *jack;
1992 struct snd_soc_jack_gpio hp_gpio;
1991 1993
1992 int sysclk; 1994 int sysclk;
1993 int sysclk_src; 1995 int sysclk_src;
@@ -2002,6 +2004,11 @@ struct rt5670_priv {
2002 int dsp_sw; /* expected parameter setting */ 2004 int dsp_sw; /* expected parameter setting */
2003 int dsp_rate; 2005 int dsp_rate;
2004 int jack_type; 2006 int jack_type;
2007 int jack_type_saved;
2005}; 2008};
2006 2009
2010void rt5670_jack_suspend(struct snd_soc_codec *codec);
2011void rt5670_jack_resume(struct snd_soc_codec *codec);
2012int rt5670_set_jack_detect(struct snd_soc_codec *codec,
2013 struct snd_soc_jack *jack);
2007#endif /* __RT5670_H__ */ 2014#endif /* __RT5670_H__ */
diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile
index a8e53c45c6b6..cd9aee9871a3 100644
--- a/sound/soc/intel/Makefile
+++ b/sound/soc/intel/Makefile
@@ -1,42 +1,10 @@
1# Core support 1# Core support
2snd-soc-sst-dsp-objs := sst-dsp.o sst-firmware.o 2obj-$(CONFIG_SND_SOC_INTEL_SST) += common/
3snd-soc-sst-acpi-objs := sst-acpi.o
4
5snd-soc-sst-mfld-platform-objs := sst-mfld-platform-pcm.o \
6 sst-mfld-platform-compress.o sst-atom-controls.o
7snd-soc-mfld-machine-objs := mfld_machine.o
8
9obj-$(CONFIG_SND_SST_MFLD_PLATFORM) += snd-soc-sst-mfld-platform.o
10obj-$(CONFIG_SND_MFLD_MACHINE) += snd-soc-mfld-machine.o
11
12obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o
13obj-$(CONFIG_SND_SOC_INTEL_SST_ACPI) += snd-soc-sst-acpi.o
14 3
15# Platform Support 4# Platform Support
16snd-soc-sst-haswell-pcm-objs := \ 5obj-$(CONFIG_SND_SOC_INTEL_HASWELL) += haswell/
17 sst-haswell-ipc.o sst-haswell-pcm.o sst-haswell-dsp.o 6obj-$(CONFIG_SND_SOC_INTEL_BAYTRAIL) += baytrail/
18snd-soc-sst-baytrail-pcm-objs := \ 7obj-$(CONFIG_SND_SOC_INTEL_BAYTRAIL) += atom/
19 sst-baytrail-ipc.o sst-baytrail-pcm.o sst-baytrail-dsp.o
20
21obj-$(CONFIG_SND_SOC_INTEL_HASWELL) += snd-soc-sst-haswell-pcm.o
22obj-$(CONFIG_SND_SOC_INTEL_BAYTRAIL) += snd-soc-sst-baytrail-pcm.o
23 8
24# Machine support 9# Machine support
25snd-soc-sst-haswell-objs := haswell.o 10obj-$(CONFIG_SND_SOC_INTEL_SST) += boards/
26snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o
27snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o
28snd-soc-sst-broadwell-objs := broadwell.o
29snd-soc-sst-bytcr-dpcm-rt5640-objs := bytcr_dpcm_rt5640.o
30snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o
31snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o
32
33obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o
34obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o
35obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o
36obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o
37obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH) += snd-soc-sst-bytcr-dpcm-rt5640.o
38obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o
39obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o
40
41# DSP driver
42obj-$(CONFIG_SND_SST_IPC) += sst/
diff --git a/sound/soc/intel/atom/Makefile b/sound/soc/intel/atom/Makefile
new file mode 100644
index 000000000000..ce8074fa6d66
--- /dev/null
+++ b/sound/soc/intel/atom/Makefile
@@ -0,0 +1,7 @@
1snd-soc-sst-mfld-platform-objs := sst-mfld-platform-pcm.o \
2 sst-mfld-platform-compress.o sst-atom-controls.o
3
4obj-$(CONFIG_SND_SST_MFLD_PLATFORM) += snd-soc-sst-mfld-platform.o
5
6# DSP driver
7obj-$(CONFIG_SND_SST_IPC) += sst/
diff --git a/sound/soc/intel/sst-atom-controls.c b/sound/soc/intel/atom/sst-atom-controls.c
index 90aa5c0476f3..90aa5c0476f3 100644
--- a/sound/soc/intel/sst-atom-controls.c
+++ b/sound/soc/intel/atom/sst-atom-controls.c
diff --git a/sound/soc/intel/sst-atom-controls.h b/sound/soc/intel/atom/sst-atom-controls.h
index daecc58f28af..daecc58f28af 100644
--- a/sound/soc/intel/sst-atom-controls.h
+++ b/sound/soc/intel/atom/sst-atom-controls.h
diff --git a/sound/soc/intel/sst-mfld-dsp.h b/sound/soc/intel/atom/sst-mfld-dsp.h
index 4257263157cd..4257263157cd 100644
--- a/sound/soc/intel/sst-mfld-dsp.h
+++ b/sound/soc/intel/atom/sst-mfld-dsp.h
diff --git a/sound/soc/intel/sst-mfld-platform-compress.c b/sound/soc/intel/atom/sst-mfld-platform-compress.c
index 395168986462..395168986462 100644
--- a/sound/soc/intel/sst-mfld-platform-compress.c
+++ b/sound/soc/intel/atom/sst-mfld-platform-compress.c
diff --git a/sound/soc/intel/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
index 2fbaf2c75d17..2fbaf2c75d17 100644
--- a/sound/soc/intel/sst-mfld-platform-pcm.c
+++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
diff --git a/sound/soc/intel/sst-mfld-platform.h b/sound/soc/intel/atom/sst-mfld-platform.h
index 9094314be2b0..9094314be2b0 100644
--- a/sound/soc/intel/sst-mfld-platform.h
+++ b/sound/soc/intel/atom/sst-mfld-platform.h
diff --git a/sound/soc/intel/sst/Makefile b/sound/soc/intel/atom/sst/Makefile
index fd21726361b5..fd21726361b5 100644
--- a/sound/soc/intel/sst/Makefile
+++ b/sound/soc/intel/atom/sst/Makefile
diff --git a/sound/soc/intel/sst/sst.c b/sound/soc/intel/atom/sst/sst.c
index 1a7eeec444b1..96c2e420cce6 100644
--- a/sound/soc/intel/sst/sst.c
+++ b/sound/soc/intel/atom/sst/sst.c
@@ -32,7 +32,7 @@
32#include <asm/platform_sst_audio.h> 32#include <asm/platform_sst_audio.h>
33#include "../sst-mfld-platform.h" 33#include "../sst-mfld-platform.h"
34#include "sst.h" 34#include "sst.h"
35#include "../sst-dsp.h" 35#include "../../common/sst-dsp.h"
36 36
37MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>"); 37MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
38MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>"); 38MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
diff --git a/sound/soc/intel/sst/sst.h b/sound/soc/intel/atom/sst/sst.h
index 3f493862e98d..3f493862e98d 100644
--- a/sound/soc/intel/sst/sst.h
+++ b/sound/soc/intel/atom/sst/sst.h
diff --git a/sound/soc/intel/sst/sst_acpi.c b/sound/soc/intel/atom/sst/sst_acpi.c
index b536ddd2517d..05f693083911 100644
--- a/sound/soc/intel/sst/sst_acpi.c
+++ b/sound/soc/intel/atom/sst/sst_acpi.c
@@ -39,7 +39,7 @@
39#include <acpi/actypes.h> 39#include <acpi/actypes.h>
40#include <acpi/acpi_bus.h> 40#include <acpi/acpi_bus.h>
41#include "../sst-mfld-platform.h" 41#include "../sst-mfld-platform.h"
42#include "../sst-dsp.h" 42#include "../../common/sst-dsp.h"
43#include "sst.h" 43#include "sst.h"
44 44
45struct sst_machines { 45struct sst_machines {
diff --git a/sound/soc/intel/sst/sst_drv_interface.c b/sound/soc/intel/atom/sst/sst_drv_interface.c
index f0e4b99b3aeb..7b50a9d17ec1 100644
--- a/sound/soc/intel/sst/sst_drv_interface.c
+++ b/sound/soc/intel/atom/sst/sst_drv_interface.c
@@ -32,7 +32,7 @@
32#include <asm/platform_sst_audio.h> 32#include <asm/platform_sst_audio.h>
33#include "../sst-mfld-platform.h" 33#include "../sst-mfld-platform.h"
34#include "sst.h" 34#include "sst.h"
35#include "../sst-dsp.h" 35#include "../../common/sst-dsp.h"
36 36
37 37
38 38
@@ -381,7 +381,7 @@ static int sst_cdev_tstamp(struct device *dev, unsigned int str_id,
381 tstamp->copied_total = fw_tstamp.ring_buffer_counter; 381 tstamp->copied_total = fw_tstamp.ring_buffer_counter;
382 tstamp->pcm_frames = fw_tstamp.frames_decoded; 382 tstamp->pcm_frames = fw_tstamp.frames_decoded;
383 tstamp->pcm_io_frames = div_u64(fw_tstamp.hardware_counter, 383 tstamp->pcm_io_frames = div_u64(fw_tstamp.hardware_counter,
384 (u64)((stream->num_ch) * SST_GET_BYTES_PER_SAMPLE(24))); 384 (u64)stream->num_ch * SST_GET_BYTES_PER_SAMPLE(24));
385 tstamp->sampling_rate = fw_tstamp.sampling_frequency; 385 tstamp->sampling_rate = fw_tstamp.sampling_frequency;
386 386
387 dev_dbg(dev, "PCM = %u\n", tstamp->pcm_io_frames); 387 dev_dbg(dev, "PCM = %u\n", tstamp->pcm_io_frames);
diff --git a/sound/soc/intel/sst/sst_ipc.c b/sound/soc/intel/atom/sst/sst_ipc.c
index 484e60978477..5a278618466c 100644
--- a/sound/soc/intel/sst/sst_ipc.c
+++ b/sound/soc/intel/atom/sst/sst_ipc.c
@@ -32,7 +32,7 @@
32#include <asm/platform_sst_audio.h> 32#include <asm/platform_sst_audio.h>
33#include "../sst-mfld-platform.h" 33#include "../sst-mfld-platform.h"
34#include "sst.h" 34#include "sst.h"
35#include "../sst-dsp.h" 35#include "../../common/sst-dsp.h"
36 36
37struct sst_block *sst_create_block(struct intel_sst_drv *ctx, 37struct sst_block *sst_create_block(struct intel_sst_drv *ctx,
38 u32 msg_id, u32 drv_id) 38 u32 msg_id, u32 drv_id)
diff --git a/sound/soc/intel/sst/sst_loader.c b/sound/soc/intel/atom/sst/sst_loader.c
index e88907ae8b15..33917146d9c4 100644
--- a/sound/soc/intel/sst/sst_loader.c
+++ b/sound/soc/intel/atom/sst/sst_loader.c
@@ -37,7 +37,7 @@
37#include <asm/platform_sst_audio.h> 37#include <asm/platform_sst_audio.h>
38#include "../sst-mfld-platform.h" 38#include "../sst-mfld-platform.h"
39#include "sst.h" 39#include "sst.h"
40#include "../sst-dsp.h" 40#include "../../common/sst-dsp.h"
41 41
42void memcpy32_toio(void __iomem *dst, const void *src, int count) 42void memcpy32_toio(void __iomem *dst, const void *src, int count)
43{ 43{
diff --git a/sound/soc/intel/sst/sst_pci.c b/sound/soc/intel/atom/sst/sst_pci.c
index 3a0b3bf0af97..3a0b3bf0af97 100644
--- a/sound/soc/intel/sst/sst_pci.c
+++ b/sound/soc/intel/atom/sst/sst_pci.c
diff --git a/sound/soc/intel/sst/sst_pvt.c b/sound/soc/intel/atom/sst/sst_pvt.c
index 4b7720864492..adb32fefd693 100644
--- a/sound/soc/intel/sst/sst_pvt.c
+++ b/sound/soc/intel/atom/sst/sst_pvt.c
@@ -34,7 +34,7 @@
34#include <asm/platform_sst_audio.h> 34#include <asm/platform_sst_audio.h>
35#include "../sst-mfld-platform.h" 35#include "../sst-mfld-platform.h"
36#include "sst.h" 36#include "sst.h"
37#include "../sst-dsp.h" 37#include "../../common/sst-dsp.h"
38 38
39int sst_shim_write(void __iomem *addr, int offset, int value) 39int sst_shim_write(void __iomem *addr, int offset, int value)
40{ 40{
@@ -111,30 +111,6 @@ int sst_wait_interruptible(struct intel_sst_drv *sst_drv_ctx,
111 111
112} 112}
113 113
114unsigned long long read_shim_data(struct intel_sst_drv *sst, int addr)
115{
116 unsigned long long val = 0;
117
118 switch (sst->dev_id) {
119 case SST_MRFLD_PCI_ID:
120 case SST_BYT_ACPI_ID:
121 val = sst_shim_read64(sst->shim, addr);
122 break;
123 }
124 return val;
125}
126
127void write_shim_data(struct intel_sst_drv *sst, int addr,
128 unsigned long long data)
129{
130 switch (sst->dev_id) {
131 case SST_MRFLD_PCI_ID:
132 case SST_BYT_ACPI_ID:
133 sst_shim_write64(sst->shim, addr, (u64) data);
134 break;
135 }
136}
137
138/* 114/*
139 * sst_wait_timeout - wait on event for timeout 115 * sst_wait_timeout - wait on event for timeout
140 * 116 *
diff --git a/sound/soc/intel/sst/sst_stream.c b/sound/soc/intel/atom/sst/sst_stream.c
index dae2a41997aa..a74c64c7053c 100644
--- a/sound/soc/intel/sst/sst_stream.c
+++ b/sound/soc/intel/atom/sst/sst_stream.c
@@ -31,7 +31,7 @@
31#include <asm/platform_sst_audio.h> 31#include <asm/platform_sst_audio.h>
32#include "../sst-mfld-platform.h" 32#include "../sst-mfld-platform.h"
33#include "sst.h" 33#include "sst.h"
34#include "../sst-dsp.h" 34#include "../../common/sst-dsp.h"
35 35
36int sst_alloc_stream_mrfld(struct intel_sst_drv *sst_drv_ctx, void *params) 36int sst_alloc_stream_mrfld(struct intel_sst_drv *sst_drv_ctx, void *params)
37{ 37{
diff --git a/sound/soc/intel/baytrail/Makefile b/sound/soc/intel/baytrail/Makefile
new file mode 100644
index 000000000000..488408cadf6d
--- /dev/null
+++ b/sound/soc/intel/baytrail/Makefile
@@ -0,0 +1,4 @@
1snd-soc-sst-baytrail-pcm-objs := \
2 sst-baytrail-ipc.o sst-baytrail-pcm.o sst-baytrail-dsp.o
3
4obj-$(CONFIG_SND_SOC_INTEL_BAYTRAIL) += snd-soc-sst-baytrail-pcm.o
diff --git a/sound/soc/intel/sst-baytrail-dsp.c b/sound/soc/intel/baytrail/sst-baytrail-dsp.c
index 5a9e56700f31..01d023cc05dd 100644
--- a/sound/soc/intel/sst-baytrail-dsp.c
+++ b/sound/soc/intel/baytrail/sst-baytrail-dsp.c
@@ -22,8 +22,8 @@
22#include <linux/platform_device.h> 22#include <linux/platform_device.h>
23#include <linux/firmware.h> 23#include <linux/firmware.h>
24 24
25#include "sst-dsp.h" 25#include "../common/sst-dsp.h"
26#include "sst-dsp-priv.h" 26#include "../common/sst-dsp-priv.h"
27#include "sst-baytrail-ipc.h" 27#include "sst-baytrail-ipc.h"
28 28
29#define SST_BYT_FW_SIGNATURE_SIZE 4 29#define SST_BYT_FW_SIGNATURE_SIZE 4
diff --git a/sound/soc/intel/sst-baytrail-ipc.c b/sound/soc/intel/baytrail/sst-baytrail-ipc.c
index b4ad98c43e5c..1efb33b36303 100644
--- a/sound/soc/intel/sst-baytrail-ipc.c
+++ b/sound/soc/intel/baytrail/sst-baytrail-ipc.c
@@ -29,8 +29,9 @@
29#include <asm/div64.h> 29#include <asm/div64.h>
30 30
31#include "sst-baytrail-ipc.h" 31#include "sst-baytrail-ipc.h"
32#include "sst-dsp.h" 32#include "../common/sst-dsp.h"
33#include "sst-dsp-priv.h" 33#include "../common/sst-dsp-priv.h"
34#include "../common/sst-ipc.h"
34 35
35/* IPC message timeout */ 36/* IPC message timeout */
36#define IPC_TIMEOUT_MSECS 300 37#define IPC_TIMEOUT_MSECS 300
@@ -142,23 +143,6 @@ struct sst_byt_fw_init {
142 u8 debug_info; 143 u8 debug_info;
143} __packed; 144} __packed;
144 145
145/* driver internal IPC message structure */
146struct ipc_message {
147 struct list_head list;
148 u64 header;
149
150 /* direction wrt host CPU */
151 char tx_data[SST_BYT_IPC_MAX_PAYLOAD_SIZE];
152 size_t tx_size;
153 char rx_data[SST_BYT_IPC_MAX_PAYLOAD_SIZE];
154 size_t rx_size;
155
156 wait_queue_head_t waitq;
157 bool complete;
158 bool wait;
159 int errno;
160};
161
162struct sst_byt_stream; 146struct sst_byt_stream;
163struct sst_byt; 147struct sst_byt;
164 148
@@ -195,14 +179,7 @@ struct sst_byt {
195 struct sst_fw *fw; 179 struct sst_fw *fw;
196 180
197 /* IPC messaging */ 181 /* IPC messaging */
198 struct list_head tx_list; 182 struct sst_generic_ipc ipc;
199 struct list_head rx_list;
200 struct list_head empty_list;
201 wait_queue_head_t wait_txq;
202 struct task_struct *tx_thread;
203 struct kthread_worker kworker;
204 struct kthread_work kwork;
205 struct ipc_message *msg;
206}; 183};
207 184
208static inline u64 sst_byt_header(int msg_id, int data, bool large, int str_id) 185static inline u64 sst_byt_header(int msg_id, int data, bool large, int str_id)
@@ -246,209 +223,6 @@ static struct sst_byt_stream *sst_byt_get_stream(struct sst_byt *byt,
246 return NULL; 223 return NULL;
247} 224}
248 225
249static void sst_byt_ipc_shim_dbg(struct sst_byt *byt, const char *text)
250{
251 struct sst_dsp *sst = byt->dsp;
252 u64 isr, ipcd, imrx, ipcx;
253
254 ipcx = sst_dsp_shim_read64_unlocked(sst, SST_IPCX);
255 isr = sst_dsp_shim_read64_unlocked(sst, SST_ISRX);
256 ipcd = sst_dsp_shim_read64_unlocked(sst, SST_IPCD);
257 imrx = sst_dsp_shim_read64_unlocked(sst, SST_IMRX);
258
259 dev_err(byt->dev,
260 "ipc: --%s-- ipcx 0x%llx isr 0x%llx ipcd 0x%llx imrx 0x%llx\n",
261 text, ipcx, isr, ipcd, imrx);
262}
263
264/* locks held by caller */
265static struct ipc_message *sst_byt_msg_get_empty(struct sst_byt *byt)
266{
267 struct ipc_message *msg = NULL;
268
269 if (!list_empty(&byt->empty_list)) {
270 msg = list_first_entry(&byt->empty_list,
271 struct ipc_message, list);
272 list_del(&msg->list);
273 }
274
275 return msg;
276}
277
278static void sst_byt_ipc_tx_msgs(struct kthread_work *work)
279{
280 struct sst_byt *byt =
281 container_of(work, struct sst_byt, kwork);
282 struct ipc_message *msg;
283 u64 ipcx;
284 unsigned long flags;
285
286 spin_lock_irqsave(&byt->dsp->spinlock, flags);
287 if (list_empty(&byt->tx_list)) {
288 spin_unlock_irqrestore(&byt->dsp->spinlock, flags);
289 return;
290 }
291
292 /* if the DSP is busy we will TX messages after IRQ */
293 ipcx = sst_dsp_shim_read64_unlocked(byt->dsp, SST_IPCX);
294 if (ipcx & SST_BYT_IPCX_BUSY) {
295 spin_unlock_irqrestore(&byt->dsp->spinlock, flags);
296 return;
297 }
298
299 msg = list_first_entry(&byt->tx_list, struct ipc_message, list);
300
301 list_move(&msg->list, &byt->rx_list);
302
303 /* send the message */
304 if (msg->header & IPC_HEADER_LARGE(true))
305 sst_dsp_outbox_write(byt->dsp, msg->tx_data, msg->tx_size);
306 sst_dsp_shim_write64_unlocked(byt->dsp, SST_IPCX, msg->header);
307
308 spin_unlock_irqrestore(&byt->dsp->spinlock, flags);
309}
310
311static inline void sst_byt_tx_msg_reply_complete(struct sst_byt *byt,
312 struct ipc_message *msg)
313{
314 msg->complete = true;
315
316 if (!msg->wait)
317 list_add_tail(&msg->list, &byt->empty_list);
318 else
319 wake_up(&msg->waitq);
320}
321
322static void sst_byt_drop_all(struct sst_byt *byt)
323{
324 struct ipc_message *msg, *tmp;
325 unsigned long flags;
326
327 /* drop all TX and Rx messages before we stall + reset DSP */
328 spin_lock_irqsave(&byt->dsp->spinlock, flags);
329 list_for_each_entry_safe(msg, tmp, &byt->tx_list, list) {
330 list_move(&msg->list, &byt->empty_list);
331 }
332
333 list_for_each_entry_safe(msg, tmp, &byt->rx_list, list) {
334 list_move(&msg->list, &byt->empty_list);
335 }
336
337 spin_unlock_irqrestore(&byt->dsp->spinlock, flags);
338}
339
340static int sst_byt_tx_wait_done(struct sst_byt *byt, struct ipc_message *msg,
341 void *rx_data)
342{
343 unsigned long flags;
344 int ret;
345
346 /* wait for DSP completion */
347 ret = wait_event_timeout(msg->waitq, msg->complete,
348 msecs_to_jiffies(IPC_TIMEOUT_MSECS));
349
350 spin_lock_irqsave(&byt->dsp->spinlock, flags);
351 if (ret == 0) {
352 list_del(&msg->list);
353 sst_byt_ipc_shim_dbg(byt, "message timeout");
354
355 ret = -ETIMEDOUT;
356 } else {
357
358 /* copy the data returned from DSP */
359 if (msg->rx_size)
360 memcpy(rx_data, msg->rx_data, msg->rx_size);
361 ret = msg->errno;
362 }
363
364 list_add_tail(&msg->list, &byt->empty_list);
365 spin_unlock_irqrestore(&byt->dsp->spinlock, flags);
366 return ret;
367}
368
369static int sst_byt_ipc_tx_message(struct sst_byt *byt, u64 header,
370 void *tx_data, size_t tx_bytes,
371 void *rx_data, size_t rx_bytes, int wait)
372{
373 unsigned long flags;
374 struct ipc_message *msg;
375
376 spin_lock_irqsave(&byt->dsp->spinlock, flags);
377
378 msg = sst_byt_msg_get_empty(byt);
379 if (msg == NULL) {
380 spin_unlock_irqrestore(&byt->dsp->spinlock, flags);
381 return -EBUSY;
382 }
383
384 msg->header = header;
385 msg->tx_size = tx_bytes;
386 msg->rx_size = rx_bytes;
387 msg->wait = wait;
388 msg->errno = 0;
389 msg->complete = false;
390
391 if (tx_bytes) {
392 /* msg content = lower 32-bit of the header + data */
393 *(u32 *)msg->tx_data = (u32)(header & (u32)-1);
394 memcpy(msg->tx_data + sizeof(u32), tx_data, tx_bytes);
395 msg->tx_size += sizeof(u32);
396 }
397
398 list_add_tail(&msg->list, &byt->tx_list);
399 spin_unlock_irqrestore(&byt->dsp->spinlock, flags);
400
401 queue_kthread_work(&byt->kworker, &byt->kwork);
402
403 if (wait)
404 return sst_byt_tx_wait_done(byt, msg, rx_data);
405 else
406 return 0;
407}
408
409static inline int sst_byt_ipc_tx_msg_wait(struct sst_byt *byt, u64 header,
410 void *tx_data, size_t tx_bytes,
411 void *rx_data, size_t rx_bytes)
412{
413 return sst_byt_ipc_tx_message(byt, header, tx_data, tx_bytes,
414 rx_data, rx_bytes, 1);
415}
416
417static inline int sst_byt_ipc_tx_msg_nowait(struct sst_byt *byt, u64 header,
418 void *tx_data, size_t tx_bytes)
419{
420 return sst_byt_ipc_tx_message(byt, header, tx_data, tx_bytes,
421 NULL, 0, 0);
422}
423
424static struct ipc_message *sst_byt_reply_find_msg(struct sst_byt *byt,
425 u64 header)
426{
427 struct ipc_message *msg = NULL, *_msg;
428 u64 mask;
429
430 /* match reply to message sent based on msg and stream IDs */
431 mask = IPC_HEADER_MSG_ID_MASK |
432 IPC_HEADER_STR_ID_MASK << IPC_HEADER_STR_ID_SHIFT;
433 header &= mask;
434
435 if (list_empty(&byt->rx_list)) {
436 dev_err(byt->dev,
437 "ipc: rx list is empty but received 0x%llx\n", header);
438 goto out;
439 }
440
441 list_for_each_entry(_msg, &byt->rx_list, list) {
442 if ((_msg->header & mask) == header) {
443 msg = _msg;
444 break;
445 }
446 }
447
448out:
449 return msg;
450}
451
452static void sst_byt_stream_update(struct sst_byt *byt, struct ipc_message *msg) 226static void sst_byt_stream_update(struct sst_byt *byt, struct ipc_message *msg)
453{ 227{
454 struct sst_byt_stream *stream; 228 struct sst_byt_stream *stream;
@@ -477,7 +251,7 @@ static int sst_byt_process_reply(struct sst_byt *byt, u64 header)
477{ 251{
478 struct ipc_message *msg; 252 struct ipc_message *msg;
479 253
480 msg = sst_byt_reply_find_msg(byt, header); 254 msg = sst_ipc_reply_find_msg(&byt->ipc, header);
481 if (msg == NULL) 255 if (msg == NULL)
482 return 1; 256 return 1;
483 257
@@ -491,7 +265,7 @@ static int sst_byt_process_reply(struct sst_byt *byt, u64 header)
491 265
492 list_del(&msg->list); 266 list_del(&msg->list);
493 /* wake up */ 267 /* wake up */
494 sst_byt_tx_msg_reply_complete(byt, msg); 268 sst_ipc_tx_msg_reply_complete(&byt->ipc, msg);
495 269
496 return 1; 270 return 1;
497} 271}
@@ -538,6 +312,7 @@ static irqreturn_t sst_byt_irq_thread(int irq, void *context)
538{ 312{
539 struct sst_dsp *sst = (struct sst_dsp *) context; 313 struct sst_dsp *sst = (struct sst_dsp *) context;
540 struct sst_byt *byt = sst_dsp_get_thread_context(sst); 314 struct sst_byt *byt = sst_dsp_get_thread_context(sst);
315 struct sst_generic_ipc *ipc = &byt->ipc;
541 u64 header; 316 u64 header;
542 unsigned long flags; 317 unsigned long flags;
543 318
@@ -569,7 +344,7 @@ static irqreturn_t sst_byt_irq_thread(int irq, void *context)
569 spin_unlock_irqrestore(&sst->spinlock, flags); 344 spin_unlock_irqrestore(&sst->spinlock, flags);
570 345
571 /* continue to send any remaining messages... */ 346 /* continue to send any remaining messages... */
572 queue_kthread_work(&byt->kworker, &byt->kwork); 347 queue_kthread_work(&ipc->kworker, &ipc->kwork);
573 348
574 return IRQ_HANDLED; 349 return IRQ_HANDLED;
575} 350}
@@ -656,7 +431,8 @@ int sst_byt_stream_commit(struct sst_byt *byt, struct sst_byt_stream *stream)
656 header = sst_byt_header(IPC_IA_ALLOC_STREAM, 431 header = sst_byt_header(IPC_IA_ALLOC_STREAM,
657 sizeof(*str_req) + sizeof(u32), 432 sizeof(*str_req) + sizeof(u32),
658 true, stream->str_id); 433 true, stream->str_id);
659 ret = sst_byt_ipc_tx_msg_wait(byt, header, str_req, sizeof(*str_req), 434 ret = sst_ipc_tx_message_wait(&byt->ipc, header, str_req,
435 sizeof(*str_req),
660 reply, sizeof(*reply)); 436 reply, sizeof(*reply));
661 if (ret < 0) { 437 if (ret < 0) {
662 dev_err(byt->dev, "ipc: error stream commit failed\n"); 438 dev_err(byt->dev, "ipc: error stream commit failed\n");
@@ -679,7 +455,7 @@ int sst_byt_stream_free(struct sst_byt *byt, struct sst_byt_stream *stream)
679 goto out; 455 goto out;
680 456
681 header = sst_byt_header(IPC_IA_FREE_STREAM, 0, false, stream->str_id); 457 header = sst_byt_header(IPC_IA_FREE_STREAM, 0, false, stream->str_id);
682 ret = sst_byt_ipc_tx_msg_wait(byt, header, NULL, 0, NULL, 0); 458 ret = sst_ipc_tx_message_wait(&byt->ipc, header, NULL, 0, NULL, 0);
683 if (ret < 0) { 459 if (ret < 0) {
684 dev_err(byt->dev, "ipc: free stream %d failed\n", 460 dev_err(byt->dev, "ipc: free stream %d failed\n",
685 stream->str_id); 461 stream->str_id);
@@ -703,9 +479,11 @@ static int sst_byt_stream_operations(struct sst_byt *byt, int type,
703 479
704 header = sst_byt_header(type, 0, false, stream_id); 480 header = sst_byt_header(type, 0, false, stream_id);
705 if (wait) 481 if (wait)
706 return sst_byt_ipc_tx_msg_wait(byt, header, NULL, 0, NULL, 0); 482 return sst_ipc_tx_message_wait(&byt->ipc, header, NULL,
483 0, NULL, 0);
707 else 484 else
708 return sst_byt_ipc_tx_msg_nowait(byt, header, NULL, 0); 485 return sst_ipc_tx_message_nowait(&byt->ipc, header,
486 NULL, 0);
709} 487}
710 488
711/* stream ALSA trigger operations */ 489/* stream ALSA trigger operations */
@@ -725,7 +503,7 @@ int sst_byt_stream_start(struct sst_byt *byt, struct sst_byt_stream *stream,
725 tx_msg = &start_stream; 503 tx_msg = &start_stream;
726 size = sizeof(start_stream); 504 size = sizeof(start_stream);
727 505
728 ret = sst_byt_ipc_tx_msg_nowait(byt, header, tx_msg, size); 506 ret = sst_ipc_tx_message_nowait(&byt->ipc, header, tx_msg, size);
729 if (ret < 0) 507 if (ret < 0)
730 dev_err(byt->dev, "ipc: error failed to start stream %d\n", 508 dev_err(byt->dev, "ipc: error failed to start stream %d\n",
731 stream->str_id); 509 stream->str_id);
@@ -790,23 +568,6 @@ int sst_byt_get_dsp_position(struct sst_byt *byt,
790 return do_div(fw_tstamp.ring_buffer_counter, buffer_size); 568 return do_div(fw_tstamp.ring_buffer_counter, buffer_size);
791} 569}
792 570
793static int msg_empty_list_init(struct sst_byt *byt)
794{
795 struct ipc_message *msg;
796 int i;
797
798 byt->msg = kzalloc(sizeof(*msg) * IPC_EMPTY_LIST_SIZE, GFP_KERNEL);
799 if (byt->msg == NULL)
800 return -ENOMEM;
801
802 for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) {
803 init_waitqueue_head(&byt->msg[i].waitq);
804 list_add(&byt->msg[i].list, &byt->empty_list);
805 }
806
807 return 0;
808}
809
810struct sst_dsp *sst_byt_get_dsp(struct sst_byt *byt) 571struct sst_dsp *sst_byt_get_dsp(struct sst_byt *byt)
811{ 572{
812 return byt->dsp; 573 return byt->dsp;
@@ -823,7 +584,7 @@ int sst_byt_dsp_suspend_late(struct device *dev, struct sst_pdata *pdata)
823 584
824 dev_dbg(byt->dev, "dsp reset\n"); 585 dev_dbg(byt->dev, "dsp reset\n");
825 sst_dsp_reset(byt->dsp); 586 sst_dsp_reset(byt->dsp);
826 sst_byt_drop_all(byt); 587 sst_ipc_drop_all(&byt->ipc);
827 dev_dbg(byt->dev, "dsp in reset\n"); 588 dev_dbg(byt->dev, "dsp in reset\n");
828 589
829 dev_dbg(byt->dev, "free all blocks and unload fw\n"); 590 dev_dbg(byt->dev, "free all blocks and unload fw\n");
@@ -876,9 +637,52 @@ int sst_byt_dsp_wait_for_ready(struct device *dev, struct sst_pdata *pdata)
876} 637}
877EXPORT_SYMBOL_GPL(sst_byt_dsp_wait_for_ready); 638EXPORT_SYMBOL_GPL(sst_byt_dsp_wait_for_ready);
878 639
640static void byt_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg)
641{
642 if (msg->header & IPC_HEADER_LARGE(true))
643 sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size);
644
645 sst_dsp_shim_write64_unlocked(ipc->dsp, SST_IPCX, msg->header);
646}
647
648static void byt_shim_dbg(struct sst_generic_ipc *ipc, const char *text)
649{
650 struct sst_dsp *sst = ipc->dsp;
651 u64 isr, ipcd, imrx, ipcx;
652
653 ipcx = sst_dsp_shim_read64_unlocked(sst, SST_IPCX);
654 isr = sst_dsp_shim_read64_unlocked(sst, SST_ISRX);
655 ipcd = sst_dsp_shim_read64_unlocked(sst, SST_IPCD);
656 imrx = sst_dsp_shim_read64_unlocked(sst, SST_IMRX);
657
658 dev_err(ipc->dev,
659 "ipc: --%s-- ipcx 0x%llx isr 0x%llx ipcd 0x%llx imrx 0x%llx\n",
660 text, ipcx, isr, ipcd, imrx);
661}
662
663static void byt_tx_data_copy(struct ipc_message *msg, char *tx_data,
664 size_t tx_size)
665{
666 /* msg content = lower 32-bit of the header + data */
667 *(u32 *)msg->tx_data = (u32)(msg->header & (u32)-1);
668 memcpy(msg->tx_data + sizeof(u32), tx_data, tx_size);
669 msg->tx_size += sizeof(u32);
670}
671
672static u64 byt_reply_msg_match(u64 header, u64 *mask)
673{
674 /* match reply to message sent based on msg and stream IDs */
675 *mask = IPC_HEADER_MSG_ID_MASK |
676 IPC_HEADER_STR_ID_MASK << IPC_HEADER_STR_ID_SHIFT;
677 header &= *mask;
678
679 return header;
680}
681
879int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) 682int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata)
880{ 683{
881 struct sst_byt *byt; 684 struct sst_byt *byt;
685 struct sst_generic_ipc *ipc;
882 struct sst_fw *byt_sst_fw; 686 struct sst_fw *byt_sst_fw;
883 struct sst_byt_fw_init init; 687 struct sst_byt_fw_init init;
884 int err; 688 int err;
@@ -889,39 +693,30 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata)
889 if (byt == NULL) 693 if (byt == NULL)
890 return -ENOMEM; 694 return -ENOMEM;
891 695
892 byt->dev = dev; 696 ipc = &byt->ipc;
893 INIT_LIST_HEAD(&byt->stream_list); 697 ipc->dev = dev;
894 INIT_LIST_HEAD(&byt->tx_list); 698 ipc->ops.tx_msg = byt_tx_msg;
895 INIT_LIST_HEAD(&byt->rx_list); 699 ipc->ops.shim_dbg = byt_shim_dbg;
896 INIT_LIST_HEAD(&byt->empty_list); 700 ipc->ops.tx_data_copy = byt_tx_data_copy;
897 init_waitqueue_head(&byt->boot_wait); 701 ipc->ops.reply_msg_match = byt_reply_msg_match;
898 init_waitqueue_head(&byt->wait_txq);
899 702
900 err = msg_empty_list_init(byt); 703 err = sst_ipc_init(ipc);
901 if (err < 0) 704 if (err != 0)
902 return -ENOMEM; 705 goto ipc_init_err;
903
904 /* start the IPC message thread */
905 init_kthread_worker(&byt->kworker);
906 byt->tx_thread = kthread_run(kthread_worker_fn,
907 &byt->kworker, "%s",
908 dev_name(byt->dev));
909 if (IS_ERR(byt->tx_thread)) {
910 err = PTR_ERR(byt->tx_thread);
911 dev_err(byt->dev, "error failed to create message TX task\n");
912 goto err_free_msg;
913 }
914 init_kthread_work(&byt->kwork, sst_byt_ipc_tx_msgs);
915 706
707 INIT_LIST_HEAD(&byt->stream_list);
708 init_waitqueue_head(&byt->boot_wait);
916 byt_dev.thread_context = byt; 709 byt_dev.thread_context = byt;
917 710
918 /* init SST shim */ 711 /* init SST shim */
919 byt->dsp = sst_dsp_new(dev, &byt_dev, pdata); 712 byt->dsp = sst_dsp_new(dev, &byt_dev, pdata);
920 if (byt->dsp == NULL) { 713 if (byt->dsp == NULL) {
921 err = -ENODEV; 714 err = -ENODEV;
922 goto dsp_err; 715 goto dsp_new_err;
923 } 716 }
924 717
718 ipc->dsp = byt->dsp;
719
925 /* keep the DSP in reset state for base FW loading */ 720 /* keep the DSP in reset state for base FW loading */
926 sst_dsp_reset(byt->dsp); 721 sst_dsp_reset(byt->dsp);
927 722
@@ -961,10 +756,10 @@ boot_err:
961 sst_fw_free(byt_sst_fw); 756 sst_fw_free(byt_sst_fw);
962fw_err: 757fw_err:
963 sst_dsp_free(byt->dsp); 758 sst_dsp_free(byt->dsp);
964dsp_err: 759dsp_new_err:
965 kthread_stop(byt->tx_thread); 760 sst_ipc_fini(ipc);
966err_free_msg: 761ipc_init_err:
967 kfree(byt->msg); 762 kfree(byt);
968 763
969 return err; 764 return err;
970} 765}
@@ -977,7 +772,6 @@ void sst_byt_dsp_free(struct device *dev, struct sst_pdata *pdata)
977 sst_dsp_reset(byt->dsp); 772 sst_dsp_reset(byt->dsp);
978 sst_fw_free_all(byt->dsp); 773 sst_fw_free_all(byt->dsp);
979 sst_dsp_free(byt->dsp); 774 sst_dsp_free(byt->dsp);
980 kthread_stop(byt->tx_thread); 775 sst_ipc_fini(&byt->ipc);
981 kfree(byt->msg);
982} 776}
983EXPORT_SYMBOL_GPL(sst_byt_dsp_free); 777EXPORT_SYMBOL_GPL(sst_byt_dsp_free);
diff --git a/sound/soc/intel/sst-baytrail-ipc.h b/sound/soc/intel/baytrail/sst-baytrail-ipc.h
index 8faff6dcf25d..8faff6dcf25d 100644
--- a/sound/soc/intel/sst-baytrail-ipc.h
+++ b/sound/soc/intel/baytrail/sst-baytrail-ipc.h
diff --git a/sound/soc/intel/sst-baytrail-pcm.c b/sound/soc/intel/baytrail/sst-baytrail-pcm.c
index 224c49c9f135..79547bec558b 100644
--- a/sound/soc/intel/sst-baytrail-pcm.c
+++ b/sound/soc/intel/baytrail/sst-baytrail-pcm.c
@@ -20,8 +20,8 @@
20#include <sound/pcm_params.h> 20#include <sound/pcm_params.h>
21#include <sound/soc.h> 21#include <sound/soc.h>
22#include "sst-baytrail-ipc.h" 22#include "sst-baytrail-ipc.h"
23#include "sst-dsp-priv.h" 23#include "../common/sst-dsp-priv.h"
24#include "sst-dsp.h" 24#include "../common/sst-dsp.h"
25 25
26#define BYT_PCM_COUNT 2 26#define BYT_PCM_COUNT 2
27 27
diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile
new file mode 100644
index 000000000000..f8237f0044eb
--- /dev/null
+++ b/sound/soc/intel/boards/Makefile
@@ -0,0 +1,15 @@
1snd-soc-sst-haswell-objs := haswell.o
2snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o
3snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o
4snd-soc-sst-broadwell-objs := broadwell.o
5snd-soc-sst-bytcr-rt5640-objs := bytcr_rt5640.o
6snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o
7snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o
8
9obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o
10obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o
11obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o
12obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o
13obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH) += snd-soc-sst-bytcr-rt5640.o
14obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o
15obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o
diff --git a/sound/soc/intel/broadwell.c b/sound/soc/intel/boards/broadwell.c
index fc5542034b9b..8bafaf6ceab1 100644
--- a/sound/soc/intel/broadwell.c
+++ b/sound/soc/intel/boards/broadwell.c
@@ -22,10 +22,10 @@
22#include <sound/jack.h> 22#include <sound/jack.h>
23#include <sound/pcm_params.h> 23#include <sound/pcm_params.h>
24 24
25#include "sst-dsp.h" 25#include "../common/sst-dsp.h"
26#include "sst-haswell-ipc.h" 26#include "../haswell/sst-haswell-ipc.h"
27 27
28#include "../codecs/rt286.h" 28#include "../../codecs/rt286.h"
29 29
30static struct snd_soc_jack broadwell_headset; 30static struct snd_soc_jack broadwell_headset;
31/* Headset jack detection DAPM pins */ 31/* Headset jack detection DAPM pins */
@@ -219,6 +219,32 @@ static struct snd_soc_dai_link broadwell_rt286_dais[] = {
219 }, 219 },
220}; 220};
221 221
222static int broadwell_suspend(struct snd_soc_card *card){
223 struct snd_soc_codec *codec;
224
225 list_for_each_entry(codec, &card->codec_dev_list, card_list) {
226 if (!strcmp(codec->component.name, "i2c-INT343A:00")) {
227 dev_dbg(codec->dev, "disabling jack detect before going to suspend.\n");
228 rt286_mic_detect(codec, NULL);
229 break;
230 }
231 }
232 return 0;
233}
234
235static int broadwell_resume(struct snd_soc_card *card){
236 struct snd_soc_codec *codec;
237
238 list_for_each_entry(codec, &card->codec_dev_list, card_list) {
239 if (!strcmp(codec->component.name, "i2c-INT343A:00")) {
240 dev_dbg(codec->dev, "enabling jack detect for resume.\n");
241 rt286_mic_detect(codec, &broadwell_headset);
242 break;
243 }
244 }
245 return 0;
246}
247
222/* broadwell audio machine driver for WPT + RT286S */ 248/* broadwell audio machine driver for WPT + RT286S */
223static struct snd_soc_card broadwell_rt286 = { 249static struct snd_soc_card broadwell_rt286 = {
224 .name = "broadwell-rt286", 250 .name = "broadwell-rt286",
@@ -232,6 +258,8 @@ static struct snd_soc_card broadwell_rt286 = {
232 .dapm_routes = broadwell_rt286_map, 258 .dapm_routes = broadwell_rt286_map,
233 .num_dapm_routes = ARRAY_SIZE(broadwell_rt286_map), 259 .num_dapm_routes = ARRAY_SIZE(broadwell_rt286_map),
234 .fully_routed = true, 260 .fully_routed = true,
261 .suspend_pre = broadwell_suspend,
262 .resume_post = broadwell_resume,
235}; 263};
236 264
237static int broadwell_audio_probe(struct platform_device *pdev) 265static int broadwell_audio_probe(struct platform_device *pdev)
diff --git a/sound/soc/intel/byt-max98090.c b/sound/soc/intel/boards/byt-max98090.c
index d8b1f038da1c..7ab8cc9fbfd5 100644
--- a/sound/soc/intel/byt-max98090.c
+++ b/sound/soc/intel/boards/byt-max98090.c
@@ -24,7 +24,7 @@
24#include <sound/pcm_params.h> 24#include <sound/pcm_params.h>
25#include <sound/soc.h> 25#include <sound/soc.h>
26#include <sound/jack.h> 26#include <sound/jack.h>
27#include "../codecs/max98090.h" 27#include "../../codecs/max98090.h"
28 28
29struct byt_max98090_private { 29struct byt_max98090_private {
30 struct snd_soc_jack jack; 30 struct snd_soc_jack jack;
diff --git a/sound/soc/intel/byt-rt5640.c b/sound/soc/intel/boards/byt-rt5640.c
index 354eaad886e1..ae89b9b966d9 100644
--- a/sound/soc/intel/byt-rt5640.c
+++ b/sound/soc/intel/boards/byt-rt5640.c
@@ -23,9 +23,9 @@
23#include <sound/pcm_params.h> 23#include <sound/pcm_params.h>
24#include <sound/soc.h> 24#include <sound/soc.h>
25#include <sound/jack.h> 25#include <sound/jack.h>
26#include "../codecs/rt5640.h" 26#include "../../codecs/rt5640.h"
27 27
28#include "sst-dsp.h" 28#include "../common/sst-dsp.h"
29 29
30static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = { 30static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = {
31 SND_SOC_DAPM_HP("Headphone", NULL), 31 SND_SOC_DAPM_HP("Headphone", NULL),
diff --git a/sound/soc/intel/bytcr_dpcm_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
index 3b262d01c1b3..7f55d59024a8 100644
--- a/sound/soc/intel/bytcr_dpcm_rt5640.c
+++ b/sound/soc/intel/boards/bytcr_rt5640.c
@@ -26,8 +26,8 @@
26#include <sound/pcm.h> 26#include <sound/pcm.h>
27#include <sound/pcm_params.h> 27#include <sound/pcm_params.h>
28#include <sound/soc.h> 28#include <sound/soc.h>
29#include "../codecs/rt5640.h" 29#include "../../codecs/rt5640.h"
30#include "sst-atom-controls.h" 30#include "../atom/sst-atom-controls.h"
31 31
32static const struct snd_soc_dapm_widget byt_dapm_widgets[] = { 32static const struct snd_soc_dapm_widget byt_dapm_widgets[] = {
33 SND_SOC_DAPM_HP("Headphone", NULL), 33 SND_SOC_DAPM_HP("Headphone", NULL),
diff --git a/sound/soc/intel/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c
index 012227997ed9..20a28b22e30f 100644
--- a/sound/soc/intel/cht_bsw_rt5645.c
+++ b/sound/soc/intel/boards/cht_bsw_rt5645.c
@@ -27,8 +27,8 @@
27#include <sound/pcm_params.h> 27#include <sound/pcm_params.h>
28#include <sound/soc.h> 28#include <sound/soc.h>
29#include <sound/jack.h> 29#include <sound/jack.h>
30#include "../codecs/rt5645.h" 30#include "../../codecs/rt5645.h"
31#include "sst-atom-controls.h" 31#include "../atom/sst-atom-controls.h"
32 32
33#define CHT_PLAT_CLK_3_HZ 19200000 33#define CHT_PLAT_CLK_3_HZ 19200000
34#define CHT_CODEC_DAI "rt5645-aif1" 34#define CHT_CODEC_DAI "rt5645-aif1"
diff --git a/sound/soc/intel/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c
index bc8dcacd5e6a..2c9cc5be439e 100644
--- a/sound/soc/intel/cht_bsw_rt5672.c
+++ b/sound/soc/intel/boards/cht_bsw_rt5672.c
@@ -22,13 +22,28 @@
22#include <sound/pcm.h> 22#include <sound/pcm.h>
23#include <sound/pcm_params.h> 23#include <sound/pcm_params.h>
24#include <sound/soc.h> 24#include <sound/soc.h>
25#include "../codecs/rt5670.h" 25#include <sound/jack.h>
26#include "sst-atom-controls.h" 26#include "../../codecs/rt5670.h"
27#include "../atom/sst-atom-controls.h"
27 28
28/* The platform clock #3 outputs 19.2Mhz clock to codec as I2S MCLK */ 29/* The platform clock #3 outputs 19.2Mhz clock to codec as I2S MCLK */
29#define CHT_PLAT_CLK_3_HZ 19200000 30#define CHT_PLAT_CLK_3_HZ 19200000
30#define CHT_CODEC_DAI "rt5670-aif1" 31#define CHT_CODEC_DAI "rt5670-aif1"
31 32
33static struct snd_soc_jack cht_bsw_headset;
34
35/* Headset jack detection DAPM pins */
36static struct snd_soc_jack_pin cht_bsw_headset_pins[] = {
37 {
38 .pin = "Headset Mic",
39 .mask = SND_JACK_MICROPHONE,
40 },
41 {
42 .pin = "Headphone",
43 .mask = SND_JACK_HEADPHONE,
44 },
45};
46
32static inline struct snd_soc_dai *cht_get_codec_dai(struct snd_soc_card *card) 47static inline struct snd_soc_dai *cht_get_codec_dai(struct snd_soc_card *card)
33{ 48{
34 int i; 49 int i;
@@ -50,6 +65,7 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
50 struct snd_soc_dapm_context *dapm = w->dapm; 65 struct snd_soc_dapm_context *dapm = w->dapm;
51 struct snd_soc_card *card = dapm->card; 66 struct snd_soc_card *card = dapm->card;
52 struct snd_soc_dai *codec_dai; 67 struct snd_soc_dai *codec_dai;
68 int ret;
53 69
54 codec_dai = cht_get_codec_dai(card); 70 codec_dai = cht_get_codec_dai(card);
55 if (!codec_dai) { 71 if (!codec_dai) {
@@ -57,17 +73,31 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
57 return -EIO; 73 return -EIO;
58 } 74 }
59 75
60 if (!SND_SOC_DAPM_EVENT_OFF(event)) 76 if (SND_SOC_DAPM_EVENT_ON(event)) {
61 return 0; 77 /* set codec PLL source to the 19.2MHz platform clock (MCLK) */
62 78 ret = snd_soc_dai_set_pll(codec_dai, 0, RT5670_PLL1_S_MCLK,
63 /* Set codec sysclk source to its internal clock because codec PLL will 79 CHT_PLAT_CLK_3_HZ, 48000 * 512);
64 * be off when idle and MCLK will also be off by ACPI when codec is 80 if (ret < 0) {
65 * runtime suspended. Codec needs clock for jack detection and button 81 dev_err(card->dev, "can't set codec pll: %d\n", ret);
66 * press. 82 return ret;
67 */ 83 }
68 snd_soc_dai_set_sysclk(codec_dai, RT5670_SCLK_S_RCCLK, 84
69 0, SND_SOC_CLOCK_IN); 85 /* set codec sysclk source to PLL */
70 86 ret = snd_soc_dai_set_sysclk(codec_dai, RT5670_SCLK_S_PLL1,
87 48000 * 512, SND_SOC_CLOCK_IN);
88 if (ret < 0) {
89 dev_err(card->dev, "can't set codec sysclk: %d\n", ret);
90 return ret;
91 }
92 } else {
93 /* Set codec sysclk source to its internal clock because codec
94 * PLL will be off when idle and MCLK will also be off by ACPI
95 * when codec is runtime suspended. Codec needs clock for jack
96 * detection and button press.
97 */
98 snd_soc_dai_set_sysclk(codec_dai, RT5670_SCLK_S_RCCLK,
99 48000 * 512, SND_SOC_CLOCK_IN);
100 }
71 return 0; 101 return 0;
72} 102}
73 103
@@ -77,7 +107,8 @@ static const struct snd_soc_dapm_widget cht_dapm_widgets[] = {
77 SND_SOC_DAPM_MIC("Int Mic", NULL), 107 SND_SOC_DAPM_MIC("Int Mic", NULL),
78 SND_SOC_DAPM_SPK("Ext Spk", NULL), 108 SND_SOC_DAPM_SPK("Ext Spk", NULL),
79 SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, 109 SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
80 platform_clock_control, SND_SOC_DAPM_POST_PMD), 110 platform_clock_control, SND_SOC_DAPM_PRE_PMU |
111 SND_SOC_DAPM_POST_PMD),
81}; 112};
82 113
83static const struct snd_soc_dapm_route cht_audio_map[] = { 114static const struct snd_soc_dapm_route cht_audio_map[] = {
@@ -162,6 +193,15 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime)
162 | RT5670_AD_MONO_L_FILTER 193 | RT5670_AD_MONO_L_FILTER
163 | RT5670_AD_MONO_R_FILTER, 194 | RT5670_AD_MONO_R_FILTER,
164 RT5670_CLK_SEL_I2S1_ASRC); 195 RT5670_CLK_SEL_I2S1_ASRC);
196
197 ret = snd_soc_card_jack_new(runtime->card, "Headset",
198 SND_JACK_HEADSET | SND_JACK_BTN_0 |
199 SND_JACK_BTN_1 | SND_JACK_BTN_2, &cht_bsw_headset,
200 cht_bsw_headset_pins, ARRAY_SIZE(cht_bsw_headset_pins));
201 if (ret)
202 return ret;
203
204 rt5670_set_jack_detect(codec, &cht_bsw_headset);
165 return 0; 205 return 0;
166} 206}
167 207
@@ -251,6 +291,35 @@ static struct snd_soc_dai_link cht_dailink[] = {
251 }, 291 },
252}; 292};
253 293
294static int cht_suspend_pre(struct snd_soc_card *card)
295{
296 struct snd_soc_codec *codec;
297
298 list_for_each_entry(codec, &card->codec_dev_list, card_list) {
299 if (!strcmp(codec->component.name, "i2c-10EC5670:00")) {
300 dev_dbg(codec->dev, "disabling jack detect before going to suspend.\n");
301 rt5670_jack_suspend(codec);
302 break;
303 }
304 }
305 return 0;
306}
307
308static int cht_resume_post(struct snd_soc_card *card)
309{
310 struct snd_soc_codec *codec;
311
312 list_for_each_entry(codec, &card->codec_dev_list, card_list) {
313 if (!strcmp(codec->component.name, "i2c-10EC5670:00")) {
314 dev_dbg(codec->dev, "enabling jack detect for resume.\n");
315 rt5670_jack_resume(codec);
316 break;
317 }
318 }
319
320 return 0;
321}
322
254/* SoC card */ 323/* SoC card */
255static struct snd_soc_card snd_soc_card_cht = { 324static struct snd_soc_card snd_soc_card_cht = {
256 .name = "cherrytrailcraudio", 325 .name = "cherrytrailcraudio",
@@ -262,6 +331,8 @@ static struct snd_soc_card snd_soc_card_cht = {
262 .num_dapm_routes = ARRAY_SIZE(cht_audio_map), 331 .num_dapm_routes = ARRAY_SIZE(cht_audio_map),
263 .controls = cht_mc_controls, 332 .controls = cht_mc_controls,
264 .num_controls = ARRAY_SIZE(cht_mc_controls), 333 .num_controls = ARRAY_SIZE(cht_mc_controls),
334 .suspend_pre = cht_suspend_pre,
335 .resume_post = cht_resume_post,
265}; 336};
266 337
267static int snd_cht_mc_probe(struct platform_device *pdev) 338static int snd_cht_mc_probe(struct platform_device *pdev)
diff --git a/sound/soc/intel/haswell.c b/sound/soc/intel/boards/haswell.c
index 00fddd3f5dfb..22558572cb9c 100644
--- a/sound/soc/intel/haswell.c
+++ b/sound/soc/intel/boards/haswell.c
@@ -21,10 +21,10 @@
21#include <sound/soc.h> 21#include <sound/soc.h>
22#include <sound/pcm_params.h> 22#include <sound/pcm_params.h>
23 23
24#include "sst-dsp.h" 24#include "../common/sst-dsp.h"
25#include "sst-haswell-ipc.h" 25#include "../haswell/sst-haswell-ipc.h"
26 26
27#include "../codecs/rt5640.h" 27#include "../../codecs/rt5640.h"
28 28
29/* Haswell ULT platforms have a Headphone and Mic jack */ 29/* Haswell ULT platforms have a Headphone and Mic jack */
30static const struct snd_soc_dapm_widget haswell_widgets[] = { 30static const struct snd_soc_dapm_widget haswell_widgets[] = {
diff --git a/sound/soc/intel/mfld_machine.c b/sound/soc/intel/boards/mfld_machine.c
index 49c09a0add79..49c09a0add79 100644
--- a/sound/soc/intel/mfld_machine.c
+++ b/sound/soc/intel/boards/mfld_machine.c
diff --git a/sound/soc/intel/common/Makefile b/sound/soc/intel/common/Makefile
new file mode 100644
index 000000000000..f24154ca4e98
--- /dev/null
+++ b/sound/soc/intel/common/Makefile
@@ -0,0 +1,7 @@
1snd-soc-sst-dsp-objs := sst-dsp.o sst-firmware.o
2snd-soc-sst-acpi-objs := sst-acpi.o
3snd-soc-sst-ipc-objs := sst-ipc.o
4
5obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o snd-soc-sst-ipc.o
6obj-$(CONFIG_SND_SOC_INTEL_SST_ACPI) += snd-soc-sst-acpi.o
7
diff --git a/sound/soc/intel/sst-acpi.c b/sound/soc/intel/common/sst-acpi.c
index 42f293f9c6e2..42f293f9c6e2 100644
--- a/sound/soc/intel/sst-acpi.c
+++ b/sound/soc/intel/common/sst-acpi.c
diff --git a/sound/soc/intel/sst-dsp-priv.h b/sound/soc/intel/common/sst-dsp-priv.h
index b9da030e312d..396d54510350 100644
--- a/sound/soc/intel/sst-dsp-priv.h
+++ b/sound/soc/intel/common/sst-dsp-priv.h
@@ -173,6 +173,16 @@ struct sst_module_runtime_context {
173}; 173};
174 174
175/* 175/*
176 * Audio DSP Module State
177 */
178enum sst_module_state {
179 SST_MODULE_STATE_UNLOADED = 0, /* default state */
180 SST_MODULE_STATE_LOADED,
181 SST_MODULE_STATE_INITIALIZED, /* and inactive */
182 SST_MODULE_STATE_ACTIVE,
183};
184
185/*
176 * Audio DSP Generic Module. 186 * Audio DSP Generic Module.
177 * 187 *
178 * Each Firmware file can consist of 1..N modules. A module can span multiple 188 * Each Firmware file can consist of 1..N modules. A module can span multiple
@@ -203,6 +213,9 @@ struct sst_module {
203 struct list_head list; /* DSP list of modules */ 213 struct list_head list; /* DSP list of modules */
204 struct list_head list_fw; /* FW list of modules */ 214 struct list_head list_fw; /* FW list of modules */
205 struct list_head runtime_list; /* list of runtime module objects*/ 215 struct list_head runtime_list; /* list of runtime module objects*/
216
217 /* state */
218 enum sst_module_state state;
206}; 219};
207 220
208/* 221/*
diff --git a/sound/soc/intel/sst-dsp.c b/sound/soc/intel/common/sst-dsp.c
index 64e94212d2d2..64e94212d2d2 100644
--- a/sound/soc/intel/sst-dsp.c
+++ b/sound/soc/intel/common/sst-dsp.c
diff --git a/sound/soc/intel/sst-dsp.h b/sound/soc/intel/common/sst-dsp.h
index 148d8c589a43..96aeb2556ad4 100644
--- a/sound/soc/intel/sst-dsp.h
+++ b/sound/soc/intel/common/sst-dsp.h
@@ -28,7 +28,6 @@
28 28
29/* Supported SST DMA Devices */ 29/* Supported SST DMA Devices */
30#define SST_DMA_TYPE_DW 1 30#define SST_DMA_TYPE_DW 1
31#define SST_DMA_TYPE_MID 2
32 31
33/* autosuspend delay 5s*/ 32/* autosuspend delay 5s*/
34#define SST_RUNTIME_SUSPEND_DELAY (5 * 1000) 33#define SST_RUNTIME_SUSPEND_DELAY (5 * 1000)
diff --git a/sound/soc/intel/sst-firmware.c b/sound/soc/intel/common/sst-firmware.c
index 4a993d16a235..ebcca6dc48d1 100644
--- a/sound/soc/intel/sst-firmware.c
+++ b/sound/soc/intel/common/sst-firmware.c
@@ -221,8 +221,6 @@ int sst_dsp_dma_get_channel(struct sst_dsp *dsp, int chan_id)
221 dma_cap_mask_t mask; 221 dma_cap_mask_t mask;
222 int ret; 222 int ret;
223 223
224 /* The Intel MID DMA engine driver needs the slave config set but
225 * Synopsis DMA engine driver safely ignores the slave config */
226 dma_cap_zero(mask); 224 dma_cap_zero(mask);
227 dma_cap_set(DMA_SLAVE, mask); 225 dma_cap_set(DMA_SLAVE, mask);
228 dma_cap_set(DMA_MEMCPY, mask); 226 dma_cap_set(DMA_MEMCPY, mask);
@@ -281,9 +279,6 @@ int sst_dma_new(struct sst_dsp *sst)
281 case SST_DMA_TYPE_DW: 279 case SST_DMA_TYPE_DW:
282 dma_dev_name = "dw_dmac"; 280 dma_dev_name = "dw_dmac";
283 break; 281 break;
284 case SST_DMA_TYPE_MID:
285 dma_dev_name = "Intel MID DMA";
286 break;
287 default: 282 default:
288 dev_err(sst->dev, "error: invalid DMA engine %d\n", 283 dev_err(sst->dev, "error: invalid DMA engine %d\n",
289 sst->pdata->dma_engine); 284 sst->pdata->dma_engine);
@@ -502,6 +497,7 @@ struct sst_module *sst_module_new(struct sst_fw *sst_fw,
502 sst_module->scratch_size = template->scratch_size; 497 sst_module->scratch_size = template->scratch_size;
503 sst_module->persistent_size = template->persistent_size; 498 sst_module->persistent_size = template->persistent_size;
504 sst_module->entry = template->entry; 499 sst_module->entry = template->entry;
500 sst_module->state = SST_MODULE_STATE_UNLOADED;
505 501
506 INIT_LIST_HEAD(&sst_module->block_list); 502 INIT_LIST_HEAD(&sst_module->block_list);
507 INIT_LIST_HEAD(&sst_module->runtime_list); 503 INIT_LIST_HEAD(&sst_module->runtime_list);
diff --git a/sound/soc/intel/common/sst-ipc.c b/sound/soc/intel/common/sst-ipc.c
new file mode 100644
index 000000000000..4b62a553823c
--- /dev/null
+++ b/sound/soc/intel/common/sst-ipc.c
@@ -0,0 +1,294 @@
1/*
2 * Intel SST generic IPC Support
3 *
4 * Copyright (C) 2015, Intel Corporation. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License version
8 * 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#include <linux/types.h>
18#include <linux/kernel.h>
19#include <linux/list.h>
20#include <linux/wait.h>
21#include <linux/module.h>
22#include <linux/spinlock.h>
23#include <linux/device.h>
24#include <linux/slab.h>
25#include <linux/workqueue.h>
26#include <linux/sched.h>
27#include <linux/delay.h>
28#include <linux/platform_device.h>
29#include <linux/kthread.h>
30#include <sound/asound.h>
31
32#include "sst-dsp.h"
33#include "sst-dsp-priv.h"
34#include "sst-ipc.h"
35
36/* IPC message timeout (msecs) */
37#define IPC_TIMEOUT_MSECS 300
38
39#define IPC_EMPTY_LIST_SIZE 8
40
41/* locks held by caller */
42static struct ipc_message *msg_get_empty(struct sst_generic_ipc *ipc)
43{
44 struct ipc_message *msg = NULL;
45
46 if (!list_empty(&ipc->empty_list)) {
47 msg = list_first_entry(&ipc->empty_list, struct ipc_message,
48 list);
49 list_del(&msg->list);
50 }
51
52 return msg;
53}
54
55static int tx_wait_done(struct sst_generic_ipc *ipc,
56 struct ipc_message *msg, void *rx_data)
57{
58 unsigned long flags;
59 int ret;
60
61 /* wait for DSP completion (in all cases atm inc pending) */
62 ret = wait_event_timeout(msg->waitq, msg->complete,
63 msecs_to_jiffies(IPC_TIMEOUT_MSECS));
64
65 spin_lock_irqsave(&ipc->dsp->spinlock, flags);
66 if (ret == 0) {
67 if (ipc->ops.shim_dbg != NULL)
68 ipc->ops.shim_dbg(ipc, "message timeout");
69
70 list_del(&msg->list);
71 ret = -ETIMEDOUT;
72 } else {
73
74 /* copy the data returned from DSP */
75 if (msg->rx_size)
76 memcpy(rx_data, msg->rx_data, msg->rx_size);
77 ret = msg->errno;
78 }
79
80 list_add_tail(&msg->list, &ipc->empty_list);
81 spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
82 return ret;
83}
84
85static int ipc_tx_message(struct sst_generic_ipc *ipc, u64 header,
86 void *tx_data, size_t tx_bytes, void *rx_data,
87 size_t rx_bytes, int wait)
88{
89 struct ipc_message *msg;
90 unsigned long flags;
91
92 spin_lock_irqsave(&ipc->dsp->spinlock, flags);
93
94 msg = msg_get_empty(ipc);
95 if (msg == NULL) {
96 spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
97 return -EBUSY;
98 }
99
100 msg->header = header;
101 msg->tx_size = tx_bytes;
102 msg->rx_size = rx_bytes;
103 msg->wait = wait;
104 msg->errno = 0;
105 msg->pending = false;
106 msg->complete = false;
107
108 if ((tx_bytes) && (ipc->ops.tx_data_copy != NULL))
109 ipc->ops.tx_data_copy(msg, tx_data, tx_bytes);
110
111 list_add_tail(&msg->list, &ipc->tx_list);
112 spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
113
114 queue_kthread_work(&ipc->kworker, &ipc->kwork);
115
116 if (wait)
117 return tx_wait_done(ipc, msg, rx_data);
118 else
119 return 0;
120}
121
122static int msg_empty_list_init(struct sst_generic_ipc *ipc)
123{
124 int i;
125
126 ipc->msg = kzalloc(sizeof(struct ipc_message) *
127 IPC_EMPTY_LIST_SIZE, GFP_KERNEL);
128 if (ipc->msg == NULL)
129 return -ENOMEM;
130
131 for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) {
132 init_waitqueue_head(&ipc->msg[i].waitq);
133 list_add(&ipc->msg[i].list, &ipc->empty_list);
134 }
135
136 return 0;
137}
138
139static void ipc_tx_msgs(struct kthread_work *work)
140{
141 struct sst_generic_ipc *ipc =
142 container_of(work, struct sst_generic_ipc, kwork);
143 struct ipc_message *msg;
144 unsigned long flags;
145 u64 ipcx;
146
147 spin_lock_irqsave(&ipc->dsp->spinlock, flags);
148
149 if (list_empty(&ipc->tx_list) || ipc->pending) {
150 spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
151 return;
152 }
153
154 /* if the DSP is busy, we will TX messages after IRQ.
155 * also postpone if we are in the middle of procesing completion irq*/
156 ipcx = sst_dsp_shim_read_unlocked(ipc->dsp, SST_IPCX);
157 if (ipcx & (SST_IPCX_BUSY | SST_IPCX_DONE)) {
158 spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
159 return;
160 }
161
162 msg = list_first_entry(&ipc->tx_list, struct ipc_message, list);
163 list_move(&msg->list, &ipc->rx_list);
164
165 if (ipc->ops.tx_msg != NULL)
166 ipc->ops.tx_msg(ipc, msg);
167
168 spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
169}
170
171int sst_ipc_tx_message_wait(struct sst_generic_ipc *ipc, u64 header,
172 void *tx_data, size_t tx_bytes, void *rx_data, size_t rx_bytes)
173{
174 return ipc_tx_message(ipc, header, tx_data, tx_bytes,
175 rx_data, rx_bytes, 1);
176}
177EXPORT_SYMBOL_GPL(sst_ipc_tx_message_wait);
178
179int sst_ipc_tx_message_nowait(struct sst_generic_ipc *ipc, u64 header,
180 void *tx_data, size_t tx_bytes)
181{
182 return ipc_tx_message(ipc, header, tx_data, tx_bytes,
183 NULL, 0, 0);
184}
185EXPORT_SYMBOL_GPL(sst_ipc_tx_message_nowait);
186
187struct ipc_message *sst_ipc_reply_find_msg(struct sst_generic_ipc *ipc,
188 u64 header)
189{
190 struct ipc_message *msg;
191 u64 mask;
192
193 if (ipc->ops.reply_msg_match != NULL)
194 header = ipc->ops.reply_msg_match(header, &mask);
195
196 if (list_empty(&ipc->rx_list)) {
197 dev_err(ipc->dev, "error: rx list empty but received 0x%llx\n",
198 header);
199 return NULL;
200 }
201
202 list_for_each_entry(msg, &ipc->rx_list, list) {
203 if ((msg->header & mask) == header)
204 return msg;
205 }
206
207 return NULL;
208}
209EXPORT_SYMBOL_GPL(sst_ipc_reply_find_msg);
210
211/* locks held by caller */
212void sst_ipc_tx_msg_reply_complete(struct sst_generic_ipc *ipc,
213 struct ipc_message *msg)
214{
215 msg->complete = true;
216
217 if (!msg->wait)
218 list_add_tail(&msg->list, &ipc->empty_list);
219 else
220 wake_up(&msg->waitq);
221}
222EXPORT_SYMBOL_GPL(sst_ipc_tx_msg_reply_complete);
223
224void sst_ipc_drop_all(struct sst_generic_ipc *ipc)
225{
226 struct ipc_message *msg, *tmp;
227 unsigned long flags;
228 int tx_drop_cnt = 0, rx_drop_cnt = 0;
229
230 /* drop all TX and Rx messages before we stall + reset DSP */
231 spin_lock_irqsave(&ipc->dsp->spinlock, flags);
232
233 list_for_each_entry_safe(msg, tmp, &ipc->tx_list, list) {
234 list_move(&msg->list, &ipc->empty_list);
235 tx_drop_cnt++;
236 }
237
238 list_for_each_entry_safe(msg, tmp, &ipc->rx_list, list) {
239 list_move(&msg->list, &ipc->empty_list);
240 rx_drop_cnt++;
241 }
242
243 spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
244
245 if (tx_drop_cnt || rx_drop_cnt)
246 dev_err(ipc->dev, "dropped IPC msg RX=%d, TX=%d\n",
247 tx_drop_cnt, rx_drop_cnt);
248}
249EXPORT_SYMBOL_GPL(sst_ipc_drop_all);
250
251int sst_ipc_init(struct sst_generic_ipc *ipc)
252{
253 int ret;
254
255 INIT_LIST_HEAD(&ipc->tx_list);
256 INIT_LIST_HEAD(&ipc->rx_list);
257 INIT_LIST_HEAD(&ipc->empty_list);
258 init_waitqueue_head(&ipc->wait_txq);
259
260 ret = msg_empty_list_init(ipc);
261 if (ret < 0)
262 return -ENOMEM;
263
264 /* start the IPC message thread */
265 init_kthread_worker(&ipc->kworker);
266 ipc->tx_thread = kthread_run(kthread_worker_fn,
267 &ipc->kworker, "%s",
268 dev_name(ipc->dev));
269 if (IS_ERR(ipc->tx_thread)) {
270 dev_err(ipc->dev, "error: failed to create message TX task\n");
271 ret = PTR_ERR(ipc->tx_thread);
272 kfree(ipc->msg);
273 return ret;
274 }
275
276 init_kthread_work(&ipc->kwork, ipc_tx_msgs);
277 return 0;
278}
279EXPORT_SYMBOL_GPL(sst_ipc_init);
280
281void sst_ipc_fini(struct sst_generic_ipc *ipc)
282{
283 if (ipc->tx_thread)
284 kthread_stop(ipc->tx_thread);
285
286 if (ipc->msg)
287 kfree(ipc->msg);
288}
289EXPORT_SYMBOL_GPL(sst_ipc_fini);
290
291/* Module information */
292MODULE_AUTHOR("Jin Yao");
293MODULE_DESCRIPTION("Intel SST IPC generic");
294MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/intel/common/sst-ipc.h b/sound/soc/intel/common/sst-ipc.h
new file mode 100644
index 000000000000..125ea451a373
--- /dev/null
+++ b/sound/soc/intel/common/sst-ipc.h
@@ -0,0 +1,91 @@
1/*
2 * Intel SST generic IPC Support
3 *
4 * Copyright (C) 2015, Intel Corporation. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License version
8 * 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#ifndef __SST_GENERIC_IPC_H
18#define __SST_GENERIC_IPC_H
19
20#include <linux/types.h>
21#include <linux/kernel.h>
22#include <linux/wait.h>
23#include <linux/list.h>
24#include <linux/workqueue.h>
25#include <linux/sched.h>
26#include <linux/kthread.h>
27
28#define IPC_MAX_MAILBOX_BYTES 256
29
30struct ipc_message {
31 struct list_head list;
32 u64 header;
33
34 /* direction wrt host CPU */
35 char tx_data[IPC_MAX_MAILBOX_BYTES];
36 size_t tx_size;
37 char rx_data[IPC_MAX_MAILBOX_BYTES];
38 size_t rx_size;
39
40 wait_queue_head_t waitq;
41 bool pending;
42 bool complete;
43 bool wait;
44 int errno;
45};
46
47struct sst_generic_ipc;
48
49struct sst_plat_ipc_ops {
50 void (*tx_msg)(struct sst_generic_ipc *, struct ipc_message *);
51 void (*shim_dbg)(struct sst_generic_ipc *, const char *);
52 void (*tx_data_copy)(struct ipc_message *, char *, size_t);
53 u64 (*reply_msg_match)(u64 header, u64 *mask);
54};
55
56/* SST generic IPC data */
57struct sst_generic_ipc {
58 struct device *dev;
59 struct sst_dsp *dsp;
60
61 /* IPC messaging */
62 struct list_head tx_list;
63 struct list_head rx_list;
64 struct list_head empty_list;
65 wait_queue_head_t wait_txq;
66 struct task_struct *tx_thread;
67 struct kthread_worker kworker;
68 struct kthread_work kwork;
69 bool pending;
70 struct ipc_message *msg;
71
72 struct sst_plat_ipc_ops ops;
73};
74
75int sst_ipc_tx_message_wait(struct sst_generic_ipc *ipc, u64 header,
76 void *tx_data, size_t tx_bytes, void *rx_data, size_t rx_bytes);
77
78int sst_ipc_tx_message_nowait(struct sst_generic_ipc *ipc, u64 header,
79 void *tx_data, size_t tx_bytes);
80
81struct ipc_message *sst_ipc_reply_find_msg(struct sst_generic_ipc *ipc,
82 u64 header);
83
84void sst_ipc_tx_msg_reply_complete(struct sst_generic_ipc *ipc,
85 struct ipc_message *msg);
86
87void sst_ipc_drop_all(struct sst_generic_ipc *ipc);
88int sst_ipc_init(struct sst_generic_ipc *ipc);
89void sst_ipc_fini(struct sst_generic_ipc *ipc);
90
91#endif
diff --git a/sound/soc/intel/haswell/Makefile b/sound/soc/intel/haswell/Makefile
new file mode 100644
index 000000000000..9c1723112d22
--- /dev/null
+++ b/sound/soc/intel/haswell/Makefile
@@ -0,0 +1,4 @@
1snd-soc-sst-haswell-pcm-objs := \
2 sst-haswell-ipc.o sst-haswell-pcm.o sst-haswell-dsp.o
3
4obj-$(CONFIG_SND_SOC_INTEL_HASWELL) += snd-soc-sst-haswell-pcm.o
diff --git a/sound/soc/intel/sst-haswell-dsp.c b/sound/soc/intel/haswell/sst-haswell-dsp.c
index 402b728c0a06..7f94920c8a4d 100644
--- a/sound/soc/intel/sst-haswell-dsp.c
+++ b/sound/soc/intel/haswell/sst-haswell-dsp.c
@@ -28,9 +28,9 @@
28#include <linux/firmware.h> 28#include <linux/firmware.h>
29#include <linux/pm_runtime.h> 29#include <linux/pm_runtime.h>
30 30
31#include "sst-dsp.h" 31#include "../common/sst-dsp.h"
32#include "sst-dsp-priv.h" 32#include "../common/sst-dsp-priv.h"
33#include "sst-haswell-ipc.h" 33#include "../haswell/sst-haswell-ipc.h"
34 34
35#include <trace/events/hswadsp.h> 35#include <trace/events/hswadsp.h>
36 36
@@ -100,6 +100,7 @@ static int hsw_parse_module(struct sst_dsp *dsp, struct sst_fw *fw,
100 && module->type != SST_HSW_MODULE_PCM 100 && module->type != SST_HSW_MODULE_PCM
101 && module->type != SST_HSW_MODULE_PCM_REFERENCE 101 && module->type != SST_HSW_MODULE_PCM_REFERENCE
102 && module->type != SST_HSW_MODULE_PCM_CAPTURE 102 && module->type != SST_HSW_MODULE_PCM_CAPTURE
103 && module->type != SST_HSW_MODULE_WAVES
103 && module->type != SST_HSW_MODULE_LPAL) 104 && module->type != SST_HSW_MODULE_LPAL)
104 return 0; 105 return 0;
105 106
@@ -139,6 +140,7 @@ static int hsw_parse_module(struct sst_dsp *dsp, struct sst_fw *fw,
139 mod->type = SST_MEM_IRAM; 140 mod->type = SST_MEM_IRAM;
140 break; 141 break;
141 case SST_HSW_DRAM: 142 case SST_HSW_DRAM:
143 case SST_HSW_REGS:
142 ram = dsp->addr.lpe; 144 ram = dsp->addr.lpe;
143 mod->offset = block->ram_offset; 145 mod->offset = block->ram_offset;
144 mod->type = SST_MEM_DRAM; 146 mod->type = SST_MEM_DRAM;
@@ -169,6 +171,7 @@ static int hsw_parse_module(struct sst_dsp *dsp, struct sst_fw *fw,
169 171
170 block = (void *)block + sizeof(*block) + block->size; 172 block = (void *)block + sizeof(*block) + block->size;
171 } 173 }
174 mod->state = SST_MODULE_STATE_LOADED;
172 175
173 return 0; 176 return 0;
174} 177}
diff --git a/sound/soc/intel/sst-haswell-ipc.c b/sound/soc/intel/haswell/sst-haswell-ipc.c
index 863a9ca34b8e..344a1e9bbce5 100644
--- a/sound/soc/intel/sst-haswell-ipc.c
+++ b/sound/soc/intel/haswell/sst-haswell-ipc.c
@@ -34,8 +34,9 @@
34#include <sound/asound.h> 34#include <sound/asound.h>
35 35
36#include "sst-haswell-ipc.h" 36#include "sst-haswell-ipc.h"
37#include "sst-dsp.h" 37#include "../common/sst-dsp.h"
38#include "sst-dsp-priv.h" 38#include "../common/sst-dsp-priv.h"
39#include "../common/sst-ipc.h"
39 40
40/* Global Message - Generic */ 41/* Global Message - Generic */
41#define IPC_GLB_TYPE_SHIFT 24 42#define IPC_GLB_TYPE_SHIFT 24
@@ -79,6 +80,15 @@
79#define IPC_LOG_ID_MASK (0xf << IPC_LOG_ID_SHIFT) 80#define IPC_LOG_ID_MASK (0xf << IPC_LOG_ID_SHIFT)
80#define IPC_LOG_ID(x) (x << IPC_LOG_ID_SHIFT) 81#define IPC_LOG_ID(x) (x << IPC_LOG_ID_SHIFT)
81 82
83/* Module Message */
84#define IPC_MODULE_OPERATION_SHIFT 20
85#define IPC_MODULE_OPERATION_MASK (0xf << IPC_MODULE_OPERATION_SHIFT)
86#define IPC_MODULE_OPERATION(x) (x << IPC_MODULE_OPERATION_SHIFT)
87
88#define IPC_MODULE_ID_SHIFT 16
89#define IPC_MODULE_ID_MASK (0xf << IPC_MODULE_ID_SHIFT)
90#define IPC_MODULE_ID(x) (x << IPC_MODULE_ID_SHIFT)
91
82/* IPC message timeout (msecs) */ 92/* IPC message timeout (msecs) */
83#define IPC_TIMEOUT_MSECS 300 93#define IPC_TIMEOUT_MSECS 300
84#define IPC_BOOT_MSECS 200 94#define IPC_BOOT_MSECS 200
@@ -115,6 +125,7 @@ enum ipc_glb_type {
115 IPC_GLB_ENTER_DX_STATE = 12, 125 IPC_GLB_ENTER_DX_STATE = 12,
116 IPC_GLB_GET_MIXER_STREAM_INFO = 13, /* Request mixer stream params */ 126 IPC_GLB_GET_MIXER_STREAM_INFO = 13, /* Request mixer stream params */
117 IPC_GLB_DEBUG_LOG_MESSAGE = 14, /* Message to or from the debug logger. */ 127 IPC_GLB_DEBUG_LOG_MESSAGE = 14, /* Message to or from the debug logger. */
128 IPC_GLB_MODULE_OPERATION = 15, /* Message to loadable fw module */
118 IPC_GLB_REQUEST_TRANSFER = 16, /* < Request Transfer for host */ 129 IPC_GLB_REQUEST_TRANSFER = 16, /* < Request Transfer for host */
119 IPC_GLB_MAX_IPC_MESSAGE_TYPE = 17, /* Maximum message number */ 130 IPC_GLB_MAX_IPC_MESSAGE_TYPE = 17, /* Maximum message number */
120}; 131};
@@ -133,6 +144,16 @@ enum ipc_glb_reply {
133 IPC_GLB_REPLY_SOURCE_NOT_STARTED = 10, /* Source was not started. */ 144 IPC_GLB_REPLY_SOURCE_NOT_STARTED = 10, /* Source was not started. */
134}; 145};
135 146
147enum ipc_module_operation {
148 IPC_MODULE_NOTIFICATION = 0,
149 IPC_MODULE_ENABLE = 1,
150 IPC_MODULE_DISABLE = 2,
151 IPC_MODULE_GET_PARAMETER = 3,
152 IPC_MODULE_SET_PARAMETER = 4,
153 IPC_MODULE_GET_INFO = 5,
154 IPC_MODULE_MAX_MESSAGE
155};
156
136/* Stream Message - Types */ 157/* Stream Message - Types */
137enum ipc_str_operation { 158enum ipc_str_operation {
138 IPC_STR_RESET = 0, 159 IPC_STR_RESET = 0,
@@ -190,23 +211,6 @@ struct sst_hsw_ipc_fw_ready {
190 u8 fw_info[IPC_MAX_MAILBOX_BYTES - 5 * sizeof(u32)]; 211 u8 fw_info[IPC_MAX_MAILBOX_BYTES - 5 * sizeof(u32)];
191} __attribute__((packed)); 212} __attribute__((packed));
192 213
193struct ipc_message {
194 struct list_head list;
195 u32 header;
196
197 /* direction wrt host CPU */
198 char tx_data[IPC_MAX_MAILBOX_BYTES];
199 size_t tx_size;
200 char rx_data[IPC_MAX_MAILBOX_BYTES];
201 size_t rx_size;
202
203 wait_queue_head_t waitq;
204 bool pending;
205 bool complete;
206 bool wait;
207 int errno;
208};
209
210struct sst_hsw_stream; 214struct sst_hsw_stream;
211struct sst_hsw; 215struct sst_hsw;
212 216
@@ -305,18 +309,19 @@ struct sst_hsw {
305 bool shutdown; 309 bool shutdown;
306 310
307 /* IPC messaging */ 311 /* IPC messaging */
308 struct list_head tx_list; 312 struct sst_generic_ipc ipc;
309 struct list_head rx_list;
310 struct list_head empty_list;
311 wait_queue_head_t wait_txq;
312 struct task_struct *tx_thread;
313 struct kthread_worker kworker;
314 struct kthread_work kwork;
315 bool pending;
316 struct ipc_message *msg;
317 313
318 /* FW log stream */ 314 /* FW log stream */
319 struct sst_hsw_log_stream log_stream; 315 struct sst_hsw_log_stream log_stream;
316
317 /* flags bit field to track module state when resume from RTD3,
318 * each bit represent state (enabled/disabled) of single module */
319 u32 enabled_modules_rtd3;
320
321 /* buffer to store parameter lines */
322 u32 param_idx_w; /* write index */
323 u32 param_idx_r; /* read index */
324 u8 param_buf[WAVES_PARAM_LINES][WAVES_PARAM_COUNT];
320}; 325};
321 326
322#define CREATE_TRACE_POINTS 327#define CREATE_TRACE_POINTS
@@ -352,6 +357,16 @@ static inline u32 msg_get_notify_reason(u32 msg)
352 return (msg & IPC_STG_TYPE_MASK) >> IPC_STG_TYPE_SHIFT; 357 return (msg & IPC_STG_TYPE_MASK) >> IPC_STG_TYPE_SHIFT;
353} 358}
354 359
360static inline u32 msg_get_module_operation(u32 msg)
361{
362 return (msg & IPC_MODULE_OPERATION_MASK) >> IPC_MODULE_OPERATION_SHIFT;
363}
364
365static inline u32 msg_get_module_id(u32 msg)
366{
367 return (msg & IPC_MODULE_ID_MASK) >> IPC_MODULE_ID_SHIFT;
368}
369
355u32 create_channel_map(enum sst_hsw_channel_config config) 370u32 create_channel_map(enum sst_hsw_channel_config config)
356{ 371{
357 switch (config) { 372 switch (config) {
@@ -417,159 +432,6 @@ static struct sst_hsw_stream *get_stream_by_id(struct sst_hsw *hsw,
417 return NULL; 432 return NULL;
418} 433}
419 434
420static void ipc_shim_dbg(struct sst_hsw *hsw, const char *text)
421{
422 struct sst_dsp *sst = hsw->dsp;
423 u32 isr, ipcd, imrx, ipcx;
424
425 ipcx = sst_dsp_shim_read_unlocked(sst, SST_IPCX);
426 isr = sst_dsp_shim_read_unlocked(sst, SST_ISRX);
427 ipcd = sst_dsp_shim_read_unlocked(sst, SST_IPCD);
428 imrx = sst_dsp_shim_read_unlocked(sst, SST_IMRX);
429
430 dev_err(hsw->dev, "ipc: --%s-- ipcx 0x%8.8x isr 0x%8.8x ipcd 0x%8.8x imrx 0x%8.8x\n",
431 text, ipcx, isr, ipcd, imrx);
432}
433
434/* locks held by caller */
435static struct ipc_message *msg_get_empty(struct sst_hsw *hsw)
436{
437 struct ipc_message *msg = NULL;
438
439 if (!list_empty(&hsw->empty_list)) {
440 msg = list_first_entry(&hsw->empty_list, struct ipc_message,
441 list);
442 list_del(&msg->list);
443 }
444
445 return msg;
446}
447
448static void ipc_tx_msgs(struct kthread_work *work)
449{
450 struct sst_hsw *hsw =
451 container_of(work, struct sst_hsw, kwork);
452 struct ipc_message *msg;
453 unsigned long flags;
454 u32 ipcx;
455
456 spin_lock_irqsave(&hsw->dsp->spinlock, flags);
457
458 if (list_empty(&hsw->tx_list) || hsw->pending) {
459 spin_unlock_irqrestore(&hsw->dsp->spinlock, flags);
460 return;
461 }
462
463 /* if the DSP is busy, we will TX messages after IRQ.
464 * also postpone if we are in the middle of procesing completion irq*/
465 ipcx = sst_dsp_shim_read_unlocked(hsw->dsp, SST_IPCX);
466 if (ipcx & (SST_IPCX_BUSY | SST_IPCX_DONE)) {
467 spin_unlock_irqrestore(&hsw->dsp->spinlock, flags);
468 return;
469 }
470
471 msg = list_first_entry(&hsw->tx_list, struct ipc_message, list);
472
473 list_move(&msg->list, &hsw->rx_list);
474
475 /* send the message */
476 sst_dsp_outbox_write(hsw->dsp, msg->tx_data, msg->tx_size);
477 sst_dsp_ipc_msg_tx(hsw->dsp, msg->header | SST_IPCX_BUSY);
478
479 spin_unlock_irqrestore(&hsw->dsp->spinlock, flags);
480}
481
482/* locks held by caller */
483static void tx_msg_reply_complete(struct sst_hsw *hsw, struct ipc_message *msg)
484{
485 msg->complete = true;
486 trace_ipc_reply("completed", msg->header);
487
488 if (!msg->wait)
489 list_add_tail(&msg->list, &hsw->empty_list);
490 else
491 wake_up(&msg->waitq);
492}
493
494static int tx_wait_done(struct sst_hsw *hsw, struct ipc_message *msg,
495 void *rx_data)
496{
497 unsigned long flags;
498 int ret;
499
500 /* wait for DSP completion (in all cases atm inc pending) */
501 ret = wait_event_timeout(msg->waitq, msg->complete,
502 msecs_to_jiffies(IPC_TIMEOUT_MSECS));
503
504 spin_lock_irqsave(&hsw->dsp->spinlock, flags);
505 if (ret == 0) {
506 ipc_shim_dbg(hsw, "message timeout");
507
508 trace_ipc_error("error message timeout for", msg->header);
509 list_del(&msg->list);
510 ret = -ETIMEDOUT;
511 } else {
512
513 /* copy the data returned from DSP */
514 if (msg->rx_size)
515 memcpy(rx_data, msg->rx_data, msg->rx_size);
516 ret = msg->errno;
517 }
518
519 list_add_tail(&msg->list, &hsw->empty_list);
520 spin_unlock_irqrestore(&hsw->dsp->spinlock, flags);
521 return ret;
522}
523
524static int ipc_tx_message(struct sst_hsw *hsw, u32 header, void *tx_data,
525 size_t tx_bytes, void *rx_data, size_t rx_bytes, int wait)
526{
527 struct ipc_message *msg;
528 unsigned long flags;
529
530 spin_lock_irqsave(&hsw->dsp->spinlock, flags);
531
532 msg = msg_get_empty(hsw);
533 if (msg == NULL) {
534 spin_unlock_irqrestore(&hsw->dsp->spinlock, flags);
535 return -EBUSY;
536 }
537
538 if (tx_bytes)
539 memcpy(msg->tx_data, tx_data, tx_bytes);
540
541 msg->header = header;
542 msg->tx_size = tx_bytes;
543 msg->rx_size = rx_bytes;
544 msg->wait = wait;
545 msg->errno = 0;
546 msg->pending = false;
547 msg->complete = false;
548
549 list_add_tail(&msg->list, &hsw->tx_list);
550 spin_unlock_irqrestore(&hsw->dsp->spinlock, flags);
551
552 queue_kthread_work(&hsw->kworker, &hsw->kwork);
553
554 if (wait)
555 return tx_wait_done(hsw, msg, rx_data);
556 else
557 return 0;
558}
559
560static inline int ipc_tx_message_wait(struct sst_hsw *hsw, u32 header,
561 void *tx_data, size_t tx_bytes, void *rx_data, size_t rx_bytes)
562{
563 return ipc_tx_message(hsw, header, tx_data, tx_bytes, rx_data,
564 rx_bytes, 1);
565}
566
567static inline int ipc_tx_message_nowait(struct sst_hsw *hsw, u32 header,
568 void *tx_data, size_t tx_bytes)
569{
570 return ipc_tx_message(hsw, header, tx_data, tx_bytes, NULL, 0, 0);
571}
572
573static void hsw_fw_ready(struct sst_hsw *hsw, u32 header) 435static void hsw_fw_ready(struct sst_hsw *hsw, u32 header)
574{ 436{
575 struct sst_hsw_ipc_fw_ready fw_ready; 437 struct sst_hsw_ipc_fw_ready fw_ready;
@@ -604,7 +466,7 @@ static void hsw_fw_ready(struct sst_hsw *hsw, u32 header)
604 /* log the FW version info got from the mailbox here. */ 466 /* log the FW version info got from the mailbox here. */
605 memcpy(fw_info, fw_ready.fw_info, fw_ready.fw_info_size); 467 memcpy(fw_info, fw_ready.fw_info, fw_ready.fw_info_size);
606 pinfo = &fw_info[0]; 468 pinfo = &fw_info[0];
607 for (i = 0; i < sizeof(tmp) / sizeof(char *); i++) 469 for (i = 0; i < ARRAY_SIZE(tmp); i++)
608 tmp[i] = strsep(&pinfo, " "); 470 tmp[i] = strsep(&pinfo, " ");
609 dev_info(hsw->dev, "FW loaded, mailbox readback FW info: type %s, - " 471 dev_info(hsw->dev, "FW loaded, mailbox readback FW info: type %s, - "
610 "version: %s.%s, build %s, source commit id: %s\n", 472 "version: %s.%s, build %s, source commit id: %s\n",
@@ -657,27 +519,6 @@ static void hsw_notification_work(struct work_struct *work)
657 sst_dsp_shim_update_bits(hsw->dsp, SST_IMRX, SST_IMRX_BUSY, 0); 519 sst_dsp_shim_update_bits(hsw->dsp, SST_IMRX, SST_IMRX_BUSY, 0);
658} 520}
659 521
660static struct ipc_message *reply_find_msg(struct sst_hsw *hsw, u32 header)
661{
662 struct ipc_message *msg;
663
664 /* clear reply bits & status bits */
665 header &= ~(IPC_STATUS_MASK | IPC_GLB_REPLY_MASK);
666
667 if (list_empty(&hsw->rx_list)) {
668 dev_err(hsw->dev, "error: rx list empty but received 0x%x\n",
669 header);
670 return NULL;
671 }
672
673 list_for_each_entry(msg, &hsw->rx_list, list) {
674 if (msg->header == header)
675 return msg;
676 }
677
678 return NULL;
679}
680
681static void hsw_stream_update(struct sst_hsw *hsw, struct ipc_message *msg) 522static void hsw_stream_update(struct sst_hsw *hsw, struct ipc_message *msg)
682{ 523{
683 struct sst_hsw_stream *stream; 524 struct sst_hsw_stream *stream;
@@ -716,7 +557,7 @@ static int hsw_process_reply(struct sst_hsw *hsw, u32 header)
716 557
717 trace_ipc_reply("processing -->", header); 558 trace_ipc_reply("processing -->", header);
718 559
719 msg = reply_find_msg(hsw, header); 560 msg = sst_ipc_reply_find_msg(&hsw->ipc, header);
720 if (msg == NULL) { 561 if (msg == NULL) {
721 trace_ipc_error("error: can't find message header", header); 562 trace_ipc_error("error: can't find message header", header);
722 return -EIO; 563 return -EIO;
@@ -727,14 +568,14 @@ static int hsw_process_reply(struct sst_hsw *hsw, u32 header)
727 case IPC_GLB_REPLY_PENDING: 568 case IPC_GLB_REPLY_PENDING:
728 trace_ipc_pending_reply("received", header); 569 trace_ipc_pending_reply("received", header);
729 msg->pending = true; 570 msg->pending = true;
730 hsw->pending = true; 571 hsw->ipc.pending = true;
731 return 1; 572 return 1;
732 case IPC_GLB_REPLY_SUCCESS: 573 case IPC_GLB_REPLY_SUCCESS:
733 if (msg->pending) { 574 if (msg->pending) {
734 trace_ipc_pending_reply("completed", header); 575 trace_ipc_pending_reply("completed", header);
735 sst_dsp_inbox_read(hsw->dsp, msg->rx_data, 576 sst_dsp_inbox_read(hsw->dsp, msg->rx_data,
736 msg->rx_size); 577 msg->rx_size);
737 hsw->pending = false; 578 hsw->ipc.pending = false;
738 } else { 579 } else {
739 /* copy data from the DSP */ 580 /* copy data from the DSP */
740 sst_dsp_outbox_read(hsw->dsp, msg->rx_data, 581 sst_dsp_outbox_read(hsw->dsp, msg->rx_data,
@@ -790,11 +631,36 @@ static int hsw_process_reply(struct sst_hsw *hsw, u32 header)
790 631
791 /* wake up and return the error if we have waiters on this message ? */ 632 /* wake up and return the error if we have waiters on this message ? */
792 list_del(&msg->list); 633 list_del(&msg->list);
793 tx_msg_reply_complete(hsw, msg); 634 sst_ipc_tx_msg_reply_complete(&hsw->ipc, msg);
794 635
795 return 1; 636 return 1;
796} 637}
797 638
639static int hsw_module_message(struct sst_hsw *hsw, u32 header)
640{
641 u32 operation, module_id;
642 int handled = 0;
643
644 operation = msg_get_module_operation(header);
645 module_id = msg_get_module_id(header);
646 dev_dbg(hsw->dev, "received module message header: 0x%8.8x\n",
647 header);
648 dev_dbg(hsw->dev, "operation: 0x%8.8x module_id: 0x%8.8x\n",
649 operation, module_id);
650
651 switch (operation) {
652 case IPC_MODULE_NOTIFICATION:
653 dev_dbg(hsw->dev, "module notification received");
654 handled = 1;
655 break;
656 default:
657 handled = hsw_process_reply(hsw, header);
658 break;
659 }
660
661 return handled;
662}
663
798static int hsw_stream_message(struct sst_hsw *hsw, u32 header) 664static int hsw_stream_message(struct sst_hsw *hsw, u32 header)
799{ 665{
800 u32 stream_msg, stream_id, stage_type; 666 u32 stream_msg, stream_id, stage_type;
@@ -890,6 +756,9 @@ static int hsw_process_notification(struct sst_hsw *hsw)
890 case IPC_GLB_DEBUG_LOG_MESSAGE: 756 case IPC_GLB_DEBUG_LOG_MESSAGE:
891 handled = hsw_log_message(hsw, header); 757 handled = hsw_log_message(hsw, header);
892 break; 758 break;
759 case IPC_GLB_MODULE_OPERATION:
760 handled = hsw_module_message(hsw, header);
761 break;
893 default: 762 default:
894 dev_err(hsw->dev, "error: unexpected type %d hdr 0x%8.8x\n", 763 dev_err(hsw->dev, "error: unexpected type %d hdr 0x%8.8x\n",
895 type, header); 764 type, header);
@@ -903,6 +772,7 @@ static irqreturn_t hsw_irq_thread(int irq, void *context)
903{ 772{
904 struct sst_dsp *sst = (struct sst_dsp *) context; 773 struct sst_dsp *sst = (struct sst_dsp *) context;
905 struct sst_hsw *hsw = sst_dsp_get_thread_context(sst); 774 struct sst_hsw *hsw = sst_dsp_get_thread_context(sst);
775 struct sst_generic_ipc *ipc = &hsw->ipc;
906 u32 ipcx, ipcd; 776 u32 ipcx, ipcd;
907 int handled; 777 int handled;
908 unsigned long flags; 778 unsigned long flags;
@@ -949,7 +819,7 @@ static irqreturn_t hsw_irq_thread(int irq, void *context)
949 spin_unlock_irqrestore(&sst->spinlock, flags); 819 spin_unlock_irqrestore(&sst->spinlock, flags);
950 820
951 /* continue to send any remaining messages... */ 821 /* continue to send any remaining messages... */
952 queue_kthread_work(&hsw->kworker, &hsw->kwork); 822 queue_kthread_work(&ipc->kworker, &ipc->kwork);
953 823
954 return IRQ_HANDLED; 824 return IRQ_HANDLED;
955} 825}
@@ -959,7 +829,8 @@ int sst_hsw_fw_get_version(struct sst_hsw *hsw,
959{ 829{
960 int ret; 830 int ret;
961 831
962 ret = ipc_tx_message_wait(hsw, IPC_GLB_TYPE(IPC_GLB_GET_FW_VERSION), 832 ret = sst_ipc_tx_message_wait(&hsw->ipc,
833 IPC_GLB_TYPE(IPC_GLB_GET_FW_VERSION),
963 NULL, 0, version, sizeof(*version)); 834 NULL, 0, version, sizeof(*version));
964 if (ret < 0) 835 if (ret < 0)
965 dev_err(hsw->dev, "error: get version failed\n"); 836 dev_err(hsw->dev, "error: get version failed\n");
@@ -1023,7 +894,8 @@ int sst_hsw_stream_set_volume(struct sst_hsw *hsw,
1023 req->channel = channel; 894 req->channel = channel;
1024 } 895 }
1025 896
1026 ret = ipc_tx_message_wait(hsw, header, req, sizeof(*req), NULL, 0); 897 ret = sst_ipc_tx_message_wait(&hsw->ipc, header, req,
898 sizeof(*req), NULL, 0);
1027 if (ret < 0) { 899 if (ret < 0) {
1028 dev_err(hsw->dev, "error: set stream volume failed\n"); 900 dev_err(hsw->dev, "error: set stream volume failed\n");
1029 return ret; 901 return ret;
@@ -1088,7 +960,8 @@ int sst_hsw_mixer_set_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel,
1088 req.curve_type = hsw->curve_type; 960 req.curve_type = hsw->curve_type;
1089 req.target_volume = volume; 961 req.target_volume = volume;
1090 962
1091 ret = ipc_tx_message_wait(hsw, header, &req, sizeof(req), NULL, 0); 963 ret = sst_ipc_tx_message_wait(&hsw->ipc, header, &req,
964 sizeof(req), NULL, 0);
1092 if (ret < 0) { 965 if (ret < 0) {
1093 dev_err(hsw->dev, "error: set mixer volume failed\n"); 966 dev_err(hsw->dev, "error: set mixer volume failed\n");
1094 return ret; 967 return ret;
@@ -1146,7 +1019,7 @@ int sst_hsw_stream_free(struct sst_hsw *hsw, struct sst_hsw_stream *stream)
1146 stream->free_req.stream_id = stream->reply.stream_hw_id; 1019 stream->free_req.stream_id = stream->reply.stream_hw_id;
1147 header = IPC_GLB_TYPE(IPC_GLB_FREE_STREAM); 1020 header = IPC_GLB_TYPE(IPC_GLB_FREE_STREAM);
1148 1021
1149 ret = ipc_tx_message_wait(hsw, header, &stream->free_req, 1022 ret = sst_ipc_tx_message_wait(&hsw->ipc, header, &stream->free_req,
1150 sizeof(stream->free_req), NULL, 0); 1023 sizeof(stream->free_req), NULL, 0);
1151 if (ret < 0) { 1024 if (ret < 0) {
1152 dev_err(hsw->dev, "error: free stream %d failed\n", 1025 dev_err(hsw->dev, "error: free stream %d failed\n",
@@ -1338,8 +1211,8 @@ int sst_hsw_stream_commit(struct sst_hsw *hsw, struct sst_hsw_stream *stream)
1338 1211
1339 header = IPC_GLB_TYPE(IPC_GLB_ALLOCATE_STREAM); 1212 header = IPC_GLB_TYPE(IPC_GLB_ALLOCATE_STREAM);
1340 1213
1341 ret = ipc_tx_message_wait(hsw, header, str_req, sizeof(*str_req), 1214 ret = sst_ipc_tx_message_wait(&hsw->ipc, header, str_req,
1342 reply, sizeof(*reply)); 1215 sizeof(*str_req), reply, sizeof(*reply));
1343 if (ret < 0) { 1216 if (ret < 0) {
1344 dev_err(hsw->dev, "error: stream commit failed\n"); 1217 dev_err(hsw->dev, "error: stream commit failed\n");
1345 return ret; 1218 return ret;
@@ -1388,7 +1261,8 @@ int sst_hsw_mixer_get_info(struct sst_hsw *hsw)
1388 1261
1389 trace_ipc_request("get global mixer info", 0); 1262 trace_ipc_request("get global mixer info", 0);
1390 1263
1391 ret = ipc_tx_message_wait(hsw, header, NULL, 0, reply, sizeof(*reply)); 1264 ret = sst_ipc_tx_message_wait(&hsw->ipc, header, NULL, 0,
1265 reply, sizeof(*reply));
1392 if (ret < 0) { 1266 if (ret < 0) {
1393 dev_err(hsw->dev, "error: get stream info failed\n"); 1267 dev_err(hsw->dev, "error: get stream info failed\n");
1394 return ret; 1268 return ret;
@@ -1409,9 +1283,10 @@ static int sst_hsw_stream_operations(struct sst_hsw *hsw, int type,
1409 header |= (stream_id << IPC_STR_ID_SHIFT); 1283 header |= (stream_id << IPC_STR_ID_SHIFT);
1410 1284
1411 if (wait) 1285 if (wait)
1412 return ipc_tx_message_wait(hsw, header, NULL, 0, NULL, 0); 1286 return sst_ipc_tx_message_wait(&hsw->ipc, header,
1287 NULL, 0, NULL, 0);
1413 else 1288 else
1414 return ipc_tx_message_nowait(hsw, header, NULL, 0); 1289 return sst_ipc_tx_message_nowait(&hsw->ipc, header, NULL, 0);
1415} 1290}
1416 1291
1417/* Stream ALSA trigger operations */ 1292/* Stream ALSA trigger operations */
@@ -1538,8 +1413,8 @@ int sst_hsw_device_set_config(struct sst_hsw *hsw,
1538 1413
1539 header = IPC_GLB_TYPE(IPC_GLB_SET_DEVICE_FORMATS); 1414 header = IPC_GLB_TYPE(IPC_GLB_SET_DEVICE_FORMATS);
1540 1415
1541 ret = ipc_tx_message_wait(hsw, header, &config, sizeof(config), 1416 ret = sst_ipc_tx_message_wait(&hsw->ipc, header, &config,
1542 NULL, 0); 1417 sizeof(config), NULL, 0);
1543 if (ret < 0) 1418 if (ret < 0)
1544 dev_err(hsw->dev, "error: set device formats failed\n"); 1419 dev_err(hsw->dev, "error: set device formats failed\n");
1545 1420
@@ -1559,8 +1434,8 @@ int sst_hsw_dx_set_state(struct sst_hsw *hsw,
1559 1434
1560 trace_ipc_request("PM enter Dx state", state); 1435 trace_ipc_request("PM enter Dx state", state);
1561 1436
1562 ret = ipc_tx_message_wait(hsw, header, &state_, sizeof(state_), 1437 ret = sst_ipc_tx_message_wait(&hsw->ipc, header, &state_,
1563 dx, sizeof(*dx)); 1438 sizeof(state_), dx, sizeof(*dx));
1564 if (ret < 0) { 1439 if (ret < 0) {
1565 dev_err(hsw->dev, "ipc: error set dx state %d failed\n", state); 1440 dev_err(hsw->dev, "ipc: error set dx state %d failed\n", state);
1566 return ret; 1441 return ret;
@@ -1703,32 +1578,6 @@ static int sst_hsw_dx_state_restore(struct sst_hsw *hsw)
1703 return 0; 1578 return 0;
1704} 1579}
1705 1580
1706static void sst_hsw_drop_all(struct sst_hsw *hsw)
1707{
1708 struct ipc_message *msg, *tmp;
1709 unsigned long flags;
1710 int tx_drop_cnt = 0, rx_drop_cnt = 0;
1711
1712 /* drop all TX and Rx messages before we stall + reset DSP */
1713 spin_lock_irqsave(&hsw->dsp->spinlock, flags);
1714
1715 list_for_each_entry_safe(msg, tmp, &hsw->tx_list, list) {
1716 list_move(&msg->list, &hsw->empty_list);
1717 tx_drop_cnt++;
1718 }
1719
1720 list_for_each_entry_safe(msg, tmp, &hsw->rx_list, list) {
1721 list_move(&msg->list, &hsw->empty_list);
1722 rx_drop_cnt++;
1723 }
1724
1725 spin_unlock_irqrestore(&hsw->dsp->spinlock, flags);
1726
1727 if (tx_drop_cnt || rx_drop_cnt)
1728 dev_err(hsw->dev, "dropped IPC msg RX=%d, TX=%d\n",
1729 tx_drop_cnt, rx_drop_cnt);
1730}
1731
1732int sst_hsw_dsp_load(struct sst_hsw *hsw) 1581int sst_hsw_dsp_load(struct sst_hsw *hsw)
1733{ 1582{
1734 struct sst_dsp *dsp = hsw->dsp; 1583 struct sst_dsp *dsp = hsw->dsp;
@@ -1808,7 +1657,7 @@ int sst_hsw_dsp_runtime_suspend(struct sst_hsw *hsw)
1808 if (ret < 0) 1657 if (ret < 0)
1809 return ret; 1658 return ret;
1810 1659
1811 sst_hsw_drop_all(hsw); 1660 sst_ipc_drop_all(&hsw->ipc);
1812 1661
1813 return 0; 1662 return 0;
1814} 1663}
@@ -1844,6 +1693,8 @@ int sst_hsw_dsp_runtime_resume(struct sst_hsw *hsw)
1844 if (ret < 0) 1693 if (ret < 0)
1845 dev_err(dev, "error: audio DSP boot failure\n"); 1694 dev_err(dev, "error: audio DSP boot failure\n");
1846 1695
1696 sst_hsw_init_module_state(hsw);
1697
1847 ret = wait_event_timeout(hsw->boot_wait, hsw->boot_complete, 1698 ret = wait_event_timeout(hsw->boot_wait, hsw->boot_complete,
1848 msecs_to_jiffies(IPC_BOOT_MSECS)); 1699 msecs_to_jiffies(IPC_BOOT_MSECS));
1849 if (ret == 0) { 1700 if (ret == 0) {
@@ -1864,26 +1715,345 @@ int sst_hsw_dsp_runtime_resume(struct sst_hsw *hsw)
1864} 1715}
1865#endif 1716#endif
1866 1717
1867static int msg_empty_list_init(struct sst_hsw *hsw) 1718struct sst_dsp *sst_hsw_get_dsp(struct sst_hsw *hsw)
1868{ 1719{
1869 int i; 1720 return hsw->dsp;
1721}
1870 1722
1871 hsw->msg = kzalloc(sizeof(struct ipc_message) * 1723void sst_hsw_init_module_state(struct sst_hsw *hsw)
1872 IPC_EMPTY_LIST_SIZE, GFP_KERNEL); 1724{
1873 if (hsw->msg == NULL) 1725 struct sst_module *module;
1874 return -ENOMEM; 1726 enum sst_hsw_module_id id;
1727
1728 /* the base fw contains several modules */
1729 for (id = SST_HSW_MODULE_BASE_FW; id < SST_HSW_MAX_MODULE_ID; id++) {
1730 module = sst_module_get_from_id(hsw->dsp, id);
1731 if (module) {
1732 /* module waves is active only after being enabled */
1733 if (id == SST_HSW_MODULE_WAVES)
1734 module->state = SST_MODULE_STATE_INITIALIZED;
1735 else
1736 module->state = SST_MODULE_STATE_ACTIVE;
1737 }
1738 }
1739}
1740
1741bool sst_hsw_is_module_loaded(struct sst_hsw *hsw, u32 module_id)
1742{
1743 struct sst_module *module;
1744
1745 module = sst_module_get_from_id(hsw->dsp, module_id);
1746 if (module == NULL || module->state == SST_MODULE_STATE_UNLOADED)
1747 return false;
1748 else
1749 return true;
1750}
1751
1752bool sst_hsw_is_module_active(struct sst_hsw *hsw, u32 module_id)
1753{
1754 struct sst_module *module;
1755
1756 module = sst_module_get_from_id(hsw->dsp, module_id);
1757 if (module != NULL && module->state == SST_MODULE_STATE_ACTIVE)
1758 return true;
1759 else
1760 return false;
1761}
1875 1762
1876 for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) { 1763void sst_hsw_set_module_enabled_rtd3(struct sst_hsw *hsw, u32 module_id)
1877 init_waitqueue_head(&hsw->msg[i].waitq); 1764{
1878 list_add(&hsw->msg[i].list, &hsw->empty_list); 1765 hsw->enabled_modules_rtd3 |= (1 << module_id);
1766}
1767
1768void sst_hsw_set_module_disabled_rtd3(struct sst_hsw *hsw, u32 module_id)
1769{
1770 hsw->enabled_modules_rtd3 &= ~(1 << module_id);
1771}
1772
1773bool sst_hsw_is_module_enabled_rtd3(struct sst_hsw *hsw, u32 module_id)
1774{
1775 return hsw->enabled_modules_rtd3 & (1 << module_id);
1776}
1777
1778void sst_hsw_reset_param_buf(struct sst_hsw *hsw)
1779{
1780 hsw->param_idx_w = 0;
1781 hsw->param_idx_r = 0;
1782 memset((void *)hsw->param_buf, 0, sizeof(hsw->param_buf));
1783}
1784
1785int sst_hsw_store_param_line(struct sst_hsw *hsw, u8 *buf)
1786{
1787 /* save line to the first available position of param buffer */
1788 if (hsw->param_idx_w > WAVES_PARAM_LINES - 1) {
1789 dev_warn(hsw->dev, "warning: param buffer overflow!\n");
1790 return -EPERM;
1791 }
1792 memcpy(hsw->param_buf[hsw->param_idx_w], buf, WAVES_PARAM_COUNT);
1793 hsw->param_idx_w++;
1794 return 0;
1795}
1796
1797int sst_hsw_load_param_line(struct sst_hsw *hsw, u8 *buf)
1798{
1799 u8 id = 0;
1800
1801 /* read the first matching line from param buffer */
1802 while (hsw->param_idx_r < WAVES_PARAM_LINES) {
1803 id = hsw->param_buf[hsw->param_idx_r][0];
1804 hsw->param_idx_r++;
1805 if (buf[0] == id) {
1806 memcpy(buf, hsw->param_buf[hsw->param_idx_r],
1807 WAVES_PARAM_COUNT);
1808 break;
1809 }
1879 } 1810 }
1811 if (hsw->param_idx_r > WAVES_PARAM_LINES - 1) {
1812 dev_dbg(hsw->dev, "end of buffer, roll to the beginning\n");
1813 hsw->param_idx_r = 0;
1814 return 0;
1815 }
1816 return 0;
1817}
1818
1819int sst_hsw_launch_param_buf(struct sst_hsw *hsw)
1820{
1821 int ret, idx;
1880 1822
1823 if (!sst_hsw_is_module_active(hsw, SST_HSW_MODULE_WAVES)) {
1824 dev_dbg(hsw->dev, "module waves is not active\n");
1825 return 0;
1826 }
1827
1828 /* put all param lines to DSP through ipc */
1829 for (idx = 0; idx < hsw->param_idx_w; idx++) {
1830 ret = sst_hsw_module_set_param(hsw,
1831 SST_HSW_MODULE_WAVES, 0, hsw->param_buf[idx][0],
1832 WAVES_PARAM_COUNT, hsw->param_buf[idx]);
1833 if (ret < 0)
1834 return ret;
1835 }
1881 return 0; 1836 return 0;
1882} 1837}
1883 1838
1884struct sst_dsp *sst_hsw_get_dsp(struct sst_hsw *hsw) 1839int sst_hsw_module_load(struct sst_hsw *hsw,
1840 u32 module_id, u32 instance_id, char *name)
1885{ 1841{
1886 return hsw->dsp; 1842 int ret = 0;
1843 const struct firmware *fw = NULL;
1844 struct sst_fw *hsw_sst_fw;
1845 struct sst_module *module;
1846 struct device *dev = hsw->dev;
1847 struct sst_dsp *dsp = hsw->dsp;
1848
1849 dev_dbg(dev, "sst_hsw_module_load id=%d, name='%s'", module_id, name);
1850
1851 module = sst_module_get_from_id(dsp, module_id);
1852 if (module == NULL) {
1853 /* loading for the first time */
1854 if (module_id == SST_HSW_MODULE_BASE_FW) {
1855 /* for base module: use fw requested in acpi probe */
1856 fw = dsp->pdata->fw;
1857 if (!fw) {
1858 dev_err(dev, "request Base fw failed\n");
1859 return -ENODEV;
1860 }
1861 } else {
1862 /* try and load any other optional modules if they are
1863 * available. Use dev_info instead of dev_err in case
1864 * request firmware failed */
1865 ret = request_firmware(&fw, name, dev);
1866 if (ret) {
1867 dev_info(dev, "fw image %s not available(%d)\n",
1868 name, ret);
1869 return ret;
1870 }
1871 }
1872 hsw_sst_fw = sst_fw_new(dsp, fw, hsw);
1873 if (hsw_sst_fw == NULL) {
1874 dev_err(dev, "error: failed to load firmware\n");
1875 ret = -ENOMEM;
1876 goto out;
1877 }
1878 module = sst_module_get_from_id(dsp, module_id);
1879 if (module == NULL) {
1880 dev_err(dev, "error: no module %d in firmware %s\n",
1881 module_id, name);
1882 }
1883 } else
1884 dev_info(dev, "module %d (%s) already loaded\n",
1885 module_id, name);
1886out:
1887 /* release fw, but base fw should be released by acpi driver */
1888 if (fw && module_id != SST_HSW_MODULE_BASE_FW)
1889 release_firmware(fw);
1890
1891 return ret;
1892}
1893
1894int sst_hsw_module_enable(struct sst_hsw *hsw,
1895 u32 module_id, u32 instance_id)
1896{
1897 int ret;
1898 u32 header = 0;
1899 struct sst_hsw_ipc_module_config config;
1900 struct sst_module *module;
1901 struct sst_module_runtime *runtime;
1902 struct device *dev = hsw->dev;
1903 struct sst_dsp *dsp = hsw->dsp;
1904
1905 if (!sst_hsw_is_module_loaded(hsw, module_id)) {
1906 dev_dbg(dev, "module %d not loaded\n", module_id);
1907 return 0;
1908 }
1909
1910 if (sst_hsw_is_module_active(hsw, module_id)) {
1911 dev_info(dev, "module %d already enabled\n", module_id);
1912 return 0;
1913 }
1914
1915 module = sst_module_get_from_id(dsp, module_id);
1916 if (module == NULL) {
1917 dev_err(dev, "module %d not valid\n", module_id);
1918 return -ENXIO;
1919 }
1920
1921 runtime = sst_module_runtime_get_from_id(module, module_id);
1922 if (runtime == NULL) {
1923 dev_err(dev, "runtime %d not valid", module_id);
1924 return -ENXIO;
1925 }
1926
1927 header = IPC_GLB_TYPE(IPC_GLB_MODULE_OPERATION) |
1928 IPC_MODULE_OPERATION(IPC_MODULE_ENABLE) |
1929 IPC_MODULE_ID(module_id);
1930 dev_dbg(dev, "module enable header: %x\n", header);
1931
1932 config.map.module_entries_count = 1;
1933 config.map.module_entries[0].module_id = module->id;
1934 config.map.module_entries[0].entry_point = module->entry;
1935
1936 config.persistent_mem.offset =
1937 sst_dsp_get_offset(dsp,
1938 runtime->persistent_offset, SST_MEM_DRAM);
1939 config.persistent_mem.size = module->persistent_size;
1940
1941 config.scratch_mem.offset =
1942 sst_dsp_get_offset(dsp,
1943 dsp->scratch_offset, SST_MEM_DRAM);
1944 config.scratch_mem.size = module->scratch_size;
1945 dev_dbg(dev, "mod %d enable p:%d @ %x, s:%d @ %x, ep: %x",
1946 config.map.module_entries[0].module_id,
1947 config.persistent_mem.size,
1948 config.persistent_mem.offset,
1949 config.scratch_mem.size, config.scratch_mem.offset,
1950 config.map.module_entries[0].entry_point);
1951
1952 ret = sst_ipc_tx_message_wait(&hsw->ipc, header,
1953 &config, sizeof(config), NULL, 0);
1954 if (ret < 0)
1955 dev_err(dev, "ipc: module enable failed - %d\n", ret);
1956 else
1957 module->state = SST_MODULE_STATE_ACTIVE;
1958
1959 return ret;
1960}
1961
1962int sst_hsw_module_disable(struct sst_hsw *hsw,
1963 u32 module_id, u32 instance_id)
1964{
1965 int ret;
1966 u32 header;
1967 struct sst_module *module;
1968 struct device *dev = hsw->dev;
1969 struct sst_dsp *dsp = hsw->dsp;
1970
1971 if (!sst_hsw_is_module_loaded(hsw, module_id)) {
1972 dev_dbg(dev, "module %d not loaded\n", module_id);
1973 return 0;
1974 }
1975
1976 if (!sst_hsw_is_module_active(hsw, module_id)) {
1977 dev_info(dev, "module %d already disabled\n", module_id);
1978 return 0;
1979 }
1980
1981 module = sst_module_get_from_id(dsp, module_id);
1982 if (module == NULL) {
1983 dev_err(dev, "module %d not valid\n", module_id);
1984 return -ENXIO;
1985 }
1986
1987 header = IPC_GLB_TYPE(IPC_GLB_MODULE_OPERATION) |
1988 IPC_MODULE_OPERATION(IPC_MODULE_DISABLE) |
1989 IPC_MODULE_ID(module_id);
1990
1991 ret = sst_ipc_tx_message_wait(&hsw->ipc, header, NULL, 0, NULL, 0);
1992 if (ret < 0)
1993 dev_err(dev, "module disable failed - %d\n", ret);
1994 else
1995 module->state = SST_MODULE_STATE_INITIALIZED;
1996
1997 return ret;
1998}
1999
2000int sst_hsw_module_set_param(struct sst_hsw *hsw,
2001 u32 module_id, u32 instance_id, u32 parameter_id,
2002 u32 param_size, char *param)
2003{
2004 int ret;
2005 unsigned char *data = NULL;
2006 u32 header = 0;
2007 u32 payload_size = 0, transfer_parameter_size = 0;
2008 dma_addr_t dma_addr = 0;
2009 struct sst_hsw_transfer_parameter *parameter;
2010 struct device *dev = hsw->dev;
2011
2012 header = IPC_GLB_TYPE(IPC_GLB_MODULE_OPERATION) |
2013 IPC_MODULE_OPERATION(IPC_MODULE_SET_PARAMETER) |
2014 IPC_MODULE_ID(module_id);
2015 dev_dbg(dev, "sst_hsw_module_set_param header=%x\n", header);
2016
2017 payload_size = param_size +
2018 sizeof(struct sst_hsw_transfer_parameter) -
2019 sizeof(struct sst_hsw_transfer_list);
2020 dev_dbg(dev, "parameter size : %d\n", param_size);
2021 dev_dbg(dev, "payload size : %d\n", payload_size);
2022
2023 if (payload_size <= SST_HSW_IPC_MAX_SHORT_PARAMETER_SIZE) {
2024 /* short parameter, mailbox can contain data */
2025 dev_dbg(dev, "transfer parameter size : %d\n",
2026 transfer_parameter_size);
2027
2028 transfer_parameter_size = ALIGN(payload_size, 4);
2029 dev_dbg(dev, "transfer parameter aligned size : %d\n",
2030 transfer_parameter_size);
2031
2032 parameter = kzalloc(transfer_parameter_size, GFP_KERNEL);
2033 if (parameter == NULL)
2034 return -ENOMEM;
2035
2036 memcpy(parameter->data, param, param_size);
2037 } else {
2038 dev_warn(dev, "transfer parameter size too large!");
2039 return 0;
2040 }
2041
2042 parameter->parameter_id = parameter_id;
2043 parameter->data_size = param_size;
2044
2045 ret = sst_ipc_tx_message_wait(&hsw->ipc, header,
2046 parameter, transfer_parameter_size , NULL, 0);
2047 if (ret < 0)
2048 dev_err(dev, "ipc: module set parameter failed - %d\n", ret);
2049
2050 kfree(parameter);
2051
2052 if (data)
2053 dma_free_coherent(hsw->dsp->dma_dev,
2054 param_size, (void *)data, dma_addr);
2055
2056 return ret;
1887} 2057}
1888 2058
1889static struct sst_dsp_device hsw_dev = { 2059static struct sst_dsp_device hsw_dev = {
@@ -1891,10 +2061,48 @@ static struct sst_dsp_device hsw_dev = {
1891 .ops = &haswell_ops, 2061 .ops = &haswell_ops,
1892}; 2062};
1893 2063
2064static void hsw_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg)
2065{
2066 /* send the message */
2067 sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size);
2068 sst_dsp_ipc_msg_tx(ipc->dsp, msg->header);
2069}
2070
2071static void hsw_shim_dbg(struct sst_generic_ipc *ipc, const char *text)
2072{
2073 struct sst_dsp *sst = ipc->dsp;
2074 u32 isr, ipcd, imrx, ipcx;
2075
2076 ipcx = sst_dsp_shim_read_unlocked(sst, SST_IPCX);
2077 isr = sst_dsp_shim_read_unlocked(sst, SST_ISRX);
2078 ipcd = sst_dsp_shim_read_unlocked(sst, SST_IPCD);
2079 imrx = sst_dsp_shim_read_unlocked(sst, SST_IMRX);
2080
2081 dev_err(ipc->dev,
2082 "ipc: --%s-- ipcx 0x%8.8x isr 0x%8.8x ipcd 0x%8.8x imrx 0x%8.8x\n",
2083 text, ipcx, isr, ipcd, imrx);
2084}
2085
2086static void hsw_tx_data_copy(struct ipc_message *msg, char *tx_data,
2087 size_t tx_size)
2088{
2089 memcpy(msg->tx_data, tx_data, tx_size);
2090}
2091
2092static u64 hsw_reply_msg_match(u64 header, u64 *mask)
2093{
2094 /* clear reply bits & status bits */
2095 header &= ~(IPC_STATUS_MASK | IPC_GLB_REPLY_MASK);
2096 *mask = (u64)-1;
2097
2098 return header;
2099}
2100
1894int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata) 2101int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata)
1895{ 2102{
1896 struct sst_hsw_ipc_fw_version version; 2103 struct sst_hsw_ipc_fw_version version;
1897 struct sst_hsw *hsw; 2104 struct sst_hsw *hsw;
2105 struct sst_generic_ipc *ipc;
1898 int ret; 2106 int ret;
1899 2107
1900 dev_dbg(dev, "initialising Audio DSP IPC\n"); 2108 dev_dbg(dev, "initialising Audio DSP IPC\n");
@@ -1903,39 +2111,30 @@ int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata)
1903 if (hsw == NULL) 2111 if (hsw == NULL)
1904 return -ENOMEM; 2112 return -ENOMEM;
1905 2113
1906 hsw->dev = dev; 2114 ipc = &hsw->ipc;
1907 INIT_LIST_HEAD(&hsw->stream_list); 2115 ipc->dev = dev;
1908 INIT_LIST_HEAD(&hsw->tx_list); 2116 ipc->ops.tx_msg = hsw_tx_msg;
1909 INIT_LIST_HEAD(&hsw->rx_list); 2117 ipc->ops.shim_dbg = hsw_shim_dbg;
1910 INIT_LIST_HEAD(&hsw->empty_list); 2118 ipc->ops.tx_data_copy = hsw_tx_data_copy;
1911 init_waitqueue_head(&hsw->boot_wait); 2119 ipc->ops.reply_msg_match = hsw_reply_msg_match;
1912 init_waitqueue_head(&hsw->wait_txq);
1913
1914 ret = msg_empty_list_init(hsw);
1915 if (ret < 0)
1916 return -ENOMEM;
1917 2120
1918 /* start the IPC message thread */ 2121 ret = sst_ipc_init(ipc);
1919 init_kthread_worker(&hsw->kworker); 2122 if (ret != 0)
1920 hsw->tx_thread = kthread_run(kthread_worker_fn, 2123 goto ipc_init_err;
1921 &hsw->kworker, "%s",
1922 dev_name(hsw->dev));
1923 if (IS_ERR(hsw->tx_thread)) {
1924 ret = PTR_ERR(hsw->tx_thread);
1925 dev_err(hsw->dev, "error: failed to create message TX task\n");
1926 goto err_free_msg;
1927 }
1928 init_kthread_work(&hsw->kwork, ipc_tx_msgs);
1929 2124
2125 INIT_LIST_HEAD(&hsw->stream_list);
2126 init_waitqueue_head(&hsw->boot_wait);
1930 hsw_dev.thread_context = hsw; 2127 hsw_dev.thread_context = hsw;
1931 2128
1932 /* init SST shim */ 2129 /* init SST shim */
1933 hsw->dsp = sst_dsp_new(dev, &hsw_dev, pdata); 2130 hsw->dsp = sst_dsp_new(dev, &hsw_dev, pdata);
1934 if (hsw->dsp == NULL) { 2131 if (hsw->dsp == NULL) {
1935 ret = -ENODEV; 2132 ret = -ENODEV;
1936 goto dsp_err; 2133 goto dsp_new_err;
1937 } 2134 }
1938 2135
2136 ipc->dsp = hsw->dsp;
2137
1939 /* allocate DMA buffer for context storage */ 2138 /* allocate DMA buffer for context storage */
1940 hsw->dx_context = dma_alloc_coherent(hsw->dsp->dma_dev, 2139 hsw->dx_context = dma_alloc_coherent(hsw->dsp->dma_dev,
1941 SST_HSW_DX_CONTEXT_SIZE, &hsw->dx_context_paddr, GFP_KERNEL); 2140 SST_HSW_DX_CONTEXT_SIZE, &hsw->dx_context_paddr, GFP_KERNEL);
@@ -1947,18 +2146,22 @@ int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata)
1947 /* keep the DSP in reset state for base FW loading */ 2146 /* keep the DSP in reset state for base FW loading */
1948 sst_dsp_reset(hsw->dsp); 2147 sst_dsp_reset(hsw->dsp);
1949 2148
1950 hsw->sst_fw = sst_fw_new(hsw->dsp, pdata->fw, hsw); 2149 /* load base module and other modules in base firmware image */
1951 if (hsw->sst_fw == NULL) { 2150 ret = sst_hsw_module_load(hsw, SST_HSW_MODULE_BASE_FW, 0, "Base");
1952 ret = -ENODEV; 2151 if (ret < 0)
1953 dev_err(dev, "error: failed to load firmware\n");
1954 goto fw_err; 2152 goto fw_err;
1955 } 2153
2154 /* try to load module waves */
2155 sst_hsw_module_load(hsw, SST_HSW_MODULE_WAVES, 0, "intel/IntcPP01.bin");
1956 2156
1957 /* allocate scratch mem regions */ 2157 /* allocate scratch mem regions */
1958 ret = sst_block_alloc_scratch(hsw->dsp); 2158 ret = sst_block_alloc_scratch(hsw->dsp);
1959 if (ret < 0) 2159 if (ret < 0)
1960 goto boot_err; 2160 goto boot_err;
1961 2161
2162 /* init param buffer */
2163 sst_hsw_reset_param_buf(hsw);
2164
1962 /* wait for DSP boot completion */ 2165 /* wait for DSP boot completion */
1963 sst_dsp_boot(hsw->dsp); 2166 sst_dsp_boot(hsw->dsp);
1964 ret = wait_event_timeout(hsw->boot_wait, hsw->boot_complete, 2167 ret = wait_event_timeout(hsw->boot_wait, hsw->boot_complete,
@@ -1971,6 +2174,9 @@ int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata)
1971 goto boot_err; 2174 goto boot_err;
1972 } 2175 }
1973 2176
2177 /* init module state after boot */
2178 sst_hsw_init_module_state(hsw);
2179
1974 /* get the FW version */ 2180 /* get the FW version */
1975 sst_hsw_fw_get_version(hsw, &version); 2181 sst_hsw_fw_get_version(hsw, &version);
1976 2182
@@ -1986,17 +2192,16 @@ int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata)
1986 2192
1987boot_err: 2193boot_err:
1988 sst_dsp_reset(hsw->dsp); 2194 sst_dsp_reset(hsw->dsp);
1989 sst_fw_free(hsw->sst_fw); 2195 sst_fw_free_all(hsw->dsp);
1990fw_err: 2196fw_err:
1991 dma_free_coherent(hsw->dsp->dma_dev, SST_HSW_DX_CONTEXT_SIZE, 2197 dma_free_coherent(hsw->dsp->dma_dev, SST_HSW_DX_CONTEXT_SIZE,
1992 hsw->dx_context, hsw->dx_context_paddr); 2198 hsw->dx_context, hsw->dx_context_paddr);
1993dma_err: 2199dma_err:
1994 sst_dsp_free(hsw->dsp); 2200 sst_dsp_free(hsw->dsp);
1995dsp_err: 2201dsp_new_err:
1996 kthread_stop(hsw->tx_thread); 2202 sst_ipc_fini(ipc);
1997err_free_msg: 2203ipc_init_err:
1998 kfree(hsw->msg); 2204 kfree(hsw);
1999
2000 return ret; 2205 return ret;
2001} 2206}
2002EXPORT_SYMBOL_GPL(sst_hsw_dsp_init); 2207EXPORT_SYMBOL_GPL(sst_hsw_dsp_init);
@@ -2010,7 +2215,6 @@ void sst_hsw_dsp_free(struct device *dev, struct sst_pdata *pdata)
2010 dma_free_coherent(hsw->dsp->dma_dev, SST_HSW_DX_CONTEXT_SIZE, 2215 dma_free_coherent(hsw->dsp->dma_dev, SST_HSW_DX_CONTEXT_SIZE,
2011 hsw->dx_context, hsw->dx_context_paddr); 2216 hsw->dx_context, hsw->dx_context_paddr);
2012 sst_dsp_free(hsw->dsp); 2217 sst_dsp_free(hsw->dsp);
2013 kthread_stop(hsw->tx_thread); 2218 sst_ipc_fini(&hsw->ipc);
2014 kfree(hsw->msg);
2015} 2219}
2016EXPORT_SYMBOL_GPL(sst_hsw_dsp_free); 2220EXPORT_SYMBOL_GPL(sst_hsw_dsp_free);
diff --git a/sound/soc/intel/sst-haswell-ipc.h b/sound/soc/intel/haswell/sst-haswell-ipc.h
index 858096041cb1..06d71aefa1fe 100644
--- a/sound/soc/intel/sst-haswell-ipc.h
+++ b/sound/soc/intel/haswell/sst-haswell-ipc.h
@@ -37,6 +37,9 @@
37#define SST_HSW_IPC_MAX_PAYLOAD_SIZE 400 37#define SST_HSW_IPC_MAX_PAYLOAD_SIZE 400
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
41#define WAVES_PARAM_COUNT 128
42#define WAVES_PARAM_LINES 160
40 43
41struct sst_hsw; 44struct sst_hsw;
42struct sst_hsw_stream; 45struct sst_hsw_stream;
@@ -187,6 +190,28 @@ enum sst_hsw_performance_action {
187 SST_HSW_PERF_STOP = 1, 190 SST_HSW_PERF_STOP = 1,
188}; 191};
189 192
193struct sst_hsw_transfer_info {
194 uint32_t destination; /* destination address */
195 uint32_t reverse:1; /* if 1 data flows from destination */
196 uint32_t size:31; /* transfer size in bytes.*/
197 uint16_t first_page_offset; /* offset to data in the first page. */
198 uint8_t packed_pages; /* page addresses. Each occupies 20 bits */
199} __attribute__((packed));
200
201struct sst_hsw_transfer_list {
202 uint32_t transfers_count;
203 struct sst_hsw_transfer_info transfers;
204} __attribute__((packed));
205
206struct sst_hsw_transfer_parameter {
207 uint32_t parameter_id;
208 uint32_t data_size;
209 union {
210 uint8_t data[1];
211 struct sst_hsw_transfer_list transfer_list;
212 };
213} __attribute__((packed));
214
190/* SST firmware module info */ 215/* SST firmware module info */
191struct sst_hsw_module_info { 216struct sst_hsw_module_info {
192 u8 name[SST_HSW_MAX_INFO_SIZE]; 217 u8 name[SST_HSW_MAX_INFO_SIZE];
@@ -215,6 +240,12 @@ struct sst_hsw_fx_enable {
215 struct sst_hsw_memory_info persistent_mem; 240 struct sst_hsw_memory_info persistent_mem;
216} __attribute__((packed)); 241} __attribute__((packed));
217 242
243struct sst_hsw_ipc_module_config {
244 struct sst_hsw_module_map map;
245 struct sst_hsw_memory_info persistent_mem;
246 struct sst_hsw_memory_info scratch_mem;
247} __attribute__((packed));
248
218struct sst_hsw_get_fx_param { 249struct sst_hsw_get_fx_param {
219 u32 parameter_id; 250 u32 parameter_id;
220 u32 param_size; 251 u32 param_size;
@@ -467,6 +498,28 @@ int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata);
467void sst_hsw_dsp_free(struct device *dev, struct sst_pdata *pdata); 498void sst_hsw_dsp_free(struct device *dev, struct sst_pdata *pdata);
468struct sst_dsp *sst_hsw_get_dsp(struct sst_hsw *hsw); 499struct sst_dsp *sst_hsw_get_dsp(struct sst_hsw *hsw);
469 500
501/* fw module function */
502void sst_hsw_init_module_state(struct sst_hsw *hsw);
503bool sst_hsw_is_module_loaded(struct sst_hsw *hsw, u32 module_id);
504bool sst_hsw_is_module_active(struct sst_hsw *hsw, u32 module_id);
505void sst_hsw_set_module_enabled_rtd3(struct sst_hsw *hsw, u32 module_id);
506void sst_hsw_set_module_disabled_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);
512
513int sst_hsw_module_load(struct sst_hsw *hsw,
514 u32 module_id, u32 instance_id, char *name);
515int sst_hsw_module_enable(struct sst_hsw *hsw,
516 u32 module_id, u32 instance_id);
517int sst_hsw_module_disable(struct sst_hsw *hsw,
518 u32 module_id, u32 instance_id);
519int sst_hsw_module_set_param(struct sst_hsw *hsw,
520 u32 module_id, u32 instance_id, u32 parameter_id,
521 u32 param_size, char *param);
522
470/* runtime module management */ 523/* runtime module management */
471struct sst_module_runtime *sst_hsw_runtime_module_create(struct sst_hsw *hsw, 524struct sst_module_runtime *sst_hsw_runtime_module_create(struct sst_hsw *hsw,
472 int mod_id, int offset); 525 int mod_id, int offset);
diff --git a/sound/soc/intel/sst-haswell-pcm.c b/sound/soc/intel/haswell/sst-haswell-pcm.c
index 7e21e8f85885..23ae0400d6db 100644
--- a/sound/soc/intel/sst-haswell-pcm.c
+++ b/sound/soc/intel/haswell/sst-haswell-pcm.c
@@ -29,9 +29,9 @@
29#include <sound/tlv.h> 29#include <sound/tlv.h>
30#include <sound/compress_driver.h> 30#include <sound/compress_driver.h>
31 31
32#include "sst-haswell-ipc.h" 32#include "../haswell/sst-haswell-ipc.h"
33#include "sst-dsp-priv.h" 33#include "../common/sst-dsp-priv.h"
34#include "sst-dsp.h" 34#include "../common/sst-dsp.h"
35 35
36#define HSW_PCM_COUNT 6 36#define HSW_PCM_COUNT 6
37#define HSW_VOLUME_MAX 0x7FFFFFFF /* 0dB */ 37#define HSW_VOLUME_MAX 0x7FFFFFFF /* 0dB */
@@ -137,6 +137,7 @@ struct hsw_priv_data {
137 struct device *dev; 137 struct device *dev;
138 enum hsw_pm_state pm_state; 138 enum hsw_pm_state pm_state;
139 struct snd_soc_card *soc_card; 139 struct snd_soc_card *soc_card;
140 struct sst_module_runtime *runtime_waves; /* sound effect module */
140 141
141 /* page tables */ 142 /* page tables */
142 struct snd_dma_buffer dmab[HSW_PCM_COUNT][2]; 143 struct snd_dma_buffer dmab[HSW_PCM_COUNT][2];
@@ -318,6 +319,93 @@ static int hsw_volume_get(struct snd_kcontrol *kcontrol,
318 return 0; 319 return 0;
319} 320}
320 321
322static int hsw_waves_switch_get(struct snd_kcontrol *kcontrol,
323 struct snd_ctl_elem_value *ucontrol)
324{
325 struct snd_soc_platform *platform = snd_soc_kcontrol_platform(kcontrol);
326 struct hsw_priv_data *pdata = snd_soc_platform_get_drvdata(platform);
327 struct sst_hsw *hsw = pdata->hsw;
328 enum sst_hsw_module_id id = SST_HSW_MODULE_WAVES;
329
330 ucontrol->value.integer.value[0] =
331 (sst_hsw_is_module_active(hsw, id) ||
332 sst_hsw_is_module_enabled_rtd3(hsw, id));
333 return 0;
334}
335
336static int hsw_waves_switch_put(struct snd_kcontrol *kcontrol,
337 struct snd_ctl_elem_value *ucontrol)
338{
339 struct snd_soc_platform *platform = snd_soc_kcontrol_platform(kcontrol);
340 struct hsw_priv_data *pdata = snd_soc_platform_get_drvdata(platform);
341 struct sst_hsw *hsw = pdata->hsw;
342 int ret = 0;
343 enum sst_hsw_module_id id = SST_HSW_MODULE_WAVES;
344 bool switch_on = (bool)ucontrol->value.integer.value[0];
345
346 /* if module is in RAM on the DSP, apply user settings to module through
347 * ipc. If module is not in RAM on the DSP, store user setting for
348 * track */
349 if (sst_hsw_is_module_loaded(hsw, id)) {
350 if (switch_on == sst_hsw_is_module_active(hsw, id))
351 return 0;
352
353 if (switch_on)
354 ret = sst_hsw_module_enable(hsw, id, 0);
355 else
356 ret = sst_hsw_module_disable(hsw, id, 0);
357 } else {
358 if (switch_on == sst_hsw_is_module_enabled_rtd3(hsw, id))
359 return 0;
360
361 if (switch_on)
362 sst_hsw_set_module_enabled_rtd3(hsw, id);
363 else
364 sst_hsw_set_module_disabled_rtd3(hsw, id);
365 }
366
367 return ret;
368}
369
370static int hsw_waves_param_get(struct snd_kcontrol *kcontrol,
371 struct snd_ctl_elem_value *ucontrol)
372{
373 struct snd_soc_platform *platform = snd_soc_kcontrol_platform(kcontrol);
374 struct hsw_priv_data *pdata = snd_soc_platform_get_drvdata(platform);
375 struct sst_hsw *hsw = pdata->hsw;
376
377 /* return a matching line from param buffer */
378 return sst_hsw_load_param_line(hsw, ucontrol->value.bytes.data);
379}
380
381static int hsw_waves_param_put(struct snd_kcontrol *kcontrol,
382 struct snd_ctl_elem_value *ucontrol)
383{
384 struct snd_soc_platform *platform = snd_soc_kcontrol_platform(kcontrol);
385 struct hsw_priv_data *pdata = snd_soc_platform_get_drvdata(platform);
386 struct sst_hsw *hsw = pdata->hsw;
387 int ret;
388 enum sst_hsw_module_id id = SST_HSW_MODULE_WAVES;
389 int param_id = ucontrol->value.bytes.data[0];
390 int param_size = WAVES_PARAM_COUNT;
391
392 /* clear param buffer and reset buffer index */
393 if (param_id == 0xFF) {
394 sst_hsw_reset_param_buf(hsw);
395 return 0;
396 }
397
398 /* store params into buffer */
399 ret = sst_hsw_store_param_line(hsw, ucontrol->value.bytes.data);
400 if (ret < 0)
401 return ret;
402
403 if (sst_hsw_is_module_active(hsw, id))
404 ret = sst_hsw_module_set_param(hsw, id, 0, param_id,
405 param_size, ucontrol->value.bytes.data);
406 return ret;
407}
408
321/* TLV used by both global and stream volumes */ 409/* TLV used by both global and stream volumes */
322static const DECLARE_TLV_DB_SCALE(hsw_vol_tlv, -9000, 300, 1); 410static const DECLARE_TLV_DB_SCALE(hsw_vol_tlv, -9000, 300, 1);
323 411
@@ -339,6 +427,12 @@ static const struct snd_kcontrol_new hsw_volume_controls[] = {
339 SOC_DOUBLE_EXT_TLV("Mic Capture Volume", 4, 0, 8, 427 SOC_DOUBLE_EXT_TLV("Mic Capture Volume", 4, 0, 8,
340 ARRAY_SIZE(volume_map) - 1, 0, 428 ARRAY_SIZE(volume_map) - 1, 0,
341 hsw_stream_volume_get, hsw_stream_volume_put, hsw_vol_tlv), 429 hsw_stream_volume_get, hsw_stream_volume_put, hsw_vol_tlv),
430 /* enable/disable module waves */
431 SOC_SINGLE_BOOL_EXT("Waves Switch", 0,
432 hsw_waves_switch_get, hsw_waves_switch_put),
433 /* set parameters to module waves */
434 SND_SOC_BYTES_EXT("Waves Set Param", WAVES_PARAM_COUNT,
435 hsw_waves_param_get, hsw_waves_param_put),
342}; 436};
343 437
344/* Create DMA buffer page table for DSP */ 438/* Create DMA buffer page table for DSP */
@@ -807,6 +901,14 @@ static int hsw_pcm_create_modules(struct hsw_priv_data *pdata)
807 pcm_data->runtime->persistent_offset; 901 pcm_data->runtime->persistent_offset;
808 } 902 }
809 903
904 /* create runtime blocks for module waves */
905 if (sst_hsw_is_module_loaded(hsw, SST_HSW_MODULE_WAVES)) {
906 pdata->runtime_waves = sst_hsw_runtime_module_create(hsw,
907 SST_HSW_MODULE_WAVES, 0);
908 if (pdata->runtime_waves == NULL)
909 goto err;
910 }
911
810 return 0; 912 return 0;
811 913
812err: 914err:
@@ -820,14 +922,17 @@ err:
820 922
821static void hsw_pcm_free_modules(struct hsw_priv_data *pdata) 923static void hsw_pcm_free_modules(struct hsw_priv_data *pdata)
822{ 924{
925 struct sst_hsw *hsw = pdata->hsw;
823 struct hsw_pcm_data *pcm_data; 926 struct hsw_pcm_data *pcm_data;
824 int i; 927 int i;
825 928
826 for (i = 0; i < ARRAY_SIZE(mod_map); i++) { 929 for (i = 0; i < ARRAY_SIZE(mod_map); i++) {
827 pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream]; 930 pcm_data = &pdata->pcm[mod_map[i].dai_id][mod_map[i].stream];
828
829 sst_hsw_runtime_module_free(pcm_data->runtime); 931 sst_hsw_runtime_module_free(pcm_data->runtime);
830 } 932 }
933 if (sst_hsw_is_module_loaded(hsw, SST_HSW_MODULE_WAVES)) {
934 sst_hsw_runtime_module_free(pdata->runtime_waves);
935 }
831} 936}
832 937
833static int hsw_pcm_new(struct snd_soc_pcm_runtime *rtd) 938static int hsw_pcm_new(struct snd_soc_pcm_runtime *rtd)
@@ -984,7 +1089,9 @@ static int hsw_pcm_probe(struct snd_soc_platform *platform)
984 } 1089 }
985 1090
986 /* allocate runtime modules */ 1091 /* allocate runtime modules */
987 hsw_pcm_create_modules(priv_data); 1092 ret = hsw_pcm_create_modules(priv_data);
1093 if (ret < 0)
1094 goto err;
988 1095
989 /* enable runtime PM with auto suspend */ 1096 /* enable runtime PM with auto suspend */
990 pm_runtime_set_autosuspend_delay(platform->dev, 1097 pm_runtime_set_autosuspend_delay(platform->dev,
@@ -996,7 +1103,7 @@ static int hsw_pcm_probe(struct snd_soc_platform *platform)
996 return 0; 1103 return 0;
997 1104
998err: 1105err:
999 for (;i >= 0; i--) { 1106 for (--i; i >= 0; i--) {
1000 if (hsw_dais[i].playback.channels_min) 1107 if (hsw_dais[i].playback.channels_min)
1001 snd_dma_free_pages(&priv_data->dmab[i][0]); 1108 snd_dma_free_pages(&priv_data->dmab[i][0]);
1002 if (hsw_dais[i].capture.channels_min) 1109 if (hsw_dais[i].capture.channels_min)
@@ -1101,10 +1208,18 @@ static int hsw_pcm_runtime_suspend(struct device *dev)
1101{ 1208{
1102 struct hsw_priv_data *pdata = dev_get_drvdata(dev); 1209 struct hsw_priv_data *pdata = dev_get_drvdata(dev);
1103 struct sst_hsw *hsw = pdata->hsw; 1210 struct sst_hsw *hsw = pdata->hsw;
1211 int ret;
1104 1212
1105 if (pdata->pm_state >= HSW_PM_STATE_RTD3) 1213 if (pdata->pm_state >= HSW_PM_STATE_RTD3)
1106 return 0; 1214 return 0;
1107 1215
1216 /* fw modules will be unloaded on RTD3, set flag to track */
1217 if (sst_hsw_is_module_active(hsw, SST_HSW_MODULE_WAVES)) {
1218 ret = sst_hsw_module_disable(hsw, SST_HSW_MODULE_WAVES, 0);
1219 if (ret < 0)
1220 return ret;
1221 sst_hsw_set_module_enabled_rtd3(hsw, SST_HSW_MODULE_WAVES);
1222 }
1108 sst_hsw_dsp_runtime_suspend(hsw); 1223 sst_hsw_dsp_runtime_suspend(hsw);
1109 sst_hsw_dsp_runtime_sleep(hsw); 1224 sst_hsw_dsp_runtime_sleep(hsw);
1110 pdata->pm_state = HSW_PM_STATE_RTD3; 1225 pdata->pm_state = HSW_PM_STATE_RTD3;
@@ -1139,6 +1254,19 @@ static int hsw_pcm_runtime_resume(struct device *dev)
1139 else if (ret == 1) /* no action required */ 1254 else if (ret == 1) /* no action required */
1140 return 0; 1255 return 0;
1141 1256
1257 /* check flag when resume */
1258 if (sst_hsw_is_module_enabled_rtd3(hsw, SST_HSW_MODULE_WAVES)) {
1259 ret = sst_hsw_module_enable(hsw, SST_HSW_MODULE_WAVES, 0);
1260 if (ret < 0)
1261 return ret;
1262 /* put parameters from buffer to dsp */
1263 ret = sst_hsw_launch_param_buf(hsw);
1264 if (ret < 0)
1265 return ret;
1266 /* unset flag */
1267 sst_hsw_set_module_disabled_rtd3(hsw, SST_HSW_MODULE_WAVES);
1268 }
1269
1142 pdata->pm_state = HSW_PM_STATE_D0; 1270 pdata->pm_state = HSW_PM_STATE_D0;
1143 return ret; 1271 return ret;
1144} 1272}