From d5c6d43b3d94e7bf421ec2aaf21b4b7c79fa1850 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 14 Jul 2017 00:04:06 +0100 Subject: ASoC: Intel: Skylake: fix type in debug message Trivial fix to typo in debug message, dst_instacne should be dst_instance Signed-off-by: Colin Ian King Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-messages.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index fb2f1f603f3c..c5b4e0a9946c 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -950,7 +950,7 @@ static void skl_dump_bind_info(struct skl_sst *ctx, struct skl_module_cfg { dev_dbg(ctx->dev, "%s: src module_id = %d src_instance=%d\n", __func__, src_module->id.module_id, src_module->id.pvt_id); - dev_dbg(ctx->dev, "%s: dst_module=%d dst_instacne=%d\n", __func__, + dev_dbg(ctx->dev, "%s: dst_module=%d dst_instance=%d\n", __func__, dst_module->id.module_id, dst_module->id.pvt_id); dev_dbg(ctx->dev, "src_module state = %d dst module state = %d\n", -- cgit v1.2.3 From 82e2b1e081906d3d86c4597250ab2939b209079f Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 13 Jul 2017 01:16:46 -0500 Subject: ASoC: Intel: Skylake: constify snd_soc_dai_ops structures These structures are only stored in the ops field of a snd_soc_dai_driver structure. That field is declared const, so snd_soc_dai_ops structures that have this property can be declared as const also. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-pcm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 0ebea34a4988..b1f2dba642c4 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -628,7 +628,7 @@ static int skl_link_hw_free(struct snd_pcm_substream *substream, return 0; } -static struct snd_soc_dai_ops skl_pcm_dai_ops = { +static const struct snd_soc_dai_ops skl_pcm_dai_ops = { .startup = skl_pcm_open, .shutdown = skl_pcm_close, .prepare = skl_pcm_prepare, @@ -637,15 +637,15 @@ static struct snd_soc_dai_ops skl_pcm_dai_ops = { .trigger = skl_pcm_trigger, }; -static struct snd_soc_dai_ops skl_dmic_dai_ops = { +static const struct snd_soc_dai_ops skl_dmic_dai_ops = { .hw_params = skl_be_hw_params, }; -static struct snd_soc_dai_ops skl_be_ssp_dai_ops = { +static const struct snd_soc_dai_ops skl_be_ssp_dai_ops = { .hw_params = skl_be_hw_params, }; -static struct snd_soc_dai_ops skl_link_dai_ops = { +static const struct snd_soc_dai_ops skl_link_dai_ops = { .prepare = skl_link_pcm_prepare, .hw_params = skl_link_hw_params, .hw_free = skl_link_hw_free, -- cgit v1.2.3 From c115a3178b1dfacd57b643934bb6bbbd1a9557f0 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 13 Jul 2017 01:26:06 -0500 Subject: ASoC: Intel: Atom: constify snd_soc_dai_ops structures These structures are only stored in the ops field of a snd_soc_dai_driver structure. That field is declared const, so snd_soc_dai_ops structures that have this property can be declared as const also. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Mark Brown --- sound/soc/intel/atom/sst-mfld-platform-pcm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c index b082b31023d5..49c7b88b5bdc 100644 --- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c @@ -471,7 +471,7 @@ static void sst_disable_ssp(struct snd_pcm_substream *substream, } } -static struct snd_soc_dai_ops sst_media_dai_ops = { +static const struct snd_soc_dai_ops sst_media_dai_ops = { .startup = sst_media_open, .shutdown = sst_media_close, .prepare = sst_media_prepare, @@ -480,11 +480,11 @@ static struct snd_soc_dai_ops sst_media_dai_ops = { .mute_stream = sst_media_digital_mute, }; -static struct snd_soc_dai_ops sst_compr_dai_ops = { +static const struct snd_soc_dai_ops sst_compr_dai_ops = { .mute_stream = sst_media_digital_mute, }; -static struct snd_soc_dai_ops sst_be_dai_ops = { +static const struct snd_soc_dai_ops sst_be_dai_ops = { .startup = sst_enable_ssp, .hw_params = sst_be_hw_params, .set_fmt = sst_set_format, -- cgit v1.2.3 From 0e46ccd5bc12ab28da9d2f514492aeead65f8332 Mon Sep 17 00:00:00 2001 From: Pradeep Tewani Date: Thu, 20 Jul 2017 11:40:55 +0530 Subject: ASoC: Intel: board: Remove .owner initialization in bxt_rt298 driver The .owner field is not required to be initialized in the driver. So, remove it. Signed-off-by: Pradeep Tewani Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/boards/bxt_rt298.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/boards/bxt_rt298.c b/sound/soc/intel/boards/bxt_rt298.c index 0c3a3cbcb884..1daf98ef9d28 100644 --- a/sound/soc/intel/boards/bxt_rt298.c +++ b/sound/soc/intel/boards/bxt_rt298.c @@ -492,7 +492,6 @@ static int bxt_card_late_probe(struct snd_soc_card *card) /* broxton audio machine driver for SPT + RT298S */ static struct snd_soc_card broxton_rt298 = { .name = "broxton-rt298", - .owner = THIS_MODULE, .dai_link = broxton_rt298_dais, .num_links = ARRAY_SIZE(broxton_rt298_dais), .controls = broxton_controls, -- cgit v1.2.3 From 669eb871c440e19351c2d476d1837ed8a62afe16 Mon Sep 17 00:00:00 2001 From: Pradeep Tewani Date: Thu, 20 Jul 2017 11:40:57 +0530 Subject: ASoC: Intel: board: Add Geminilake platform support Geminilake also features rt298 codec, so use the same machine driver as Broxton. Geminilake uses SSP2 instead of SSP5. Signed-off-by: Pradeep Tewani Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/boards/bxt_rt298.c | 84 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 3 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/boards/bxt_rt298.c b/sound/soc/intel/boards/bxt_rt298.c index 1daf98ef9d28..a4b5bcb1f6f8 100644 --- a/sound/soc/intel/boards/bxt_rt298.c +++ b/sound/soc/intel/boards/bxt_rt298.c @@ -114,7 +114,44 @@ static const struct snd_soc_dapm_route broxton_rt298_map[] = { { "iDisp2 Tx", NULL, "iDisp2_out"}, { "hifi1", NULL, "iDisp1 Tx"}, { "iDisp1 Tx", NULL, "iDisp1_out"}, +}; + +static const struct snd_soc_dapm_route geminilake_rt298_map[] = { + /* speaker */ + {"Speaker", NULL, "SPOR"}, + {"Speaker", NULL, "SPOL"}, + + /* HP jack connectors - unknown if we have jack detect */ + {"Headphone Jack", NULL, "HPO Pin"}, + + /* other jacks */ + {"MIC1", NULL, "Mic Jack"}, + + /* digital mics */ + {"DMIC1 Pin", NULL, "DMIC2"}, + {"DMic", NULL, "SoC DMIC"}, + + {"HDMI1", NULL, "hif5-0 Output"}, + {"HDMI2", NULL, "hif6-0 Output"}, + {"HDMI2", NULL, "hif7-0 Output"}, + + /* CODEC BE connections */ + { "AIF1 Playback", NULL, "ssp2 Tx"}, + { "ssp2 Tx", NULL, "codec0_out"}, + { "ssp2 Tx", NULL, "codec1_out"}, + + { "codec0_in", NULL, "ssp2 Rx" }, + { "ssp2 Rx", NULL, "AIF1 Capture" }, + { "dmic01_hifi", NULL, "DMIC01 Rx" }, + { "DMIC01 Rx", NULL, "Capture" }, + + { "hifi3", NULL, "iDisp3 Tx"}, + { "iDisp3 Tx", NULL, "iDisp3_out"}, + { "hifi2", NULL, "iDisp2 Tx"}, + { "iDisp2 Tx", NULL, "iDisp2_out"}, + { "hifi1", NULL, "iDisp1 Tx"}, + { "iDisp1 Tx", NULL, "iDisp1_out"}, }; static int broxton_rt298_fe_init(struct snd_soc_pcm_runtime *rtd) @@ -505,9 +542,41 @@ static struct snd_soc_card broxton_rt298 = { }; +static struct snd_soc_card geminilake_rt298 = { + .name = "geminilake-rt298", + .dai_link = broxton_rt298_dais, + .num_links = ARRAY_SIZE(broxton_rt298_dais), + .controls = broxton_controls, + .num_controls = ARRAY_SIZE(broxton_controls), + .dapm_widgets = broxton_widgets, + .num_dapm_widgets = ARRAY_SIZE(broxton_widgets), + .dapm_routes = geminilake_rt298_map, + .num_dapm_routes = ARRAY_SIZE(geminilake_rt298_map), + .fully_routed = true, + .late_probe = bxt_card_late_probe, +}; + static int broxton_audio_probe(struct platform_device *pdev) { struct bxt_rt286_private *ctx; + struct snd_soc_card *card = + (struct snd_soc_card *)pdev->id_entry->driver_data; + int i; + + for (i = 0; i < ARRAY_SIZE(broxton_rt298_dais); i++) { + if (!strncmp(card->dai_link[i].codec_name, "i2c-INT343A:00", + I2C_NAME_SIZE)) { + if (!strncmp(card->name, "broxton-rt298", + PLATFORM_NAME_SIZE)) { + card->dai_link[i].name = "SSP5-Codec"; + card->dai_link[i].cpu_dai_name = "SSP5 Pin"; + } else if (!strncmp(card->name, "geminilake-rt298", + PLATFORM_NAME_SIZE)) { + card->dai_link[i].name = "SSP2-Codec"; + card->dai_link[i].cpu_dai_name = "SSP2 Pin"; + } + } + } ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC); if (!ctx) @@ -515,18 +584,26 @@ static int broxton_audio_probe(struct platform_device *pdev) INIT_LIST_HEAD(&ctx->hdmi_pcm_list); - broxton_rt298.dev = &pdev->dev; - snd_soc_card_set_drvdata(&broxton_rt298, ctx); + card->dev = &pdev->dev; + snd_soc_card_set_drvdata(card, ctx); - return devm_snd_soc_register_card(&pdev->dev, &broxton_rt298); + return devm_snd_soc_register_card(&pdev->dev, card); } +static const struct platform_device_id bxt_board_ids[] = { + { .name = "bxt_alc298s_i2s", .driver_data = + (unsigned long)&broxton_rt298 }, + { .name = "glk_alc298s_i2s", .driver_data = + (unsigned long)&geminilake_rt298 }, +}; + static struct platform_driver broxton_audio = { .probe = broxton_audio_probe, .driver = { .name = "bxt_alc298s_i2s", .pm = &snd_soc_pm_ops, }, + .id_table = bxt_board_ids, }; module_platform_driver(broxton_audio) @@ -536,3 +613,4 @@ MODULE_AUTHOR("Senthilnathan Veppur "); MODULE_DESCRIPTION("Intel SST Audio for Broxton"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:bxt_alc298s_i2s"); +MODULE_ALIAS("platform:glk_alc298s_i2s"); -- cgit v1.2.3 From 82444cdb4673c146d43f3f5ff3baf582d4f4cb41 Mon Sep 17 00:00:00 2001 From: Pradeep Tewani Date: Tue, 25 Jul 2017 11:59:46 +0530 Subject: ASoC: Intel: board: Fix missing sentinel for bxt_board_id Without a sentinel in the array of platform devices, we can get a panic so add a sentinel. Full stack dump below: [ 231.564705] BUG: KASAN: global-out-of-bounds in platform_match+0xb0/0x146 [ 231.565500] Read of size 1 at addr ffffffff8380a1a0 by task swapper/0/1 [ 231.566280] [ 231.566594] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.12.0-00289-g152771f #1 [ 231.567526] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.9.3-20161025_171302-gandalf 04/01/2014 [ 231.568730] Call Trace: [ 231.569128] dump_stack+0xf8/0x14a [ 231.569615] print_address_description+0x57/0x1e4 [ 231.570216] ? driver_probe_device+0x814/0x814 [ 231.570798] kasan_report+0x1cb/0x1eb [ 231.571302] ? platform_match+0xb0/0x146 [ 231.571833] __asan_load1+0x45/0x47 [ 231.572324] platform_match+0xb0/0x146 [ 231.572843] ? platform_uevent+0x73/0x73 [ 231.573370] __driver_attach+0x47/0x16a [ 231.573890] bus_for_each_dev+0x11a/0x15c [ 231.574422] ? bus_remove_file+0x57/0x57 [ 231.574951] ? do_raw_spin_unlock+0xc3/0xe0 [ 231.575501] driver_attach+0x2b/0x2e [ 231.576002] bus_add_driver+0x25e/0x3c5 [ 231.576520] ? set_debug_rodata+0x20/0x20 [ 231.584776] driver_register+0x13e/0x19d [ 231.585305] __platform_driver_register+0x6c/0x71 [ 231.585908] ? skl_driver_init+0x20/0x20 [ 231.586436] broxton_audio_init+0x17/0x19 [ 231.586976] do_one_initcall+0x11a/0x221 [ 231.587499] ? start_kernel+0x525/0x525 [ 231.588020] ? lock_downgrade+0x281/0x2ec [ 231.588557] ? trace_hardirqs_on_caller+0x223/0x267 [ 231.589169] ? _raw_spin_unlock_irqrestore+0x49/0x55 [ 231.589791] ? set_debug_rodata+0x20/0x20 [ 231.590324] kernel_init_freeable+0x1fd/0x2b0 [ 231.590891] ? rest_init+0x17c/0x17c [ 231.591384] kernel_init+0x11/0x157 [ 231.591876] ? rest_init+0x17c/0x17c [ 231.592371] ret_from_fork+0x2a/0x40 [ 231.592865] [ 231.593166] The buggy address belongs to the variable: [ 231.593806] bxt_board_ids+0x40/0x9e0 Fixes: 152771fbc3 ("ASoC: Intel: board: Add Geminilake platform support") Reported-by: kbuild test robot Signed-off-by: Pradeep Tewani Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/boards/bxt_rt298.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/boards/bxt_rt298.c b/sound/soc/intel/boards/bxt_rt298.c index a4b5bcb1f6f8..7843104fadcb 100644 --- a/sound/soc/intel/boards/bxt_rt298.c +++ b/sound/soc/intel/boards/bxt_rt298.c @@ -595,6 +595,7 @@ static const struct platform_device_id bxt_board_ids[] = { (unsigned long)&broxton_rt298 }, { .name = "glk_alc298s_i2s", .driver_data = (unsigned long)&geminilake_rt298 }, + {} }; static struct platform_driver broxton_audio = { -- cgit v1.2.3 From c06425705a2565e6747b0adba6027c7b0b04858f Mon Sep 17 00:00:00 2001 From: Kevin Cheng Date: Thu, 27 Jul 2017 16:38:36 +0800 Subject: ASoC: Intel: Add Kabylake machine driver for RT5663 This patch adds Kabylake I2S machine driver which uses RT5663 as headset on ssp1. Signed-off-by: Kevin Cheng Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/boards/kbl_rt5663_max98927.c | 246 +++++++++++++++++++++++---- 1 file changed, 209 insertions(+), 37 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/boards/kbl_rt5663_max98927.c b/sound/soc/intel/boards/kbl_rt5663_max98927.c index f9ba97788157..090331bd6900 100644 --- a/sound/soc/intel/boards/kbl_rt5663_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_max98927.c @@ -34,7 +34,7 @@ #define MAXIM_DEV0_NAME "i2c-MX98927:00" #define MAXIM_DEV1_NAME "i2c-MX98927:01" -static struct snd_soc_card kabylake_audio_card; +static struct snd_soc_card *kabylake_audio_card; static const struct snd_pcm_hw_constraint_list *dmic_constraints; static struct snd_soc_jack skylake_hdmi[3]; @@ -117,6 +117,49 @@ static const struct snd_soc_dapm_route kabylake_map[] = { { "iDisp1 Tx", NULL, "iDisp1_out"}, }; +enum { + KBL_DPCM_AUDIO_5663_PB = 0, + KBL_DPCM_AUDIO_5663_CP, + KBL_DPCM_AUDIO_5663_HDMI1_PB, + KBL_DPCM_AUDIO_5663_HDMI2_PB, +}; + +static const struct snd_kcontrol_new kabylake_5663_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone Jack"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), +}; + +static const struct snd_soc_dapm_widget kabylake_5663_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_SPK("DP", NULL), + SND_SOC_DAPM_SPK("HDMI", NULL), +}; + +static const struct snd_soc_dapm_route kabylake_5663_map[] = { + { "Headphone Jack", NULL, "HPOL" }, + { "Headphone Jack", NULL, "HPOR" }, + + /* other jacks */ + { "IN1P", NULL, "Headset Mic" }, + { "IN1N", NULL, "Headset Mic" }, + + { "HDMI", NULL, "hif5 Output" }, + { "DP", NULL, "hif6 Output" }, + + /* CODEC BE connections */ + { "AIF Playback", NULL, "ssp1 Tx" }, + { "ssp1 Tx", NULL, "codec1_out" }, + + { "codec0_in", NULL, "ssp1 Rx" }, + { "ssp1 Rx", NULL, "AIF Capture" }, + + { "hifi2", NULL, "iDisp2 Tx"}, + { "iDisp2 Tx", NULL, "iDisp2_out"}, + { "hifi1", NULL, "iDisp1 Tx"}, + { "iDisp1 Tx", NULL, "iDisp1_out"}, +}; + static struct snd_soc_codec_conf max98927_codec_conf[] = { { .dev_name = MAXIM_DEV0_NAME, @@ -165,7 +208,7 @@ static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd) * Headset buttons map to the google Reference headset. * These can be configured by userspace. */ - ret = snd_soc_card_jack_new(&kabylake_audio_card, "Headset Jack", + ret = snd_soc_card_jack_new(kabylake_audio_card, "Headset Jack", SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2 | SND_JACK_BTN_3, &ctx->kabylake_headset, NULL, 0); @@ -173,8 +216,18 @@ static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd) dev_err(rtd->dev, "Headset Jack creation failed %d\n", ret); return ret; } - rt5663_set_jack_detect(codec, &ctx->kabylake_headset); + return ret; +} + +static int kabylake_rt5663_max98927_codec_init(struct snd_soc_pcm_runtime *rtd) +{ + int ret; + + ret = kabylake_rt5663_codec_init(rtd); + if (ret) + return ret; + ret = snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC"); if (ret) { dev_err(rtd->dev, "SoC DMIC ignore suspend failed %d\n", ret); @@ -184,7 +237,7 @@ static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd) return ret; } -static int kabylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd) +static int kabylake_hdmi_init(struct snd_soc_pcm_runtime *rtd, int device) { struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *dai = rtd->codec_dai; @@ -194,7 +247,7 @@ static int kabylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd) if (!pcm) return -ENOMEM; - pcm->device = KBL_DPCM_AUDIO_HDMI1_PB; + pcm->device = device; pcm->codec_dai = dai; list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); @@ -202,40 +255,29 @@ static int kabylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd) return 0; } -static int kabylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd) +static int kabylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd) { - struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = rtd->codec_dai; - struct kbl_hdmi_pcm *pcm; - - pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); - if (!pcm) - return -ENOMEM; - - pcm->device = KBL_DPCM_AUDIO_HDMI2_PB; - pcm->codec_dai = dai; - - list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); + return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI1_PB); +} - return 0; +static int kabylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd) +{ + return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI2_PB); } static int kabylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd) { - struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = rtd->codec_dai; - struct kbl_hdmi_pcm *pcm; - - pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); - if (!pcm) - return -ENOMEM; - - pcm->device = KBL_DPCM_AUDIO_HDMI3_PB; - pcm->codec_dai = dai; + return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI3_PB); +} - list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); +static int kabylake_5663_hdmi1_init(struct snd_soc_pcm_runtime *rtd) +{ + return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_5663_HDMI1_PB); +} - return 0; +static int kabylake_5663_hdmi2_init(struct snd_soc_pcm_runtime *rtd) +{ + return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_5663_HDMI2_PB); } static unsigned int rates[] = { @@ -538,7 +580,7 @@ static struct snd_soc_dai_link kabylake_dais[] = { .no_pcm = 1, .codec_name = "i2c-10EC5663:00", .codec_dai_name = KBL_REALTEK_CODEC_DAI, - .init = kabylake_rt5663_codec_init, + .init = kabylake_rt5663_max98927_codec_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ignore_pmdown_time = 1, @@ -594,6 +636,108 @@ static struct snd_soc_dai_link kabylake_dais[] = { }, }; +static struct snd_soc_dai_link kabylake_5663_dais[] = { + /* Front End DAI links */ + [KBL_DPCM_AUDIO_5663_PB] = { + .name = "Kbl Audio Port", + .stream_name = "Audio", + .cpu_dai_name = "System Pin", + .platform_name = "0000:00:1f.3", + .dynamic = 1, + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .nonatomic = 1, + .trigger = { + SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .dpcm_playback = 1, + .ops = &kabylake_rt5663_fe_ops, + }, + [KBL_DPCM_AUDIO_5663_CP] = { + .name = "Kbl Audio Capture Port", + .stream_name = "Audio Record", + .cpu_dai_name = "System Pin", + .platform_name = "0000:00:1f.3", + .dynamic = 1, + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .nonatomic = 1, + .trigger = { + SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .dpcm_capture = 1, + .ops = &kabylake_rt5663_fe_ops, + }, + [KBL_DPCM_AUDIO_5663_HDMI1_PB] = { + .name = "Kbl HDMI Port1", + .stream_name = "Hdmi1", + .cpu_dai_name = "HDMI1 Pin", + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .platform_name = "0000:00:1f.3", + .dpcm_playback = 1, + .init = NULL, + .trigger = { + SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .nonatomic = 1, + .dynamic = 1, + }, + [KBL_DPCM_AUDIO_5663_HDMI2_PB] = { + .name = "Kbl HDMI Port2", + .stream_name = "Hdmi2", + .cpu_dai_name = "HDMI2 Pin", + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .platform_name = "0000:00:1f.3", + .dpcm_playback = 1, + .init = NULL, + .trigger = { + SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .nonatomic = 1, + .dynamic = 1, + }, + + /* Back End DAI links */ + { + /* SSP1 - Codec */ + .name = "SSP1-Codec", + .id = 0, + .cpu_dai_name = "SSP1 Pin", + .platform_name = "0000:00:1f.3", + .no_pcm = 1, + .codec_name = "i2c-10EC5663:00", + .codec_dai_name = KBL_REALTEK_CODEC_DAI, + .init = kabylake_rt5663_codec_init, + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + .ignore_pmdown_time = 1, + .be_hw_params_fixup = kabylake_ssp_fixup, + .ops = &kabylake_rt5663_ops, + .dpcm_playback = 1, + .dpcm_capture = 1, + }, + { + .name = "iDisp1", + .id = 1, + .cpu_dai_name = "iDisp1 Pin", + .codec_name = "ehdaudio0D2", + .codec_dai_name = "intel-hdmi-hifi1", + .platform_name = "0000:00:1f.3", + .dpcm_playback = 1, + .init = kabylake_5663_hdmi1_init, + .no_pcm = 1, + }, + { + .name = "iDisp2", + .id = 2, + .cpu_dai_name = "iDisp2 Pin", + .codec_name = "ehdaudio0D2", + .codec_dai_name = "intel-hdmi-hifi2", + .platform_name = "0000:00:1f.3", + .init = kabylake_5663_hdmi2_init, + .dpcm_playback = 1, + .no_pcm = 1, + }, +}; + #define NAME_SIZE 32 static int kabylake_card_late_probe(struct snd_soc_card *card) { @@ -624,7 +768,7 @@ static int kabylake_card_late_probe(struct snd_soc_card *card) } /* kabylake audio machine driver for SPT + RT5663 */ -static struct snd_soc_card kabylake_audio_card = { +static struct snd_soc_card kabylake_audio_card_rt5663_m98927 = { .name = "kblrt5663max", .owner = THIS_MODULE, .dai_link = kabylake_dais, @@ -641,6 +785,22 @@ static struct snd_soc_card kabylake_audio_card = { .late_probe = kabylake_card_late_probe, }; +/* kabylake audio machine driver for RT5663 */ +static struct snd_soc_card kabylake_audio_card_rt5663 = { + .name = "kblrt5663", + .owner = THIS_MODULE, + .dai_link = kabylake_5663_dais, + .num_links = ARRAY_SIZE(kabylake_5663_dais), + .controls = kabylake_5663_controls, + .num_controls = ARRAY_SIZE(kabylake_5663_controls), + .dapm_widgets = kabylake_5663_widgets, + .num_dapm_widgets = ARRAY_SIZE(kabylake_5663_widgets), + .dapm_routes = kabylake_5663_map, + .num_dapm_routes = ARRAY_SIZE(kabylake_5663_map), + .fully_routed = true, + .late_probe = kabylake_card_late_probe, +}; + static int kabylake_audio_probe(struct platform_device *pdev) { struct kbl_rt5663_private *ctx; @@ -652,19 +812,30 @@ static int kabylake_audio_probe(struct platform_device *pdev) INIT_LIST_HEAD(&ctx->hdmi_pcm_list); - kabylake_audio_card.dev = &pdev->dev; - snd_soc_card_set_drvdata(&kabylake_audio_card, ctx); + kabylake_audio_card = + (struct snd_soc_card *)pdev->id_entry->driver_data; + + kabylake_audio_card->dev = &pdev->dev; + snd_soc_card_set_drvdata(kabylake_audio_card, ctx); pdata = dev_get_drvdata(&pdev->dev); if (pdata) dmic_constraints = pdata->dmic_num == 2 ? &constraints_dmic_2ch : &constraints_dmic_channels; - return devm_snd_soc_register_card(&pdev->dev, &kabylake_audio_card); + return devm_snd_soc_register_card(&pdev->dev, kabylake_audio_card); } static const struct platform_device_id kbl_board_ids[] = { - { .name = "kbl_rt5663_m98927" }, + { + .name = "kbl_rt5663", + .driver_data = (kernel_ulong_t)&kabylake_audio_card_rt5663, + }, + { + .name = "kbl_rt5663_m98927", + .driver_data = + (kernel_ulong_t)&kabylake_audio_card_rt5663_m98927, + }, { } }; @@ -684,4 +855,5 @@ MODULE_DESCRIPTION("Audio Machine driver-RT5663 & MAX98927 in I2S mode"); MODULE_AUTHOR("Naveen M "); MODULE_AUTHOR("Harsha Priya "); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:kbl_rt5663"); MODULE_ALIAS("platform:kbl_rt5663_m98927"); -- cgit v1.2.3 From 0dfa7a046aa9a3e3dcaee59bfc23598679fc4247 Mon Sep 17 00:00:00 2001 From: Kevin Cheng Date: Thu, 27 Jul 2017 16:38:37 +0800 Subject: ASoC: Intel: Add Kabylake RT5663 machine driver entry Adds Kabylake rt5663 machine driver entry into machine table Signed-off-by: Kevin Cheng Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 334917ee41cf..01a2dd6518a4 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -981,6 +981,11 @@ static struct sst_acpi_mach sst_kbl_devdata[] = { .quirk_data = &kbl_poppy_codecs, .pdata = &skl_dmic_data }, + { + .id = "10EC5663", + .drv_name = "kbl_rt5663", + .fw_filename = "intel/dsp_fw_kbl.bin", + }, {} }; -- cgit v1.2.3 From cc4db0e257d6a5d5ae2e2f042ac8d261caaf08fc Mon Sep 17 00:00:00 2001 From: Harsha Priya N Date: Thu, 27 Jul 2017 17:41:27 -0700 Subject: ASoC: Intel: Enabling 4 slot IV feedback for max98927 on Kabylake platform This patch enables 4 slot IV feedback for max98927 speaker amp codec. Signed-off-by: Harsha Priya Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c index 3fe4a0807095..74bbc008c965 100644 --- a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c @@ -365,11 +365,18 @@ static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, return ret; } } - if (!strcmp(codec_dai->component->name, MAXIM_DEV0_NAME) || - !strcmp(codec_dai->component->name, MAXIM_DEV1_NAME)) { - ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF0, 3, 8, 16); + if (!strcmp(codec_dai->component->name, MAXIM_DEV0_NAME)) { + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x30, 3, 8, 16); if (ret < 0) { - dev_err(rtd->dev, "set TDM slot err:%d\n", ret); + dev_err(rtd->dev, "DEV0 TDM slot err:%d\n", ret); + return ret; + } + } + + if (!strcmp(codec_dai->component->name, MAXIM_DEV1_NAME)) { + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xC0, 3, 8, 16); + if (ret < 0) { + dev_err(rtd->dev, "DEV1 TDM slot err:%d\n", ret); return ret; } } -- cgit v1.2.3 From 60767abcea3dd1d47a4bd38398e1e8c1864975eb Mon Sep 17 00:00:00 2001 From: "guneshwor.o.singh@intel.com" Date: Fri, 28 Jul 2017 16:12:13 +0530 Subject: ASoC: Intel: Skylake: Reset the controller in probe Controller can be in reset state by default. Capability structure traversal requires the controller to be out of reset else it results in broken capability parsing. Hence make sure that controller is out of reset before parsing capabilities by doing a full reset. Signed-off-by: Guneshwor Singh Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 01a2dd6518a4..b9e1310673f0 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -702,6 +702,8 @@ static int skl_first_init(struct hdac_ext_bus *ebus) return -ENXIO; } + skl_init_chip(bus, true); + snd_hdac_bus_parse_capabilities(bus); if (skl_acquire_irq(ebus, 0) < 0) -- cgit v1.2.3 From 3fbbcf4dadb6c01d6411bac715a7448f96c3724c Mon Sep 17 00:00:00 2001 From: Dronamraju Santosh P K Date: Fri, 28 Jul 2017 16:12:14 +0530 Subject: ASoC: Intel: bxtn: Remove code loader reference in cleanup Since Broxton does not use code loader DMA, remove code loader cleanup in its dsp cleanup routine. Remove the iounmap too as it is done in skl_free_dsp(). Signed-off-by: Dronamraju Santosh P K Signed-off-by: Guneshwor Singh Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/bxt-sst.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c index cf11b84888b9..08a2c5eb59fa 100644 --- a/sound/soc/intel/skylake/bxt-sst.c +++ b/sound/soc/intel/skylake/bxt-sst.c @@ -629,11 +629,6 @@ void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) release_firmware(ctx->dsp->fw); skl_freeup_uuid_list(ctx); skl_ipc_free(&ctx->ipc); - ctx->dsp->cl_dev.ops.cl_cleanup_controller(ctx->dsp); - - if (ctx->dsp->addr.lpe) - iounmap(ctx->dsp->addr.lpe); - ctx->dsp->ops->free(ctx->dsp); } EXPORT_SYMBOL_GPL(bxt_sst_dsp_cleanup); -- cgit v1.2.3 From 693c0fb26a312d7cc866b1e9195187789b69e7e6 Mon Sep 17 00:00:00 2001 From: "guneshwor.o.singh@intel.com" Date: Fri, 28 Jul 2017 16:12:15 +0530 Subject: ASoC: Intel: Skylake: Remove return check for skl_codec_create() Since skl_codec_create() always returns 0, make it return void and remove return check. Signed-off-by: Guneshwor Singh Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index b9e1310673f0..ab651517e8b8 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -528,7 +528,7 @@ static int probe_codec(struct hdac_ext_bus *ebus, int addr) } /* Codec initialization */ -static int skl_codec_create(struct hdac_ext_bus *ebus) +static void skl_codec_create(struct hdac_ext_bus *ebus) { struct hdac_bus *bus = ebus_to_hbus(ebus); int c, max_slots; @@ -559,8 +559,6 @@ static int skl_codec_create(struct hdac_ext_bus *ebus) } } } - - return 0; } static const struct hdac_bus_ops bus_core_ops = { @@ -612,9 +610,7 @@ static void skl_probe_work(struct work_struct *work) dev_info(bus->dev, "no hda codecs found!\n"); /* create codec instances */ - err = skl_codec_create(ebus); - if (err < 0) - goto out_err; + skl_codec_create(ebus); if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { err = snd_hdac_display_power(bus, false); -- cgit v1.2.3 From 10a5439f0e4db0b1c4c2a2f6c916d6501cfeae50 Mon Sep 17 00:00:00 2001 From: "guneshwor.o.singh@intel.com" Date: Fri, 28 Jul 2017 16:12:16 +0530 Subject: ASoC: Intel: Skylake: Fix potential null pointer dereference Check if the next sink is not null to avoid potential null pointer dereference in skl_tplg_bind_sinks(). Signed-off-by: Guneshwor Singh Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-topology.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 68c3f121efc3..8c3ce08f366d 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -925,7 +925,7 @@ static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w, } } - if (!sink) + if (!sink && next_sink) return skl_tplg_bind_sinks(next_sink, skl, src_w, src_mconfig); return 0; -- cgit v1.2.3 From da3cbb40f35b4b5ab66df9a23a717a4a5df1f992 Mon Sep 17 00:00:00 2001 From: Naveen Manohar Date: Wed, 2 Aug 2017 11:43:33 +0530 Subject: ASoC: Intel: kbl: Add new FEs for Multi-Playback & Echo-Reference Adding new frontends to support: 1. Parallel playback on 2 ports simultaneously 2. Echo reference capture capability Signed-off-by: Naveen M Signed-off-by: Sathya Prakash M R Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-pcm.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index b1f2dba642c4..debdaac2c3a2 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -674,6 +674,32 @@ static struct snd_soc_dai_driver skl_platform_dai[] = { .sig_bits = 32, }, }, +{ + .name = "System Pin2", + .ops = &skl_pcm_dai_ops, + .playback = { + .stream_name = "Headset Playback", + .channels_min = HDA_MONO, + .channels_max = HDA_STEREO, + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_8000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, + }, +}, +{ + .name = "Echoref Pin", + .ops = &skl_pcm_dai_ops, + .capture = { + .stream_name = "Echoreference Capture", + .channels_min = HDA_STEREO, + .channels_max = HDA_STEREO, + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_8000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, + }, +}, { .name = "Reference Pin", .ops = &skl_pcm_dai_ops, -- cgit v1.2.3 From b32ee384ac18d3e4db0ef45d23c3ff1c67113529 Mon Sep 17 00:00:00 2001 From: Naveen Manohar Date: Wed, 2 Aug 2017 11:43:34 +0530 Subject: ASoC: Intel: kbl: Add DAI links for Multi-Playback & Echo-reference Add new FE DAI links to support: 1. Parallel playback on 2 ports simultaneously 2. Echo reference capture capability Signed-off-by: Naveen M Signed-off-by: Sathya Prakash M R Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/boards/kbl_rt5663_max98927.c | 24 ++++++++++++++++++++++ .../soc/intel/boards/kbl_rt5663_rt5514_max98927.c | 24 ++++++++++++++++++++++ 2 files changed, 48 insertions(+) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/boards/kbl_rt5663_max98927.c b/sound/soc/intel/boards/kbl_rt5663_max98927.c index 090331bd6900..4c70d5a3028c 100644 --- a/sound/soc/intel/boards/kbl_rt5663_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_max98927.c @@ -52,6 +52,8 @@ struct kbl_rt5663_private { enum { KBL_DPCM_AUDIO_PB = 0, KBL_DPCM_AUDIO_CP, + KBL_DPCM_AUDIO_HS_PB, + KBL_DPCM_AUDIO_ECHO_REF_CP, KBL_DPCM_AUDIO_REF_CP, KBL_DPCM_AUDIO_DMIC_CP, KBL_DPCM_AUDIO_HDMI1_PB, @@ -485,6 +487,28 @@ static struct snd_soc_dai_link kabylake_dais[] = { .dpcm_capture = 1, .ops = &kabylake_rt5663_fe_ops, }, + [KBL_DPCM_AUDIO_HS_PB] = { + .name = "Kbl Audio Headset Playback", + .stream_name = "Headset Audio", + .cpu_dai_name = "System Pin2", + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .platform_name = "0000:00:1f.3", + .dpcm_playback = 1, + .nonatomic = 1, + .dynamic = 1, + }, + [KBL_DPCM_AUDIO_ECHO_REF_CP] = { + .name = "Kbl Audio Echo Reference cap", + .stream_name = "Echoreference Capture", + .cpu_dai_name = "Echoref Pin", + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .platform_name = "0000:00:1f.3", + .init = NULL, + .capture_only = 1, + .nonatomic = 1, + }, [KBL_DPCM_AUDIO_REF_CP] = { .name = "Kbl Audio Reference cap", .stream_name = "Wake on Voice", diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c index 74bbc008c965..64364de165be 100644 --- a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c @@ -62,6 +62,8 @@ struct kbl_codec_private { enum { KBL_DPCM_AUDIO_PB = 0, KBL_DPCM_AUDIO_CP, + KBL_DPCM_AUDIO_HS_PB, + KBL_DPCM_AUDIO_ECHO_REF_CP, KBL_DPCM_AUDIO_DMIC_CP, KBL_DPCM_AUDIO_HDMI1_PB, KBL_DPCM_AUDIO_HDMI2_PB, @@ -456,6 +458,28 @@ static struct snd_soc_dai_link kabylake_dais[] = { .dpcm_capture = 1, .ops = &kabylake_rt5663_fe_ops, }, + [KBL_DPCM_AUDIO_HS_PB] = { + .name = "Kbl Audio Headset Playback", + .stream_name = "Headset Audio", + .cpu_dai_name = "System Pin2", + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .platform_name = "0000:00:1f.3", + .dpcm_playback = 1, + .nonatomic = 1, + .dynamic = 1, + }, + [KBL_DPCM_AUDIO_ECHO_REF_CP] = { + .name = "Kbl Audio Echo Reference cap", + .stream_name = "Echoreference Capture", + .cpu_dai_name = "Echoref Pin", + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .platform_name = "0000:00:1f.3", + .init = NULL, + .capture_only = 1, + .nonatomic = 1, + }, [KBL_DPCM_AUDIO_DMIC_CP] = { .name = "Kbl Audio DMIC cap", .stream_name = "dmiccap", -- cgit v1.2.3 From 0b06122fc8d0949a0aa7b817d98e031104802611 Mon Sep 17 00:00:00 2001 From: Naveen Manohar Date: Wed, 2 Aug 2017 11:43:35 +0530 Subject: ASoC: Intel: kbl: Add map for new DAIs for Multi-Playback & Echo Ref Modified DAPM Machine map for machine to suit the toplogy change required to enable features: Multi-Endpoint Playback Echo Reference Capture Signed-off-by: Naveen M Signed-off-by: Sathya Prakash M R Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/boards/kbl_rt5663_max98927.c | 6 +++--- sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/boards/kbl_rt5663_max98927.c b/sound/soc/intel/boards/kbl_rt5663_max98927.c index 4c70d5a3028c..12b34b9a0104 100644 --- a/sound/soc/intel/boards/kbl_rt5663_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_max98927.c @@ -99,12 +99,12 @@ static const struct snd_soc_dapm_route kabylake_map[] = { /* CODEC BE connections */ { "Left HiFi Playback", NULL, "ssp0 Tx" }, { "Right HiFi Playback", NULL, "ssp0 Tx" }, - { "ssp0 Tx", NULL, "codec0_out" }, + { "ssp0 Tx", NULL, "spk_out" }, { "AIF Playback", NULL, "ssp1 Tx" }, - { "ssp1 Tx", NULL, "codec1_out" }, + { "ssp1 Tx", NULL, "hs_out" }, - { "codec0_in", NULL, "ssp1 Rx" }, + { "hs_in", NULL, "ssp1 Rx" }, { "ssp1 Rx", NULL, "AIF Capture" }, /* DMIC */ diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c index 64364de165be..5ec942885b69 100644 --- a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c @@ -107,12 +107,12 @@ static const struct snd_soc_dapm_route kabylake_map[] = { /* CODEC BE connections */ { "Left HiFi Playback", NULL, "ssp0 Tx" }, { "Right HiFi Playback", NULL, "ssp0 Tx" }, - { "ssp0 Tx", NULL, "codec0_out" }, + { "ssp0 Tx", NULL, "spk_out" }, { "AIF Playback", NULL, "ssp1 Tx" }, - { "ssp1 Tx", NULL, "codec1_out" }, + { "ssp1 Tx", NULL, "hs_out" }, - { "codec0_in", NULL, "ssp1 Rx" }, + { "hs_in", NULL, "ssp1 Rx" }, { "ssp1 Rx", NULL, "AIF Capture" }, { "codec1_in", NULL, "ssp0 Rx" }, -- cgit v1.2.3 From 363d45385f403fdf60fe9f563ba87093289d7b35 Mon Sep 17 00:00:00 2001 From: Dharageswari R Date: Wed, 2 Aug 2017 21:51:12 +0530 Subject: ASoC: Intel: Skylake: Add num of cores in dsp ops Number of dsp cores may differ for different platforms hence adding it in dsp ops. Signed-off-by: Dharageswari R Signed-off-by: Guneshwor Singh Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/bxt-sst.c | 1 - sound/soc/intel/skylake/skl-messages.c | 6 ++++++ sound/soc/intel/skylake/skl-sst.c | 2 -- sound/soc/intel/skylake/skl.h | 1 + 4 files changed, 7 insertions(+), 3 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c index 08a2c5eb59fa..c404a42b670a 100644 --- a/sound/soc/intel/skylake/bxt-sst.c +++ b/sound/soc/intel/skylake/bxt-sst.c @@ -584,7 +584,6 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, /* set the D0i3 check */ skl->ipc.ops.check_dsp_lp_on = skl_ipc_check_D0i0; - skl->cores.count = 2; skl->boot_complete = false; init_waitqueue_head(&skl->boot_wait); INIT_DELAYED_WORK(&skl->d0i3.work, bxt_set_dsp_D0i3); diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index c5b4e0a9946c..7892e445e87b 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -201,6 +201,7 @@ static struct skl_dsp_loader_ops bxt_get_loader_ops(void) static const struct skl_dsp_ops dsp_ops[] = { { .id = 0x9d70, + .num_cores = 2, .loader_ops = skl_get_loader_ops, .init = skl_sst_dsp_init, .init_fw = skl_sst_init_fw, @@ -208,6 +209,7 @@ static const struct skl_dsp_ops dsp_ops[] = { }, { .id = 0x9d71, + .num_cores = 2, .loader_ops = skl_get_loader_ops, .init = kbl_sst_dsp_init, .init_fw = skl_sst_init_fw, @@ -215,6 +217,7 @@ static const struct skl_dsp_ops dsp_ops[] = { }, { .id = 0x5a98, + .num_cores = 2, .loader_ops = bxt_get_loader_ops, .init = bxt_sst_dsp_init, .init_fw = bxt_sst_init_fw, @@ -222,6 +225,7 @@ static const struct skl_dsp_ops dsp_ops[] = { }, { .id = 0x3198, + .num_cores = 2, .loader_ops = bxt_get_loader_ops, .init = bxt_sst_dsp_init, .init_fw = bxt_sst_init_fw, @@ -275,6 +279,8 @@ int skl_init_dsp(struct skl *skl) return ret; skl->skl_sst->dsp_ops = ops; + skl->skl_sst->cores.count = ops->num_cores; + dev_dbg(bus->dev, "dsp registration status=%d\n", ret); return ret; diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index aba9ea11ac74..fd99e74cda03 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c @@ -563,8 +563,6 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, sst->fw_ops = skl_fw_ops; - skl->cores.count = 2; - return 0; } EXPORT_SYMBOL_GPL(skl_sst_dsp_init); diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index a6b134b4c037..20017ee4685c 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h @@ -90,6 +90,7 @@ struct skl_machine_pdata { struct skl_dsp_ops { int id; + unsigned int num_cores; struct skl_dsp_loader_ops (*loader_ops)(void); int (*init)(struct device *dev, void __iomem *mmio_base, int irq, const char *fw_name, -- cgit v1.2.3 From f0a550a88373b0b076785e059cca15f32ae9ffeb Mon Sep 17 00:00:00 2001 From: Guneshwor Singh Date: Wed, 2 Aug 2017 21:51:13 +0530 Subject: ASoC: Intel: Skylake: Use num_core to allocate instead of macro For different platforms, number of dsp cores can vary. So instead of creating array of size SKL_DSP_CORES_MAX, use num_core in dsp_ops() of the respective platform to allocate core usage counts and states. Signed-off-by: Guneshwor Singh Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-messages.c | 18 +++++++++++++++++- sound/soc/intel/skylake/skl-sst-dsp.c | 2 +- sound/soc/intel/skylake/skl-sst-ipc.h | 6 ++---- 3 files changed, 20 insertions(+), 6 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index 7892e445e87b..c6b60ee5b196 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -253,6 +253,7 @@ int skl_init_dsp(struct skl *skl) struct skl_dsp_loader_ops loader_ops; int irq = bus->irq; const struct skl_dsp_ops *ops; + struct skl_dsp_cores *cores; int ret; /* enable ppcap interrupt */ @@ -279,7 +280,19 @@ int skl_init_dsp(struct skl *skl) return ret; skl->skl_sst->dsp_ops = ops; - skl->skl_sst->cores.count = ops->num_cores; + cores = &skl->skl_sst->cores; + cores->count = ops->num_cores; + + cores->state = kcalloc(cores->count, sizeof(*cores->state), GFP_KERNEL); + if (!cores->state) + return -ENOMEM; + + cores->usage_count = kcalloc(cores->count, sizeof(*cores->usage_count), + GFP_KERNEL); + if (!cores->usage_count) { + kfree(cores->state); + return -ENOMEM; + } dev_dbg(bus->dev, "dsp registration status=%d\n", ret); @@ -297,6 +310,9 @@ int skl_free_dsp(struct skl *skl) ctx->dsp_ops->cleanup(bus->dev, ctx); + kfree(ctx->cores.state); + kfree(ctx->cores.usage_count); + if (ctx->dsp->addr.lpe) iounmap(ctx->dsp->addr.lpe); diff --git a/sound/soc/intel/skylake/skl-sst-dsp.c b/sound/soc/intel/skylake/skl-sst-dsp.c index 08332723c700..c2ba5ff1632c 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.c +++ b/sound/soc/intel/skylake/skl-sst-dsp.c @@ -47,7 +47,7 @@ void skl_dsp_init_core_state(struct sst_dsp *ctx) skl->cores.state[SKL_DSP_CORE0_ID] = SKL_DSP_RUNNING; skl->cores.usage_count[SKL_DSP_CORE0_ID] = 1; - for (i = SKL_DSP_CORE0_ID + 1; i < SKL_DSP_CORES_MAX; i++) { + for (i = SKL_DSP_CORE0_ID + 1; i < skl->cores.count; i++) { skl->cores.state[i] = SKL_DSP_RESET; skl->cores.usage_count[i] = 0; } diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h index e057da2713c6..e485e8f5ea2c 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.h +++ b/sound/soc/intel/skylake/skl-sst-ipc.h @@ -44,12 +44,10 @@ struct skl_ipc_header { u32 extension; }; -#define SKL_DSP_CORES_MAX 2 - struct skl_dsp_cores { unsigned int count; - enum skl_dsp_states state[SKL_DSP_CORES_MAX]; - int usage_count[SKL_DSP_CORES_MAX]; + enum skl_dsp_states *state; + int *usage_count; }; /** -- cgit v1.2.3 From 4147a6e59a5c0b9cb0eeaa3e1f39fd9da491f35a Mon Sep 17 00:00:00 2001 From: Pardha Saradhi K Date: Wed, 2 Aug 2017 21:51:14 +0530 Subject: ASoC: Intel: Skylake: Add dsp cores management This patch adds support to manage additional cores on a demand basis. For instance, if module is set to run on certain core, the particular core is powered up in module init. The same is again powered down in module unload. Signed-off-by: Pardha Saradhi K Signed-off-by: Guneshwor Singh Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-topology.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 8c3ce08f366d..350d2387f737 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -596,24 +596,35 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) if (mconfig->id.pvt_id < 0) return ret; skl_tplg_set_module_init_data(w); + + ret = skl_dsp_get_core(ctx->dsp, mconfig->core_id); + if (ret < 0) { + dev_err(ctx->dev, "Failed to wake up core %d ret=%d\n", + mconfig->core_id, ret); + return ret; + } + ret = skl_init_module(ctx, mconfig); if (ret < 0) { skl_put_pvt_id(ctx, uuid_mod, &mconfig->id.pvt_id); - return ret; + goto err; } skl_tplg_alloc_pipe_mcps(skl, mconfig); ret = skl_tplg_set_module_params(w, ctx); if (ret < 0) - return ret; + goto err; } return 0; +err: + skl_dsp_put_core(ctx->dsp, mconfig->core_id); + return ret; } static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx, struct skl_pipe *pipe) { - int ret; + int ret = 0; struct skl_pipe_module *w_module = NULL; struct skl_module_cfg *mconfig = NULL; @@ -630,10 +641,17 @@ static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx, return -EIO; } skl_put_pvt_id(ctx, uuid_mod, &mconfig->id.pvt_id); + + ret = skl_dsp_put_core(ctx->dsp, mconfig->core_id); + if (ret < 0) { + /* don't return; continue with other modules */ + dev_err(ctx->dev, "Failed to sleep core %d ret=%d\n", + mconfig->core_id, ret); + } } /* no modules to unload in this path, so return */ - return 0; + return ret; } /* -- cgit v1.2.3 From a838dcc286754f6ea6bcbee8eb76a5d626642fa7 Mon Sep 17 00:00:00 2001 From: Guneshwor Singh Date: Wed, 2 Aug 2017 21:51:15 +0530 Subject: ASoC: Intel: cnl: Add cnl dsp functions and registers This adds Cannonlake specific registers and support for CNL dsp related library functions for programming the registers to power up/down dsp cores, set/unset reset states for each core, enable/disable ipc interrupts and few wrappers to be called from elsewhere. Signed-off-by: Guneshwor Singh Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/cnl-sst-dsp.c | 274 ++++++++++++++++++++++++++++++++++ sound/soc/intel/skylake/cnl-sst-dsp.h | 106 +++++++++++++ 2 files changed, 380 insertions(+) create mode 100644 sound/soc/intel/skylake/cnl-sst-dsp.c create mode 100644 sound/soc/intel/skylake/cnl-sst-dsp.h (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/cnl-sst-dsp.c b/sound/soc/intel/skylake/cnl-sst-dsp.c new file mode 100644 index 000000000000..2f8326707c21 --- /dev/null +++ b/sound/soc/intel/skylake/cnl-sst-dsp.c @@ -0,0 +1,274 @@ +/* + * cnl-sst-dsp.c - CNL SST library generic function + * + * Copyright (C) 2016-17, Intel Corporation. + * Author: Guneshwor Singh + * + * Modified from: + * SKL SST library generic function + * Copyright (C) 2014-15, Intel Corporation. + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ +#include +#include "../common/sst-dsp.h" +#include "../common/sst-ipc.h" +#include "../common/sst-dsp-priv.h" +#include "cnl-sst-dsp.h" + +/* various timeout values */ +#define CNL_DSP_PU_TO 50 +#define CNL_DSP_PD_TO 50 +#define CNL_DSP_RESET_TO 50 + +static int +cnl_dsp_core_set_reset_state(struct sst_dsp *ctx, unsigned int core_mask) +{ + /* update bits */ + sst_dsp_shim_update_bits_unlocked(ctx, + CNL_ADSP_REG_ADSPCS, CNL_ADSPCS_CRST(core_mask), + CNL_ADSPCS_CRST(core_mask)); + + /* poll with timeout to check if operation successful */ + return sst_dsp_register_poll(ctx, + CNL_ADSP_REG_ADSPCS, + CNL_ADSPCS_CRST(core_mask), + CNL_ADSPCS_CRST(core_mask), + CNL_DSP_RESET_TO, + "Set reset"); +} + +static int +cnl_dsp_core_unset_reset_state(struct sst_dsp *ctx, unsigned int core_mask) +{ + /* update bits */ + sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, + CNL_ADSPCS_CRST(core_mask), 0); + + /* poll with timeout to check if operation successful */ + return sst_dsp_register_poll(ctx, + CNL_ADSP_REG_ADSPCS, + CNL_ADSPCS_CRST(core_mask), + 0, + CNL_DSP_RESET_TO, + "Unset reset"); +} + +static bool is_cnl_dsp_core_enable(struct sst_dsp *ctx, unsigned int core_mask) +{ + int val; + bool is_enable; + + val = sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPCS); + + is_enable = (val & CNL_ADSPCS_CPA(core_mask)) && + (val & CNL_ADSPCS_SPA(core_mask)) && + !(val & CNL_ADSPCS_CRST(core_mask)) && + !(val & CNL_ADSPCS_CSTALL(core_mask)); + + dev_dbg(ctx->dev, "DSP core(s) enabled? %d: core_mask %#x\n", + is_enable, core_mask); + + return is_enable; +} + +static int cnl_dsp_reset_core(struct sst_dsp *ctx, unsigned int core_mask) +{ + /* stall core */ + sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, + CNL_ADSPCS_CSTALL(core_mask), + CNL_ADSPCS_CSTALL(core_mask)); + + /* set reset state */ + return cnl_dsp_core_set_reset_state(ctx, core_mask); +} + +static int cnl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask) +{ + int ret; + + /* unset reset state */ + ret = cnl_dsp_core_unset_reset_state(ctx, core_mask); + if (ret < 0) + return ret; + + /* run core */ + sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, + CNL_ADSPCS_CSTALL(core_mask), 0); + + if (!is_cnl_dsp_core_enable(ctx, core_mask)) { + cnl_dsp_reset_core(ctx, core_mask); + dev_err(ctx->dev, "DSP core mask %#x enable failed\n", + core_mask); + ret = -EIO; + } + + return ret; +} + +static int cnl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask) +{ + /* update bits */ + sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, + CNL_ADSPCS_SPA(core_mask), + CNL_ADSPCS_SPA(core_mask)); + + /* poll with timeout to check if operation successful */ + return sst_dsp_register_poll(ctx, CNL_ADSP_REG_ADSPCS, + CNL_ADSPCS_CPA(core_mask), + CNL_ADSPCS_CPA(core_mask), + CNL_DSP_PU_TO, + "Power up"); +} + +static int cnl_dsp_core_power_down(struct sst_dsp *ctx, unsigned int core_mask) +{ + /* update bits */ + sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, + CNL_ADSPCS_SPA(core_mask), 0); + + /* poll with timeout to check if operation successful */ + return sst_dsp_register_poll(ctx, + CNL_ADSP_REG_ADSPCS, + CNL_ADSPCS_CPA(core_mask), + 0, + CNL_DSP_PD_TO, + "Power down"); +} + +int cnl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask) +{ + int ret; + + /* power up */ + ret = cnl_dsp_core_power_up(ctx, core_mask); + if (ret < 0) { + dev_dbg(ctx->dev, "DSP core mask %#x power up failed", + core_mask); + return ret; + } + + return cnl_dsp_start_core(ctx, core_mask); +} + +int cnl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask) +{ + int ret; + + ret = cnl_dsp_reset_core(ctx, core_mask); + if (ret < 0) { + dev_err(ctx->dev, "DSP core mask %#x reset failed\n", + core_mask); + return ret; + } + + /* power down core*/ + ret = cnl_dsp_core_power_down(ctx, core_mask); + if (ret < 0) { + dev_err(ctx->dev, "DSP core mask %#x power down failed\n", + core_mask); + return ret; + } + + if (is_cnl_dsp_core_enable(ctx, core_mask)) { + dev_err(ctx->dev, "DSP core mask %#x disable failed\n", + core_mask); + ret = -EIO; + } + + return ret; +} + +irqreturn_t cnl_dsp_sst_interrupt(int irq, void *dev_id) +{ + struct sst_dsp *ctx = dev_id; + u32 val; + irqreturn_t ret = IRQ_NONE; + + spin_lock(&ctx->spinlock); + + val = sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPIS); + ctx->intr_status = val; + + if (val == 0xffffffff) { + spin_unlock(&ctx->spinlock); + return IRQ_NONE; + } + + if (val & CNL_ADSPIS_IPC) { + cnl_ipc_int_disable(ctx); + ret = IRQ_WAKE_THREAD; + } + + spin_unlock(&ctx->spinlock); + + return ret; +} + +void cnl_dsp_free(struct sst_dsp *dsp) +{ + cnl_ipc_int_disable(dsp); + + free_irq(dsp->irq, dsp); + cnl_ipc_op_int_disable(dsp); + cnl_dsp_disable_core(dsp, SKL_DSP_CORE0_MASK); +} +EXPORT_SYMBOL_GPL(cnl_dsp_free); + +void cnl_ipc_int_enable(struct sst_dsp *ctx) +{ + sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_ADSPIC, + CNL_ADSPIC_IPC, CNL_ADSPIC_IPC); +} + +void cnl_ipc_int_disable(struct sst_dsp *ctx) +{ + sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPIC, + CNL_ADSPIC_IPC, 0); +} + +void cnl_ipc_op_int_enable(struct sst_dsp *ctx) +{ + /* enable IPC DONE interrupt */ + sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL, + CNL_ADSP_REG_HIPCCTL_DONE, + CNL_ADSP_REG_HIPCCTL_DONE); + + /* enable IPC BUSY interrupt */ + sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL, + CNL_ADSP_REG_HIPCCTL_BUSY, + CNL_ADSP_REG_HIPCCTL_BUSY); +} + +void cnl_ipc_op_int_disable(struct sst_dsp *ctx) +{ + /* disable IPC DONE interrupt */ + sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL, + CNL_ADSP_REG_HIPCCTL_DONE, 0); + + /* disable IPC BUSY interrupt */ + sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL, + CNL_ADSP_REG_HIPCCTL_BUSY, 0); +} + +bool cnl_ipc_int_status(struct sst_dsp *ctx) +{ + return sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPIS) & + CNL_ADSPIS_IPC; +} + +void cnl_ipc_free(struct sst_generic_ipc *ipc) +{ + cnl_ipc_op_int_disable(ipc->dsp); + sst_ipc_fini(ipc); +} diff --git a/sound/soc/intel/skylake/cnl-sst-dsp.h b/sound/soc/intel/skylake/cnl-sst-dsp.h new file mode 100644 index 000000000000..2fe41b137a2c --- /dev/null +++ b/sound/soc/intel/skylake/cnl-sst-dsp.h @@ -0,0 +1,106 @@ +/* + * Cannonlake SST DSP Support + * + * Copyright (C) 2016-17, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#ifndef __CNL_SST_DSP_H__ +#define __CNL_SST_DSP_H__ + +struct sst_dsp; +struct skl_sst; +struct sst_dsp_device; +struct sst_generic_ipc; + +/* Intel HD Audio General DSP Registers */ +#define CNL_ADSP_GEN_BASE 0x0 +#define CNL_ADSP_REG_ADSPCS (CNL_ADSP_GEN_BASE + 0x04) +#define CNL_ADSP_REG_ADSPIC (CNL_ADSP_GEN_BASE + 0x08) +#define CNL_ADSP_REG_ADSPIS (CNL_ADSP_GEN_BASE + 0x0c) + +/* Intel HD Audio Inter-Processor Communication Registers */ +#define CNL_ADSP_IPC_BASE 0xc0 +#define CNL_ADSP_REG_HIPCTDR (CNL_ADSP_IPC_BASE + 0x00) +#define CNL_ADSP_REG_HIPCTDA (CNL_ADSP_IPC_BASE + 0x04) +#define CNL_ADSP_REG_HIPCTDD (CNL_ADSP_IPC_BASE + 0x08) +#define CNL_ADSP_REG_HIPCIDR (CNL_ADSP_IPC_BASE + 0x10) +#define CNL_ADSP_REG_HIPCIDA (CNL_ADSP_IPC_BASE + 0x14) +#define CNL_ADSP_REG_HIPCIDD (CNL_ADSP_IPC_BASE + 0x18) +#define CNL_ADSP_REG_HIPCCTL (CNL_ADSP_IPC_BASE + 0x28) + +/* HIPCTDR */ +#define CNL_ADSP_REG_HIPCTDR_BUSY BIT(31) + +/* HIPCTDA */ +#define CNL_ADSP_REG_HIPCTDA_DONE BIT(31) + +/* HIPCIDR */ +#define CNL_ADSP_REG_HIPCIDR_BUSY BIT(31) + +/* HIPCIDA */ +#define CNL_ADSP_REG_HIPCIDA_DONE BIT(31) + +/* CNL HIPCCTL */ +#define CNL_ADSP_REG_HIPCCTL_DONE BIT(1) +#define CNL_ADSP_REG_HIPCCTL_BUSY BIT(0) + +/* CNL HIPCT */ +#define CNL_ADSP_REG_HIPCT_BUSY BIT(31) + +/* Intel HD Audio SRAM Window 1 */ +#define CNL_ADSP_SRAM1_BASE 0xa0000 + +#define CNL_ADSP_MMIO_LEN 0x10000 + +#define CNL_ADSP_W0_STAT_SZ 0x1000 + +#define CNL_ADSP_W0_UP_SZ 0x1000 + +#define CNL_ADSP_W1_SZ 0x1000 + +#define CNL_FW_STS_MASK 0xf + +#define CNL_ADSPIC_IPC 0x1 +#define CNL_ADSPIS_IPC 0x1 + +#define CNL_DSP_CORES 4 +#define CNL_DSP_CORES_MASK ((1 << CNL_DSP_CORES) - 1) + +/* core reset - asserted high */ +#define CNL_ADSPCS_CRST_SHIFT 0 +#define CNL_ADSPCS_CRST(x) (x << CNL_ADSPCS_CRST_SHIFT) + +/* core run/stall - when set to 1 core is stalled */ +#define CNL_ADSPCS_CSTALL_SHIFT 8 +#define CNL_ADSPCS_CSTALL(x) (x << CNL_ADSPCS_CSTALL_SHIFT) + +/* set power active - when set to 1 turn core on */ +#define CNL_ADSPCS_SPA_SHIFT 16 +#define CNL_ADSPCS_SPA(x) (x << CNL_ADSPCS_SPA_SHIFT) + +/* current power active - power status of cores, set by hardware */ +#define CNL_ADSPCS_CPA_SHIFT 24 +#define CNL_ADSPCS_CPA(x) (x << CNL_ADSPCS_CPA_SHIFT) + +int cnl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core); +int cnl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core); +irqreturn_t cnl_dsp_sst_interrupt(int irq, void *dev_id); +void cnl_dsp_free(struct sst_dsp *dsp); + +void cnl_ipc_int_enable(struct sst_dsp *ctx); +void cnl_ipc_int_disable(struct sst_dsp *ctx); +void cnl_ipc_op_int_enable(struct sst_dsp *ctx); +void cnl_ipc_op_int_disable(struct sst_dsp *ctx); +bool cnl_ipc_int_status(struct sst_dsp *ctx); +void cnl_ipc_free(struct sst_generic_ipc *ipc); + +#endif /*__CNL_SST_DSP_H__*/ -- cgit v1.2.3 From 2eed1b024a11b497766604ee8f95e22711859af2 Mon Sep 17 00:00:00 2001 From: Guneshwor Singh Date: Wed, 2 Aug 2017 21:51:16 +0530 Subject: ASoC: Intel: Skylake: Move platform specific init to platform dsp_init() Move ipc_init() from helper function to respective platform's dsp_init() as ipc_init() per platform can be different. Signed-off-by: Guneshwor Singh Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/bxt-sst.c | 4 ++++ sound/soc/intel/skylake/skl-sst-utils.c | 6 +----- sound/soc/intel/skylake/skl-sst.c | 4 ++++ 3 files changed, 9 insertions(+), 5 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c index c404a42b670a..71042aceb25f 100644 --- a/sound/soc/intel/skylake/bxt-sst.c +++ b/sound/soc/intel/skylake/bxt-sst.c @@ -581,6 +581,10 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, sst_dsp_mailbox_init(sst, (BXT_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), SKL_ADSP_W0_UP_SZ, BXT_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ); + ret = skl_ipc_init(dev, skl); + if (ret) + return ret; + /* set the D0i3 check */ skl->ipc.ops.check_dsp_lp_on = skl_ipc_check_D0i0; diff --git a/sound/soc/intel/skylake/skl-sst-utils.c b/sound/soc/intel/skylake/skl-sst-utils.c index 81ee251881b4..369ef7ce981c 100644 --- a/sound/soc/intel/skylake/skl-sst-utils.c +++ b/sound/soc/intel/skylake/skl-sst-utils.c @@ -368,7 +368,6 @@ int skl_sst_ctx_init(struct device *dev, int irq, const char *fw_name, { struct skl_sst *skl; struct sst_dsp *sst; - int ret; skl = devm_kzalloc(dev, sizeof(*skl), GFP_KERNEL); if (skl == NULL) @@ -388,15 +387,12 @@ int skl_sst_ctx_init(struct device *dev, int irq, const char *fw_name, sst->dsp_ops = dsp_ops; init_waitqueue_head(&skl->mod_load_wait); INIT_LIST_HEAD(&sst->module_list); - ret = skl_ipc_init(dev, skl); - if (ret) - return ret; skl->is_first_boot = true; if (dsp) *dsp = skl; - return ret; + return 0; } int skl_prepare_lib_load(struct skl_sst *skl, struct skl_lib_info *linfo, diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index fd99e74cda03..6cc586d3f03b 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c @@ -561,6 +561,10 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, sst_dsp_mailbox_init(sst, (SKL_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), SKL_ADSP_W0_UP_SZ, SKL_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ); + ret = skl_ipc_init(dev, skl); + if (ret) + return ret; + sst->fw_ops = skl_fw_ops; return 0; -- cgit v1.2.3 From 4bdb04f0e1b7600b87a92b4f98ba5490ceffdf4f Mon Sep 17 00:00:00 2001 From: Guneshwor Singh Date: Wed, 2 Aug 2017 21:51:17 +0530 Subject: ASoC: Intel: cnl: Unstatify common ipc functions Common ipc functions can be reused for cnl, so make them non-static. Signed-off-by: Guneshwor Singh Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-sst-ipc.c | 6 +++--- sound/soc/intel/skylake/skl-sst-ipc.h | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/skl-sst-ipc.c b/sound/soc/intel/skylake/skl-sst-ipc.c index 498b15345b1a..5234fafb758a 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.c +++ b/sound/soc/intel/skylake/skl-sst-ipc.c @@ -283,7 +283,7 @@ enum skl_ipc_module_msg { IPC_MOD_SET_D0IX = 8 }; -static void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data, +void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data, size_t tx_size) { if (tx_size) @@ -347,7 +347,7 @@ out: } -static int skl_ipc_process_notification(struct sst_generic_ipc *ipc, +int skl_ipc_process_notification(struct sst_generic_ipc *ipc, struct skl_ipc_header header) { struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc); @@ -406,7 +406,7 @@ static int skl_ipc_set_reply_error_code(u32 reply) } } -static void skl_ipc_process_reply(struct sst_generic_ipc *ipc, +void skl_ipc_process_reply(struct sst_generic_ipc *ipc, struct skl_ipc_header header) { struct ipc_message *msg; diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h index e485e8f5ea2c..55f2d2ce09df 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.h +++ b/sound/soc/intel/skylake/skl-sst-ipc.h @@ -212,4 +212,10 @@ void skl_ipc_free(struct sst_generic_ipc *ipc); int skl_ipc_init(struct device *dev, struct skl_sst *skl); void skl_clear_module_cnt(struct sst_dsp *ctx); +void skl_ipc_process_reply(struct sst_generic_ipc *ipc, + struct skl_ipc_header header); +int skl_ipc_process_notification(struct sst_generic_ipc *ipc, + struct skl_ipc_header header); +void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data, + size_t tx_size); #endif /* __SKL_IPC_H */ -- cgit v1.2.3 From cb6a552846297094aac942a588fe7ed7922a6c11 Mon Sep 17 00:00:00 2001 From: Guneshwor Singh Date: Wed, 2 Aug 2017 21:51:18 +0530 Subject: ASoC: Intel: cnl: Add sst library functions for cnl platform This adds the necessary DSP functions specific for the Cannonlake platform which includes firmware download using host DMA, DO/D3 handlers, irq_thread handlers and sst ops. Signed-off-by: Guneshwor Singh Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/Makefile | 5 +- sound/soc/intel/skylake/cnl-sst-dsp.h | 6 + sound/soc/intel/skylake/cnl-sst.c | 495 ++++++++++++++++++++++++++++++++++ 3 files changed, 504 insertions(+), 2 deletions(-) create mode 100644 sound/soc/intel/skylake/cnl-sst.c (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/Makefile b/sound/soc/intel/skylake/Makefile index e7d77722d560..3380deb81015 100644 --- a/sound/soc/intel/skylake/Makefile +++ b/sound/soc/intel/skylake/Makefile @@ -8,7 +8,8 @@ endif obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl.o # Skylake IPC Support -snd-soc-skl-ipc-objs := skl-sst-ipc.o skl-sst-dsp.o skl-sst-cldma.o \ - skl-sst.o bxt-sst.o skl-sst-utils.o +snd-soc-skl-ipc-objs := skl-sst-ipc.o skl-sst-dsp.o cnl-sst-dsp.o \ + skl-sst-cldma.o skl-sst.o bxt-sst.o cnl-sst.o \ + skl-sst-utils.o obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl-ipc.o diff --git a/sound/soc/intel/skylake/cnl-sst-dsp.h b/sound/soc/intel/skylake/cnl-sst-dsp.h index 2fe41b137a2c..09bd218df5c4 100644 --- a/sound/soc/intel/skylake/cnl-sst-dsp.h +++ b/sound/soc/intel/skylake/cnl-sst-dsp.h @@ -103,4 +103,10 @@ void cnl_ipc_op_int_disable(struct sst_dsp *ctx); bool cnl_ipc_int_status(struct sst_dsp *ctx); void cnl_ipc_free(struct sst_generic_ipc *ipc); +int cnl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, + const char *fw_name, struct skl_dsp_loader_ops dsp_ops, + struct skl_sst **dsp); +int cnl_sst_init_fw(struct device *dev, struct skl_sst *ctx); +void cnl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx); + #endif /*__CNL_SST_DSP_H__*/ diff --git a/sound/soc/intel/skylake/cnl-sst.c b/sound/soc/intel/skylake/cnl-sst.c new file mode 100644 index 000000000000..7dcfe66a20e2 --- /dev/null +++ b/sound/soc/intel/skylake/cnl-sst.c @@ -0,0 +1,495 @@ +/* + * cnl-sst.c - DSP library functions for CNL platform + * + * Copyright (C) 2016-17, Intel Corporation. + * + * Author: Guneshwor Singh + * + * Modified from: + * HDA DSP library functions for SKL platform + * Copyright (C) 2014-15, Intel Corporation. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#include +#include +#include +#include + +#include "../common/sst-dsp.h" +#include "../common/sst-dsp-priv.h" +#include "../common/sst-ipc.h" +#include "cnl-sst-dsp.h" +#include "skl-sst-dsp.h" +#include "skl-sst-ipc.h" + +#define CNL_FW_ROM_INIT 0x1 +#define CNL_FW_INIT 0x5 +#define CNL_IPC_PURGE 0x01004000 +#define CNL_INIT_TIMEOUT 300 +#define CNL_BASEFW_TIMEOUT 3000 + +#define CNL_ADSP_SRAM0_BASE 0x80000 + +/* Firmware status window */ +#define CNL_ADSP_FW_STATUS CNL_ADSP_SRAM0_BASE +#define CNL_ADSP_ERROR_CODE (CNL_ADSP_FW_STATUS + 0x4) + +#define CNL_INSTANCE_ID 0 +#define CNL_BASE_FW_MODULE_ID 0 +#define CNL_ADSP_FW_HDR_OFFSET 0x2000 +#define CNL_ROM_CTRL_DMA_ID 0x9 + +static int cnl_prepare_fw(struct sst_dsp *ctx, const void *fwdata, u32 fwsize) +{ + + int ret, stream_tag; + + stream_tag = ctx->dsp_ops.prepare(ctx->dev, 0x40, fwsize, &ctx->dmab); + if (stream_tag <= 0) { + dev_err(ctx->dev, "dma prepare failed: 0%#x\n", stream_tag); + return stream_tag; + } + + ctx->dsp_ops.stream_tag = stream_tag; + memcpy(ctx->dmab.area, fwdata, fwsize); + + /* purge FW request */ + sst_dsp_shim_write(ctx, CNL_ADSP_REG_HIPCIDR, + CNL_ADSP_REG_HIPCIDR_BUSY | (CNL_IPC_PURGE | + ((stream_tag - 1) << CNL_ROM_CTRL_DMA_ID))); + + ret = cnl_dsp_enable_core(ctx, SKL_DSP_CORE0_MASK); + if (ret < 0) { + dev_err(ctx->dev, "dsp boot core failed ret: %d\n", ret); + ret = -EIO; + goto base_fw_load_failed; + } + + /* enable interrupt */ + cnl_ipc_int_enable(ctx); + cnl_ipc_op_int_enable(ctx); + + ret = sst_dsp_register_poll(ctx, CNL_ADSP_FW_STATUS, CNL_FW_STS_MASK, + CNL_FW_ROM_INIT, CNL_INIT_TIMEOUT, + "rom load"); + if (ret < 0) { + dev_err(ctx->dev, "rom init timeout, ret: %d\n", ret); + goto base_fw_load_failed; + } + + return 0; + +base_fw_load_failed: + ctx->dsp_ops.cleanup(ctx->dev, &ctx->dmab, stream_tag); + cnl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); + + return ret; +} + +static int sst_transfer_fw_host_dma(struct sst_dsp *ctx) +{ + int ret; + + ctx->dsp_ops.trigger(ctx->dev, true, ctx->dsp_ops.stream_tag); + ret = sst_dsp_register_poll(ctx, CNL_ADSP_FW_STATUS, CNL_FW_STS_MASK, + CNL_FW_INIT, CNL_BASEFW_TIMEOUT, + "firmware boot"); + + ctx->dsp_ops.trigger(ctx->dev, false, ctx->dsp_ops.stream_tag); + ctx->dsp_ops.cleanup(ctx->dev, &ctx->dmab, ctx->dsp_ops.stream_tag); + + return ret; +} + +static int cnl_load_base_firmware(struct sst_dsp *ctx) +{ + struct firmware stripped_fw; + struct skl_sst *cnl = ctx->thread_context; + int ret; + + if (!ctx->fw) { + ret = request_firmware(&ctx->fw, ctx->fw_name, ctx->dev); + if (ret < 0) { + dev_err(ctx->dev, "request firmware failed: %d\n", ret); + goto cnl_load_base_firmware_failed; + } + } + + /* parse uuids if first boot */ + if (cnl->is_first_boot) { + ret = snd_skl_parse_uuids(ctx, ctx->fw, + CNL_ADSP_FW_HDR_OFFSET, 0); + if (ret < 0) + goto cnl_load_base_firmware_failed; + } + + stripped_fw.data = ctx->fw->data; + stripped_fw.size = ctx->fw->size; + skl_dsp_strip_extended_manifest(&stripped_fw); + + ret = cnl_prepare_fw(ctx, stripped_fw.data, stripped_fw.size); + if (ret < 0) { + dev_err(ctx->dev, "prepare firmware failed: %d\n", ret); + goto cnl_load_base_firmware_failed; + } + + ret = sst_transfer_fw_host_dma(ctx); + if (ret < 0) { + dev_err(ctx->dev, "transfer firmware failed: %d\n", ret); + cnl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); + goto cnl_load_base_firmware_failed; + } + + ret = wait_event_timeout(cnl->boot_wait, cnl->boot_complete, + msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); + if (ret == 0) { + dev_err(ctx->dev, "FW ready timed-out\n"); + cnl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); + ret = -EIO; + goto cnl_load_base_firmware_failed; + } + + cnl->fw_loaded = true; + + return 0; + +cnl_load_base_firmware_failed: + release_firmware(ctx->fw); + ctx->fw = NULL; + + return ret; +} + +static int cnl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) +{ + struct skl_sst *cnl = ctx->thread_context; + unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); + struct skl_ipc_dxstate_info dx; + int ret; + + if (!cnl->fw_loaded) { + cnl->boot_complete = false; + ret = cnl_load_base_firmware(ctx); + if (ret < 0) { + dev_err(ctx->dev, "fw reload failed: %d\n", ret); + return ret; + } + + cnl->cores.state[core_id] = SKL_DSP_RUNNING; + return ret; + } + + ret = cnl_dsp_enable_core(ctx, core_mask); + if (ret < 0) { + dev_err(ctx->dev, "enable dsp core %d failed: %d\n", + core_id, ret); + goto err; + } + + if (core_id == SKL_DSP_CORE0_ID) { + /* enable interrupt */ + cnl_ipc_int_enable(ctx); + cnl_ipc_op_int_enable(ctx); + cnl->boot_complete = false; + + ret = wait_event_timeout(cnl->boot_wait, cnl->boot_complete, + msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); + if (ret == 0) { + dev_err(ctx->dev, + "dsp boot timeout, status=%#x error=%#x\n", + sst_dsp_shim_read(ctx, CNL_ADSP_FW_STATUS), + sst_dsp_shim_read(ctx, CNL_ADSP_ERROR_CODE)); + goto err; + } + } else { + dx.core_mask = core_mask; + dx.dx_mask = core_mask; + + ret = skl_ipc_set_dx(&cnl->ipc, CNL_INSTANCE_ID, + CNL_BASE_FW_MODULE_ID, &dx); + if (ret < 0) { + dev_err(ctx->dev, "set_dx failed, core: %d ret: %d\n", + core_id, ret); + goto err; + } + } + cnl->cores.state[core_id] = SKL_DSP_RUNNING; + + return 0; +err: + cnl_dsp_disable_core(ctx, core_mask); + + return ret; +} + +static int cnl_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id) +{ + struct skl_sst *cnl = ctx->thread_context; + unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); + struct skl_ipc_dxstate_info dx; + int ret; + + dx.core_mask = core_mask; + dx.dx_mask = SKL_IPC_D3_MASK; + + ret = skl_ipc_set_dx(&cnl->ipc, CNL_INSTANCE_ID, + CNL_BASE_FW_MODULE_ID, &dx); + if (ret < 0) { + dev_err(ctx->dev, + "dsp core %d to d3 failed; continue reset\n", + core_id); + cnl->fw_loaded = false; + } + + /* disable interrupts if core 0 */ + if (core_id == SKL_DSP_CORE0_ID) { + skl_ipc_op_int_disable(ctx); + skl_ipc_int_disable(ctx); + } + + ret = cnl_dsp_disable_core(ctx, core_mask); + if (ret < 0) { + dev_err(ctx->dev, "disable dsp core %d failed: %d\n", + core_id, ret); + return ret; + } + + cnl->cores.state[core_id] = SKL_DSP_RESET; + + return ret; +} + +static unsigned int cnl_get_errno(struct sst_dsp *ctx) +{ + return sst_dsp_shim_read(ctx, CNL_ADSP_ERROR_CODE); +} + +static struct skl_dsp_fw_ops cnl_fw_ops = { + .set_state_D0 = cnl_set_dsp_D0, + .set_state_D3 = cnl_set_dsp_D3, + .load_fw = cnl_load_base_firmware, + .get_fw_errcode = cnl_get_errno, +}; + +static struct sst_ops cnl_ops = { + .irq_handler = cnl_dsp_sst_interrupt, + .write = sst_shim32_write, + .read = sst_shim32_read, + .ram_read = sst_memcpy_fromio_32, + .ram_write = sst_memcpy_toio_32, + .free = cnl_dsp_free, +}; + +#define CNL_IPC_GLB_NOTIFY_RSP_SHIFT 29 +#define CNL_IPC_GLB_NOTIFY_RSP_MASK 0x1 +#define CNL_IPC_GLB_NOTIFY_RSP_TYPE(x) (((x) >> CNL_IPC_GLB_NOTIFY_RSP_SHIFT) \ + & CNL_IPC_GLB_NOTIFY_RSP_MASK) + +static irqreturn_t cnl_dsp_irq_thread_handler(int irq, void *context) +{ + struct sst_dsp *dsp = context; + struct skl_sst *cnl = sst_dsp_get_thread_context(dsp); + struct sst_generic_ipc *ipc = &cnl->ipc; + struct skl_ipc_header header = {0}; + u32 hipcida, hipctdr, hipctdd; + int ipc_irq = 0; + + /* here we handle ipc interrupts only */ + if (!(dsp->intr_status & CNL_ADSPIS_IPC)) + return IRQ_NONE; + + hipcida = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCIDA); + hipctdr = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCTDR); + + /* reply message from dsp */ + if (hipcida & CNL_ADSP_REG_HIPCIDA_DONE) { + sst_dsp_shim_update_bits(dsp, CNL_ADSP_REG_HIPCCTL, + CNL_ADSP_REG_HIPCCTL_DONE, 0); + + /* clear done bit - tell dsp operation is complete */ + sst_dsp_shim_update_bits_forced(dsp, CNL_ADSP_REG_HIPCIDA, + CNL_ADSP_REG_HIPCIDA_DONE, CNL_ADSP_REG_HIPCIDA_DONE); + + ipc_irq = 1; + + /* unmask done interrupt */ + sst_dsp_shim_update_bits(dsp, CNL_ADSP_REG_HIPCCTL, + CNL_ADSP_REG_HIPCCTL_DONE, CNL_ADSP_REG_HIPCCTL_DONE); + } + + /* new message from dsp */ + if (hipctdr & CNL_ADSP_REG_HIPCTDR_BUSY) { + hipctdd = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCTDD); + header.primary = hipctdr; + header.extension = hipctdd; + dev_dbg(dsp->dev, "IPC irq: Firmware respond primary:%x", + header.primary); + dev_dbg(dsp->dev, "IPC irq: Firmware respond extension:%x", + header.extension); + + if (CNL_IPC_GLB_NOTIFY_RSP_TYPE(header.primary)) { + /* Handle Immediate reply from DSP Core */ + skl_ipc_process_reply(ipc, header); + } else { + dev_dbg(dsp->dev, "IPC irq: Notification from firmware\n"); + skl_ipc_process_notification(ipc, header); + } + /* clear busy interrupt */ + sst_dsp_shim_update_bits_forced(dsp, CNL_ADSP_REG_HIPCTDR, + CNL_ADSP_REG_HIPCTDR_BUSY, CNL_ADSP_REG_HIPCTDR_BUSY); + + /* set done bit to ack dsp */ + sst_dsp_shim_update_bits_forced(dsp, CNL_ADSP_REG_HIPCTDA, + CNL_ADSP_REG_HIPCTDA_DONE, CNL_ADSP_REG_HIPCTDA_DONE); + ipc_irq = 1; + } + + if (ipc_irq == 0) + return IRQ_NONE; + + cnl_ipc_int_enable(dsp); + + /* continue to send any remaining messages */ + schedule_work(&ipc->kwork); + + return IRQ_HANDLED; +} + +static struct sst_dsp_device cnl_dev = { + .thread = cnl_dsp_irq_thread_handler, + .ops = &cnl_ops, +}; + +static void cnl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg) +{ + struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->header); + + if (msg->tx_size) + sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size); + sst_dsp_shim_write_unlocked(ipc->dsp, CNL_ADSP_REG_HIPCIDD, + header->extension); + sst_dsp_shim_write_unlocked(ipc->dsp, CNL_ADSP_REG_HIPCIDR, + header->primary | CNL_ADSP_REG_HIPCIDR_BUSY); +} + +static bool cnl_ipc_is_dsp_busy(struct sst_dsp *dsp) +{ + u32 hipcidr; + + hipcidr = sst_dsp_shim_read_unlocked(dsp, CNL_ADSP_REG_HIPCIDR); + + return (hipcidr & CNL_ADSP_REG_HIPCIDR_BUSY); +} + +static int cnl_ipc_init(struct device *dev, struct skl_sst *cnl) +{ + struct sst_generic_ipc *ipc; + int err; + + ipc = &cnl->ipc; + ipc->dsp = cnl->dsp; + ipc->dev = dev; + + ipc->tx_data_max_size = CNL_ADSP_W1_SZ; + ipc->rx_data_max_size = CNL_ADSP_W0_UP_SZ; + + err = sst_ipc_init(ipc); + if (err) + return err; + + /* + * overriding tx_msg and is_dsp_busy since + * ipc registers are different for cnl + */ + ipc->ops.tx_msg = cnl_ipc_tx_msg; + ipc->ops.tx_data_copy = skl_ipc_tx_data_copy; + ipc->ops.is_dsp_busy = cnl_ipc_is_dsp_busy; + + return 0; +} + +int cnl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, + const char *fw_name, struct skl_dsp_loader_ops dsp_ops, + struct skl_sst **dsp) +{ + struct skl_sst *cnl; + struct sst_dsp *sst; + int ret; + + ret = skl_sst_ctx_init(dev, irq, fw_name, dsp_ops, dsp, &cnl_dev); + if (ret < 0) { + dev_err(dev, "%s: no device\n", __func__); + return ret; + } + + cnl = *dsp; + sst = cnl->dsp; + sst->fw_ops = cnl_fw_ops; + sst->addr.lpe = mmio_base; + sst->addr.shim = mmio_base; + sst->addr.sram0_base = CNL_ADSP_SRAM0_BASE; + sst->addr.sram1_base = CNL_ADSP_SRAM1_BASE; + sst->addr.w0_stat_sz = CNL_ADSP_W0_STAT_SZ; + sst->addr.w0_up_sz = CNL_ADSP_W0_UP_SZ; + + sst_dsp_mailbox_init(sst, (CNL_ADSP_SRAM0_BASE + CNL_ADSP_W0_STAT_SZ), + CNL_ADSP_W0_UP_SZ, CNL_ADSP_SRAM1_BASE, + CNL_ADSP_W1_SZ); + + ret = cnl_ipc_init(dev, cnl); + if (ret) + return ret; + + cnl->boot_complete = false; + init_waitqueue_head(&cnl->boot_wait); + + return 0; +} +EXPORT_SYMBOL_GPL(cnl_sst_dsp_init); + +int cnl_sst_init_fw(struct device *dev, struct skl_sst *ctx) +{ + int ret; + struct sst_dsp *sst = ctx->dsp; + + ret = ctx->dsp->fw_ops.load_fw(sst); + if (ret < 0) { + dev_err(dev, "load base fw failed: %d", ret); + return ret; + } + + skl_dsp_init_core_state(sst); + + ctx->is_first_boot = false; + + return 0; +} +EXPORT_SYMBOL_GPL(cnl_sst_init_fw); + +void cnl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) +{ + if (ctx->dsp->fw) + release_firmware(ctx->dsp->fw); + + skl_freeup_uuid_list(ctx); + cnl_ipc_free(&ctx->ipc); + + ctx->dsp->ops->free(ctx->dsp); +} +EXPORT_SYMBOL_GPL(cnl_sst_dsp_cleanup); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Intel Cannonlake IPC driver"); -- cgit v1.2.3 From b003a345dc67c7a1c468ad8ff10b24d7dd12e12c Mon Sep 17 00:00:00 2001 From: Guneshwor Singh Date: Wed, 2 Aug 2017 21:51:19 +0530 Subject: ASoC: Intel: cnl: add dsp ops for cannonlake Add cannonlake dsp support by adding its dsp_ops. Signed-off-by: Guneshwor Singh Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-messages.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index c6b60ee5b196..bfb3332a77ca 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -22,6 +22,7 @@ #include #include #include "skl-sst-dsp.h" +#include "cnl-sst-dsp.h" #include "skl-sst-ipc.h" #include "skl.h" #include "../common/sst-dsp.h" @@ -231,6 +232,14 @@ static const struct skl_dsp_ops dsp_ops[] = { .init_fw = bxt_sst_init_fw, .cleanup = bxt_sst_dsp_cleanup }, + { + .id = 0x9dc8, + .num_cores = 4, + .loader_ops = bxt_get_loader_ops, + .init = cnl_sst_dsp_init, + .init_fw = cnl_sst_init_fw, + .cleanup = cnl_sst_dsp_cleanup + }, }; const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id) -- cgit v1.2.3 From 86d7ce3dd717e09a442d35dae3f9c62c03e024d8 Mon Sep 17 00:00:00 2001 From: Guneshwor Singh Date: Wed, 2 Aug 2017 21:51:20 +0530 Subject: ASoC: Intel: cnl: add pci id for cnl Enable cnl by adding its pci id in skl_ids[]. Signed-off-by: Guneshwor Singh Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index ab651517e8b8..e612a4097275 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -996,6 +996,14 @@ static struct sst_acpi_mach sst_glk_devdata[] = { }, }; +static const struct sst_acpi_mach sst_cnl_devdata[] = { + { + .id = "INT34C2", + .drv_name = "cnl_rt274", + .fw_filename = "intel/dsp_fw_cnl.bin", + }, +}; + /* PCI IDs */ static const struct pci_device_id skl_ids[] = { /* Sunrise Point-LP */ @@ -1010,6 +1018,9 @@ static const struct pci_device_id skl_ids[] = { /* GLK */ { PCI_DEVICE(0x8086, 0x3198), .driver_data = (unsigned long)&sst_glk_devdata}, + /* CNL */ + { PCI_DEVICE(0x8086, 0x9dc8), + .driver_data = (unsigned long)&sst_cnl_devdata}, { 0, } }; MODULE_DEVICE_TABLE(pci, skl_ids); -- cgit v1.2.3 From 67e8ee9b4b387f5c4d12ad9b926a78a9bf3dc275 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Thu, 3 Aug 2017 23:20:01 +0530 Subject: ASoC: Intel: constify pci_device_id. pci_device_id are not supposed to change at runtime. All functions working with pci_device_id provided by work with const pci_device_id. So mark the non-const structs as const. Signed-off-by: Arvind Yadav Signed-off-by: Mark Brown --- sound/soc/intel/atom/sst/sst_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/atom/sst/sst_pci.c b/sound/soc/intel/atom/sst/sst_pci.c index 3a0b3bf0af97..6906ee624cf6 100644 --- a/sound/soc/intel/atom/sst/sst_pci.c +++ b/sound/soc/intel/atom/sst/sst_pci.c @@ -181,7 +181,7 @@ static void intel_sst_remove(struct pci_dev *pci) } /* PCI Routines */ -static struct pci_device_id intel_sst_ids[] = { +static const struct pci_device_id intel_sst_ids[] = { { PCI_VDEVICE(INTEL, SST_MRFLD_PCI_ID), 0}, { 0, } }; -- cgit v1.2.3 From 80cc4df8b46e91c28a6d39dd0ba76bd9c83c18ce Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Mon, 14 Aug 2017 17:08:41 +0530 Subject: ASoC: Intel: make snd_soc_platform_driver const Make these const as they are only passed as the 2nd argument to the function snd_soc_register_platform, which is of type const. Done using Coccinelle. Signed-off-by: Bhumika Goyal Signed-off-by: Mark Brown --- sound/soc/intel/atom/sst-mfld-platform-pcm.c | 2 +- sound/soc/intel/baytrail/sst-baytrail-pcm.c | 2 +- sound/soc/intel/haswell/sst-haswell-pcm.c | 2 +- sound/soc/intel/skylake/skl-pcm.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c index 49c7b88b5bdc..b272df5ce0e8 100644 --- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c @@ -705,7 +705,7 @@ static int sst_soc_probe(struct snd_soc_platform *platform) return sst_dsp_init_v2_dpcm(platform); } -static struct snd_soc_platform_driver sst_soc_platform_drv = { +static const struct snd_soc_platform_driver sst_soc_platform_drv = { .probe = sst_soc_probe, .ops = &sst_platform_ops, .compr_ops = &sst_platform_compr_ops, diff --git a/sound/soc/intel/baytrail/sst-baytrail-pcm.c b/sound/soc/intel/baytrail/sst-baytrail-pcm.c index 4765ad474544..84cb568c3ad6 100644 --- a/sound/soc/intel/baytrail/sst-baytrail-pcm.c +++ b/sound/soc/intel/baytrail/sst-baytrail-pcm.c @@ -395,7 +395,7 @@ static int sst_byt_pcm_remove(struct snd_soc_platform *platform) return 0; } -static struct snd_soc_platform_driver byt_soc_platform = { +static const struct snd_soc_platform_driver byt_soc_platform = { .probe = sst_byt_pcm_probe, .remove = sst_byt_pcm_remove, .ops = &sst_byt_pcm_ops, diff --git a/sound/soc/intel/haswell/sst-haswell-pcm.c b/sound/soc/intel/haswell/sst-haswell-pcm.c index 9e4094e2c6e3..c044400540ec 100644 --- a/sound/soc/intel/haswell/sst-haswell-pcm.c +++ b/sound/soc/intel/haswell/sst-haswell-pcm.c @@ -1135,7 +1135,7 @@ static int hsw_pcm_remove(struct snd_soc_platform *platform) return 0; } -static struct snd_soc_platform_driver hsw_soc_platform = { +static const struct snd_soc_platform_driver hsw_soc_platform = { .probe = hsw_pcm_probe, .remove = hsw_pcm_remove, .ops = &hsw_pcm_ops, diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index debdaac2c3a2..e98d8252a026 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -1310,7 +1310,7 @@ static int skl_platform_soc_probe(struct snd_soc_platform *platform) return 0; } -static struct snd_soc_platform_driver skl_platform_drv = { +static const struct snd_soc_platform_driver skl_platform_drv = { .probe = skl_platform_soc_probe, .ops = &skl_platform_ops, .pcm_new = skl_pcm_new, -- cgit v1.2.3 From f2c402ba55fe7cc3924de683ac5eef99c75eab04 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Mon, 14 Aug 2017 11:26:27 +0530 Subject: ASoC: intel: constify snd_pcm_ops structures snd_pcm_ops are not supposed to change at runtime. All functions working with snd_pcm_ops provided by work with const snd_pcm_ops. So mark the non-const structs as const. Signed-off-by: Arvind Yadav Signed-off-by: Mark Brown --- sound/soc/intel/baytrail/sst-baytrail-pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/baytrail/sst-baytrail-pcm.c b/sound/soc/intel/baytrail/sst-baytrail-pcm.c index 84cb568c3ad6..c54529320f07 100644 --- a/sound/soc/intel/baytrail/sst-baytrail-pcm.c +++ b/sound/soc/intel/baytrail/sst-baytrail-pcm.c @@ -309,7 +309,7 @@ static int sst_byt_pcm_mmap(struct snd_pcm_substream *substream, return snd_pcm_lib_default_mmap(substream, vma); } -static struct snd_pcm_ops sst_byt_pcm_ops = { +static const struct snd_pcm_ops sst_byt_pcm_ops = { .open = sst_byt_pcm_open, .close = sst_byt_pcm_close, .ioctl = snd_pcm_lib_ioctl, -- cgit v1.2.3 From 2d5f8487818b9231dfb244adda5e890e004b4a76 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Fri, 11 Aug 2017 21:26:49 +0530 Subject: ASoC: Intel: kbl: make snd_pcm_hw_constraint_list const Make these const as they are only passed to the function snd_pcm_hw_constraint_list having the corresponding argument as const. Done using Coccinelle. Signed-off-by: Bhumika Goyal Signed-off-by: Mark Brown --- sound/soc/intel/boards/kbl_rt5663_max98927.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/boards/kbl_rt5663_max98927.c b/sound/soc/intel/boards/kbl_rt5663_max98927.c index 12b34b9a0104..8bdd6131c6ad 100644 --- a/sound/soc/intel/boards/kbl_rt5663_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_max98927.c @@ -286,7 +286,7 @@ static unsigned int rates[] = { 48000, }; -static struct snd_pcm_hw_constraint_list constraints_rates = { +static const struct snd_pcm_hw_constraint_list constraints_rates = { .count = ARRAY_SIZE(rates), .list = rates, .mask = 0, @@ -296,7 +296,7 @@ static unsigned int channels[] = { 2, }; -static struct snd_pcm_hw_constraint_list constraints_channels = { +static const struct snd_pcm_hw_constraint_list constraints_channels = { .count = ARRAY_SIZE(channels), .list = channels, .mask = 0, @@ -425,7 +425,7 @@ static unsigned int rates_16000[] = { 16000, }; -static struct snd_pcm_hw_constraint_list constraints_16000 = { +static const struct snd_pcm_hw_constraint_list constraints_16000 = { .count = ARRAY_SIZE(rates_16000), .list = rates_16000, }; -- cgit v1.2.3 From 2788808a1bb4dd0b20c4cea2a98b9fda4c354682 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Fri, 11 Aug 2017 21:57:15 +0530 Subject: ASoC: Intel: Skylake: make skl_dsp_fw_ops const Make these const as they are only used during a copy operation. Done using Coccinelle. Signed-off-by: Bhumika Goyal Signed-off-by: Mark Brown --- sound/soc/intel/skylake/bxt-sst.c | 2 +- sound/soc/intel/skylake/cnl-sst.c | 2 +- sound/soc/intel/skylake/skl-sst.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c index 71042aceb25f..5e1ac99ffa8b 100644 --- a/sound/soc/intel/skylake/bxt-sst.c +++ b/sound/soc/intel/skylake/bxt-sst.c @@ -530,7 +530,7 @@ static int bxt_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id) return 0; } -static struct skl_dsp_fw_ops bxt_fw_ops = { +static const struct skl_dsp_fw_ops bxt_fw_ops = { .set_state_D0 = bxt_set_dsp_D0, .set_state_D3 = bxt_set_dsp_D3, .set_state_D0i3 = bxt_schedule_dsp_D0i3, diff --git a/sound/soc/intel/skylake/cnl-sst.c b/sound/soc/intel/skylake/cnl-sst.c index 7dcfe66a20e2..48ef04d5da89 100644 --- a/sound/soc/intel/skylake/cnl-sst.c +++ b/sound/soc/intel/skylake/cnl-sst.c @@ -277,7 +277,7 @@ static unsigned int cnl_get_errno(struct sst_dsp *ctx) return sst_dsp_shim_read(ctx, CNL_ADSP_ERROR_CODE); } -static struct skl_dsp_fw_ops cnl_fw_ops = { +static const struct skl_dsp_fw_ops cnl_fw_ops = { .set_state_D0 = cnl_set_dsp_D0, .set_state_D3 = cnl_set_dsp_D3, .load_fw = cnl_load_base_firmware, diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index 6cc586d3f03b..a7ad734f591d 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c @@ -503,7 +503,7 @@ static void skl_clear_module_table(struct sst_dsp *ctx) } } -static struct skl_dsp_fw_ops skl_fw_ops = { +static const struct skl_dsp_fw_ops skl_fw_ops = { .set_state_D0 = skl_set_dsp_D0, .set_state_D3 = skl_set_dsp_D3, .load_fw = skl_load_base_firmware, @@ -512,7 +512,7 @@ static struct skl_dsp_fw_ops skl_fw_ops = { .unload_mod = skl_unload_module, }; -static struct skl_dsp_fw_ops kbl_fw_ops = { +static const struct skl_dsp_fw_ops kbl_fw_ops = { .set_state_D0 = skl_set_dsp_D0, .set_state_D3 = skl_set_dsp_D3, .load_fw = skl_load_base_firmware, -- cgit v1.2.3 From 70bad123ea5bec47329bc8681cbb8e8431188ba2 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 12 Aug 2017 08:33:02 +0200 Subject: ASoC: Intel: constify snd_compr_codec_caps structures These snd_compr_codec_caps structures are only copied into other structures, so they can be const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Mark Brown --- sound/soc/intel/atom/sst/sst_drv_interface.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/atom/sst/sst_drv_interface.c b/sound/soc/intel/atom/sst/sst_drv_interface.c index ce689c5af5ab..71af5449be90 100644 --- a/sound/soc/intel/atom/sst/sst_drv_interface.c +++ b/sound/soc/intel/atom/sst/sst_drv_interface.c @@ -407,7 +407,7 @@ static int sst_cdev_caps(struct snd_compr_caps *caps) return 0; } -static struct snd_compr_codec_caps caps_mp3 = { +static const struct snd_compr_codec_caps caps_mp3 = { .num_descriptors = 1, .descriptor[0].max_ch = 2, .descriptor[0].sample_rates[0] = 48000, @@ -424,7 +424,7 @@ static struct snd_compr_codec_caps caps_mp3 = { .descriptor[0].formats = 0, }; -static struct snd_compr_codec_caps caps_aac = { +static const struct snd_compr_codec_caps caps_aac = { .num_descriptors = 2, .descriptor[1].max_ch = 2, .descriptor[0].sample_rates[0] = 48000, -- cgit v1.2.3 From 92ec46da6e35f5f7ff39741517a9466c82d1afb9 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Fri, 11 Aug 2017 11:25:41 +0200 Subject: ASoC: Medfield: Delete an error message for a failed memory allocation in snd_mfld_mc_probe() Omit an extra message for a memory allocation failure in this function. This issue was detected by using the Coccinelle software. Link: http://events.linuxfoundation.org/sites/events/files/slides/LCJ16-Refactor_Strings-WSang_0.pdf Signed-off-by: Markus Elfring Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/boards/mfld_machine.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/boards/mfld_machine.c b/sound/soc/intel/boards/mfld_machine.c index 4e08885f37aa..6f44acfb4aae 100644 --- a/sound/soc/intel/boards/mfld_machine.c +++ b/sound/soc/intel/boards/mfld_machine.c @@ -376,10 +376,8 @@ static int snd_mfld_mc_probe(struct platform_device *pdev) /* audio interrupt base of SRAM location where * interrupts are stored by System FW */ mc_drv_ctx = devm_kzalloc(&pdev->dev, sizeof(*mc_drv_ctx), GFP_ATOMIC); - if (!mc_drv_ctx) { - pr_err("allocation failed\n"); + if (!mc_drv_ctx) return -ENOMEM; - } irq_mem = platform_get_resource_byname( pdev, IORESOURCE_MEM, "IRQ_BASE"); -- cgit v1.2.3 From 393a829bb2f7e12403cb7ff3b62539c27a543a2c Mon Sep 17 00:00:00 2001 From: Harsha Priya N Date: Wed, 16 Aug 2017 15:37:11 -0700 Subject: ASoC: Intel: kbl_rt5663_rt5514_max98927: Add rt5514 spi dailink This patch adds a dai to rt5514-spi driver for wake on voice functionality. Signed-off-by: Hsin-yu Chao Signed-off-by: Harsha Priya Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/Kconfig | 3 ++- sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index b301bfff1c09..b3c7f554ec30 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -255,11 +255,12 @@ config SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH config SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH tristate "ASoC Audio driver for KBL with RT5663, RT5514 and MAX98927 in I2S Mode" - depends on X86_INTEL_LPSS && I2C + depends on X86_INTEL_LPSS && I2C && SPI select SND_SOC_INTEL_SST select SND_SOC_INTEL_SKYLAKE select SND_SOC_RT5663 select SND_SOC_RT5514 + select SND_SOC_RT5514_SPI select SND_SOC_MAX98927 select SND_SOC_HDAC_HDMI help diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c index 5ec942885b69..b51dff6fe25b 100644 --- a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c @@ -65,6 +65,7 @@ enum { KBL_DPCM_AUDIO_HS_PB, KBL_DPCM_AUDIO_ECHO_REF_CP, KBL_DPCM_AUDIO_DMIC_CP, + KBL_DPCM_AUDIO_RT5514_DSP, KBL_DPCM_AUDIO_HDMI1_PB, KBL_DPCM_AUDIO_HDMI2_PB, }; @@ -480,6 +481,14 @@ static struct snd_soc_dai_link kabylake_dais[] = { .capture_only = 1, .nonatomic = 1, }, + [KBL_DPCM_AUDIO_RT5514_DSP] = { + .name = "rt5514 dsp", + .stream_name = "Wake on Voice", + .cpu_dai_name = "spi-PRP0001:00", + .platform_name = "spi-PRP0001:00", + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + }, [KBL_DPCM_AUDIO_DMIC_CP] = { .name = "Kbl Audio DMIC cap", .stream_name = "dmiccap", -- cgit v1.2.3 From a7468e478a95db31c0f64e8497fadd9df5c49789 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Thu, 17 Aug 2017 15:46:08 +0530 Subject: ASoC: Intel: Atom: make snd_pcm_hardware const Make this const as it is only used in a copy operation. Done using Coccinelle. Signed-off-by: Bhumika Goyal Signed-off-by: Mark Brown --- sound/soc/intel/atom/sst-mfld-platform-pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c index b272df5ce0e8..43e7fdd19f29 100644 --- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c @@ -76,7 +76,7 @@ int sst_unregister_dsp(struct sst_device *dev) } EXPORT_SYMBOL_GPL(sst_unregister_dsp); -static struct snd_pcm_hardware sst_platform_pcm_hw = { +static const struct snd_pcm_hardware sst_platform_pcm_hw = { .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_DOUBLE | SNDRV_PCM_INFO_PAUSE | -- cgit v1.2.3 From 8df397ff0e281d5324d4b7a7e9fa56c4188e0a66 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Thu, 17 Aug 2017 15:46:09 +0530 Subject: ASoC: Intel: Skylake: make snd_pcm_hardware const Make this const as it is only passed as the 2nd argument to the function snd_soc_set_runtime_hwparams, which is const. Done using Coccinelle. Signed-off-by: Bhumika Goyal Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index e98d8252a026..f6c9adb6faa2 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -33,7 +33,7 @@ #define HDA_STEREO 2 #define HDA_QUAD 4 -static struct snd_pcm_hardware azx_pcm_hw = { +static const struct snd_pcm_hardware azx_pcm_hw = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | -- cgit v1.2.3 From d46b1828406f74bc2d9ffe15e9a7b76ddbffbf7f Mon Sep 17 00:00:00 2001 From: Harsha Priya N Date: Wed, 16 Aug 2017 16:19:55 +0530 Subject: ASoC: Intel: kbl: Enabling ASRC for RT5663 codec on kabylake platform Patch fixes cracking noise in rt5663 headphones for kbl platform by calling rt5663_sel_asrc_clk_src() for RT5663_AD_STEREO_FILTER to set ASRC. The ASRC function is for asynchronous MCLK and LRCLK. For RT5663 ASRC should be enabled to support pcm format with 100fs. ASRC function will track i2s clock and generate corresponding system clock for codec. Calling this func helps select clock source for both RT5663_AD_STEREO_FILTER and RT5663_DA_STEREO_FILTER filters which fixes the crackling sound. Signed-off-by: Harsha Priya Signed-off-by: Shruthi Sudhakar Signed-off-by: Naveen M Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/boards/kbl_rt5663_max98927.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/boards/kbl_rt5663_max98927.c b/sound/soc/intel/boards/kbl_rt5663_max98927.c index 8bdd6131c6ad..c1442147d138 100644 --- a/sound/soc/intel/boards/kbl_rt5663_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_max98927.c @@ -356,11 +356,13 @@ static int kabylake_rt5663_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai = rtd->codec_dai; int ret; - ret = snd_soc_dai_set_sysclk(codec_dai, - RT5663_SCLK_S_MCLK, 24576000, SND_SOC_CLOCK_IN); /* use ASRC for internal clocks, as PLL rate isn't multiple of BCLK */ - rt5663_sel_asrc_clk_src(codec_dai->codec, RT5663_DA_STEREO_FILTER, 1); + rt5663_sel_asrc_clk_src(codec_dai->codec, + RT5663_DA_STEREO_FILTER | RT5663_AD_STEREO_FILTER, + RT5663_CLK_SEL_I2S1_ASRC); + ret = snd_soc_dai_set_sysclk(codec_dai, + RT5663_SCLK_S_MCLK, 24576000, SND_SOC_CLOCK_IN); if (ret < 0) dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret); -- cgit v1.2.3 From 80b649039240ec41a6ab0a5e347853bc78abfd2d Mon Sep 17 00:00:00 2001 From: Harsha Priya N Date: Mon, 21 Aug 2017 12:26:52 -0700 Subject: ASoC: Intel: Headset button support in kabylake machine driver This patch adds headset button support for kabylake machine driver (kbl_rt5663_rt5514_max98927). Signed-off-by: Hsin-yu Chao Signed-off-by: Harsha Priya Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c index b51dff6fe25b..69681b04d7fc 100644 --- a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c @@ -18,6 +18,7 @@ * GNU General Public License for more details. */ +#include #include #include #include @@ -176,6 +177,7 @@ static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd) int ret; struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_jack *jack; /* * Headset buttons map to the google Reference headset. @@ -190,6 +192,12 @@ static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd) return ret; } + jack = &ctx->kabylake_headset; + snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_MEDIA); + snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); + snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); + snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); + rt5663_set_jack_detect(codec, &ctx->kabylake_headset); ret = snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "DMIC"); -- cgit v1.2.3 From 3b3011adada3bba47c56c205634e1b32512e0c7c Mon Sep 17 00:00:00 2001 From: "Subhransu S. Prusty" Date: Tue, 22 Aug 2017 16:45:50 +0530 Subject: ASoC: Intel: Skylake: Fix to free dsp resource on ipc_init failure For some dsp init error path, irq and few more resources are not freed. This results in oops. So, fix it by freeing up the resources on ipc_init failure. Signed-off-by: Subhransu S. Prusty Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/bxt-sst.c | 4 +++- sound/soc/intel/skylake/cnl-sst.c | 4 +++- sound/soc/intel/skylake/skl-sst.c | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c index 5e1ac99ffa8b..4524211960e4 100644 --- a/sound/soc/intel/skylake/bxt-sst.c +++ b/sound/soc/intel/skylake/bxt-sst.c @@ -582,8 +582,10 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, SKL_ADSP_W0_UP_SZ, BXT_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ); ret = skl_ipc_init(dev, skl); - if (ret) + if (ret) { + skl_dsp_free(sst); return ret; + } /* set the D0i3 check */ skl->ipc.ops.check_dsp_lp_on = skl_ipc_check_D0i0; diff --git a/sound/soc/intel/skylake/cnl-sst.c b/sound/soc/intel/skylake/cnl-sst.c index 48ef04d5da89..387de388ce29 100644 --- a/sound/soc/intel/skylake/cnl-sst.c +++ b/sound/soc/intel/skylake/cnl-sst.c @@ -450,8 +450,10 @@ int cnl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, CNL_ADSP_W1_SZ); ret = cnl_ipc_init(dev, cnl); - if (ret) + if (ret) { + skl_dsp_free(sst); return ret; + } cnl->boot_complete = false; init_waitqueue_head(&cnl->boot_wait); diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index a7ad734f591d..a436abf2fe3f 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c @@ -562,8 +562,10 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, SKL_ADSP_W0_UP_SZ, SKL_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ); ret = skl_ipc_init(dev, skl); - if (ret) + if (ret) { + skl_dsp_free(sst); return ret; + } sst->fw_ops = skl_fw_ops; -- cgit v1.2.3 From f77d443c4c299aff5ad9c74811dd063f4d8bebcf Mon Sep 17 00:00:00 2001 From: "Subhransu S. Prusty" Date: Tue, 22 Aug 2017 16:45:51 +0530 Subject: ASoC: Intel: Skylake: Fix to free resources for dsp_init failure unmap mmio and free memory resources if dsp_init fails. Signed-off-by: Subhransu S. Prusty Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-messages.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index bfb3332a77ca..f0f11f597b21 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -277,8 +277,10 @@ int skl_init_dsp(struct skl *skl) } ops = skl_get_dsp_ops(skl->pci->device); - if (!ops) - return -EIO; + if (!ops) { + goto unmap_mmio; + ret = -EIO; + } loader_ops = ops->loader_ops(); ret = ops->init(bus->dev, mmio_base, irq, @@ -286,25 +288,35 @@ int skl_init_dsp(struct skl *skl) &skl->skl_sst); if (ret < 0) - return ret; + goto unmap_mmio; skl->skl_sst->dsp_ops = ops; cores = &skl->skl_sst->cores; cores->count = ops->num_cores; cores->state = kcalloc(cores->count, sizeof(*cores->state), GFP_KERNEL); - if (!cores->state) - return -ENOMEM; + if (!cores->state) { + ret = -ENOMEM; + goto unmap_mmio; + } cores->usage_count = kcalloc(cores->count, sizeof(*cores->usage_count), GFP_KERNEL); if (!cores->usage_count) { - kfree(cores->state); - return -ENOMEM; + ret = -ENOMEM; + goto free_core_state; } dev_dbg(bus->dev, "dsp registration status=%d\n", ret); + return 0; + +free_core_state: + kfree(cores->state); + +unmap_mmio: + iounmap(mmio_base); + return ret; } -- cgit v1.2.3 From c360e0c3ab8ef8d0fd6b5501a407b9a2be4f204d Mon Sep 17 00:00:00 2001 From: "Subhransu S. Prusty" Date: Tue, 22 Aug 2017 16:45:52 +0530 Subject: ASoC: Intel: Skylake: Fix to free correct dev id in free_irq The dev_id passed by the driver in request_threaded_irq is an ebus pointer, whereas to free_irq it is hdac_bus. Fix by passing correct dev_id to free_irq. Signed-off-by: Subhransu S. Prusty Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index e612a4097275..d62ffbc93d54 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -415,7 +415,7 @@ static int skl_free(struct hdac_ext_bus *ebus) snd_hdac_ext_stop_streams(ebus); if (bus->irq >= 0) - free_irq(bus->irq, (void *)bus); + free_irq(bus->irq, (void *)ebus); snd_hdac_bus_free_stream_pages(bus); snd_hdac_stream_free_all(ebus); snd_hdac_link_free_all(ebus); -- cgit v1.2.3 From 7b992c24de78a206b3abd07192686d2d5db5012c Mon Sep 17 00:00:00 2001 From: "Subhransu S. Prusty" Date: Tue, 22 Aug 2017 16:45:53 +0530 Subject: ASoC: Intel: Skylake: Fix DSP core ref count for init failure During dsp init failure, the ref count is not incremented and dsp is powered down. But as the skl driver calls put_core for the init failure it decrements the dsp core ref count and ref count becomes unbalanced. This results in dsp core powered up in further runtime suspend/resume cycles and never powered down. So increment the ref count before dsp core powerup and for any failure, decrement in put_core will be balanced. Signed-off-by: Subhransu S. Prusty Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-sst-dsp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/skl-sst-dsp.c b/sound/soc/intel/skylake/skl-sst-dsp.c index c2ba5ff1632c..19ee1d4f3bdf 100644 --- a/sound/soc/intel/skylake/skl-sst-dsp.c +++ b/sound/soc/intel/skylake/skl-sst-dsp.c @@ -351,6 +351,8 @@ int skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id) return -EINVAL; } + skl->cores.usage_count[core_id]++; + if (skl->cores.state[core_id] == SKL_DSP_RESET) { ret = ctx->fw_ops.set_state_D0(ctx, core_id); if (ret < 0) { @@ -359,8 +361,6 @@ int skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id) } } - skl->cores.usage_count[core_id]++; - out: dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n", core_id, skl->cores.state[core_id], -- cgit v1.2.3 From 9149916f1e8c912c585ddebf12a98e99bd81aafe Mon Sep 17 00:00:00 2001 From: "Subhransu S. Prusty" Date: Wed, 23 Aug 2017 19:37:12 +0530 Subject: ASoC: Intel: Skylake: Fix uninitialized return On failure to get dsp_ops, dsp_init returns error without assigning ret. ret is assigned in code path which will never be executed. Fix it. Fixes: f77d443c4c29 ("ASoC: Intel: Skylake: Fix to free resources for dsp_init failure" Reported-by: kbuild test robot Signed-off-by: Subhransu S. Prusty Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-messages.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index f0f11f597b21..697d07bc1b5a 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -278,8 +278,8 @@ int skl_init_dsp(struct skl *skl) ops = skl_get_dsp_ops(skl->pci->device); if (!ops) { - goto unmap_mmio; ret = -EIO; + goto unmap_mmio; } loader_ops = ops->loader_ops(); -- cgit v1.2.3 From 9fc129f6e5de01ce5fccf033485e40dfa429b45c Mon Sep 17 00:00:00 2001 From: Shreyas NC Date: Wed, 23 Aug 2017 19:33:48 +0530 Subject: ASoC: Intel: Skylake: Parse multiple manifest data blocks Currently we can parse a single manifest data block. But manifest private data can have multiple data blocks. So, fix the parsing logic to parse multiple data blocks by returning offset of each parsed data block. Signed-off-by: Shreyas NC Signed-off-by: Guneshwor Singh Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-topology.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 350d2387f737..f14b373f65d7 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -2721,14 +2721,12 @@ static int skl_tplg_get_manifest_tkn(struct device *dev, tkn_count = tkn_count + ret; tkn_elem++; - tuple_size += tkn_count * - sizeof(struct snd_soc_tplg_vendor_value_elem); - break; } + tuple_size += (tkn_count * sizeof(*tkn_elem)); tkn_count = 0; } - return 0; + return off; } /* @@ -2751,11 +2749,10 @@ static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest, num_blocks = ret; off += array->size; - array = (struct snd_soc_tplg_vendor_array *) - (manifest->priv.data + off); - /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */ while (num_blocks > 0) { + array = (struct snd_soc_tplg_vendor_array *) + (manifest->priv.data + off); ret = skl_tplg_get_desc_blocks(dev, array); if (ret < 0) @@ -2789,6 +2786,7 @@ static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest, } else { return -EINVAL; } + off += ret; } return 0; -- cgit v1.2.3 From ca312fda690e94c704bcb0e21b73b5d5bd1cf1ff Mon Sep 17 00:00:00 2001 From: Shreyas NC Date: Wed, 23 Aug 2017 19:33:50 +0530 Subject: ASoC: Intel: Skylake: Commonize parsing of format tokens Format resource tokens can be a part of either the widget or manifest private data. In the current model, format resources come as a part of widget private data and they come as a part of topology manifest in the newly introduced model. So add a common function that can fill up either of the structures. Signed-off-by: Shreyas NC Signed-off-by: Guneshwor Singh Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-topology.c | 47 +++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 21 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index f14b373f65d7..df808fbf14b5 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -1948,27 +1948,9 @@ static int skl_tplg_fill_pins_info(struct device *dev, * on the direction */ static int skl_tplg_fill_fmt(struct device *dev, - struct skl_module_cfg *mconfig, u32 tkn, - u32 value, u32 dir, u32 pin_count) + struct skl_module_fmt *dst_fmt, + u32 tkn, u32 value) { - struct skl_module_fmt *dst_fmt; - - switch (dir) { - case SKL_DIR_IN: - dst_fmt = mconfig->in_fmt; - dst_fmt += pin_count; - break; - - case SKL_DIR_OUT: - dst_fmt = mconfig->out_fmt; - dst_fmt += pin_count; - break; - - default: - dev_err(dev, "Invalid direction value\n"); - return -EINVAL; - } - switch (tkn) { case SKL_TKN_U32_FMT_CH: dst_fmt->channels = value; @@ -2010,6 +1992,29 @@ static int skl_tplg_fill_fmt(struct device *dev, return 0; } +static int skl_tplg_widget_fill_fmt(struct device *dev, + struct skl_module_cfg *mconfig, + u32 tkn, u32 val, u32 dir, int fmt_idx) +{ + struct skl_module_fmt *dst_fmt; + + switch (dir) { + case SKL_DIR_IN: + dst_fmt = &mconfig->in_fmt[fmt_idx]; + break; + + case SKL_DIR_OUT: + dst_fmt = &mconfig->out_fmt[fmt_idx]; + break; + + default: + dev_err(dev, "Invalid direction: %d\n", dir); + return -EINVAL; + } + + return skl_tplg_fill_fmt(dev, dst_fmt, tkn, val); +} + static int skl_tplg_get_uuid(struct device *dev, struct skl_module_cfg *mconfig, struct snd_soc_tplg_vendor_uuid_elem *uuid_tkn) { @@ -2190,7 +2195,7 @@ static int skl_tplg_get_token(struct device *dev, case SKL_TKN_U32_FMT_INTERLEAVE: case SKL_TKN_U32_FMT_SAMPLE_TYPE: case SKL_TKN_U32_FMT_CH_MAP: - ret = skl_tplg_fill_fmt(dev, mconfig, tkn_elem->token, + ret = skl_tplg_widget_fill_fmt(dev, mconfig, tkn_elem->token, tkn_elem->value, dir, pin_index); if (ret < 0) -- cgit v1.2.3 From 822c3b044f7fbecc9894fcd3d19fc2ad51232fdb Mon Sep 17 00:00:00 2001 From: Shreyas NC Date: Wed, 23 Aug 2017 19:33:51 +0530 Subject: ASoC: Intel: Skylake: Add driver structures to be filled from topology manifest The topology manifest would include module common data including resource and interface table. The resource table consists of resources required by the dsp module such as buffer size, cycles per second, number of input/output pins. And, the interface table consists of pcm parameters per module which can be referenced later. So define the structures accordingly to represent topology manifest data in the driver. Signed-off-by: Shreyas NC Signed-off-by: Guneshwor Singh Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-topology.h | 52 ++++++++++++++++++++++++++++++++++ sound/soc/intel/skylake/skl.h | 2 ++ 2 files changed, 54 insertions(+) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index c25e8868b84e..93b2ba8c40f7 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -44,6 +44,13 @@ #define SKL_DEFAULT_MIC_SEL_GAIN 0x3FF #define SKL_MIC_SEL_SWITCH 0x3 +#define SKL_OUTPUT_PIN 0 +#define SKL_INPUT_PIN 1 +#define SKL_MAX_PATH_CONFIGS 8 +#define SKL_MAX_MODULES_IN_PIPE 8 +#define SKL_MAX_MODULE_FORMATS 32 +#define SKL_MAX_MODULE_RESOURCES 32 + enum skl_channel_index { SKL_CHANNEL_LEFT = 0, SKL_CHANNEL_RIGHT = 1, @@ -292,6 +299,51 @@ enum d0i3_capability { SKL_D0I3_NON_STREAMING = 2, }; +struct skl_module_pin_fmt { + u8 id; + struct skl_module_fmt fmt; +}; + +struct skl_module_iface { + u8 fmt_idx; + u8 nr_in_fmt; + u8 nr_out_fmt; + struct skl_module_pin_fmt inputs[MAX_IN_QUEUE]; + struct skl_module_pin_fmt outputs[MAX_OUT_QUEUE]; +}; + +struct skl_module_pin_resources { + u8 pin_index; + u32 buf_size; +}; + +struct skl_module_res { + u8 id; + u32 is_pages; + u32 cps; + u32 ibs; + u32 obs; + u32 dma_buffer_size; + u32 cpc; + u8 nr_input_pins; + u8 nr_output_pins; + struct skl_module_pin_resources input[MAX_IN_QUEUE]; + struct skl_module_pin_resources output[MAX_OUT_QUEUE]; +}; + +struct skl_module { + uuid_le uuid; + u8 loadable; + u8 input_pin_type; + u8 output_pin_type; + u8 max_input_pins; + u8 max_output_pins; + u8 nr_resources; + u8 nr_interfaces; + struct skl_module_res resources[SKL_MAX_MODULE_RESOURCES]; + struct skl_module_iface formats[SKL_MAX_MODULE_FORMATS]; +}; + struct skl_module_cfg { u8 guid[16]; struct skl_module_inst_id id; diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index 20017ee4685c..8d9d6899f761 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h @@ -71,6 +71,8 @@ struct skl { struct work_struct probe_work; struct skl_debug *debugfs; + u8 nr_modules; + struct skl_module **modules; }; #define skl_to_ebus(s) (&(s)->ebus) -- cgit v1.2.3 From db6ed55de6da1125ff349bfe4ef12d18c366e893 Mon Sep 17 00:00:00 2001 From: Shreyas NC Date: Wed, 23 Aug 2017 19:33:52 +0530 Subject: ASoC: Intel: Skylake: Populate module data from topology manifest All the module common data will now be populated in the topology manifest. This includes the resource and interface list supported by the module. With this, driver need not compute the resources required by each dsp module for a particular pcm parameter since it comes as a part of the topology manifest. So, add functions to parse the manifest tokens to populate the module config data structure. Signed-off-by: Shreyas NC Signed-off-by: Guneshwor Singh Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-topology.c | 320 ++++++++++++++++++++++++++++++++- 1 file changed, 316 insertions(+), 4 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index df808fbf14b5..f39883067f63 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -2037,6 +2037,104 @@ static void skl_tplg_fill_pin_dynamic_val( mpin[i].is_dynamic = value; } +/* + * Resource table in the manifest has pin specific resources + * like pin and pin buffer size + */ +static int skl_tplg_manifest_pin_res_tkn(struct device *dev, + struct snd_soc_tplg_vendor_value_elem *tkn_elem, + struct skl_module_res *res, int pin_idx, int dir) +{ + struct skl_module_pin_resources *m_pin; + + switch (dir) { + case SKL_DIR_IN: + m_pin = &res->input[pin_idx]; + break; + + case SKL_DIR_OUT: + m_pin = &res->output[pin_idx]; + break; + + default: + dev_err(dev, "Invalid pin direction: %d\n", dir); + return -EINVAL; + } + + switch (tkn_elem->token) { + case SKL_TKN_MM_U32_RES_PIN_ID: + m_pin->pin_index = tkn_elem->value; + break; + + case SKL_TKN_MM_U32_PIN_BUF: + m_pin->buf_size = tkn_elem->value; + break; + + default: + dev_err(dev, "Invalid token: %d\n", tkn_elem->token); + return -EINVAL; + } + + return 0; +} + +/* + * Fill module specific resources from the manifest's resource + * table like CPS, DMA size, mem_pages. + */ +static int skl_tplg_fill_res_tkn(struct device *dev, + struct snd_soc_tplg_vendor_value_elem *tkn_elem, + struct skl_module_res *res, + int pin_idx, int dir) +{ + int ret, tkn_count = 0; + + if (!res) + return -EINVAL; + + switch (tkn_elem->token) { + case SKL_TKN_MM_U32_CPS: + res->cps = tkn_elem->value; + break; + + case SKL_TKN_MM_U32_DMA_SIZE: + res->dma_buffer_size = tkn_elem->value; + break; + + case SKL_TKN_MM_U32_CPC: + res->cpc = tkn_elem->value; + break; + + case SKL_TKN_U32_MEM_PAGES: + res->is_pages = tkn_elem->value; + break; + + case SKL_TKN_U32_OBS: + res->obs = tkn_elem->value; + break; + + case SKL_TKN_U32_IBS: + res->ibs = tkn_elem->value; + break; + + case SKL_TKN_MM_U32_RES_PIN_ID: + case SKL_TKN_MM_U32_PIN_BUF: + ret = skl_tplg_manifest_pin_res_tkn(dev, tkn_elem, res, + pin_idx, dir); + if (ret < 0) + return ret; + break; + + default: + dev_err(dev, "Not a res type token: %d", tkn_elem->token); + return -EINVAL; + + } + tkn_count++; + + return tkn_count; +} + /* * Parse tokens to fill up the module private data */ @@ -2625,13 +2723,13 @@ static int skl_tplg_fill_str_mfest_tkn(struct device *dev, str_elem->string, ARRAY_SIZE(skl->skl_sst->lib_info[ref_count].name)); ref_count++; - tkn_count++; break; default: dev_err(dev, "Not a string token %d\n", str_elem->token); break; } + tkn_count++; return tkn_count; } @@ -2657,26 +2755,236 @@ static int skl_tplg_get_str_tkn(struct device *dev, return tkn_count; } +static int skl_tplg_manifest_fill_fmt(struct device *dev, + struct skl_module_iface *fmt, + struct snd_soc_tplg_vendor_value_elem *tkn_elem, + u32 dir, int fmt_idx) +{ + struct skl_module_pin_fmt *dst_fmt; + struct skl_module_fmt *mod_fmt; + int ret; + + if (!fmt) + return -EINVAL; + + switch (dir) { + case SKL_DIR_IN: + dst_fmt = &fmt->inputs[fmt_idx]; + break; + + case SKL_DIR_OUT: + dst_fmt = &fmt->outputs[fmt_idx]; + break; + + default: + dev_err(dev, "Invalid direction: %d\n", dir); + return -EINVAL; + } + + mod_fmt = &dst_fmt->fmt; + + switch (tkn_elem->token) { + case SKL_TKN_MM_U32_INTF_PIN_ID: + dst_fmt->id = tkn_elem->value; + break; + + default: + ret = skl_tplg_fill_fmt(dev, mod_fmt, tkn_elem->token, + tkn_elem->value); + if (ret < 0) + return ret; + break; + } + + return 0; +} + +static int skl_tplg_fill_mod_info(struct device *dev, + struct snd_soc_tplg_vendor_value_elem *tkn_elem, + struct skl_module *mod) +{ + + if (!mod) + return -EINVAL; + + switch (tkn_elem->token) { + case SKL_TKN_U8_IN_PIN_TYPE: + mod->input_pin_type = tkn_elem->value; + break; + + case SKL_TKN_U8_OUT_PIN_TYPE: + mod->output_pin_type = tkn_elem->value; + break; + + case SKL_TKN_U8_IN_QUEUE_COUNT: + mod->max_input_pins = tkn_elem->value; + break; + + case SKL_TKN_U8_OUT_QUEUE_COUNT: + mod->max_output_pins = tkn_elem->value; + break; + + case SKL_TKN_MM_U8_NUM_RES: + mod->nr_resources = tkn_elem->value; + break; + + case SKL_TKN_MM_U8_NUM_INTF: + mod->nr_interfaces = tkn_elem->value; + break; + + default: + dev_err(dev, "Invalid mod info token %d", tkn_elem->token); + return -EINVAL; + } + + return 0; +} + + static int skl_tplg_get_int_tkn(struct device *dev, struct snd_soc_tplg_vendor_value_elem *tkn_elem, struct skl *skl) { - int tkn_count = 0; + int tkn_count = 0, ret; + static int mod_idx, res_val_idx, intf_val_idx, dir, pin_idx; + struct skl_module_res *res = NULL; + struct skl_module_iface *fmt = NULL; + struct skl_module *mod = NULL; + int i; + + if (skl->modules) { + mod = skl->modules[mod_idx]; + res = &mod->resources[res_val_idx]; + fmt = &mod->formats[intf_val_idx]; + } switch (tkn_elem->token) { case SKL_TKN_U32_LIB_COUNT: skl->skl_sst->lib_count = tkn_elem->value; - tkn_count++; + break; + + case SKL_TKN_U8_NUM_MOD: + skl->nr_modules = tkn_elem->value; + skl->modules = devm_kcalloc(dev, skl->nr_modules, + sizeof(*skl->modules), GFP_KERNEL); + if (!skl->modules) + return -ENOMEM; + + for (i = 0; i < skl->nr_modules; i++) { + skl->modules[i] = devm_kzalloc(dev, + sizeof(struct skl_module), GFP_KERNEL); + if (!skl->modules[i]) + return -ENOMEM; + } + break; + + case SKL_TKN_MM_U8_MOD_IDX: + mod_idx = tkn_elem->value; + break; + + case SKL_TKN_U8_IN_PIN_TYPE: + case SKL_TKN_U8_OUT_PIN_TYPE: + case SKL_TKN_U8_IN_QUEUE_COUNT: + case SKL_TKN_U8_OUT_QUEUE_COUNT: + case SKL_TKN_MM_U8_NUM_RES: + case SKL_TKN_MM_U8_NUM_INTF: + ret = skl_tplg_fill_mod_info(dev, tkn_elem, mod); + if (ret < 0) + return ret; + break; + + case SKL_TKN_U32_DIR_PIN_COUNT: + dir = tkn_elem->value & SKL_IN_DIR_BIT_MASK; + pin_idx = (tkn_elem->value & SKL_PIN_COUNT_MASK) >> 4; + break; + + case SKL_TKN_MM_U32_RES_ID: + if (!res) + return -EINVAL; + + res->id = tkn_elem->value; + res_val_idx = tkn_elem->value; + break; + + case SKL_TKN_MM_U32_FMT_ID: + if (!fmt) + return -EINVAL; + + fmt->fmt_idx = tkn_elem->value; + intf_val_idx = tkn_elem->value; + break; + + case SKL_TKN_MM_U32_CPS: + case SKL_TKN_MM_U32_DMA_SIZE: + case SKL_TKN_MM_U32_CPC: + case SKL_TKN_U32_MEM_PAGES: + case SKL_TKN_U32_OBS: + case SKL_TKN_U32_IBS: + case SKL_TKN_MM_U32_RES_PIN_ID: + case SKL_TKN_MM_U32_PIN_BUF: + ret = skl_tplg_fill_res_tkn(dev, tkn_elem, res, pin_idx, dir); + if (ret < 0) + return ret; + + break; + + case SKL_TKN_MM_U32_NUM_IN_FMT: + if (!fmt) + return -EINVAL; + + res->nr_input_pins = tkn_elem->value; + break; + + case SKL_TKN_MM_U32_NUM_OUT_FMT: + if (!fmt) + return -EINVAL; + + res->nr_output_pins = tkn_elem->value; + break; + + case SKL_TKN_U32_FMT_CH: + case SKL_TKN_U32_FMT_FREQ: + case SKL_TKN_U32_FMT_BIT_DEPTH: + case SKL_TKN_U32_FMT_SAMPLE_SIZE: + case SKL_TKN_U32_FMT_CH_CONFIG: + case SKL_TKN_U32_FMT_INTERLEAVE: + case SKL_TKN_U32_FMT_SAMPLE_TYPE: + case SKL_TKN_U32_FMT_CH_MAP: + case SKL_TKN_MM_U32_INTF_PIN_ID: + ret = skl_tplg_manifest_fill_fmt(dev, fmt, tkn_elem, + dir, pin_idx); + if (ret < 0) + return ret; break; default: dev_err(dev, "Not a manifest token %d\n", tkn_elem->token); return -EINVAL; } + tkn_count++; return tkn_count; } +static int skl_tplg_get_manifest_uuid(struct device *dev, + struct skl *skl, + struct snd_soc_tplg_vendor_uuid_elem *uuid_tkn) +{ + static int ref_count; + struct skl_module *mod; + + if (uuid_tkn->token == SKL_TKN_UUID) { + mod = skl->modules[ref_count]; + memcpy(&mod->uuid, &uuid_tkn->uuid, sizeof(uuid_tkn->uuid)); + ref_count++; + } else { + dev_err(dev, "Not an UUID token tkn %d\n", uuid_tkn->token); + return -EINVAL; + } + + return 0; +} + /* * Fill the manifest structure by parsing the tokens based on the * type. @@ -2709,7 +3017,11 @@ static int skl_tplg_get_manifest_tkn(struct device *dev, continue; case SND_SOC_TPLG_TUPLE_TYPE_UUID: - dev_warn(dev, "no uuid tokens for skl tplf manifest\n"); + ret = skl_tplg_get_manifest_uuid(dev, skl, array->uuid); + if (ret < 0) + return ret; + + tuple_size += sizeof(*array->uuid); continue; default: -- cgit v1.2.3 From f6fa56e22559ade7287ca7c1b7218a08f516f379 Mon Sep 17 00:00:00 2001 From: Ramesh Babu Date: Wed, 23 Aug 2017 19:33:53 +0530 Subject: ASoC: Intel: Skylake: Parse and update module config structure A dsp path and the modules in the path can support various pcm configurations. The list of supported pcm configurations from topology manifest would be stored and later selected runtime based on the hw pcm params. For legacy, module data is filled in the 0th index of resource and interface table. To accommodate both models, change the relevant structures and populate them by parsing newly defined tokens. This change is backward compatible with the existing model where driver computes the resources required by each dsp module. Signed-off-by: Ramesh Babu Signed-off-by: Shreyas NC Signed-off-by: Guneshwor Singh Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-messages.c | 59 ++++-- sound/soc/intel/skylake/skl-pcm.c | 3 +- sound/soc/intel/skylake/skl-topology.c | 342 +++++++++++++++++++++++++-------- sound/soc/intel/skylake/skl-topology.h | 25 +++ 4 files changed, 334 insertions(+), 95 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index 697d07bc1b5a..ea83e8bfb136 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -443,9 +443,12 @@ static void skl_set_base_module_format(struct skl_sst *ctx, struct skl_module_cfg *mconfig, struct skl_base_cfg *base_cfg) { - struct skl_module_fmt *format = &mconfig->in_fmt[0]; + struct skl_module *module = mconfig->module; + struct skl_module_res *res = &module->resources[mconfig->res_idx]; + struct skl_module_iface *fmt = &module->formats[mconfig->fmt_idx]; + struct skl_module_fmt *format = &fmt->inputs[0].fmt; - base_cfg->audio_fmt.number_of_channels = (u8)format->channels; + base_cfg->audio_fmt.number_of_channels = format->channels; base_cfg->audio_fmt.s_freq = format->s_freq; base_cfg->audio_fmt.bit_depth = format->bit_depth; @@ -460,10 +463,10 @@ static void skl_set_base_module_format(struct skl_sst *ctx, base_cfg->audio_fmt.interleaving = format->interleaving_style; - base_cfg->cps = mconfig->mcps; - base_cfg->ibs = mconfig->ibs; - base_cfg->obs = mconfig->obs; - base_cfg->is_pages = mconfig->mem_pages; + base_cfg->cps = res->cps; + base_cfg->ibs = res->ibs; + base_cfg->obs = res->obs; + base_cfg->is_pages = res->is_pages; } /* @@ -551,6 +554,9 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, struct skl_cpr_cfg *cpr_mconfig) { u32 dma_io_buf; + struct skl_module_res *res; + int res_idx = mconfig->res_idx; + struct skl *skl = get_skl_ctx(ctx->dev); cpr_mconfig->gtw_cfg.node_id = skl_get_node_id(ctx, mconfig); @@ -559,19 +565,27 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, return; } + if (skl->nr_modules) { + res = &mconfig->module->resources[mconfig->res_idx]; + cpr_mconfig->gtw_cfg.dma_buffer_size = res->dma_buffer_size; + goto skip_buf_size_calc; + } else { + res = &mconfig->module->resources[res_idx]; + } + switch (mconfig->hw_conn_type) { case SKL_CONN_SOURCE: if (mconfig->dev_type == SKL_DEVICE_HDAHOST) - dma_io_buf = mconfig->ibs; + dma_io_buf = res->ibs; else - dma_io_buf = mconfig->obs; + dma_io_buf = res->obs; break; case SKL_CONN_SINK: if (mconfig->dev_type == SKL_DEVICE_HDAHOST) - dma_io_buf = mconfig->obs; + dma_io_buf = res->obs; else - dma_io_buf = mconfig->ibs; + dma_io_buf = res->ibs; break; default: @@ -586,11 +600,12 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, /* fallback to 2ms default value */ if (!cpr_mconfig->gtw_cfg.dma_buffer_size) { if (mconfig->hw_conn_type == SKL_CONN_SOURCE) - cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->obs; + cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * res->obs; else - cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->ibs; + cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * res->ibs; } +skip_buf_size_calc: cpr_mconfig->cpr_feature_mask = 0; cpr_mconfig->gtw_cfg.config_length = 0; @@ -638,7 +653,9 @@ static void skl_setup_out_format(struct skl_sst *ctx, struct skl_module_cfg *mconfig, struct skl_audio_data_format *out_fmt) { - struct skl_module_fmt *format = &mconfig->out_fmt[0]; + struct skl_module *module = mconfig->module; + struct skl_module_iface *fmt = &module->formats[mconfig->fmt_idx]; + struct skl_module_fmt *format = &fmt->outputs[0].fmt; out_fmt->number_of_channels = (u8)format->channels; out_fmt->s_freq = format->s_freq; @@ -663,7 +680,9 @@ static void skl_set_src_format(struct skl_sst *ctx, struct skl_module_cfg *mconfig, struct skl_src_module_cfg *src_mconfig) { - struct skl_module_fmt *fmt = &mconfig->out_fmt[0]; + struct skl_module *module = mconfig->module; + struct skl_module_iface *iface = &module->formats[mconfig->fmt_idx]; + struct skl_module_fmt *fmt = &iface->outputs[0].fmt; skl_set_base_module_format(ctx, mconfig, (struct skl_base_cfg *)src_mconfig); @@ -680,7 +699,9 @@ static void skl_set_updown_mixer_format(struct skl_sst *ctx, struct skl_module_cfg *mconfig, struct skl_up_down_mixer_cfg *mixer_mconfig) { - struct skl_module_fmt *fmt = &mconfig->out_fmt[0]; + struct skl_module *module = mconfig->module; + struct skl_module_iface *iface = &module->formats[mconfig->fmt_idx]; + struct skl_module_fmt *fmt = &iface->outputs[0].fmt; int i = 0; skl_set_base_module_format(ctx, mconfig, @@ -1013,8 +1034,8 @@ int skl_unbind_modules(struct skl_sst *ctx, struct skl_ipc_bind_unbind_msg msg; struct skl_module_inst_id src_id = src_mcfg->id; struct skl_module_inst_id dst_id = dst_mcfg->id; - int in_max = dst_mcfg->max_in_queue; - int out_max = src_mcfg->max_out_queue; + int in_max = dst_mcfg->module->max_input_pins; + int out_max = src_mcfg->module->max_output_pins; int src_index, dst_index, src_pin_state, dst_pin_state; skl_dump_bind_info(ctx, src_mcfg, dst_mcfg); @@ -1075,8 +1096,8 @@ int skl_bind_modules(struct skl_sst *ctx, { int ret; struct skl_ipc_bind_unbind_msg msg; - int in_max = dst_mcfg->max_in_queue; - int out_max = src_mcfg->max_out_queue; + int in_max = dst_mcfg->module->max_input_pins; + int out_max = src_mcfg->module->max_output_pins; int src_index, dst_index; skl_dump_bind_info(ctx, src_mcfg, dst_mcfg); diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index f6c9adb6faa2..a756882b9029 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -1233,7 +1233,8 @@ static int skl_get_module_info(struct skl *skl, struct skl_module_cfg *mconfig) list_for_each_entry(module, &ctx->uuid_list, list) { if (uuid_le_cmp(*uuid_mod, module->uuid) == 0) { mconfig->id.module_id = module->id; - mconfig->is_loadable = module->is_loadable; + if (mconfig->module) + mconfig->module->loadable = module->is_loadable; return 0; } } diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index f39883067f63..22f768ca3c73 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -49,6 +49,9 @@ static const int mic_quatro_list[][SKL_CH_QUATRO] = { {0, 1, 2, 3}, }; +#define CHECK_HW_PARAMS(ch, freq, bps, prm_ch, prm_freq, prm_bps) \ + ((ch == prm_ch) && (bps == prm_bps) && (freq == prm_freq)) + void skl_tplg_d0i3_get(struct skl *skl, enum d0i3_capability caps) { struct skl_d0i3_data *d0i3 = &skl->skl_sst->d0i3; @@ -153,8 +156,10 @@ static bool skl_is_pipe_mcps_avail(struct skl *skl, struct skl_module_cfg *mconfig) { struct skl_sst *ctx = skl->skl_sst; + u8 res_idx = mconfig->res_idx; + struct skl_module_res *res = &mconfig->module->resources[res_idx]; - if (skl->resource.mcps + mconfig->mcps > skl->resource.max_mcps) { + if (skl->resource.mcps + res->cps > skl->resource.max_mcps) { dev_err(ctx->dev, "%s: module_id %d instance %d\n", __func__, mconfig->id.module_id, mconfig->id.instance_id); @@ -170,7 +175,10 @@ static bool skl_is_pipe_mcps_avail(struct skl *skl, static void skl_tplg_alloc_pipe_mcps(struct skl *skl, struct skl_module_cfg *mconfig) { - skl->resource.mcps += mconfig->mcps; + u8 res_idx = mconfig->res_idx; + struct skl_module_res *res = &mconfig->module->resources[res_idx]; + + skl->resource.mcps += res->cps; } /* @@ -179,7 +187,11 @@ static void skl_tplg_alloc_pipe_mcps(struct skl *skl, static void skl_tplg_free_pipe_mcps(struct skl *skl, struct skl_module_cfg *mconfig) { - skl->resource.mcps -= mconfig->mcps; + u8 res_idx = mconfig->res_idx; + struct skl_module_res *res = &mconfig->module->resources[res_idx]; + + res = &mconfig->module->resources[res_idx]; + skl->resource.mcps -= res->cps; } /* @@ -195,17 +207,21 @@ skl_tplg_free_pipe_mem(struct skl *skl, struct skl_module_cfg *mconfig) static void skl_dump_mconfig(struct skl_sst *ctx, struct skl_module_cfg *mcfg) { + struct skl_module_iface *iface = &mcfg->module->formats[0]; + dev_dbg(ctx->dev, "Dumping config\n"); dev_dbg(ctx->dev, "Input Format:\n"); - dev_dbg(ctx->dev, "channels = %d\n", mcfg->in_fmt[0].channels); - dev_dbg(ctx->dev, "s_freq = %d\n", mcfg->in_fmt[0].s_freq); - dev_dbg(ctx->dev, "ch_cfg = %d\n", mcfg->in_fmt[0].ch_cfg); - dev_dbg(ctx->dev, "valid bit depth = %d\n", mcfg->in_fmt[0].valid_bit_depth); + dev_dbg(ctx->dev, "channels = %d\n", iface->inputs[0].fmt.channels); + dev_dbg(ctx->dev, "s_freq = %d\n", iface->inputs[0].fmt.s_freq); + dev_dbg(ctx->dev, "ch_cfg = %d\n", iface->inputs[0].fmt.ch_cfg); + dev_dbg(ctx->dev, "valid bit depth = %d\n", + iface->inputs[0].fmt.valid_bit_depth); dev_dbg(ctx->dev, "Output Format:\n"); - dev_dbg(ctx->dev, "channels = %d\n", mcfg->out_fmt[0].channels); - dev_dbg(ctx->dev, "s_freq = %d\n", mcfg->out_fmt[0].s_freq); - dev_dbg(ctx->dev, "valid bit depth = %d\n", mcfg->out_fmt[0].valid_bit_depth); - dev_dbg(ctx->dev, "ch_cfg = %d\n", mcfg->out_fmt[0].ch_cfg); + dev_dbg(ctx->dev, "channels = %d\n", iface->outputs[0].fmt.channels); + dev_dbg(ctx->dev, "s_freq = %d\n", iface->outputs[0].fmt.s_freq); + dev_dbg(ctx->dev, "valid bit depth = %d\n", + iface->outputs[0].fmt.valid_bit_depth); + dev_dbg(ctx->dev, "ch_cfg = %d\n", iface->outputs[0].fmt.ch_cfg); } static void skl_tplg_update_chmap(struct skl_module_fmt *fmt, int chs) @@ -273,8 +289,8 @@ static void skl_tplg_update_params_fixup(struct skl_module_cfg *m_cfg, struct skl_module_fmt *in_fmt, *out_fmt; /* Fixups will be applied to pin 0 only */ - in_fmt = &m_cfg->in_fmt[0]; - out_fmt = &m_cfg->out_fmt[0]; + in_fmt = &m_cfg->module->formats[0].inputs[0].fmt; + out_fmt = &m_cfg->module->formats[0].outputs[0].fmt; if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (is_fe) { @@ -312,21 +328,23 @@ static void skl_tplg_update_buffer_size(struct skl_sst *ctx, { int multiplier = 1; struct skl_module_fmt *in_fmt, *out_fmt; + struct skl_module_res *res; /* Since fixups is applied to pin 0 only, ibs, obs needs * change for pin 0 only */ - in_fmt = &mcfg->in_fmt[0]; - out_fmt = &mcfg->out_fmt[0]; + res = &mcfg->module->resources[0]; + in_fmt = &mcfg->module->formats[0].inputs[0].fmt; + out_fmt = &mcfg->module->formats[0].outputs[0].fmt; if (mcfg->m_type == SKL_MODULE_TYPE_SRCINT) multiplier = 5; - mcfg->ibs = DIV_ROUND_UP(in_fmt->s_freq, 1000) * + res->ibs = DIV_ROUND_UP(in_fmt->s_freq, 1000) * in_fmt->channels * (in_fmt->bit_depth >> 3) * multiplier; - mcfg->obs = DIV_ROUND_UP(out_fmt->s_freq, 1000) * + res->obs = DIV_ROUND_UP(out_fmt->s_freq, 1000) * out_fmt->channels * (out_fmt->bit_depth >> 3) * multiplier; } @@ -365,6 +383,8 @@ static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w, struct nhlt_specific_cfg *cfg; struct skl *skl = get_skl_ctx(ctx->dev); u8 dev_type = skl_tplg_be_dev_type(m_cfg->dev_type); + int fmt_idx = m_cfg->fmt_idx; + struct skl_module_iface *m_iface = &m_cfg->module->formats[fmt_idx]; /* check if we already have blob */ if (m_cfg->formats_config.caps_size > 0) @@ -375,23 +395,23 @@ static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w, case SKL_DEVICE_DMIC: link_type = NHLT_LINK_DMIC; dir = SNDRV_PCM_STREAM_CAPTURE; - s_freq = m_cfg->in_fmt[0].s_freq; - s_fmt = m_cfg->in_fmt[0].bit_depth; - ch = m_cfg->in_fmt[0].channels; + s_freq = m_iface->inputs[0].fmt.s_freq; + s_fmt = m_iface->inputs[0].fmt.bit_depth; + ch = m_iface->inputs[0].fmt.channels; break; case SKL_DEVICE_I2S: link_type = NHLT_LINK_SSP; if (m_cfg->hw_conn_type == SKL_CONN_SOURCE) { dir = SNDRV_PCM_STREAM_PLAYBACK; - s_freq = m_cfg->out_fmt[0].s_freq; - s_fmt = m_cfg->out_fmt[0].bit_depth; - ch = m_cfg->out_fmt[0].channels; + s_freq = m_iface->outputs[0].fmt.s_freq; + s_fmt = m_iface->outputs[0].fmt.bit_depth; + ch = m_iface->outputs[0].fmt.channels; } else { dir = SNDRV_PCM_STREAM_CAPTURE; - s_freq = m_cfg->in_fmt[0].s_freq; - s_fmt = m_cfg->in_fmt[0].bit_depth; - ch = m_cfg->in_fmt[0].channels; + s_freq = m_iface->inputs[0].fmt.s_freq; + s_fmt = m_iface->inputs[0].fmt.bit_depth; + ch = m_iface->inputs[0].fmt.channels; } break; @@ -549,6 +569,7 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) struct snd_soc_dapm_widget *w; struct skl_module_cfg *mconfig; struct skl_sst *ctx = skl->skl_sst; + u8 cfg_idx; int ret = 0; list_for_each_entry(w_module, &pipe->w_list, node) { @@ -564,11 +585,15 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) return -EIO; } + cfg_idx = mconfig->pipe->cur_config_idx; + mconfig->fmt_idx = mconfig->mod_cfg[cfg_idx].fmt_idx; + mconfig->res_idx = mconfig->mod_cfg[cfg_idx].res_idx; + /* check resource available */ if (!skl_is_pipe_mcps_avail(skl, mconfig)) return -ENOMEM; - if (mconfig->is_loadable && ctx->dsp->fw_ops.load_mod) { + if (mconfig->module->loadable && ctx->dsp->fw_ops.load_mod) { ret = ctx->dsp->fw_ops.load_mod(ctx->dsp, mconfig->id.module_id, mconfig->guid); if (ret < 0) @@ -633,7 +658,7 @@ static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx, mconfig = w_module->w->priv; uuid_mod = (uuid_le *)mconfig->guid; - if (mconfig->is_loadable && ctx->dsp->fw_ops.unload_mod && + if (mconfig->module->loadable && ctx->dsp->fw_ops.unload_mod && mconfig->m_state > SKL_MODULE_UNINIT) { ret = ctx->dsp->fw_ops.unload_mod(ctx->dsp, mconfig->id.module_id); @@ -654,6 +679,65 @@ static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx, return ret; } +/* + * Here, we select pipe format based on the pipe type and pipe + * direction to determine the current config index for the pipeline. + * The config index is then used to select proper module resources. + * Intermediate pipes currently have a fixed format hence we select the + * 0th configuratation by default for such pipes. + */ +static int +skl_tplg_get_pipe_config(struct skl *skl, struct skl_module_cfg *mconfig) +{ + struct skl_sst *ctx = skl->skl_sst; + struct skl_pipe *pipe = mconfig->pipe; + struct skl_pipe_params *params = pipe->p_params; + struct skl_path_config *pconfig = &pipe->configs[0]; + struct skl_pipe_fmt *fmt = NULL; + bool in_fmt = false; + int i; + + if (pipe->nr_cfgs == 0) { + pipe->cur_config_idx = 0; + return 0; + } + + if (pipe->conn_type == SKL_PIPE_CONN_TYPE_NONE) { + dev_dbg(ctx->dev, "No conn_type detected, take 0th config\n"); + pipe->cur_config_idx = 0; + pipe->memory_pages = pconfig->mem_pages; + + return 0; + } + + if ((pipe->conn_type == SKL_PIPE_CONN_TYPE_FE && + pipe->direction == SNDRV_PCM_STREAM_PLAYBACK) || + (pipe->conn_type == SKL_PIPE_CONN_TYPE_BE && + pipe->direction == SNDRV_PCM_STREAM_CAPTURE)) + in_fmt = true; + + for (i = 0; i < pipe->nr_cfgs; i++) { + pconfig = &pipe->configs[i]; + if (in_fmt) + fmt = &pconfig->in_fmt; + else + fmt = &pconfig->out_fmt; + + if (CHECK_HW_PARAMS(params->ch, params->s_freq, params->s_fmt, + fmt->channels, fmt->freq, fmt->bps)) { + pipe->cur_config_idx = i; + pipe->memory_pages = pconfig->mem_pages; + dev_dbg(ctx->dev, "Using pipe config: %d\n", i); + + return 0; + } + } + + dev_err(ctx->dev, "Invalid pipe config: %d %d %d for pipe: %d\n", + params->ch, params->s_freq, params->s_fmt, pipe->ppl_id); + return -EINVAL; +} + /* * Mixer module represents a pipeline. So in the Pre-PMU event of mixer we * need create the pipeline. So we do following: @@ -673,6 +757,10 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, struct skl_sst *ctx = skl->skl_sst; struct skl_module_deferred_bind *modules; + ret = skl_tplg_get_pipe_config(skl, mconfig); + if (ret < 0) + return ret; + /* check resource available */ if (!skl_is_pipe_mcps_avail(skl, mconfig)) return -EBUSY; @@ -776,12 +864,12 @@ static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w, * check all out/in pins are in bind state. * if so set the module param */ - for (i = 0; i < mcfg->max_out_queue; i++) { + for (i = 0; i < mcfg->module->max_output_pins; i++) { if (mcfg->m_out_pin[i].pin_state != SKL_PIN_BIND_DONE) return 0; } - for (i = 0; i < mcfg->max_in_queue; i++) { + for (i = 0; i < mcfg->module->max_input_pins; i++) { if (mcfg->m_in_pin[i].pin_state != SKL_PIN_BIND_DONE) return 0; } @@ -832,7 +920,7 @@ static int skl_tplg_module_add_deferred_bind(struct skl *skl, int i; /* only supported for module with static pin connection */ - for (i = 0; i < dst->max_in_queue; i++) { + for (i = 0; i < dst->module->max_input_pins; i++) { struct skl_module_pin *pin = &dst->m_in_pin[i]; if (pin->is_dynamic) @@ -1092,7 +1180,7 @@ static int skl_tplg_mixer_dapm_pre_pmd_event(struct snd_soc_dapm_widget *w, if (ret) return ret; - for (i = 0; i < sink_mconfig->max_in_queue; i++) { + for (i = 0; i < sink_mconfig->module->max_input_pins; i++) { if (sink_mconfig->m_in_pin[i].pin_state == SKL_PIN_BIND_DONE) { src_mconfig = sink_mconfig->m_in_pin[i].tgt_mcfg; if (!src_mconfig) @@ -1203,7 +1291,7 @@ static int skl_tplg_pga_dapm_post_pmd_event(struct snd_soc_dapm_widget *w, if (ret) return ret; - for (i = 0; i < src_mconfig->max_out_queue; i++) { + for (i = 0; i < src_mconfig->module->max_output_pins; i++) { if (src_mconfig->m_out_pin[i].pin_state == SKL_PIN_BIND_DONE) { sink_mconfig = src_mconfig->m_out_pin[i].tgt_mcfg; if (!sink_mconfig) @@ -1497,14 +1585,22 @@ int skl_tplg_update_pipe_params(struct device *dev, struct skl_module_cfg *mconfig, struct skl_pipe_params *params) { + struct skl_module_res *res = &mconfig->module->resources[0]; + struct skl *skl = get_skl_ctx(dev); struct skl_module_fmt *format = NULL; + u8 cfg_idx = mconfig->pipe->cur_config_idx; skl_tplg_fill_dma_id(mconfig, params); + mconfig->fmt_idx = mconfig->mod_cfg[cfg_idx].fmt_idx; + mconfig->res_idx = mconfig->mod_cfg[cfg_idx].res_idx; + + if (skl->nr_modules) + return 0; if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) - format = &mconfig->in_fmt[0]; + format = &mconfig->module->formats[0].inputs[0].fmt; else - format = &mconfig->out_fmt[0]; + format = &mconfig->module->formats[0].outputs[0].fmt; /* set the hw_params */ format->s_freq = params->s_freq; @@ -1532,11 +1628,11 @@ int skl_tplg_update_pipe_params(struct device *dev, } if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) { - mconfig->ibs = (format->s_freq / 1000) * + res->ibs = (format->s_freq / 1000) * (format->channels) * (format->bit_depth >> 3); } else { - mconfig->obs = (format->s_freq / 1000) * + res->obs = (format->s_freq / 1000) * (format->channels) * (format->bit_depth >> 3); } @@ -1810,6 +1906,54 @@ static const struct snd_soc_tplg_kcontrol_ops skl_tplg_kcontrol_ops[] = { }, }; +static int skl_tplg_fill_pipe_cfg(struct device *dev, + struct skl_pipe *pipe, u32 tkn, + u32 tkn_val, int conf_idx, int dir) +{ + struct skl_pipe_fmt *fmt; + struct skl_path_config *config; + + switch (dir) { + case SKL_DIR_IN: + fmt = &pipe->configs[conf_idx].in_fmt; + break; + + case SKL_DIR_OUT: + fmt = &pipe->configs[conf_idx].out_fmt; + break; + + default: + dev_err(dev, "Invalid direction: %d\n", dir); + return -EINVAL; + } + + config = &pipe->configs[conf_idx]; + + switch (tkn) { + case SKL_TKN_U32_CFG_FREQ: + fmt->freq = tkn_val; + break; + + case SKL_TKN_U8_CFG_CHAN: + fmt->channels = tkn_val; + break; + + case SKL_TKN_U8_CFG_BPS: + fmt->bps = tkn_val; + break; + + case SKL_TKN_U32_PATH_MEM_PGS: + config->mem_pages = tkn_val; + break; + + default: + dev_err(dev, "Invalid token config: %d\n", tkn); + return -EINVAL; + } + + return 0; +} + static int skl_tplg_fill_pipe_tkn(struct device *dev, struct skl_pipe *pipe, u32 tkn, u32 tkn_val) @@ -1832,6 +1976,14 @@ static int skl_tplg_fill_pipe_tkn(struct device *dev, pipe->lp_mode = tkn_val; break; + case SKL_TKN_U32_PIPE_DIRECTION: + pipe->direction = tkn_val; + break; + + case SKL_TKN_U32_NUM_CONFIGS: + pipe->nr_cfgs = tkn_val; + break; + default: dev_err(dev, "Token not handled %d\n", tkn); return -EINVAL; @@ -1993,18 +2145,21 @@ static int skl_tplg_fill_fmt(struct device *dev, } static int skl_tplg_widget_fill_fmt(struct device *dev, - struct skl_module_cfg *mconfig, + struct skl_module_iface *fmt, u32 tkn, u32 val, u32 dir, int fmt_idx) { struct skl_module_fmt *dst_fmt; + if (!fmt) + return -EINVAL; + switch (dir) { case SKL_DIR_IN: - dst_fmt = &mconfig->in_fmt[fmt_idx]; + dst_fmt = &fmt->inputs[fmt_idx].fmt; break; case SKL_DIR_OUT: - dst_fmt = &mconfig->out_fmt[fmt_idx]; + dst_fmt = &fmt->outputs[fmt_idx].fmt; break; default: @@ -2117,6 +2272,10 @@ static int skl_tplg_fill_res_tkn(struct device *dev, res->ibs = tkn_elem->value; break; + case SKL_TKN_U32_MAX_MCPS: + res->cps = tkn_elem->value; + break; + case SKL_TKN_MM_U32_RES_PIN_ID: case SKL_TKN_MM_U32_PIN_BUF: ret = skl_tplg_manifest_pin_res_tkn(dev, tkn_elem, res, @@ -2145,49 +2304,54 @@ static int skl_tplg_get_token(struct device *dev, int tkn_count = 0; int ret; static int is_pipe_exists; - static int pin_index, dir; + static int pin_index, dir, conf_idx; + struct skl_module_iface *iface = NULL; + struct skl_module_res *res = NULL; + int res_idx = mconfig->res_idx; + int fmt_idx = mconfig->fmt_idx; + + /* + * If the manifest structure contains no modules, fill all + * the module data to 0th index. + * res_idx and fmt_idx are default set to 0. + */ + if (skl->nr_modules == 0) { + res = &mconfig->module->resources[res_idx]; + iface = &mconfig->module->formats[fmt_idx]; + } if (tkn_elem->token > SKL_TKN_MAX) return -EINVAL; switch (tkn_elem->token) { case SKL_TKN_U8_IN_QUEUE_COUNT: - mconfig->max_in_queue = tkn_elem->value; - mconfig->m_in_pin = devm_kzalloc(dev, mconfig->max_in_queue * - sizeof(*mconfig->m_in_pin), - GFP_KERNEL); - if (!mconfig->m_in_pin) - return -ENOMEM; - + mconfig->module->max_input_pins = tkn_elem->value; break; case SKL_TKN_U8_OUT_QUEUE_COUNT: - mconfig->max_out_queue = tkn_elem->value; - mconfig->m_out_pin = devm_kzalloc(dev, mconfig->max_out_queue * - sizeof(*mconfig->m_out_pin), - GFP_KERNEL); - - if (!mconfig->m_out_pin) - return -ENOMEM; - + mconfig->module->max_output_pins = tkn_elem->value; break; case SKL_TKN_U8_DYN_IN_PIN: + if (!mconfig->m_in_pin) + mconfig->m_in_pin = devm_kzalloc(dev, MAX_IN_QUEUE * + sizeof(*mconfig->m_in_pin), GFP_KERNEL); if (!mconfig->m_in_pin) return -ENOMEM; - skl_tplg_fill_pin_dynamic_val(mconfig->m_in_pin, - mconfig->max_in_queue, tkn_elem->value); - + skl_tplg_fill_pin_dynamic_val(mconfig->m_in_pin, MAX_IN_QUEUE, + tkn_elem->value); break; case SKL_TKN_U8_DYN_OUT_PIN: + if (!mconfig->m_out_pin) + mconfig->m_out_pin = devm_kzalloc(dev, MAX_IN_QUEUE * + sizeof(*mconfig->m_in_pin), GFP_KERNEL); if (!mconfig->m_out_pin) return -ENOMEM; - skl_tplg_fill_pin_dynamic_val(mconfig->m_out_pin, - mconfig->max_out_queue, tkn_elem->value); - + skl_tplg_fill_pin_dynamic_val(mconfig->m_out_pin, MAX_OUT_QUEUE, + tkn_elem->value); break; case SKL_TKN_U8_TIME_SLOT: @@ -2215,19 +2379,13 @@ static int skl_tplg_get_token(struct device *dev, break; case SKL_TKN_U32_MEM_PAGES: - mconfig->mem_pages = tkn_elem->value; - break; - case SKL_TKN_U32_MAX_MCPS: - mconfig->mcps = tkn_elem->value; - break; - case SKL_TKN_U32_OBS: - mconfig->obs = tkn_elem->value; - break; - case SKL_TKN_U32_IBS: - mconfig->ibs = tkn_elem->value; + ret = skl_tplg_fill_res_tkn(dev, tkn_elem, res, dir, pin_index); + if (ret < 0) + return ret; + break; case SKL_TKN_U32_VBUS_ID: @@ -2260,10 +2418,16 @@ static int skl_tplg_get_token(struct device *dev, break; + case SKL_TKN_U32_PIPE_CONFIG_ID: + conf_idx = tkn_elem->value; + break; + case SKL_TKN_U32_PIPE_CONN_TYPE: case SKL_TKN_U32_PIPE_PRIORITY: case SKL_TKN_U32_PIPE_MEM_PGS: case SKL_TKN_U32_PMODE: + case SKL_TKN_U32_PIPE_DIRECTION: + case SKL_TKN_U32_NUM_CONFIGS: if (is_pipe_exists) { ret = skl_tplg_fill_pipe_tkn(dev, mconfig->pipe, tkn_elem->token, tkn_elem->value); @@ -2273,6 +2437,27 @@ static int skl_tplg_get_token(struct device *dev, break; + case SKL_TKN_U32_PATH_MEM_PGS: + case SKL_TKN_U32_CFG_FREQ: + case SKL_TKN_U8_CFG_CHAN: + case SKL_TKN_U8_CFG_BPS: + if (mconfig->pipe->nr_cfgs) { + ret = skl_tplg_fill_pipe_cfg(dev, mconfig->pipe, + tkn_elem->token, tkn_elem->value, + conf_idx, dir); + if (ret < 0) + return ret; + } + break; + + case SKL_TKN_CFG_MOD_RES_ID: + mconfig->mod_cfg[conf_idx].res_idx = tkn_elem->value; + break; + + case SKL_TKN_CFG_MOD_FMT_ID: + mconfig->mod_cfg[conf_idx].fmt_idx = tkn_elem->value; + break; + /* * SKL_TKN_U32_DIR_PIN_COUNT token has the value for both * direction and the pin count. The first four bits represent @@ -2293,7 +2478,7 @@ static int skl_tplg_get_token(struct device *dev, case SKL_TKN_U32_FMT_INTERLEAVE: case SKL_TKN_U32_FMT_SAMPLE_TYPE: case SKL_TKN_U32_FMT_CH_MAP: - ret = skl_tplg_widget_fill_fmt(dev, mconfig, tkn_elem->token, + ret = skl_tplg_widget_fill_fmt(dev, iface, tkn_elem->token, tkn_elem->value, dir, pin_index); if (ret < 0) @@ -2518,11 +2703,11 @@ static void skl_clear_pin_config(struct snd_soc_platform *platform, strlen(platform->component.name))) { mconfig = w->priv; pipe = mconfig->pipe; - for (i = 0; i < mconfig->max_in_queue; i++) { + for (i = 0; i < mconfig->module->max_input_pins; i++) { mconfig->m_in_pin[i].in_use = false; mconfig->m_in_pin[i].pin_state = SKL_PIN_UNBIND; } - for (i = 0; i < mconfig->max_out_queue; i++) { + for (i = 0; i < mconfig->module->max_output_pins; i++) { mconfig->m_out_pin[i].in_use = false; mconfig->m_out_pin[i].pin_state = SKL_PIN_UNBIND; } @@ -2581,6 +2766,13 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, if (!mconfig) return -ENOMEM; + if (skl->nr_modules == 0) { + mconfig->module = devm_kzalloc(bus->dev, + sizeof(*mconfig->module), GFP_KERNEL); + if (!mconfig->module) + return -ENOMEM; + } + w->priv = mconfig; /* diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index 93b2ba8c40f7..90903a15fa1d 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -273,6 +273,23 @@ struct skl_pipe_params { unsigned int link_bps; }; +struct skl_pipe_fmt { + u32 freq; + u8 channels; + u8 bps; +}; + +struct skl_pipe_mcfg { + u8 res_idx; + u8 fmt_idx; +}; + +struct skl_path_config { + u8 mem_pages; + struct skl_pipe_fmt in_fmt; + struct skl_pipe_fmt out_fmt; +}; + struct skl_pipe { u8 ppl_id; u8 pipe_priority; @@ -281,6 +298,10 @@ struct skl_pipe { u8 lp_mode; struct skl_pipe_params *p_params; enum skl_pipe_state state; + u8 direction; + u8 cur_config_idx; + u8 nr_cfgs; + struct skl_path_config configs[SKL_MAX_PATH_CONFIGS]; struct list_head w_list; bool passthru; }; @@ -347,6 +368,9 @@ struct skl_module { struct skl_module_cfg { u8 guid[16]; struct skl_module_inst_id id; + struct skl_module *module; + int res_idx; + int fmt_idx; u8 domain; bool homogenous_inputs; bool homogenous_outputs; @@ -381,6 +405,7 @@ struct skl_module_cfg { enum skl_module_state m_state; struct skl_pipe *pipe; struct skl_specific_cfg formats_config; + struct skl_pipe_mcfg mod_cfg[SKL_MAX_MODULES_IN_PIPE]; }; struct skl_algo_data { -- cgit v1.2.3 From 91fe0e70dbfb1142e17cebaa9186794b51a28cf7 Mon Sep 17 00:00:00 2001 From: Jeeja KP Date: Wed, 23 Aug 2017 19:33:54 +0530 Subject: ASoC: Intel: Skylake: Update module id in pin connections Each module's id comes from the topology and gets updated in the driver. This patch updates the input and output pin connections of each module by matching the uuid for each module. Signed-off-by: Jeeja KP Signed-off-by: Guneshwor Singh Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-pcm.c | 41 +++++++++++++++++++++++++++++++--- sound/soc/intel/skylake/skl-topology.h | 1 + 2 files changed, 39 insertions(+), 3 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index a756882b9029..2b1e513b1680 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -1220,8 +1220,11 @@ static int skl_pcm_new(struct snd_soc_pcm_runtime *rtd) static int skl_get_module_info(struct skl *skl, struct skl_module_cfg *mconfig) { struct skl_sst *ctx = skl->skl_sst; + struct skl_module_inst_id *pin_id; + uuid_le *uuid_mod, *uuid_tplg; + struct skl_module *skl_module; struct uuid_module *module; - uuid_le *uuid_mod; + int i, ret = -EIO; uuid_mod = (uuid_le *)mconfig->guid; @@ -1235,11 +1238,43 @@ static int skl_get_module_info(struct skl *skl, struct skl_module_cfg *mconfig) mconfig->id.module_id = module->id; if (mconfig->module) mconfig->module->loadable = module->is_loadable; - return 0; + ret = 0; + break; } } - return -EIO; + if (ret) + return ret; + + uuid_mod = &module->uuid; + ret = -EIO; + for (i = 0; i < skl->nr_modules; i++) { + skl_module = skl->modules[i]; + uuid_tplg = &skl_module->uuid; + if (!uuid_le_cmp(*uuid_mod, *uuid_tplg)) { + mconfig->module = skl_module; + ret = 0; + break; + } + } + if (skl->nr_modules && ret) + return ret; + + list_for_each_entry(module, &ctx->uuid_list, list) { + for (i = 0; i < MAX_IN_QUEUE; i++) { + pin_id = &mconfig->m_in_pin[i].id; + if (!uuid_le_cmp(pin_id->mod_uuid, module->uuid)) + pin_id->module_id = module->id; + } + + for (i = 0; i < MAX_OUT_QUEUE; i++) { + pin_id = &mconfig->m_out_pin[i].id; + if (!uuid_le_cmp(pin_id->mod_uuid, module->uuid)) + pin_id->module_id = module->id; + } + } + + return 0; } static int skl_populate_modules(struct skl *skl) diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index 90903a15fa1d..4975904480e9 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -221,6 +221,7 @@ struct skl_kpb_params { }; struct skl_module_inst_id { + uuid_le mod_uuid; int module_id; u32 instance_id; int pvt_id; -- cgit v1.2.3 From c20252cf9230eb7abd8bce9fdb2ce9bdd6743689 Mon Sep 17 00:00:00 2001 From: Naveen M Date: Sat, 26 Aug 2017 04:04:09 +0530 Subject: ASoC: Intel: kbl: Add MST route change to kbl machine drivers To support MST hdmi audio, modify the current routes to be based on port in rt5663_max98927 & rt5663_rt5514_max98927 machine. Signed-off-by: Naveen M Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/boards/kbl_rt5663_max98927.c | 8 +++----- sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c | 7 ++----- 2 files changed, 5 insertions(+), 10 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/boards/kbl_rt5663_max98927.c b/sound/soc/intel/boards/kbl_rt5663_max98927.c index c1442147d138..941480c3e906 100644 --- a/sound/soc/intel/boards/kbl_rt5663_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_max98927.c @@ -74,8 +74,9 @@ static const struct snd_soc_dapm_widget kabylake_widgets[] = { SND_SOC_DAPM_SPK("Left Spk", NULL), SND_SOC_DAPM_SPK("Right Spk", NULL), SND_SOC_DAPM_MIC("SoC DMIC", NULL), - SND_SOC_DAPM_SPK("DP", NULL), - SND_SOC_DAPM_SPK("HDMI", NULL), + SND_SOC_DAPM_SPK("HDMI1", NULL), + SND_SOC_DAPM_SPK("HDMI2", NULL), + SND_SOC_DAPM_SPK("HDMI3", NULL), }; @@ -93,9 +94,6 @@ static const struct snd_soc_dapm_route kabylake_map[] = { { "IN1N", NULL, "Headset Mic" }, { "DMic", NULL, "SoC DMIC" }, - { "HDMI", NULL, "hif5 Output" }, - { "DP", NULL, "hif6 Output" }, - /* CODEC BE connections */ { "Left HiFi Playback", NULL, "ssp0 Tx" }, { "Right HiFi Playback", NULL, "ssp0 Tx" }, diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c index 69681b04d7fc..d042255235c1 100644 --- a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c @@ -85,8 +85,8 @@ static const struct snd_soc_dapm_widget kabylake_widgets[] = { SND_SOC_DAPM_SPK("Left Spk", NULL), SND_SOC_DAPM_SPK("Right Spk", NULL), SND_SOC_DAPM_MIC("DMIC", NULL), - SND_SOC_DAPM_SPK("DP", NULL), - SND_SOC_DAPM_SPK("HDMI", NULL), + SND_SOC_DAPM_SPK("HDMI1", NULL), + SND_SOC_DAPM_SPK("HDMI2", NULL), }; @@ -103,9 +103,6 @@ static const struct snd_soc_dapm_route kabylake_map[] = { { "IN1P", NULL, "Headset Mic" }, { "IN1N", NULL, "Headset Mic" }, - { "HDMI", NULL, "hif5 Output" }, - { "DP", NULL, "hif6 Output" }, - /* CODEC BE connections */ { "Left HiFi Playback", NULL, "ssp0 Tx" }, { "Right HiFi Playback", NULL, "ssp0 Tx" }, -- cgit v1.2.3 From 3a13347f05fdba9d889891245f154816197868f4 Mon Sep 17 00:00:00 2001 From: Naveen M Date: Sat, 26 Aug 2017 04:04:10 +0530 Subject: ASoC: Intel: kbl: Add jack port initialize in kbl machine drivers After the pcm jack is created, create and initialize the pin switch widget for each port. For hdmi audio, invoke hdac_hdmi_jack_port_init func() in rt5663_max98927 & rt5663_rt5514_max98927 to enable the pin, when monitor is connected. Signed-off-by: Naveen M Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/boards/kbl_rt5663_max98927.c | 7 ++++++- sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/boards/kbl_rt5663_max98927.c b/sound/soc/intel/boards/kbl_rt5663_max98927.c index 941480c3e906..3fa85c32b9f8 100644 --- a/sound/soc/intel/boards/kbl_rt5663_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_max98927.c @@ -767,10 +767,12 @@ static int kabylake_card_late_probe(struct snd_soc_card *card) { struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(card); struct kbl_hdmi_pcm *pcm; + struct snd_soc_codec *codec = NULL; int err, i = 0; char jack_name[NAME_SIZE]; list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { + codec = pcm->codec_dai->codec; snprintf(jack_name, sizeof(jack_name), "HDMI/DP, pcm=%d Jack", pcm->device); err = snd_soc_card_jack_new(card, jack_name, @@ -788,7 +790,10 @@ static int kabylake_card_late_probe(struct snd_soc_card *card) i++; } - return 0; + if (!codec) + return -EINVAL; + + return hdac_hdmi_jack_port_init(codec, &card->dapm); } /* kabylake audio machine driver for SPT + RT5663 */ diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c index d042255235c1..11bd5ef1e3b2 100644 --- a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c @@ -600,10 +600,12 @@ static int kabylake_card_late_probe(struct snd_soc_card *card) { struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(card); struct kbl_hdmi_pcm *pcm; + struct snd_soc_codec *codec = NULL; int err, i = 0; char jack_name[NAME_SIZE]; list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { + codec = pcm->codec_dai->codec; err = snd_soc_card_jack_new(card, jack_name, SND_JACK_AVOUT, &ctx->kabylake_hdmi[i], NULL, 0); @@ -617,7 +619,10 @@ static int kabylake_card_late_probe(struct snd_soc_card *card) i++; } - return 0; + if (!codec) + return -EINVAL; + + return hdac_hdmi_jack_port_init(codec, &card->dapm); } /* -- cgit v1.2.3 From 64220b9d10a5546b6dd1154ccaf43522ae7d02fc Mon Sep 17 00:00:00 2001 From: Naveen Manohar Date: Sat, 26 Aug 2017 03:21:39 +0530 Subject: ASoC: Intel: kbl: Add map for Maxim IV Feedback MAX98927 provides IV feedback on the capture widget. Here we are connecting the capture widget to SSP0_RX and SSP0_RX to the algorithm running on host. Signed-off-by: Naveen M Signed-off-by: Sathya Prakash M R Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/boards/kbl_rt5663_max98927.c | 5 +++++ sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c | 5 +++++ 2 files changed, 10 insertions(+) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/boards/kbl_rt5663_max98927.c b/sound/soc/intel/boards/kbl_rt5663_max98927.c index 3fa85c32b9f8..7f7607420706 100644 --- a/sound/soc/intel/boards/kbl_rt5663_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_max98927.c @@ -105,6 +105,11 @@ static const struct snd_soc_dapm_route kabylake_map[] = { { "hs_in", NULL, "ssp1 Rx" }, { "ssp1 Rx", NULL, "AIF Capture" }, + /* IV feedback path */ + { "codec0_fb_in", NULL, "ssp0 Rx"}, + { "ssp0 Rx", NULL, "Left HiFi Capture" }, + { "ssp0 Rx", NULL, "Right HiFi Capture" }, + /* DMIC */ { "dmic01_hifi", NULL, "DMIC01 Rx" }, { "DMIC01 Rx", NULL, "DMIC AIF" }, diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c index 11bd5ef1e3b2..4689991bcc86 100644 --- a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c @@ -117,6 +117,11 @@ static const struct snd_soc_dapm_route kabylake_map[] = { { "codec1_in", NULL, "ssp0 Rx" }, { "ssp0 Rx", NULL, "AIF1 Capture" }, + /* IV feedback path */ + { "codec0_fb_in", NULL, "ssp0 Rx"}, + { "ssp0 Rx", NULL, "Left HiFi Capture" }, + { "ssp0 Rx", NULL, "Right HiFi Capture" }, + /* DMIC */ { "DMIC1L", NULL, "DMIC" }, { "DMIC1R", NULL, "DMIC" }, -- cgit v1.2.3 From 38a770859e10f566c434ae0d3f380954280f262b Mon Sep 17 00:00:00 2001 From: Pradeep Tewani Date: Fri, 1 Sep 2017 13:36:13 +0530 Subject: ASoC: Intel: Skylake: Add IPC to configure the copier secondary pins Copier can support upto 4 output pins. However, only pin 0 is configured as a part of copier initialization. Configuring rest of pins require the separate IPC to be sent to fw. Signed-off-by: Pradeep Tewani Acked-By: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-messages.c | 53 ++++++++++++++++++++++++++++++---- sound/soc/intel/skylake/skl-topology.h | 5 ++++ 2 files changed, 53 insertions(+), 5 deletions(-) (limited to 'sound/soc/intel') diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index ea83e8bfb136..89f70133c8e4 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -1083,6 +1083,21 @@ int skl_unbind_modules(struct skl_sst *ctx, return ret; } +static void fill_pin_params(struct skl_audio_data_format *pin_fmt, + struct skl_module_fmt *format) +{ + pin_fmt->number_of_channels = format->channels; + pin_fmt->s_freq = format->s_freq; + pin_fmt->bit_depth = format->bit_depth; + pin_fmt->valid_bit_depth = format->valid_bit_depth; + pin_fmt->ch_cfg = format->ch_cfg; + pin_fmt->sample_type = format->sample_type; + pin_fmt->channel_map = format->ch_map; + pin_fmt->interleaving = format->interleaving_style; +} + +#define CPR_SINK_FMT_PARAM_ID 2 + /* * Once a module is instantiated it need to be 'bind' with other modules in * the pipeline. For binding we need to find the module pins which are bind @@ -1094,11 +1109,15 @@ int skl_bind_modules(struct skl_sst *ctx, struct skl_module_cfg *src_mcfg, struct skl_module_cfg *dst_mcfg) { - int ret; + int ret = 0; struct skl_ipc_bind_unbind_msg msg; int in_max = dst_mcfg->module->max_input_pins; int out_max = src_mcfg->module->max_output_pins; int src_index, dst_index; + struct skl_module_fmt *format; + struct skl_cpr_pin_fmt pin_fmt; + struct skl_module *module; + struct skl_module_iface *fmt; skl_dump_bind_info(ctx, src_mcfg, dst_mcfg); @@ -1117,6 +1136,29 @@ int skl_bind_modules(struct skl_sst *ctx, return -EINVAL; } + /* + * Copier module requires the separate large_config_set_ipc to + * configure the pins other than 0 + */ + if (src_mcfg->m_type == SKL_MODULE_TYPE_COPIER && src_index > 0) { + pin_fmt.sink_id = src_index; + module = src_mcfg->module; + fmt = &module->formats[src_mcfg->fmt_idx]; + + /* Input fmt is same as that of src module input cfg */ + format = &fmt->inputs[0].fmt; + fill_pin_params(&(pin_fmt.src_fmt), format); + + format = &fmt->outputs[src_index].fmt; + fill_pin_params(&(pin_fmt.dst_fmt), format); + ret = skl_set_module_params(ctx, (void *)&pin_fmt, + sizeof(struct skl_cpr_pin_fmt), + CPR_SINK_FMT_PARAM_ID, src_mcfg); + + if (ret < 0) + goto out; + } + msg.dst_queue = dst_index; dev_dbg(ctx->dev, "src queue = %d dst queue =%d\n", @@ -1134,11 +1176,12 @@ int skl_bind_modules(struct skl_sst *ctx, src_mcfg->m_state = SKL_MODULE_BIND_DONE; src_mcfg->m_out_pin[src_index].pin_state = SKL_PIN_BIND_DONE; dst_mcfg->m_in_pin[dst_index].pin_state = SKL_PIN_BIND_DONE; - } else { - /* error case , if IPC fails, clear the queue index */ - skl_free_queue(src_mcfg->m_out_pin, src_index); - skl_free_queue(dst_mcfg->m_in_pin, dst_index); + return ret; } +out: + /* error case , if IPC fails, clear the queue index */ + skl_free_queue(src_mcfg->m_out_pin, src_index); + skl_free_queue(dst_mcfg->m_in_pin, dst_index); return ret; } diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index 4975904480e9..2717db92036b 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -138,6 +138,11 @@ struct skl_cpr_cfg { struct skl_cpr_gtw_cfg gtw_cfg; } __packed; +struct skl_cpr_pin_fmt { + u32 sink_id; + struct skl_audio_data_format src_fmt; + struct skl_audio_data_format dst_fmt; +} __packed; struct skl_src_module_cfg { struct skl_base_cfg base_cfg; -- cgit v1.2.3