aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/intel
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2016-07-24 17:07:22 -0400
committerMark Brown <broonie@kernel.org>2016-07-24 17:07:22 -0400
commit44d624622e57ad60e652da4d7bde43aadab350bf (patch)
tree30a330c8fa9a051f147f82e336823f800e9d4e11 /sound/soc/intel
parent0d911262808d07af538c23b1b6d249b3a4a9a431 (diff)
parent1b00126cb3de017274e899ac559a744d4e3dbd61 (diff)
Merge remote-tracking branch 'asoc/topic/intel' into asoc-next
Diffstat (limited to 'sound/soc/intel')
-rw-r--r--sound/soc/intel/Kconfig73
-rw-r--r--sound/soc/intel/atom/sst/sst_acpi.c44
-rw-r--r--sound/soc/intel/boards/Makefile2
-rw-r--r--sound/soc/intel/boards/bxt_da7219_max98357a.c460
-rw-r--r--sound/soc/intel/boards/bxt_rt298.c118
-rw-r--r--sound/soc/intel/boards/cht_bsw_rt5645.c20
-rw-r--r--sound/soc/intel/boards/skl_nau88l25_max98357a.c51
-rw-r--r--sound/soc/intel/boards/skl_nau88l25_ssm4567.c51
-rw-r--r--sound/soc/intel/boards/skl_rt286.c9
-rw-r--r--sound/soc/intel/common/Makefile4
-rw-r--r--sound/soc/intel/common/sst-acpi.h4
-rw-r--r--sound/soc/intel/common/sst-dsp-priv.h4
-rw-r--r--sound/soc/intel/common/sst-dsp.c69
-rw-r--r--sound/soc/intel/common/sst-dsp.h2
-rw-r--r--sound/soc/intel/common/sst-firmware.c68
-rw-r--r--sound/soc/intel/haswell/sst-haswell-pcm.c1
-rw-r--r--sound/soc/intel/skylake/Makefile2
-rw-r--r--sound/soc/intel/skylake/bxt-sst.c202
-rw-r--r--sound/soc/intel/skylake/skl-messages.c53
-rw-r--r--sound/soc/intel/skylake/skl-nhlt.c40
-rw-r--r--sound/soc/intel/skylake/skl-nhlt.h22
-rw-r--r--sound/soc/intel/skylake/skl-pcm.c93
-rw-r--r--sound/soc/intel/skylake/skl-sst-dsp.c260
-rw-r--r--sound/soc/intel/skylake/skl-sst-dsp.h102
-rw-r--r--sound/soc/intel/skylake/skl-sst-ipc.c4
-rw-r--r--sound/soc/intel/skylake/skl-sst-ipc.h18
-rw-r--r--sound/soc/intel/skylake/skl-sst-utils.c256
-rw-r--r--sound/soc/intel/skylake/skl-sst.c124
-rw-r--r--sound/soc/intel/skylake/skl-topology.c217
-rw-r--r--sound/soc/intel/skylake/skl-topology.h6
-rw-r--r--sound/soc/intel/skylake/skl.c39
-rw-r--r--sound/soc/intel/skylake/skl.h10
32 files changed, 1980 insertions, 448 deletions
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig
index 91c15abb625e..a20c3dfbcb5d 100644
--- a/sound/soc/intel/Kconfig
+++ b/sound/soc/intel/Kconfig
@@ -7,7 +7,7 @@ config SND_MFLD_MACHINE
7 help 7 help
8 This adds support for ASoC machine driver for Intel(R) MID Medfield platform 8 This adds support for ASoC machine driver for Intel(R) MID Medfield platform
9 used as alsa device in audio substem in Intel(R) MID devices 9 used as alsa device in audio substem in Intel(R) MID devices
10 Say Y if you have such a device 10 Say Y if you have such a device.
11 If unsure select "N". 11 If unsure select "N".
12 12
13config SND_SST_MFLD_PLATFORM 13config SND_SST_MFLD_PLATFORM
@@ -25,7 +25,6 @@ config SND_SST_IPC_ACPI
25 tristate 25 tristate
26 select SND_SST_IPC 26 select SND_SST_IPC
27 select SND_SOC_INTEL_SST 27 select SND_SOC_INTEL_SST
28 depends on ACPI
29 28
30config SND_SOC_INTEL_SST 29config SND_SOC_INTEL_SST
31 tristate 30 tristate
@@ -33,6 +32,12 @@ config SND_SOC_INTEL_SST
33 select SND_SOC_INTEL_SST_MATCH if ACPI 32 select SND_SOC_INTEL_SST_MATCH if ACPI
34 depends on (X86 || COMPILE_TEST) 33 depends on (X86 || COMPILE_TEST)
35 34
35# firmware stuff depends DW_DMAC_CORE; since there is no depends-on from
36# the reverse selection, each machine driver needs to select
37# SND_SOC_INTEL_SST_FIRMWARE carefully depending on DW_DMAC_CORE
38config SND_SOC_INTEL_SST_FIRMWARE
39 tristate
40
36config SND_SOC_INTEL_SST_ACPI 41config SND_SOC_INTEL_SST_ACPI
37 tristate 42 tristate
38 43
@@ -48,16 +53,33 @@ config SND_SOC_INTEL_BAYTRAIL
48config SND_SOC_INTEL_HASWELL_MACH 53config SND_SOC_INTEL_HASWELL_MACH
49 tristate "ASoC Audio DSP support for Intel Haswell Lynxpoint" 54 tristate "ASoC Audio DSP support for Intel Haswell Lynxpoint"
50 depends on X86_INTEL_LPSS && I2C && I2C_DESIGNWARE_PLATFORM 55 depends on X86_INTEL_LPSS && I2C && I2C_DESIGNWARE_PLATFORM
51 depends on DW_DMAC_CORE=y 56 depends on DW_DMAC_CORE
52 select SND_SOC_INTEL_SST 57 select SND_SOC_INTEL_SST
58 select SND_SOC_INTEL_SST_FIRMWARE
53 select SND_SOC_INTEL_HASWELL 59 select SND_SOC_INTEL_HASWELL
54 select SND_SOC_RT5640 60 select SND_SOC_RT5640
55 help 61 help
56 This adds support for the Lynxpoint Audio DSP on Intel(R) Haswell 62 This adds support for the Lynxpoint Audio DSP on Intel(R) Haswell
57 Ultrabook platforms. 63 Ultrabook platforms.
58 Say Y if you have such a device 64 Say Y if you have such a device.
59 If unsure select "N". 65 If unsure select "N".
60 66
67config SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH
68 tristate "ASoC Audio driver for Broxton with DA7219 and MAX98357A in I2S Mode"
69 depends on X86 && ACPI && I2C
70 select SND_SOC_INTEL_SST
71 select SND_SOC_INTEL_SKYLAKE
72 select SND_SOC_DA7219
73 select SND_SOC_MAX98357A
74 select SND_SOC_DMIC
75 select SND_SOC_HDAC_HDMI
76 select SND_HDA_DSP_LOADER
77 help
78 This adds support for ASoC machine driver for Broxton-P platforms
79 with DA7219 + MAX98357A I2S audio codec.
80 Say Y if you have such a device.
81 If unsure select "N".
82
61config SND_SOC_INTEL_BXT_RT298_MACH 83config SND_SOC_INTEL_BXT_RT298_MACH
62 tristate "ASoC Audio driver for Broxton with RT298 I2S mode" 84 tristate "ASoC Audio driver for Broxton with RT298 I2S mode"
63 depends on X86 && ACPI && I2C 85 depends on X86 && ACPI && I2C
@@ -70,26 +92,28 @@ config SND_SOC_INTEL_BXT_RT298_MACH
70 help 92 help
71 This adds support for ASoC machine driver for Broxton platforms 93 This adds support for ASoC machine driver for Broxton platforms
72 with RT286 I2S audio codec. 94 with RT286 I2S audio codec.
73 Say Y if you have such a device 95 Say Y if you have such a device.
74 If unsure select "N". 96 If unsure select "N".
75 97
76config SND_SOC_INTEL_BYT_RT5640_MACH 98config SND_SOC_INTEL_BYT_RT5640_MACH
77 tristate "ASoC Audio driver for Intel Baytrail with RT5640 codec" 99 tristate "ASoC Audio driver for Intel Baytrail with RT5640 codec"
78 depends on X86_INTEL_LPSS && I2C 100 depends on X86_INTEL_LPSS && I2C
79 depends on DW_DMAC_CORE=y && (SND_SST_IPC_ACPI = n) 101 depends on DW_DMAC_CORE && (SND_SST_IPC_ACPI = n)
80 select SND_SOC_INTEL_SST 102 select SND_SOC_INTEL_SST
103 select SND_SOC_INTEL_SST_FIRMWARE
81 select SND_SOC_INTEL_BAYTRAIL 104 select SND_SOC_INTEL_BAYTRAIL
82 select SND_SOC_RT5640 105 select SND_SOC_RT5640
83 help 106 help
84 This adds audio driver for Intel Baytrail platform based boards 107 This adds audio driver for Intel Baytrail platform based boards
85 with the RT5640 audio codec. This driver is deprecated, use 108 with the RT5640 audio codec. This driver is deprecated, use
86 SND_SOC_INTEL_BYTCR_RT5640_MACH instead for better functionality 109 SND_SOC_INTEL_BYTCR_RT5640_MACH instead for better functionality.
87 110
88config SND_SOC_INTEL_BYT_MAX98090_MACH 111config SND_SOC_INTEL_BYT_MAX98090_MACH
89 tristate "ASoC Audio driver for Intel Baytrail with MAX98090 codec" 112 tristate "ASoC Audio driver for Intel Baytrail with MAX98090 codec"
90 depends on X86_INTEL_LPSS && I2C 113 depends on X86_INTEL_LPSS && I2C
91 depends on DW_DMAC_CORE=y && (SND_SST_IPC_ACPI = n) 114 depends on DW_DMAC_CORE && (SND_SST_IPC_ACPI = n)
92 select SND_SOC_INTEL_SST 115 select SND_SOC_INTEL_SST
116 select SND_SOC_INTEL_SST_FIRMWARE
93 select SND_SOC_INTEL_BAYTRAIL 117 select SND_SOC_INTEL_BAYTRAIL
94 select SND_SOC_MAX98090 118 select SND_SOC_MAX98090
95 help 119 help
@@ -100,19 +124,20 @@ config SND_SOC_INTEL_BROADWELL_MACH
100 tristate "ASoC Audio DSP support for Intel Broadwell Wildcatpoint" 124 tristate "ASoC Audio DSP support for Intel Broadwell Wildcatpoint"
101 depends on X86_INTEL_LPSS && I2C && DW_DMAC && \ 125 depends on X86_INTEL_LPSS && I2C && DW_DMAC && \
102 I2C_DESIGNWARE_PLATFORM 126 I2C_DESIGNWARE_PLATFORM
103 depends on DW_DMAC_CORE=y 127 depends on DW_DMAC_CORE
104 select SND_SOC_INTEL_SST 128 select SND_SOC_INTEL_SST
129 select SND_SOC_INTEL_SST_FIRMWARE
105 select SND_SOC_INTEL_HASWELL 130 select SND_SOC_INTEL_HASWELL
106 select SND_SOC_RT286 131 select SND_SOC_RT286
107 help 132 help
108 This adds support for the Wilcatpoint Audio DSP on Intel(R) Broadwell 133 This adds support for the Wilcatpoint Audio DSP on Intel(R) Broadwell
109 Ultrabook platforms. 134 Ultrabook platforms.
110 Say Y if you have such a device 135 Say Y if you have such a device.
111 If unsure select "N". 136 If unsure select "N".
112 137
113config SND_SOC_INTEL_BYTCR_RT5640_MACH 138config SND_SOC_INTEL_BYTCR_RT5640_MACH
114 tristate "ASoC Audio driver for Intel Baytrail and Baytrail-CR with RT5640 codec" 139 tristate "ASoC Audio driver for Intel Baytrail and Baytrail-CR with RT5640 codec"
115 depends on X86 && I2C 140 depends on X86 && I2C && ACPI
116 select SND_SOC_RT5640 141 select SND_SOC_RT5640
117 select SND_SST_MFLD_PLATFORM 142 select SND_SST_MFLD_PLATFORM
118 select SND_SST_IPC_ACPI 143 select SND_SST_IPC_ACPI
@@ -120,12 +145,12 @@ config SND_SOC_INTEL_BYTCR_RT5640_MACH
120 help 145 help
121 This adds support for ASoC machine driver for Intel(R) Baytrail and Baytrail-CR 146 This adds support for ASoC machine driver for Intel(R) Baytrail and Baytrail-CR
122 platforms with RT5640 audio codec. 147 platforms with RT5640 audio codec.
123 Say Y if you have such a device 148 Say Y if you have such a device.
124 If unsure select "N". 149 If unsure select "N".
125 150
126config SND_SOC_INTEL_BYTCR_RT5651_MACH 151config SND_SOC_INTEL_BYTCR_RT5651_MACH
127 tristate "ASoC Audio driver for Intel Baytrail and Baytrail-CR with RT5651 codec" 152 tristate "ASoC Audio driver for Intel Baytrail and Baytrail-CR with RT5651 codec"
128 depends on X86 && I2C 153 depends on X86 && I2C && ACPI
129 select SND_SOC_RT5651 154 select SND_SOC_RT5651
130 select SND_SST_MFLD_PLATFORM 155 select SND_SST_MFLD_PLATFORM
131 select SND_SST_IPC_ACPI 156 select SND_SST_IPC_ACPI
@@ -133,12 +158,12 @@ config SND_SOC_INTEL_BYTCR_RT5651_MACH
133 help 158 help
134 This adds support for ASoC machine driver for Intel(R) Baytrail and Baytrail-CR 159 This adds support for ASoC machine driver for Intel(R) Baytrail and Baytrail-CR
135 platforms with RT5651 audio codec. 160 platforms with RT5651 audio codec.
136 Say Y if you have such a device 161 Say Y if you have such a device.
137 If unsure select "N". 162 If unsure select "N".
138 163
139config SND_SOC_INTEL_CHT_BSW_RT5672_MACH 164config SND_SOC_INTEL_CHT_BSW_RT5672_MACH
140 tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with RT5672 codec" 165 tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with RT5672 codec"
141 depends on X86_INTEL_LPSS && I2C 166 depends on X86_INTEL_LPSS && I2C && ACPI
142 select SND_SOC_RT5670 167 select SND_SOC_RT5670
143 select SND_SST_MFLD_PLATFORM 168 select SND_SST_MFLD_PLATFORM
144 select SND_SST_IPC_ACPI 169 select SND_SST_IPC_ACPI
@@ -146,12 +171,12 @@ config SND_SOC_INTEL_CHT_BSW_RT5672_MACH
146 help 171 help
147 This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell 172 This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell
148 platforms with RT5672 audio codec. 173 platforms with RT5672 audio codec.
149 Say Y if you have such a device 174 Say Y if you have such a device.
150 If unsure select "N". 175 If unsure select "N".
151 176
152config SND_SOC_INTEL_CHT_BSW_RT5645_MACH 177config SND_SOC_INTEL_CHT_BSW_RT5645_MACH
153 tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with RT5645/5650 codec" 178 tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with RT5645/5650 codec"
154 depends on X86_INTEL_LPSS && I2C 179 depends on X86_INTEL_LPSS && I2C && ACPI
155 select SND_SOC_RT5645 180 select SND_SOC_RT5645
156 select SND_SST_MFLD_PLATFORM 181 select SND_SST_MFLD_PLATFORM
157 select SND_SST_IPC_ACPI 182 select SND_SST_IPC_ACPI
@@ -163,16 +188,16 @@ config SND_SOC_INTEL_CHT_BSW_RT5645_MACH
163 188
164config SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH 189config SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH
165 tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with MAX98090 & TI codec" 190 tristate "ASoC Audio driver for Intel Cherrytrail & Braswell with MAX98090 & TI codec"
166 depends on X86_INTEL_LPSS && I2C 191 depends on X86_INTEL_LPSS && I2C && ACPI
167 select SND_SOC_MAX98090 192 select SND_SOC_MAX98090
168 select SND_SOC_TS3A227E 193 select SND_SOC_TS3A227E
169 select SND_SST_MFLD_PLATFORM 194 select SND_SST_MFLD_PLATFORM
170 select SND_SST_IPC_ACPI 195 select SND_SST_IPC_ACPI
171 select SND_SOC_INTEL_SST_MATCH if ACPI 196 select SND_SOC_INTEL_SST_MATCH if ACPI
172 help 197 help
173 This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell 198 This adds support for ASoC machine driver for Intel(R) Cherrytrail & Braswell
174 platforms with MAX98090 audio codec it also can support TI jack chip as aux device. 199 platforms with MAX98090 audio codec it also can support TI jack chip as aux device.
175 If unsure select "N". 200 If unsure select "N".
176 201
177config SND_SOC_INTEL_SKYLAKE 202config SND_SOC_INTEL_SKYLAKE
178 tristate 203 tristate
@@ -192,7 +217,7 @@ config SND_SOC_INTEL_SKL_RT286_MACH
192 help 217 help
193 This adds support for ASoC machine driver for Skylake platforms 218 This adds support for ASoC machine driver for Skylake platforms
194 with RT286 I2S audio codec. 219 with RT286 I2S audio codec.
195 Say Y if you have such a device 220 Say Y if you have such a device.
196 If unsure select "N". 221 If unsure select "N".
197 222
198config SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH 223config SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH
@@ -207,7 +232,7 @@ config SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH
207 help 232 help
208 This adds support for ASoC Onboard Codec I2S machine driver. This will 233 This adds support for ASoC Onboard Codec I2S machine driver. This will
209 create an alsa sound card for NAU88L25 + SSM4567. 234 create an alsa sound card for NAU88L25 + SSM4567.
210 Say Y if you have such a device 235 Say Y if you have such a device.
211 If unsure select "N". 236 If unsure select "N".
212 237
213config SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH 238config SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH
@@ -222,5 +247,5 @@ config SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH
222 help 247 help
223 This adds support for ASoC Onboard Codec I2S machine driver. This will 248 This adds support for ASoC Onboard Codec I2S machine driver. This will
224 create an alsa sound card for NAU88L25 + MAX98357A. 249 create an alsa sound card for NAU88L25 + MAX98357A.
225 Say Y if you have such a device 250 Say Y if you have such a device.
226 If unsure select "N". 251 If unsure select "N".
diff --git a/sound/soc/intel/atom/sst/sst_acpi.c b/sound/soc/intel/atom/sst/sst_acpi.c
index 3bc4b63b2f9d..4d3184971227 100644
--- a/sound/soc/intel/atom/sst/sst_acpi.c
+++ b/sound/soc/intel/atom/sst/sst_acpi.c
@@ -28,6 +28,7 @@
28#include <linux/firmware.h> 28#include <linux/firmware.h>
29#include <linux/pm_runtime.h> 29#include <linux/pm_runtime.h>
30#include <linux/pm_qos.h> 30#include <linux/pm_qos.h>
31#include <linux/dmi.h>
31#include <linux/acpi.h> 32#include <linux/acpi.h>
32#include <asm/platform_sst_audio.h> 33#include <asm/platform_sst_audio.h>
33#include <sound/core.h> 34#include <sound/core.h>
@@ -237,6 +238,9 @@ static int sst_acpi_probe(struct platform_device *pdev)
237 dev_err(dev, "No matching machine driver found\n"); 238 dev_err(dev, "No matching machine driver found\n");
238 return -ENODEV; 239 return -ENODEV;
239 } 240 }
241 if (mach->machine_quirk)
242 mach = mach->machine_quirk(mach);
243
240 pdata = mach->pdata; 244 pdata = mach->pdata;
241 245
242 ret = kstrtouint(id->id, 16, &dev_id); 246 ret = kstrtouint(id->id, 16, &dev_id);
@@ -320,6 +324,44 @@ static int sst_acpi_remove(struct platform_device *pdev)
320 return 0; 324 return 0;
321} 325}
322 326
327static unsigned long cht_machine_id;
328
329#define CHT_SURFACE_MACH 1
330
331static int cht_surface_quirk_cb(const struct dmi_system_id *id)
332{
333 cht_machine_id = CHT_SURFACE_MACH;
334 return 1;
335}
336
337
338static const struct dmi_system_id cht_table[] = {
339 {
340 .callback = cht_surface_quirk_cb,
341 .matches = {
342 DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
343 DMI_MATCH(DMI_PRODUCT_NAME, "Surface 3"),
344 },
345 },
346};
347
348
349static struct sst_acpi_mach cht_surface_mach = {
350 "10EC5640", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
351 &chv_platform_data };
352
353static struct sst_acpi_mach *cht_quirk(void *arg)
354{
355 struct sst_acpi_mach *mach = arg;
356
357 dmi_check_system(cht_table);
358
359 if (cht_machine_id == CHT_SURFACE_MACH)
360 return &cht_surface_mach;
361 else
362 return mach;
363}
364
323static struct sst_acpi_mach sst_acpi_bytcr[] = { 365static struct sst_acpi_mach sst_acpi_bytcr[] = {
324 {"10EC5640", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL, 366 {"10EC5640", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL,
325 &byt_rvp_platform_data }, 367 &byt_rvp_platform_data },
@@ -343,7 +385,7 @@ static struct sst_acpi_mach sst_acpi_chv[] = {
343 {"193C9890", "cht-bsw-max98090", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, 385 {"193C9890", "cht-bsw-max98090", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
344 &chv_platform_data }, 386 &chv_platform_data },
345 /* some CHT-T platforms rely on RT5640, use Baytrail machine driver */ 387 /* some CHT-T platforms rely on RT5640, use Baytrail machine driver */
346 {"10EC5640", "bytcr_rt5640", "intel/fw_sst_22a8.bin", "bytcr_rt5640", NULL, 388 {"10EC5640", "bytcr_rt5640", "intel/fw_sst_22a8.bin", "bytcr_rt5640", cht_quirk,
347 &chv_platform_data }, 389 &chv_platform_data },
348 390
349 {}, 391 {},
diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile
index a8506774f510..dac03a06bfd8 100644
--- a/sound/soc/intel/boards/Makefile
+++ b/sound/soc/intel/boards/Makefile
@@ -2,6 +2,7 @@ snd-soc-sst-haswell-objs := haswell.o
2snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o 2snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o
3snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o 3snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o
4snd-soc-sst-broadwell-objs := broadwell.o 4snd-soc-sst-broadwell-objs := broadwell.o
5snd-soc-sst-bxt-da7219_max98357a-objs := bxt_da7219_max98357a.o
5snd-soc-sst-bxt-rt298-objs := bxt_rt298.o 6snd-soc-sst-bxt-rt298-objs := bxt_rt298.o
6snd-soc-sst-bytcr-rt5640-objs := bytcr_rt5640.o 7snd-soc-sst-bytcr-rt5640-objs := bytcr_rt5640.o
7snd-soc-sst-bytcr-rt5651-objs := bytcr_rt5651.o 8snd-soc-sst-bytcr-rt5651-objs := bytcr_rt5651.o
@@ -15,6 +16,7 @@ snd-soc-skl_nau88l25_ssm4567-objs := skl_nau88l25_ssm4567.o
15obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o 16obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o
16obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o 17obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o
17obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o 18obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o
19obj-$(CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH) += snd-soc-sst-bxt-da7219_max98357a.o
18obj-$(CONFIG_SND_SOC_INTEL_BXT_RT298_MACH) += snd-soc-sst-bxt-rt298.o 20obj-$(CONFIG_SND_SOC_INTEL_BXT_RT298_MACH) += snd-soc-sst-bxt-rt298.o
19obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o 21obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o
20obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH) += snd-soc-sst-bytcr-rt5640.o 22obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH) += snd-soc-sst-bytcr-rt5640.o
diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c
new file mode 100644
index 000000000000..3774b117d365
--- /dev/null
+++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c
@@ -0,0 +1,460 @@
1/*
2 * Intel Broxton-P I2S Machine Driver
3 *
4 * Copyright (C) 2016, Intel Corporation. All rights reserved.
5 *
6 * Modified from:
7 * Intel Skylake I2S Machine driver
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License version
11 * 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
18
19#include <linux/module.h>
20#include <linux/platform_device.h>
21#include <sound/core.h>
22#include <sound/jack.h>
23#include <sound/pcm.h>
24#include <sound/pcm_params.h>
25#include <sound/soc.h>
26#include "../../codecs/hdac_hdmi.h"
27#include "../../codecs/da7219.h"
28#include "../../codecs/da7219-aad.h"
29
30#define BXT_DIALOG_CODEC_DAI "da7219-hifi"
31#define BXT_MAXIM_CODEC_DAI "HiFi"
32#define DUAL_CHANNEL 2
33
34static struct snd_soc_jack broxton_headset;
35
36enum {
37 BXT_DPCM_AUDIO_PB = 0,
38 BXT_DPCM_AUDIO_CP,
39 BXT_DPCM_AUDIO_REF_CP,
40 BXT_DPCM_AUDIO_HDMI1_PB,
41 BXT_DPCM_AUDIO_HDMI2_PB,
42 BXT_DPCM_AUDIO_HDMI3_PB,
43};
44
45static const struct snd_kcontrol_new broxton_controls[] = {
46 SOC_DAPM_PIN_SWITCH("Headphone Jack"),
47 SOC_DAPM_PIN_SWITCH("Headset Mic"),
48 SOC_DAPM_PIN_SWITCH("Spk"),
49};
50
51static const struct snd_soc_dapm_widget broxton_widgets[] = {
52 SND_SOC_DAPM_HP("Headphone Jack", NULL),
53 SND_SOC_DAPM_MIC("Headset Mic", NULL),
54 SND_SOC_DAPM_SPK("Spk", NULL),
55 SND_SOC_DAPM_MIC("SoC DMIC", NULL),
56 SND_SOC_DAPM_SPK("HDMI1", NULL),
57 SND_SOC_DAPM_SPK("HDMI2", NULL),
58 SND_SOC_DAPM_SPK("HDMI3", NULL),
59};
60
61static const struct snd_soc_dapm_route broxton_map[] = {
62 /* HP jack connectors - unknown if we have jack detection */
63 {"Headphone Jack", NULL, "HPL"},
64 {"Headphone Jack", NULL, "HPR"},
65
66 /* speaker */
67 {"Spk", NULL, "Speaker"},
68
69 /* other jacks */
70 {"MIC", NULL, "Headset Mic"},
71
72 /* digital mics */
73 {"DMic", NULL, "SoC DMIC"},
74
75 /* CODEC BE connections */
76 {"HiFi Playback", NULL, "ssp5 Tx"},
77 {"ssp5 Tx", NULL, "codec0_out"},
78
79 {"Playback", NULL, "ssp1 Tx"},
80 {"ssp1 Tx", NULL, "codec1_out"},
81
82 {"codec0_in", NULL, "ssp1 Rx"},
83 {"ssp1 Rx", NULL, "Capture"},
84
85 {"HDMI1", NULL, "hif5 Output"},
86 {"HDMI2", NULL, "hif6 Output"},
87 {"HDMI3", NULL, "hif7 Output"},
88
89 {"hifi3", NULL, "iDisp3 Tx"},
90 {"iDisp3 Tx", NULL, "iDisp3_out"},
91 {"hifi2", NULL, "iDisp2 Tx"},
92 {"iDisp2 Tx", NULL, "iDisp2_out"},
93 {"hifi1", NULL, "iDisp1 Tx"},
94 {"iDisp1 Tx", NULL, "iDisp1_out"},
95
96 /* DMIC */
97 {"dmic01_hifi", NULL, "DMIC01 Rx"},
98 {"DMIC01 Rx", NULL, "DMIC AIF"},
99};
100
101static int broxton_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
102 struct snd_pcm_hw_params *params)
103{
104 struct snd_interval *rate = hw_param_interval(params,
105 SNDRV_PCM_HW_PARAM_RATE);
106 struct snd_interval *channels = hw_param_interval(params,
107 SNDRV_PCM_HW_PARAM_CHANNELS);
108 struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
109
110 /* The ADSP will convert the FE rate to 48k, stereo */
111 rate->min = rate->max = 48000;
112 channels->min = channels->max = DUAL_CHANNEL;
113
114 /* set SSP to 24 bit */
115 snd_mask_none(fmt);
116 snd_mask_set(fmt, SNDRV_PCM_FORMAT_S24_LE);
117
118 return 0;
119}
120
121static int broxton_da7219_codec_init(struct snd_soc_pcm_runtime *rtd)
122{
123 int ret;
124 struct snd_soc_codec *codec = rtd->codec;
125
126 /*
127 * Headset buttons map to the google Reference headset.
128 * These can be configured by userspace.
129 */
130 ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
131 SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 |
132 SND_JACK_BTN_2 | SND_JACK_BTN_3, &broxton_headset,
133 NULL, 0);
134 if (ret) {
135 dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
136 return ret;
137 }
138
139 da7219_aad_jack_det(codec, &broxton_headset);
140
141 snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC");
142
143 return ret;
144}
145
146static int broxton_hdmi_init(struct snd_soc_pcm_runtime *rtd)
147{
148 struct snd_soc_dai *dai = rtd->codec_dai;
149
150 return hdac_hdmi_jack_init(dai, BXT_DPCM_AUDIO_HDMI1_PB + dai->id);
151}
152
153static int broxton_da7219_fe_init(struct snd_soc_pcm_runtime *rtd)
154{
155 struct snd_soc_dapm_context *dapm;
156 struct snd_soc_component *component = rtd->cpu_dai->component;
157
158 dapm = snd_soc_component_get_dapm(component);
159 snd_soc_dapm_ignore_suspend(dapm, "Reference Capture");
160
161 return 0;
162}
163
164static unsigned int rates[] = {
165 48000,
166};
167
168static struct snd_pcm_hw_constraint_list constraints_rates = {
169 .count = ARRAY_SIZE(rates),
170 .list = rates,
171 .mask = 0,
172};
173
174static unsigned int channels[] = {
175 DUAL_CHANNEL,
176};
177
178static struct snd_pcm_hw_constraint_list constraints_channels = {
179 .count = ARRAY_SIZE(channels),
180 .list = channels,
181 .mask = 0,
182};
183
184static int bxt_fe_startup(struct snd_pcm_substream *substream)
185{
186 struct snd_pcm_runtime *runtime = substream->runtime;
187
188 /*
189 * On this platform for PCM device we support,
190 * 48Khz
191 * stereo
192 * 16 bit audio
193 */
194
195 runtime->hw.channels_max = DUAL_CHANNEL;
196 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
197 &constraints_channels);
198
199 runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
200 snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
201
202 snd_pcm_hw_constraint_list(runtime, 0,
203 SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
204
205 return 0;
206}
207
208static const struct snd_soc_ops broxton_da7219_fe_ops = {
209 .startup = bxt_fe_startup,
210};
211
212static int broxton_da7219_hw_params(struct snd_pcm_substream *substream,
213 struct snd_pcm_hw_params *params)
214{
215 struct snd_soc_pcm_runtime *rtd = substream->private_data;
216 struct snd_soc_dai *codec_dai = rtd->codec_dai;
217 int ret;
218
219 ret = snd_soc_dai_set_sysclk(codec_dai,
220 DA7219_CLKSRC_MCLK, 19200000, SND_SOC_CLOCK_IN);
221 if (ret < 0)
222 dev_err(codec_dai->dev, "can't set codec sysclk configuration\n");
223
224 ret = snd_soc_dai_set_pll(codec_dai, 0,
225 DA7219_SYSCLK_PLL_SRM, 0, DA7219_PLL_FREQ_OUT_98304);
226 if (ret < 0) {
227 dev_err(codec_dai->dev, "failed to start PLL: %d\n", ret);
228 return -EIO;
229 }
230
231 return ret;
232}
233
234static int broxton_da7219_hw_free(struct snd_pcm_substream *substream)
235{
236 struct snd_soc_pcm_runtime *rtd = substream->private_data;
237 struct snd_soc_dai *codec_dai = rtd->codec_dai;
238 int ret;
239
240 ret = snd_soc_dai_set_pll(codec_dai, 0,
241 DA7219_SYSCLK_MCLK, 0, 0);
242 if (ret < 0) {
243 dev_err(codec_dai->dev, "failed to stop PLL: %d\n", ret);
244 return -EIO;
245 }
246
247 return ret;
248}
249
250static struct snd_soc_ops broxton_da7219_ops = {
251 .hw_params = broxton_da7219_hw_params,
252 .hw_free = broxton_da7219_hw_free,
253};
254
255/* broxton digital audio interface glue - connects codec <--> CPU */
256static struct snd_soc_dai_link broxton_dais[] = {
257 /* Front End DAI links */
258 [BXT_DPCM_AUDIO_PB]
259 {
260 .name = "Bxt Audio Port",
261 .stream_name = "Audio",
262 .cpu_dai_name = "System Pin",
263 .platform_name = "0000:00:0e.0",
264 .dynamic = 1,
265 .codec_name = "snd-soc-dummy",
266 .codec_dai_name = "snd-soc-dummy-dai",
267 .nonatomic = 1,
268 .init = broxton_da7219_fe_init,
269 .trigger = {
270 SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
271 .dpcm_playback = 1,
272 .ops = &broxton_da7219_fe_ops,
273 },
274 [BXT_DPCM_AUDIO_CP]
275 {
276 .name = "Bxt Audio Capture Port",
277 .stream_name = "Audio Record",
278 .cpu_dai_name = "System Pin",
279 .platform_name = "0000:00:0e.0",
280 .dynamic = 1,
281 .codec_name = "snd-soc-dummy",
282 .codec_dai_name = "snd-soc-dummy-dai",
283 .nonatomic = 1,
284 .trigger = {
285 SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
286 .dpcm_capture = 1,
287 .ops = &broxton_da7219_fe_ops,
288 },
289 [BXT_DPCM_AUDIO_REF_CP]
290 {
291 .name = "Bxt Audio Reference cap",
292 .stream_name = "Refcap",
293 .cpu_dai_name = "Reference Pin",
294 .codec_name = "snd-soc-dummy",
295 .codec_dai_name = "snd-soc-dummy-dai",
296 .platform_name = "0000:00:0e.0",
297 .init = NULL,
298 .dpcm_capture = 1,
299 .ignore_suspend = 1,
300 .nonatomic = 1,
301 .dynamic = 1,
302 },
303 [BXT_DPCM_AUDIO_HDMI1_PB]
304 {
305 .name = "Bxt HDMI Port1",
306 .stream_name = "Hdmi1",
307 .cpu_dai_name = "HDMI1 Pin",
308 .codec_name = "snd-soc-dummy",
309 .codec_dai_name = "snd-soc-dummy-dai",
310 .platform_name = "0000:00:0e.0",
311 .dpcm_playback = 1,
312 .init = NULL,
313 .nonatomic = 1,
314 .dynamic = 1,
315 },
316 [BXT_DPCM_AUDIO_HDMI2_PB]
317 {
318 .name = "Bxt HDMI Port2",
319 .stream_name = "Hdmi2",
320 .cpu_dai_name = "HDMI2 Pin",
321 .codec_name = "snd-soc-dummy",
322 .codec_dai_name = "snd-soc-dummy-dai",
323 .platform_name = "0000:00:0e.0",
324 .dpcm_playback = 1,
325 .init = NULL,
326 .nonatomic = 1,
327 .dynamic = 1,
328 },
329 [BXT_DPCM_AUDIO_HDMI3_PB]
330 {
331 .name = "Bxt HDMI Port3",
332 .stream_name = "Hdmi3",
333 .cpu_dai_name = "HDMI3 Pin",
334 .codec_name = "snd-soc-dummy",
335 .codec_dai_name = "snd-soc-dummy-dai",
336 .platform_name = "0000:00:0e.0",
337 .dpcm_playback = 1,
338 .init = NULL,
339 .nonatomic = 1,
340 .dynamic = 1,
341 },
342 /* Back End DAI links */
343 {
344 /* SSP5 - Codec */
345 .name = "SSP5-Codec",
346 .id = 0,
347 .cpu_dai_name = "SSP5 Pin",
348 .platform_name = "0000:00:0e.0",
349 .no_pcm = 1,
350 .codec_name = "MX98357A:00",
351 .codec_dai_name = BXT_MAXIM_CODEC_DAI,
352 .dai_fmt = SND_SOC_DAIFMT_I2S |
353 SND_SOC_DAIFMT_NB_NF |
354 SND_SOC_DAIFMT_CBS_CFS,
355 .ignore_pmdown_time = 1,
356 .be_hw_params_fixup = broxton_ssp_fixup,
357 .dpcm_playback = 1,
358 },
359 {
360 /* SSP1 - Codec */
361 .name = "SSP1-Codec",
362 .id = 1,
363 .cpu_dai_name = "SSP1 Pin",
364 .platform_name = "0000:00:0e.0",
365 .no_pcm = 1,
366 .codec_name = "i2c-DLGS7219:00",
367 .codec_dai_name = BXT_DIALOG_CODEC_DAI,
368 .init = broxton_da7219_codec_init,
369 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
370 SND_SOC_DAIFMT_CBS_CFS,
371 .ignore_pmdown_time = 1,
372 .be_hw_params_fixup = broxton_ssp_fixup,
373 .ops = &broxton_da7219_ops,
374 .dpcm_playback = 1,
375 .dpcm_capture = 1,
376 },
377 {
378 .name = "dmic01",
379 .id = 2,
380 .cpu_dai_name = "DMIC01 Pin",
381 .codec_name = "dmic-codec",
382 .codec_dai_name = "dmic-hifi",
383 .platform_name = "0000:00:0e.0",
384 .ignore_suspend = 1,
385 .dpcm_capture = 1,
386 .no_pcm = 1,
387 },
388 {
389 .name = "iDisp1",
390 .id = 3,
391 .cpu_dai_name = "iDisp1 Pin",
392 .codec_name = "ehdaudio0D2",
393 .codec_dai_name = "intel-hdmi-hifi1",
394 .platform_name = "0000:00:0e.0",
395 .init = broxton_hdmi_init,
396 .dpcm_playback = 1,
397 .no_pcm = 1,
398 },
399 {
400 .name = "iDisp2",
401 .id = 4,
402 .cpu_dai_name = "iDisp2 Pin",
403 .codec_name = "ehdaudio0D2",
404 .codec_dai_name = "intel-hdmi-hifi2",
405 .platform_name = "0000:00:0e.0",
406 .init = broxton_hdmi_init,
407 .dpcm_playback = 1,
408 .no_pcm = 1,
409 },
410 {
411 .name = "iDisp3",
412 .id = 5,
413 .cpu_dai_name = "iDisp3 Pin",
414 .codec_name = "ehdaudio0D2",
415 .codec_dai_name = "intel-hdmi-hifi3",
416 .platform_name = "0000:00:0e.0",
417 .init = broxton_hdmi_init,
418 .dpcm_playback = 1,
419 .no_pcm = 1,
420 },
421};
422
423/* broxton audio machine driver for SPT + da7219 */
424static struct snd_soc_card broxton_audio_card = {
425 .name = "bxtda7219max",
426 .owner = THIS_MODULE,
427 .dai_link = broxton_dais,
428 .num_links = ARRAY_SIZE(broxton_dais),
429 .controls = broxton_controls,
430 .num_controls = ARRAY_SIZE(broxton_controls),
431 .dapm_widgets = broxton_widgets,
432 .num_dapm_widgets = ARRAY_SIZE(broxton_widgets),
433 .dapm_routes = broxton_map,
434 .num_dapm_routes = ARRAY_SIZE(broxton_map),
435 .fully_routed = true,
436};
437
438static int broxton_audio_probe(struct platform_device *pdev)
439{
440 broxton_audio_card.dev = &pdev->dev;
441 return devm_snd_soc_register_card(&pdev->dev, &broxton_audio_card);
442}
443
444static struct platform_driver broxton_audio = {
445 .probe = broxton_audio_probe,
446 .driver = {
447 .name = "bxt_da7219_max98357a_i2s",
448 .pm = &snd_soc_pm_ops,
449 },
450};
451module_platform_driver(broxton_audio)
452
453/* Module information */
454MODULE_DESCRIPTION("Audio Machine driver-DA7219 & MAX98357A in I2S mode");
455MODULE_AUTHOR("Sathyanarayana Nujella <sathyanarayana.nujella@intel.com>");
456MODULE_AUTHOR("Rohit Ainapure <rohit.m.ainapure@intel.com>");
457MODULE_AUTHOR("Harsha Priya <harshapriya.n@intel.com>");
458MODULE_AUTHOR("Conrad Cooke <conrad.cooke@intel.com>");
459MODULE_LICENSE("GPL v2");
460MODULE_ALIAS("platform:bxt_da7219_max98357a_i2s");
diff --git a/sound/soc/intel/boards/bxt_rt298.c b/sound/soc/intel/boards/bxt_rt298.c
index f4787515c0ed..253d7bfbf511 100644
--- a/sound/soc/intel/boards/bxt_rt298.c
+++ b/sound/soc/intel/boards/bxt_rt298.c
@@ -33,6 +33,7 @@ enum {
33 BXT_DPCM_AUDIO_PB = 0, 33 BXT_DPCM_AUDIO_PB = 0,
34 BXT_DPCM_AUDIO_CP, 34 BXT_DPCM_AUDIO_CP,
35 BXT_DPCM_AUDIO_REF_CP, 35 BXT_DPCM_AUDIO_REF_CP,
36 BXT_DPCM_AUDIO_DMIC_CP,
36 BXT_DPCM_AUDIO_HDMI1_PB, 37 BXT_DPCM_AUDIO_HDMI1_PB,
37 BXT_DPCM_AUDIO_HDMI2_PB, 38 BXT_DPCM_AUDIO_HDMI2_PB,
38 BXT_DPCM_AUDIO_HDMI3_PB, 39 BXT_DPCM_AUDIO_HDMI3_PB,
@@ -88,6 +89,7 @@ static const struct snd_soc_dapm_route broxton_rt298_map[] = {
88 /* CODEC BE connections */ 89 /* CODEC BE connections */
89 { "AIF1 Playback", NULL, "ssp5 Tx"}, 90 { "AIF1 Playback", NULL, "ssp5 Tx"},
90 { "ssp5 Tx", NULL, "codec0_out"}, 91 { "ssp5 Tx", NULL, "codec0_out"},
92 { "ssp5 Tx", NULL, "codec1_out"},
91 93
92 { "codec0_in", NULL, "ssp5 Rx" }, 94 { "codec0_in", NULL, "ssp5 Rx" },
93 { "ssp5 Rx", NULL, "AIF1 Capture" }, 95 { "ssp5 Rx", NULL, "AIF1 Capture" },
@@ -104,6 +106,17 @@ static const struct snd_soc_dapm_route broxton_rt298_map[] = {
104 106
105}; 107};
106 108
109static int broxton_rt298_fe_init(struct snd_soc_pcm_runtime *rtd)
110{
111 struct snd_soc_dapm_context *dapm;
112 struct snd_soc_component *component = rtd->cpu_dai->component;
113
114 dapm = snd_soc_component_get_dapm(component);
115 snd_soc_dapm_ignore_suspend(dapm, "Reference Capture");
116
117 return 0;
118}
119
107static int broxton_rt298_codec_init(struct snd_soc_pcm_runtime *rtd) 120static int broxton_rt298_codec_init(struct snd_soc_pcm_runtime *rtd)
108{ 121{
109 struct snd_soc_codec *codec = rtd->codec; 122 struct snd_soc_codec *codec = rtd->codec;
@@ -118,6 +131,9 @@ static int broxton_rt298_codec_init(struct snd_soc_pcm_runtime *rtd)
118 return ret; 131 return ret;
119 132
120 rt298_mic_detect(codec, &broxton_headset); 133 rt298_mic_detect(codec, &broxton_headset);
134
135 snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC");
136
121 return 0; 137 return 0;
122} 138}
123 139
@@ -169,6 +185,89 @@ static struct snd_soc_ops broxton_rt298_ops = {
169 .hw_params = broxton_rt298_hw_params, 185 .hw_params = broxton_rt298_hw_params,
170}; 186};
171 187
188static unsigned int rates[] = {
189 48000,
190};
191
192static struct snd_pcm_hw_constraint_list constraints_rates = {
193 .count = ARRAY_SIZE(rates),
194 .list = rates,
195 .mask = 0,
196};
197
198static int broxton_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
199 struct snd_pcm_hw_params *params)
200{
201 struct snd_interval *channels = hw_param_interval(params,
202 SNDRV_PCM_HW_PARAM_CHANNELS);
203 if (params_channels(params) == 2)
204 channels->min = channels->max = 2;
205 else
206 channels->min = channels->max = 4;
207
208 return 0;
209}
210
211static unsigned int channels_dmic[] = {
212 2, 4,
213};
214
215static struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
216 .count = ARRAY_SIZE(channels_dmic),
217 .list = channels_dmic,
218 .mask = 0,
219};
220
221static int broxton_dmic_startup(struct snd_pcm_substream *substream)
222{
223 struct snd_pcm_runtime *runtime = substream->runtime;
224
225 runtime->hw.channels_max = 4;
226 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
227 &constraints_dmic_channels);
228
229 return snd_pcm_hw_constraint_list(substream->runtime, 0,
230 SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
231}
232
233static struct snd_soc_ops broxton_dmic_ops = {
234 .startup = broxton_dmic_startup,
235};
236
237static unsigned int channels[] = {
238 2,
239};
240
241static struct snd_pcm_hw_constraint_list constraints_channels = {
242 .count = ARRAY_SIZE(channels),
243 .list = channels,
244 .mask = 0,
245};
246
247static int bxt_fe_startup(struct snd_pcm_substream *substream)
248{
249 struct snd_pcm_runtime *runtime = substream->runtime;
250
251 /*
252 * on this platform for PCM device we support:
253 * 48Khz
254 * stereo
255 */
256
257 runtime->hw.channels_max = 2;
258 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
259 &constraints_channels);
260
261 snd_pcm_hw_constraint_list(runtime, 0,
262 SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
263
264 return 0;
265}
266
267static const struct snd_soc_ops broxton_rt286_fe_ops = {
268 .startup = bxt_fe_startup,
269};
270
172/* broxton digital audio interface glue - connects codec <--> CPU */ 271/* broxton digital audio interface glue - connects codec <--> CPU */
173static struct snd_soc_dai_link broxton_rt298_dais[] = { 272static struct snd_soc_dai_link broxton_rt298_dais[] = {
174 /* Front End DAI links */ 273 /* Front End DAI links */
@@ -182,8 +281,10 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = {
182 .dynamic = 1, 281 .dynamic = 1,
183 .codec_name = "snd-soc-dummy", 282 .codec_name = "snd-soc-dummy",
184 .codec_dai_name = "snd-soc-dummy-dai", 283 .codec_dai_name = "snd-soc-dummy-dai",
284 .init = broxton_rt298_fe_init,
185 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, 285 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
186 .dpcm_playback = 1, 286 .dpcm_playback = 1,
287 .ops = &broxton_rt286_fe_ops,
187 }, 288 },
188 [BXT_DPCM_AUDIO_CP] 289 [BXT_DPCM_AUDIO_CP]
189 { 290 {
@@ -197,6 +298,7 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = {
197 .codec_dai_name = "snd-soc-dummy-dai", 298 .codec_dai_name = "snd-soc-dummy-dai",
198 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, 299 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
199 .dpcm_capture = 1, 300 .dpcm_capture = 1,
301 .ops = &broxton_rt286_fe_ops,
200 }, 302 },
201 [BXT_DPCM_AUDIO_REF_CP] 303 [BXT_DPCM_AUDIO_REF_CP]
202 { 304 {
@@ -211,6 +313,20 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = {
211 .nonatomic = 1, 313 .nonatomic = 1,
212 .dynamic = 1, 314 .dynamic = 1,
213 }, 315 },
316 [BXT_DPCM_AUDIO_DMIC_CP]
317 {
318 .name = "Bxt Audio DMIC cap",
319 .stream_name = "dmiccap",
320 .cpu_dai_name = "DMIC Pin",
321 .codec_name = "snd-soc-dummy",
322 .codec_dai_name = "snd-soc-dummy-dai",
323 .platform_name = "0000:00:0e.0",
324 .init = NULL,
325 .dpcm_capture = 1,
326 .nonatomic = 1,
327 .dynamic = 1,
328 .ops = &broxton_dmic_ops,
329 },
214 [BXT_DPCM_AUDIO_HDMI1_PB] 330 [BXT_DPCM_AUDIO_HDMI1_PB]
215 { 331 {
216 .name = "Bxt HDMI Port1", 332 .name = "Bxt HDMI Port1",
@@ -276,6 +392,7 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = {
276 .codec_name = "dmic-codec", 392 .codec_name = "dmic-codec",
277 .codec_dai_name = "dmic-hifi", 393 .codec_dai_name = "dmic-hifi",
278 .platform_name = "0000:00:0e.0", 394 .platform_name = "0000:00:0e.0",
395 .be_hw_params_fixup = broxton_dmic_fixup,
279 .ignore_suspend = 1, 396 .ignore_suspend = 1,
280 .dpcm_capture = 1, 397 .dpcm_capture = 1,
281 .no_pcm = 1, 398 .no_pcm = 1,
@@ -341,6 +458,7 @@ static struct platform_driver broxton_audio = {
341 .probe = broxton_audio_probe, 458 .probe = broxton_audio_probe,
342 .driver = { 459 .driver = {
343 .name = "bxt_alc298s_i2s", 460 .name = "bxt_alc298s_i2s",
461 .pm = &snd_soc_pm_ops,
344 }, 462 },
345}; 463};
346module_platform_driver(broxton_audio) 464module_platform_driver(broxton_audio)
diff --git a/sound/soc/intel/boards/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c
index d7ef292c402d..56056ed7fcfd 100644
--- a/sound/soc/intel/boards/cht_bsw_rt5645.c
+++ b/sound/soc/intel/boards/cht_bsw_rt5645.c
@@ -30,6 +30,7 @@
30#include <sound/jack.h> 30#include <sound/jack.h>
31#include "../../codecs/rt5645.h" 31#include "../../codecs/rt5645.h"
32#include "../atom/sst-atom-controls.h" 32#include "../atom/sst-atom-controls.h"
33#include "../common/sst-acpi.h"
33 34
34#define CHT_PLAT_CLK_3_HZ 19200000 35#define CHT_PLAT_CLK_3_HZ 19200000
35#define CHT_CODEC_DAI "rt5645-aif1" 36#define CHT_CODEC_DAI "rt5645-aif1"
@@ -340,10 +341,13 @@ static struct snd_soc_card snd_soc_card_chtrt5650 = {
340}; 341};
341 342
342static struct cht_acpi_card snd_soc_cards[] = { 343static struct cht_acpi_card snd_soc_cards[] = {
344 {"10EC5640", CODEC_TYPE_RT5645, &snd_soc_card_chtrt5645},
343 {"10EC5645", CODEC_TYPE_RT5645, &snd_soc_card_chtrt5645}, 345 {"10EC5645", CODEC_TYPE_RT5645, &snd_soc_card_chtrt5645},
344 {"10EC5650", CODEC_TYPE_RT5650, &snd_soc_card_chtrt5650}, 346 {"10EC5650", CODEC_TYPE_RT5650, &snd_soc_card_chtrt5650},
345}; 347};
346 348
349static char cht_rt5640_codec_name[16]; /* i2c-<HID>:00 with HID being 8 chars */
350
347static int snd_cht_mc_probe(struct platform_device *pdev) 351static int snd_cht_mc_probe(struct platform_device *pdev)
348{ 352{
349 int ret_val = 0; 353 int ret_val = 0;
@@ -351,6 +355,9 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
351 struct cht_mc_private *drv; 355 struct cht_mc_private *drv;
352 struct snd_soc_card *card = snd_soc_cards[0].soc_card; 356 struct snd_soc_card *card = snd_soc_cards[0].soc_card;
353 char codec_name[16]; 357 char codec_name[16];
358 struct sst_acpi_mach *mach;
359 const char *i2c_name = NULL;
360 int dai_index = 0;
354 361
355 drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC); 362 drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC);
356 if (!drv) 363 if (!drv)
@@ -366,12 +373,23 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
366 } 373 }
367 } 374 }
368 card->dev = &pdev->dev; 375 card->dev = &pdev->dev;
376 mach = card->dev->platform_data;
369 sprintf(codec_name, "i2c-%s:00", drv->acpi_card->codec_id); 377 sprintf(codec_name, "i2c-%s:00", drv->acpi_card->codec_id);
370 378
371 /* set correct codec name */ 379 /* set correct codec name */
372 for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) 380 for (i = 0; i < ARRAY_SIZE(cht_dailink); i++)
373 if (!strcmp(card->dai_link[i].codec_name, "i2c-10EC5645:00")) 381 if (!strcmp(card->dai_link[i].codec_name, "i2c-10EC5645:00")) {
374 card->dai_link[i].codec_name = kstrdup(codec_name, GFP_KERNEL); 382 card->dai_link[i].codec_name = kstrdup(codec_name, GFP_KERNEL);
383 dai_index = i;
384 }
385
386 /* fixup codec name based on HID */
387 i2c_name = sst_acpi_find_name_from_hid(mach->id);
388 if (i2c_name != NULL) {
389 snprintf(cht_rt5640_codec_name, sizeof(cht_rt5640_codec_name),
390 "%s%s", "i2c-", i2c_name);
391 cht_dailink[dai_index].codec_name = cht_rt5640_codec_name;
392 }
375 393
376 snd_soc_card_set_drvdata(card, drv); 394 snd_soc_card_set_drvdata(card, drv);
377 ret_val = devm_snd_soc_register_card(&pdev->dev, card); 395 ret_val = devm_snd_soc_register_card(&pdev->dev, card);
diff --git a/sound/soc/intel/boards/skl_nau88l25_max98357a.c b/sound/soc/intel/boards/skl_nau88l25_max98357a.c
index d2808652b974..25db5be7fdfa 100644
--- a/sound/soc/intel/boards/skl_nau88l25_max98357a.c
+++ b/sound/soc/intel/boards/skl_nau88l25_max98357a.c
@@ -23,12 +23,15 @@
23#include <sound/soc.h> 23#include <sound/soc.h>
24#include "../../codecs/nau8825.h" 24#include "../../codecs/nau8825.h"
25#include "../../codecs/hdac_hdmi.h" 25#include "../../codecs/hdac_hdmi.h"
26#include "../skylake/skl.h"
26 27
27#define SKL_NUVOTON_CODEC_DAI "nau8825-hifi" 28#define SKL_NUVOTON_CODEC_DAI "nau8825-hifi"
28#define SKL_MAXIM_CODEC_DAI "HiFi" 29#define SKL_MAXIM_CODEC_DAI "HiFi"
30#define DMIC_CH(p) p->list[p->count-1]
29 31
30static struct snd_soc_jack skylake_headset; 32static struct snd_soc_jack skylake_headset;
31static struct snd_soc_card skylake_audio_card; 33static struct snd_soc_card skylake_audio_card;
34static const struct snd_pcm_hw_constraint_list *dmic_constraints;
32 35
33struct skl_hdmi_pcm { 36struct skl_hdmi_pcm {
34 struct list_head head; 37 struct list_head head;
@@ -339,7 +342,7 @@ static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
339 struct snd_interval *channels = hw_param_interval(params, 342 struct snd_interval *channels = hw_param_interval(params,
340 SNDRV_PCM_HW_PARAM_CHANNELS); 343 SNDRV_PCM_HW_PARAM_CHANNELS);
341 344
342 if (params_channels(params) == 2) 345 if (params_channels(params) == 2 || DMIC_CH(dmic_constraints) == 2)
343 channels->min = channels->max = 2; 346 channels->min = channels->max = 2;
344 else 347 else
345 channels->min = channels->max = 4; 348 channels->min = channels->max = 4;
@@ -357,13 +360,23 @@ static struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
357 .mask = 0, 360 .mask = 0,
358}; 361};
359 362
363static const unsigned int dmic_2ch[] = {
364 2,
365};
366
367static const struct snd_pcm_hw_constraint_list constraints_dmic_2ch = {
368 .count = ARRAY_SIZE(dmic_2ch),
369 .list = dmic_2ch,
370 .mask = 0,
371};
372
360static int skylake_dmic_startup(struct snd_pcm_substream *substream) 373static int skylake_dmic_startup(struct snd_pcm_substream *substream)
361{ 374{
362 struct snd_pcm_runtime *runtime = substream->runtime; 375 struct snd_pcm_runtime *runtime = substream->runtime;
363 376
364 runtime->hw.channels_max = 4; 377 runtime->hw.channels_max = DMIC_CH(dmic_constraints);
365 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 378 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
366 &constraints_dmic_channels); 379 dmic_constraints);
367 380
368 return snd_pcm_hw_constraint_list(substream->runtime, 0, 381 return snd_pcm_hw_constraint_list(substream->runtime, 0,
369 SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); 382 SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
@@ -382,8 +395,22 @@ static struct snd_pcm_hw_constraint_list constraints_16000 = {
382 .list = rates_16000, 395 .list = rates_16000,
383}; 396};
384 397
398static const unsigned int ch_mono[] = {
399 1,
400};
401
402static const struct snd_pcm_hw_constraint_list constraints_refcap = {
403 .count = ARRAY_SIZE(ch_mono),
404 .list = ch_mono,
405};
406
385static int skylake_refcap_startup(struct snd_pcm_substream *substream) 407static int skylake_refcap_startup(struct snd_pcm_substream *substream)
386{ 408{
409 substream->runtime->hw.channels_max = 1;
410 snd_pcm_hw_constraint_list(substream->runtime, 0,
411 SNDRV_PCM_HW_PARAM_CHANNELS,
412 &constraints_refcap);
413
387 return snd_pcm_hw_constraint_list(substream->runtime, 0, 414 return snd_pcm_hw_constraint_list(substream->runtime, 0,
388 SNDRV_PCM_HW_PARAM_RATE, 415 SNDRV_PCM_HW_PARAM_RATE,
389 &constraints_16000); 416 &constraints_16000);
@@ -610,6 +637,7 @@ static struct snd_soc_card skylake_audio_card = {
610static int skylake_audio_probe(struct platform_device *pdev) 637static int skylake_audio_probe(struct platform_device *pdev)
611{ 638{
612 struct skl_nau8825_private *ctx; 639 struct skl_nau8825_private *ctx;
640 struct skl_machine_pdata *pdata;
613 641
614 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC); 642 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC);
615 if (!ctx) 643 if (!ctx)
@@ -620,15 +648,27 @@ static int skylake_audio_probe(struct platform_device *pdev)
620 skylake_audio_card.dev = &pdev->dev; 648 skylake_audio_card.dev = &pdev->dev;
621 snd_soc_card_set_drvdata(&skylake_audio_card, ctx); 649 snd_soc_card_set_drvdata(&skylake_audio_card, ctx);
622 650
651 pdata = dev_get_drvdata(&pdev->dev);
652 if (pdata)
653 dmic_constraints = pdata->dmic_num == 2 ?
654 &constraints_dmic_2ch : &constraints_dmic_channels;
655
623 return devm_snd_soc_register_card(&pdev->dev, &skylake_audio_card); 656 return devm_snd_soc_register_card(&pdev->dev, &skylake_audio_card);
624} 657}
625 658
659static const struct platform_device_id skl_board_ids[] = {
660 { .name = "skl_n88l25_m98357a" },
661 { .name = "kbl_n88l25_m98357a" },
662 { }
663};
664
626static struct platform_driver skylake_audio = { 665static struct platform_driver skylake_audio = {
627 .probe = skylake_audio_probe, 666 .probe = skylake_audio_probe,
628 .driver = { 667 .driver = {
629 .name = "skl_nau88l25_max98357a_i2s", 668 .name = "skl_n88l25_m98357a",
630 .pm = &snd_soc_pm_ops, 669 .pm = &snd_soc_pm_ops,
631 }, 670 },
671 .id_table = skl_board_ids,
632}; 672};
633 673
634module_platform_driver(skylake_audio) 674module_platform_driver(skylake_audio)
@@ -637,4 +677,5 @@ module_platform_driver(skylake_audio)
637MODULE_DESCRIPTION("Audio Machine driver-NAU88L25 & MAX98357A in I2S mode"); 677MODULE_DESCRIPTION("Audio Machine driver-NAU88L25 & MAX98357A in I2S mode");
638MODULE_AUTHOR("Rohit Ainapure <rohit.m.ainapure@intel.com"); 678MODULE_AUTHOR("Rohit Ainapure <rohit.m.ainapure@intel.com");
639MODULE_LICENSE("GPL v2"); 679MODULE_LICENSE("GPL v2");
640MODULE_ALIAS("platform:skl_nau88l25_max98357a_i2s"); 680MODULE_ALIAS("platform:skl_n88l25_m98357a");
681MODULE_ALIAS("platform:kbl_n88l25_m98357a");
diff --git a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c
index e19aa99c4f72..69c5d5da4e86 100644
--- a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c
+++ b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c
@@ -27,12 +27,15 @@
27#include <sound/pcm_params.h> 27#include <sound/pcm_params.h>
28#include "../../codecs/nau8825.h" 28#include "../../codecs/nau8825.h"
29#include "../../codecs/hdac_hdmi.h" 29#include "../../codecs/hdac_hdmi.h"
30#include "../skylake/skl.h"
30 31
31#define SKL_NUVOTON_CODEC_DAI "nau8825-hifi" 32#define SKL_NUVOTON_CODEC_DAI "nau8825-hifi"
32#define SKL_SSM_CODEC_DAI "ssm4567-hifi" 33#define SKL_SSM_CODEC_DAI "ssm4567-hifi"
34#define DMIC_CH(p) p->list[p->count-1]
33 35
34static struct snd_soc_jack skylake_headset; 36static struct snd_soc_jack skylake_headset;
35static struct snd_soc_card skylake_audio_card; 37static struct snd_soc_card skylake_audio_card;
38static const struct snd_pcm_hw_constraint_list *dmic_constraints;
36 39
37struct skl_hdmi_pcm { 40struct skl_hdmi_pcm {
38 struct list_head head; 41 struct list_head head;
@@ -367,7 +370,7 @@ static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
367{ 370{
368 struct snd_interval *channels = hw_param_interval(params, 371 struct snd_interval *channels = hw_param_interval(params,
369 SNDRV_PCM_HW_PARAM_CHANNELS); 372 SNDRV_PCM_HW_PARAM_CHANNELS);
370 if (params_channels(params) == 2) 373 if (params_channels(params) == 2 || DMIC_CH(dmic_constraints) == 2)
371 channels->min = channels->max = 2; 374 channels->min = channels->max = 2;
372 else 375 else
373 channels->min = channels->max = 4; 376 channels->min = channels->max = 4;
@@ -405,13 +408,23 @@ static struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
405 .mask = 0, 408 .mask = 0,
406}; 409};
407 410
411static const unsigned int dmic_2ch[] = {
412 2,
413};
414
415static const struct snd_pcm_hw_constraint_list constraints_dmic_2ch = {
416 .count = ARRAY_SIZE(dmic_2ch),
417 .list = dmic_2ch,
418 .mask = 0,
419};
420
408static int skylake_dmic_startup(struct snd_pcm_substream *substream) 421static int skylake_dmic_startup(struct snd_pcm_substream *substream)
409{ 422{
410 struct snd_pcm_runtime *runtime = substream->runtime; 423 struct snd_pcm_runtime *runtime = substream->runtime;
411 424
412 runtime->hw.channels_max = 4; 425 runtime->hw.channels_max = DMIC_CH(dmic_constraints);
413 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 426 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
414 &constraints_dmic_channels); 427 dmic_constraints);
415 428
416 return snd_pcm_hw_constraint_list(substream->runtime, 0, 429 return snd_pcm_hw_constraint_list(substream->runtime, 0,
417 SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); 430 SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
@@ -430,8 +443,22 @@ static struct snd_pcm_hw_constraint_list constraints_16000 = {
430 .list = rates_16000, 443 .list = rates_16000,
431}; 444};
432 445
446static const unsigned int ch_mono[] = {
447 1,
448};
449
450static const struct snd_pcm_hw_constraint_list constraints_refcap = {
451 .count = ARRAY_SIZE(ch_mono),
452 .list = ch_mono,
453};
454
433static int skylake_refcap_startup(struct snd_pcm_substream *substream) 455static int skylake_refcap_startup(struct snd_pcm_substream *substream)
434{ 456{
457 substream->runtime->hw.channels_max = 1;
458 snd_pcm_hw_constraint_list(substream->runtime, 0,
459 SNDRV_PCM_HW_PARAM_CHANNELS,
460 &constraints_refcap);
461
435 return snd_pcm_hw_constraint_list(substream->runtime, 0, 462 return snd_pcm_hw_constraint_list(substream->runtime, 0,
436 SNDRV_PCM_HW_PARAM_RATE, 463 SNDRV_PCM_HW_PARAM_RATE,
437 &constraints_16000); 464 &constraints_16000);
@@ -662,6 +689,7 @@ static struct snd_soc_card skylake_audio_card = {
662static int skylake_audio_probe(struct platform_device *pdev) 689static int skylake_audio_probe(struct platform_device *pdev)
663{ 690{
664 struct skl_nau88125_private *ctx; 691 struct skl_nau88125_private *ctx;
692 struct skl_machine_pdata *pdata;
665 693
666 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC); 694 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC);
667 if (!ctx) 695 if (!ctx)
@@ -672,15 +700,27 @@ static int skylake_audio_probe(struct platform_device *pdev)
672 skylake_audio_card.dev = &pdev->dev; 700 skylake_audio_card.dev = &pdev->dev;
673 snd_soc_card_set_drvdata(&skylake_audio_card, ctx); 701 snd_soc_card_set_drvdata(&skylake_audio_card, ctx);
674 702
703 pdata = dev_get_drvdata(&pdev->dev);
704 if (pdata)
705 dmic_constraints = pdata->dmic_num == 2 ?
706 &constraints_dmic_2ch : &constraints_dmic_channels;
707
675 return devm_snd_soc_register_card(&pdev->dev, &skylake_audio_card); 708 return devm_snd_soc_register_card(&pdev->dev, &skylake_audio_card);
676} 709}
677 710
711static const struct platform_device_id skl_board_ids[] = {
712 { .name = "skl_n88l25_s4567" },
713 { .name = "kbl_n88l25_s4567" },
714 { }
715};
716
678static struct platform_driver skylake_audio = { 717static struct platform_driver skylake_audio = {
679 .probe = skylake_audio_probe, 718 .probe = skylake_audio_probe,
680 .driver = { 719 .driver = {
681 .name = "skl_nau88l25_ssm4567_i2s", 720 .name = "skl_n88l25_s4567",
682 .pm = &snd_soc_pm_ops, 721 .pm = &snd_soc_pm_ops,
683 }, 722 },
723 .id_table = skl_board_ids,
684}; 724};
685 725
686module_platform_driver(skylake_audio) 726module_platform_driver(skylake_audio)
@@ -693,4 +733,5 @@ MODULE_AUTHOR("Sathya Prakash M R <sathya.prakash.m.r@intel.com>");
693MODULE_AUTHOR("Yong Zhi <yong.zhi@intel.com>"); 733MODULE_AUTHOR("Yong Zhi <yong.zhi@intel.com>");
694MODULE_DESCRIPTION("Intel Audio Machine driver for SKL with NAU88L25 and SSM4567 in I2S Mode"); 734MODULE_DESCRIPTION("Intel Audio Machine driver for SKL with NAU88L25 and SSM4567 in I2S Mode");
695MODULE_LICENSE("GPL v2"); 735MODULE_LICENSE("GPL v2");
696MODULE_ALIAS("platform:skl_nau88l25_ssm4567_i2s"); 736MODULE_ALIAS("platform:skl_n88l25_s4567");
737MODULE_ALIAS("platform:kbl_n88l25_s4567");
diff --git a/sound/soc/intel/boards/skl_rt286.c b/sound/soc/intel/boards/skl_rt286.c
index 426b48233fdb..88c61e8cb87f 100644
--- a/sound/soc/intel/boards/skl_rt286.c
+++ b/sound/soc/intel/boards/skl_rt286.c
@@ -505,12 +505,20 @@ static int skylake_audio_probe(struct platform_device *pdev)
505 return devm_snd_soc_register_card(&pdev->dev, &skylake_rt286); 505 return devm_snd_soc_register_card(&pdev->dev, &skylake_rt286);
506} 506}
507 507
508static const struct platform_device_id skl_board_ids[] = {
509 { .name = "skl_alc286s_i2s" },
510 { .name = "kbl_alc286s_i2s" },
511 { }
512};
513
508static struct platform_driver skylake_audio = { 514static struct platform_driver skylake_audio = {
509 .probe = skylake_audio_probe, 515 .probe = skylake_audio_probe,
510 .driver = { 516 .driver = {
511 .name = "skl_alc286s_i2s", 517 .name = "skl_alc286s_i2s",
512 .pm = &snd_soc_pm_ops, 518 .pm = &snd_soc_pm_ops,
513 }, 519 },
520 .id_table = skl_board_ids,
521
514}; 522};
515 523
516module_platform_driver(skylake_audio) 524module_platform_driver(skylake_audio)
@@ -520,3 +528,4 @@ MODULE_AUTHOR("Omair Mohammed Abdullah <omair.m.abdullah@intel.com>");
520MODULE_DESCRIPTION("Intel SST Audio for Skylake"); 528MODULE_DESCRIPTION("Intel SST Audio for Skylake");
521MODULE_LICENSE("GPL v2"); 529MODULE_LICENSE("GPL v2");
522MODULE_ALIAS("platform:skl_alc286s_i2s"); 530MODULE_ALIAS("platform:skl_alc286s_i2s");
531MODULE_ALIAS("platform:kbl_alc286s_i2s");
diff --git a/sound/soc/intel/common/Makefile b/sound/soc/intel/common/Makefile
index fbbb25c2ceed..1a35149bcad7 100644
--- a/sound/soc/intel/common/Makefile
+++ b/sound/soc/intel/common/Makefile
@@ -2,9 +2,9 @@ snd-soc-sst-dsp-objs := sst-dsp.o
2snd-soc-sst-acpi-objs := sst-acpi.o 2snd-soc-sst-acpi-objs := sst-acpi.o
3snd-soc-sst-match-objs := sst-match-acpi.o 3snd-soc-sst-match-objs := sst-match-acpi.o
4snd-soc-sst-ipc-objs := sst-ipc.o 4snd-soc-sst-ipc-objs := sst-ipc.o
5 5snd-soc-sst-firmware-objs := sst-firmware.o
6snd-soc-sst-dsp-$(CONFIG_DW_DMAC_CORE) += sst-firmware.o
7 6
8obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o snd-soc-sst-ipc.o 7obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o snd-soc-sst-ipc.o
9obj-$(CONFIG_SND_SOC_INTEL_SST_ACPI) += snd-soc-sst-acpi.o 8obj-$(CONFIG_SND_SOC_INTEL_SST_ACPI) += snd-soc-sst-acpi.o
10obj-$(CONFIG_SND_SOC_INTEL_SST_MATCH) += snd-soc-sst-match.o 9obj-$(CONFIG_SND_SOC_INTEL_SST_MATCH) += snd-soc-sst-match.o
10obj-$(CONFIG_SND_SOC_INTEL_SST_FIRMWARE) += snd-soc-sst-firmware.o
diff --git a/sound/soc/intel/common/sst-acpi.h b/sound/soc/intel/common/sst-acpi.h
index 8398cb227ba9..5d2949324d0e 100644
--- a/sound/soc/intel/common/sst-acpi.h
+++ b/sound/soc/intel/common/sst-acpi.h
@@ -20,7 +20,7 @@
20#if IS_ENABLED(CONFIG_ACPI) 20#if IS_ENABLED(CONFIG_ACPI)
21const char *sst_acpi_find_name_from_hid(const u8 hid[ACPI_ID_LEN]); 21const char *sst_acpi_find_name_from_hid(const u8 hid[ACPI_ID_LEN]);
22#else 22#else
23inline const char *sst_acpi_find_name_from_hid(const u8 hid[ACPI_ID_LEN]) 23static inline const char *sst_acpi_find_name_from_hid(const u8 hid[ACPI_ID_LEN])
24{ 24{
25 return NULL; 25 return NULL;
26} 26}
@@ -40,6 +40,6 @@ struct sst_acpi_mach {
40 40
41 /* board name */ 41 /* board name */
42 const char *board; 42 const char *board;
43 void (*machine_quirk)(void); 43 struct sst_acpi_mach * (*machine_quirk)(void *arg);
44 void *pdata; 44 void *pdata;
45}; 45};
diff --git a/sound/soc/intel/common/sst-dsp-priv.h b/sound/soc/intel/common/sst-dsp-priv.h
index 97dc1ae05e69..d13c84364c3c 100644
--- a/sound/soc/intel/common/sst-dsp-priv.h
+++ b/sound/soc/intel/common/sst-dsp-priv.h
@@ -383,10 +383,6 @@ struct sst_mem_block *sst_mem_block_register(struct sst_dsp *dsp, u32 offset,
383 u32 index, void *private); 383 u32 index, void *private);
384void sst_mem_block_unregister_all(struct sst_dsp *dsp); 384void sst_mem_block_unregister_all(struct sst_dsp *dsp);
385 385
386/* Create/Free DMA resources */
387int sst_dma_new(struct sst_dsp *sst);
388void sst_dma_free(struct sst_dma *dma);
389
390u32 sst_dsp_get_offset(struct sst_dsp *dsp, u32 offset, 386u32 sst_dsp_get_offset(struct sst_dsp *dsp, u32 offset,
391 enum sst_mem_type type); 387 enum sst_mem_type type);
392#endif 388#endif
diff --git a/sound/soc/intel/common/sst-dsp.c b/sound/soc/intel/common/sst-dsp.c
index b5bbdf4fe93a..c00ede4ea4d7 100644
--- a/sound/soc/intel/common/sst-dsp.c
+++ b/sound/soc/intel/common/sst-dsp.c
@@ -285,7 +285,7 @@ int sst_dsp_register_poll(struct sst_dsp *ctx, u32 offset, u32 mask,
285 } 285 }
286 286
287 reg = sst_dsp_shim_read_unlocked(ctx, offset); 287 reg = sst_dsp_shim_read_unlocked(ctx, offset);
288 dev_info(ctx->dev, "FW Poll Status: reg=%#x %s %s\n", reg, operation, 288 dev_dbg(ctx->dev, "FW Poll Status: reg=%#x %s %s\n", reg, operation,
289 (time < timeout) ? "successful" : "timedout"); 289 (time < timeout) ? "successful" : "timedout");
290 ret = time < timeout ? 0 : -ETIME; 290 ret = time < timeout ? 0 : -ETIME;
291 291
@@ -420,73 +420,6 @@ void sst_dsp_inbox_read(struct sst_dsp *sst, void *message, size_t bytes)
420} 420}
421EXPORT_SYMBOL_GPL(sst_dsp_inbox_read); 421EXPORT_SYMBOL_GPL(sst_dsp_inbox_read);
422 422
423#ifdef CONFIG_DW_DMAC_CORE
424struct sst_dsp *sst_dsp_new(struct device *dev,
425 struct sst_dsp_device *sst_dev, struct sst_pdata *pdata)
426{
427 struct sst_dsp *sst;
428 int err;
429
430 dev_dbg(dev, "initialising audio DSP id 0x%x\n", pdata->id);
431
432 sst = devm_kzalloc(dev, sizeof(*sst), GFP_KERNEL);
433 if (sst == NULL)
434 return NULL;
435
436 spin_lock_init(&sst->spinlock);
437 mutex_init(&sst->mutex);
438 sst->dev = dev;
439 sst->dma_dev = pdata->dma_dev;
440 sst->thread_context = sst_dev->thread_context;
441 sst->sst_dev = sst_dev;
442 sst->id = pdata->id;
443 sst->irq = pdata->irq;
444 sst->ops = sst_dev->ops;
445 sst->pdata = pdata;
446 INIT_LIST_HEAD(&sst->used_block_list);
447 INIT_LIST_HEAD(&sst->free_block_list);
448 INIT_LIST_HEAD(&sst->module_list);
449 INIT_LIST_HEAD(&sst->fw_list);
450 INIT_LIST_HEAD(&sst->scratch_block_list);
451
452 /* Initialise SST Audio DSP */
453 if (sst->ops->init) {
454 err = sst->ops->init(sst, pdata);
455 if (err < 0)
456 return NULL;
457 }
458
459 /* Register the ISR */
460 err = request_threaded_irq(sst->irq, sst->ops->irq_handler,
461 sst_dev->thread, IRQF_SHARED, "AudioDSP", sst);
462 if (err)
463 goto irq_err;
464
465 err = sst_dma_new(sst);
466 if (err)
467 dev_warn(dev, "sst_dma_new failed %d\n", err);
468
469 return sst;
470
471irq_err:
472 if (sst->ops->free)
473 sst->ops->free(sst);
474
475 return NULL;
476}
477EXPORT_SYMBOL_GPL(sst_dsp_new);
478
479void sst_dsp_free(struct sst_dsp *sst)
480{
481 free_irq(sst->irq, sst);
482 if (sst->ops->free)
483 sst->ops->free(sst);
484
485 sst_dma_free(sst->dma);
486}
487EXPORT_SYMBOL_GPL(sst_dsp_free);
488#endif
489
490/* Module information */ 423/* Module information */
491MODULE_AUTHOR("Liam Girdwood"); 424MODULE_AUTHOR("Liam Girdwood");
492MODULE_DESCRIPTION("Intel SST Core"); 425MODULE_DESCRIPTION("Intel SST Core");
diff --git a/sound/soc/intel/common/sst-dsp.h b/sound/soc/intel/common/sst-dsp.h
index 0b84c719ec48..859f0de00339 100644
--- a/sound/soc/intel/common/sst-dsp.h
+++ b/sound/soc/intel/common/sst-dsp.h
@@ -216,7 +216,7 @@ struct sst_pdata {
216 void *dsp; 216 void *dsp;
217}; 217};
218 218
219#ifdef CONFIG_DW_DMAC_CORE 219#if IS_ENABLED(CONFIG_DW_DMAC_CORE)
220/* Initialization */ 220/* Initialization */
221struct sst_dsp *sst_dsp_new(struct device *dev, 221struct sst_dsp *sst_dsp_new(struct device *dev,
222 struct sst_dsp_device *sst_dev, struct sst_pdata *pdata); 222 struct sst_dsp_device *sst_dev, struct sst_pdata *pdata);
diff --git a/sound/soc/intel/common/sst-firmware.c b/sound/soc/intel/common/sst-firmware.c
index 25993527370b..a086c35f91bb 100644
--- a/sound/soc/intel/common/sst-firmware.c
+++ b/sound/soc/intel/common/sst-firmware.c
@@ -1211,3 +1211,71 @@ u32 sst_dsp_get_offset(struct sst_dsp *dsp, u32 offset,
1211 } 1211 }
1212} 1212}
1213EXPORT_SYMBOL_GPL(sst_dsp_get_offset); 1213EXPORT_SYMBOL_GPL(sst_dsp_get_offset);
1214
1215struct sst_dsp *sst_dsp_new(struct device *dev,
1216 struct sst_dsp_device *sst_dev, struct sst_pdata *pdata)
1217{
1218 struct sst_dsp *sst;
1219 int err;
1220
1221 dev_dbg(dev, "initialising audio DSP id 0x%x\n", pdata->id);
1222
1223 sst = devm_kzalloc(dev, sizeof(*sst), GFP_KERNEL);
1224 if (sst == NULL)
1225 return NULL;
1226
1227 spin_lock_init(&sst->spinlock);
1228 mutex_init(&sst->mutex);
1229 sst->dev = dev;
1230 sst->dma_dev = pdata->dma_dev;
1231 sst->thread_context = sst_dev->thread_context;
1232 sst->sst_dev = sst_dev;
1233 sst->id = pdata->id;
1234 sst->irq = pdata->irq;
1235 sst->ops = sst_dev->ops;
1236 sst->pdata = pdata;
1237 INIT_LIST_HEAD(&sst->used_block_list);
1238 INIT_LIST_HEAD(&sst->free_block_list);
1239 INIT_LIST_HEAD(&sst->module_list);
1240 INIT_LIST_HEAD(&sst->fw_list);
1241 INIT_LIST_HEAD(&sst->scratch_block_list);
1242
1243 /* Initialise SST Audio DSP */
1244 if (sst->ops->init) {
1245 err = sst->ops->init(sst, pdata);
1246 if (err < 0)
1247 return NULL;
1248 }
1249
1250 /* Register the ISR */
1251 err = request_threaded_irq(sst->irq, sst->ops->irq_handler,
1252 sst_dev->thread, IRQF_SHARED, "AudioDSP", sst);
1253 if (err)
1254 goto irq_err;
1255
1256 err = sst_dma_new(sst);
1257 if (err)
1258 dev_warn(dev, "sst_dma_new failed %d\n", err);
1259
1260 return sst;
1261
1262irq_err:
1263 if (sst->ops->free)
1264 sst->ops->free(sst);
1265
1266 return NULL;
1267}
1268EXPORT_SYMBOL_GPL(sst_dsp_new);
1269
1270void sst_dsp_free(struct sst_dsp *sst)
1271{
1272 free_irq(sst->irq, sst);
1273 if (sst->ops->free)
1274 sst->ops->free(sst);
1275
1276 sst_dma_free(sst->dma);
1277}
1278EXPORT_SYMBOL_GPL(sst_dsp_free);
1279
1280MODULE_DESCRIPTION("Intel SST Firmware Loader");
1281MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/intel/haswell/sst-haswell-pcm.c b/sound/soc/intel/haswell/sst-haswell-pcm.c
index 994256b39b9c..3154525c2b83 100644
--- a/sound/soc/intel/haswell/sst-haswell-pcm.c
+++ b/sound/soc/intel/haswell/sst-haswell-pcm.c
@@ -819,7 +819,6 @@ static int hsw_pcm_open(struct snd_pcm_substream *substream)
819 mutex_lock(&pcm_data->mutex); 819 mutex_lock(&pcm_data->mutex);
820 pm_runtime_get_sync(pdata->dev); 820 pm_runtime_get_sync(pdata->dev);
821 821
822 snd_soc_pcm_set_drvdata(rtd, pcm_data);
823 pcm_data->substream = substream; 822 pcm_data->substream = substream;
824 823
825 snd_soc_set_runtime_hwparams(substream, &hsw_pcm_hardware); 824 snd_soc_set_runtime_hwparams(substream, &hsw_pcm_hardware);
diff --git a/sound/soc/intel/skylake/Makefile b/sound/soc/intel/skylake/Makefile
index c28f5d0e1d99..60fbc9bbe473 100644
--- a/sound/soc/intel/skylake/Makefile
+++ b/sound/soc/intel/skylake/Makefile
@@ -5,6 +5,6 @@ obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl.o
5 5
6# Skylake IPC Support 6# Skylake IPC Support
7snd-soc-skl-ipc-objs := skl-sst-ipc.o skl-sst-dsp.o skl-sst-cldma.o \ 7snd-soc-skl-ipc-objs := skl-sst-ipc.o skl-sst-dsp.o skl-sst-cldma.o \
8 skl-sst.o bxt-sst.o 8 skl-sst.o bxt-sst.o skl-sst-utils.o
9 9
10obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl-ipc.o 10obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl-ipc.o
diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c
index 8b95e09e23e8..2663781278aa 100644
--- a/sound/soc/intel/skylake/bxt-sst.c
+++ b/sound/soc/intel/skylake/bxt-sst.c
@@ -37,11 +37,19 @@
37 37
38#define BXT_ADSP_SRAM1_BASE 0xA0000 38#define BXT_ADSP_SRAM1_BASE 0xA0000
39 39
40#define BXT_INSTANCE_ID 0
41#define BXT_BASE_FW_MODULE_ID 0
42
40static unsigned int bxt_get_errorcode(struct sst_dsp *ctx) 43static unsigned int bxt_get_errorcode(struct sst_dsp *ctx)
41{ 44{
42 return sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE); 45 return sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE);
43} 46}
44 47
48/*
49 * First boot sequence has some extra steps. Core 0 waits for power
50 * status on core 1, so power up core 1 also momentarily, keep it in
51 * reset/stall and then turn it off
52 */
45static int sst_bxt_prepare_fw(struct sst_dsp *ctx, 53static int sst_bxt_prepare_fw(struct sst_dsp *ctx,
46 const void *fwdata, u32 fwsize) 54 const void *fwdata, u32 fwsize)
47{ 55{
@@ -49,7 +57,7 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx,
49 u32 reg; 57 u32 reg;
50 58
51 stream_tag = ctx->dsp_ops.prepare(ctx->dev, 0x40, fwsize, &ctx->dmab); 59 stream_tag = ctx->dsp_ops.prepare(ctx->dev, 0x40, fwsize, &ctx->dmab);
52 if (stream_tag < 0) { 60 if (stream_tag <= 0) {
53 dev_err(ctx->dev, "Failed to prepare DMA FW loading err: %x\n", 61 dev_err(ctx->dev, "Failed to prepare DMA FW loading err: %x\n",
54 stream_tag); 62 stream_tag);
55 return stream_tag; 63 return stream_tag;
@@ -58,17 +66,27 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx,
58 ctx->dsp_ops.stream_tag = stream_tag; 66 ctx->dsp_ops.stream_tag = stream_tag;
59 memcpy(ctx->dmab.area, fwdata, fwsize); 67 memcpy(ctx->dmab.area, fwdata, fwsize);
60 68
61 /* Purge FW request */ 69 /* Step 1: Power up core 0 and core1 */
70 ret = skl_dsp_core_power_up(ctx, SKL_DSP_CORE0_MASK |
71 SKL_DSP_CORE_MASK(1));
72 if (ret < 0) {
73 dev_err(ctx->dev, "dsp core0/1 power up failed\n");
74 goto base_fw_load_failed;
75 }
76
77 /* Step 2: Purge FW request */
62 sst_dsp_shim_write(ctx, SKL_ADSP_REG_HIPCI, SKL_ADSP_REG_HIPCI_BUSY | 78 sst_dsp_shim_write(ctx, SKL_ADSP_REG_HIPCI, SKL_ADSP_REG_HIPCI_BUSY |
63 BXT_IPC_PURGE_FW | (stream_tag - 1)); 79 (BXT_IPC_PURGE_FW | ((stream_tag - 1) << 9)));
64 80
65 ret = skl_dsp_enable_core(ctx); 81 /* Step 3: Unset core0 reset state & unstall/run core0 */
82 ret = skl_dsp_start_core(ctx, SKL_DSP_CORE0_MASK);
66 if (ret < 0) { 83 if (ret < 0) {
67 dev_err(ctx->dev, "Boot dsp core failed ret: %d\n", ret); 84 dev_err(ctx->dev, "Start dsp core failed ret: %d\n", ret);
68 ret = -EIO; 85 ret = -EIO;
69 goto base_fw_load_failed; 86 goto base_fw_load_failed;
70 } 87 }
71 88
89 /* Step 4: Wait for DONE Bit */
72 for (i = BXT_INIT_TIMEOUT; i > 0; --i) { 90 for (i = BXT_INIT_TIMEOUT; i > 0; --i) {
73 reg = sst_dsp_shim_read(ctx, SKL_ADSP_REG_HIPCIE); 91 reg = sst_dsp_shim_read(ctx, SKL_ADSP_REG_HIPCIE);
74 92
@@ -88,10 +106,18 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx,
88 SKL_ADSP_REG_HIPCIE_DONE); 106 SKL_ADSP_REG_HIPCIE_DONE);
89 } 107 }
90 108
91 /* enable Interrupt */ 109 /* Step 5: power down core1 */
110 ret = skl_dsp_core_power_down(ctx, SKL_DSP_CORE_MASK(1));
111 if (ret < 0) {
112 dev_err(ctx->dev, "dsp core1 power down failed\n");
113 goto base_fw_load_failed;
114 }
115
116 /* Step 6: Enable Interrupt */
92 skl_ipc_int_enable(ctx); 117 skl_ipc_int_enable(ctx);
93 skl_ipc_op_int_enable(ctx); 118 skl_ipc_op_int_enable(ctx);
94 119
120 /* Step 7: Wait for ROM init */
95 for (i = BXT_INIT_TIMEOUT; i > 0; --i) { 121 for (i = BXT_INIT_TIMEOUT; i > 0; --i) {
96 if (SKL_FW_INIT == 122 if (SKL_FW_INIT ==
97 (sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS) & 123 (sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS) &
@@ -112,7 +138,8 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx,
112 138
113base_fw_load_failed: 139base_fw_load_failed:
114 ctx->dsp_ops.cleanup(ctx->dev, &ctx->dmab, stream_tag); 140 ctx->dsp_ops.cleanup(ctx->dev, &ctx->dmab, stream_tag);
115 skl_dsp_disable_core(ctx); 141 skl_dsp_core_power_down(ctx, SKL_DSP_CORE_MASK(1));
142 skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
116 return ret; 143 return ret;
117} 144}
118 145
@@ -130,23 +157,41 @@ static int sst_transfer_fw_host_dma(struct sst_dsp *ctx)
130 return ret; 157 return ret;
131} 158}
132 159
160#define BXT_ADSP_FW_BIN_HDR_OFFSET 0x2000
161
133static int bxt_load_base_firmware(struct sst_dsp *ctx) 162static int bxt_load_base_firmware(struct sst_dsp *ctx)
134{ 163{
135 const struct firmware *fw = NULL; 164 struct firmware stripped_fw;
136 struct skl_sst *skl = ctx->thread_context; 165 struct skl_sst *skl = ctx->thread_context;
137 int ret; 166 int ret;
138 167
139 ret = request_firmware(&fw, ctx->fw_name, ctx->dev); 168 ret = request_firmware(&ctx->fw, ctx->fw_name, ctx->dev);
140 if (ret < 0) { 169 if (ret < 0) {
141 dev_err(ctx->dev, "Request firmware failed %d\n", ret); 170 dev_err(ctx->dev, "Request firmware failed %d\n", ret);
142 goto sst_load_base_firmware_failed; 171 goto sst_load_base_firmware_failed;
143 } 172 }
144 173
145 ret = sst_bxt_prepare_fw(ctx, fw->data, fw->size); 174 /* check for extended manifest */
175 if (ctx->fw == NULL)
176 goto sst_load_base_firmware_failed;
177
178 ret = snd_skl_parse_uuids(ctx, BXT_ADSP_FW_BIN_HDR_OFFSET);
179 if (ret < 0)
180 goto sst_load_base_firmware_failed;
181
182 stripped_fw.data = ctx->fw->data;
183 stripped_fw.size = ctx->fw->size;
184 skl_dsp_strip_extended_manifest(&stripped_fw);
185
186 ret = sst_bxt_prepare_fw(ctx, stripped_fw.data, stripped_fw.size);
146 /* Retry Enabling core and ROM load. Retry seemed to help */ 187 /* Retry Enabling core and ROM load. Retry seemed to help */
147 if (ret < 0) { 188 if (ret < 0) {
148 ret = sst_bxt_prepare_fw(ctx, fw->data, fw->size); 189 ret = sst_bxt_prepare_fw(ctx, stripped_fw.data, stripped_fw.size);
149 if (ret < 0) { 190 if (ret < 0) {
191 dev_err(ctx->dev, "Error code=0x%x: FW status=0x%x\n",
192 sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE),
193 sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS));
194
150 dev_err(ctx->dev, "Core En/ROM load fail:%d\n", ret); 195 dev_err(ctx->dev, "Core En/ROM load fail:%d\n", ret);
151 goto sst_load_base_firmware_failed; 196 goto sst_load_base_firmware_failed;
152 } 197 }
@@ -159,83 +204,135 @@ static int bxt_load_base_firmware(struct sst_dsp *ctx)
159 sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE), 204 sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE),
160 sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS)); 205 sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS));
161 206
162 skl_dsp_disable_core(ctx); 207 skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
163 } else { 208 } else {
164 dev_dbg(ctx->dev, "Firmware download successful\n"); 209 dev_dbg(ctx->dev, "Firmware download successful\n");
165 ret = wait_event_timeout(skl->boot_wait, skl->boot_complete, 210 ret = wait_event_timeout(skl->boot_wait, skl->boot_complete,
166 msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); 211 msecs_to_jiffies(SKL_IPC_BOOT_MSECS));
167 if (ret == 0) { 212 if (ret == 0) {
168 dev_err(ctx->dev, "DSP boot fail, FW Ready timeout\n"); 213 dev_err(ctx->dev, "DSP boot fail, FW Ready timeout\n");
169 skl_dsp_disable_core(ctx); 214 skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
170 ret = -EIO; 215 ret = -EIO;
171 } else { 216 } else {
172 skl_dsp_set_state_locked(ctx, SKL_DSP_RUNNING);
173 ret = 0; 217 ret = 0;
218 skl->fw_loaded = true;
174 } 219 }
175 } 220 }
176 221
177sst_load_base_firmware_failed: 222sst_load_base_firmware_failed:
178 release_firmware(fw); 223 release_firmware(ctx->fw);
179 return ret; 224 return ret;
180} 225}
181 226
182static int bxt_set_dsp_D0(struct sst_dsp *ctx) 227static int bxt_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id)
183{ 228{
184 struct skl_sst *skl = ctx->thread_context; 229 struct skl_sst *skl = ctx->thread_context;
185 int ret; 230 int ret;
231 struct skl_ipc_dxstate_info dx;
232 unsigned int core_mask = SKL_DSP_CORE_MASK(core_id);
186 233
187 skl->boot_complete = false; 234 if (skl->fw_loaded == false) {
188 235 skl->boot_complete = false;
189 ret = skl_dsp_enable_core(ctx); 236 ret = bxt_load_base_firmware(ctx);
190 if (ret < 0) { 237 if (ret < 0)
191 dev_err(ctx->dev, "enable dsp core failed ret: %d\n", ret); 238 dev_err(ctx->dev, "reload fw failed: %d\n", ret);
192 return ret; 239 return ret;
193 } 240 }
194 241
195 /* enable interrupt */ 242 /* If core 0 is being turned on, turn on core 1 as well */
196 skl_ipc_int_enable(ctx); 243 if (core_id == SKL_DSP_CORE0_ID)
197 skl_ipc_op_int_enable(ctx); 244 ret = skl_dsp_core_power_up(ctx, core_mask |
245 SKL_DSP_CORE_MASK(1));
246 else
247 ret = skl_dsp_core_power_up(ctx, core_mask);
248
249 if (ret < 0)
250 goto err;
251
252 if (core_id == SKL_DSP_CORE0_ID) {
253
254 /*
255 * Enable interrupt after SPA is set and before
256 * DSP is unstalled
257 */
258 skl_ipc_int_enable(ctx);
259 skl_ipc_op_int_enable(ctx);
260 skl->boot_complete = false;
261 }
198 262
199 ret = wait_event_timeout(skl->boot_wait, skl->boot_complete, 263 ret = skl_dsp_start_core(ctx, core_mask);
200 msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); 264 if (ret < 0)
201 if (ret == 0) { 265 goto err;
202 dev_err(ctx->dev, "ipc: error DSP boot timeout\n"); 266
203 dev_err(ctx->dev, "Error code=0x%x: FW status=0x%x\n", 267 if (core_id == SKL_DSP_CORE0_ID) {
204 sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE), 268 ret = wait_event_timeout(skl->boot_wait,
205 sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS)); 269 skl->boot_complete,
206 return -EIO; 270 msecs_to_jiffies(SKL_IPC_BOOT_MSECS));
271
272 /* If core 1 was turned on for booting core 0, turn it off */
273 skl_dsp_core_power_down(ctx, SKL_DSP_CORE_MASK(1));
274 if (ret == 0) {
275 dev_err(ctx->dev, "%s: DSP boot timeout\n", __func__);
276 dev_err(ctx->dev, "Error code=0x%x: FW status=0x%x\n",
277 sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE),
278 sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS));
279 dev_err(ctx->dev, "Failed to set core0 to D0 state\n");
280 ret = -EIO;
281 goto err;
282 }
283 }
284
285 /* Tell FW if additional core in now On */
286
287 if (core_id != SKL_DSP_CORE0_ID) {
288 dx.core_mask = core_mask;
289 dx.dx_mask = core_mask;
290
291 ret = skl_ipc_set_dx(&skl->ipc, BXT_INSTANCE_ID,
292 BXT_BASE_FW_MODULE_ID, &dx);
293 if (ret < 0) {
294 dev_err(ctx->dev, "IPC set_dx for core %d fail: %d\n",
295 core_id, ret);
296 goto err;
297 }
207 } 298 }
208 299
209 skl_dsp_set_state_locked(ctx, SKL_DSP_RUNNING); 300 skl->cores.state[core_id] = SKL_DSP_RUNNING;
210 return 0; 301 return 0;
302err:
303 if (core_id == SKL_DSP_CORE0_ID)
304 core_mask |= SKL_DSP_CORE_MASK(1);
305 skl_dsp_disable_core(ctx, core_mask);
306
307 return ret;
211} 308}
212 309
213static int bxt_set_dsp_D3(struct sst_dsp *ctx) 310static int bxt_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id)
214{ 311{
312 int ret;
215 struct skl_ipc_dxstate_info dx; 313 struct skl_ipc_dxstate_info dx;
216 struct skl_sst *skl = ctx->thread_context; 314 struct skl_sst *skl = ctx->thread_context;
217 int ret = 0; 315 unsigned int core_mask = SKL_DSP_CORE_MASK(core_id);
218 316
219 if (!is_skl_dsp_running(ctx)) 317 dx.core_mask = core_mask;
220 return ret;
221
222 dx.core_mask = SKL_DSP_CORE0_MASK;
223 dx.dx_mask = SKL_IPC_D3_MASK; 318 dx.dx_mask = SKL_IPC_D3_MASK;
224 319
225 ret = skl_ipc_set_dx(&skl->ipc, SKL_INSTANCE_ID, 320 dev_dbg(ctx->dev, "core mask=%x dx_mask=%x\n",
226 SKL_BASE_FW_MODULE_ID, &dx); 321 dx.core_mask, dx.dx_mask);
227 if (ret < 0) { 322
228 dev_err(ctx->dev, "Failed to set DSP to D3 state: %d\n", ret); 323 ret = skl_ipc_set_dx(&skl->ipc, BXT_INSTANCE_ID,
229 return ret; 324 BXT_BASE_FW_MODULE_ID, &dx);
230 } 325 if (ret < 0)
326 dev_err(ctx->dev,
327 "Failed to set DSP to D3:core id = %d;Continue reset\n",
328 core_id);
231 329
232 ret = skl_dsp_disable_core(ctx); 330 ret = skl_dsp_disable_core(ctx, core_mask);
233 if (ret < 0) { 331 if (ret < 0) {
234 dev_err(ctx->dev, "disbale dsp core failed: %d\n", ret); 332 dev_err(ctx->dev, "Failed to disable core %d", ret);
235 ret = -EIO; 333 return ret;
236 } 334 }
237 335 skl->cores.state[core_id] = SKL_DSP_RESET;
238 skl_dsp_set_state_locked(ctx, SKL_DSP_RESET);
239 return 0; 336 return 0;
240} 337}
241 338
@@ -274,6 +371,7 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
274 371
275 skl->dev = dev; 372 skl->dev = dev;
276 skl_dev.thread_context = skl; 373 skl_dev.thread_context = skl;
374 INIT_LIST_HEAD(&skl->uuid_list);
277 375
278 skl->dsp = skl_dsp_ctx_init(dev, &skl_dev, irq); 376 skl->dsp = skl_dsp_ctx_init(dev, &skl_dev, irq);
279 if (!skl->dsp) { 377 if (!skl->dsp) {
@@ -296,6 +394,7 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
296 if (ret) 394 if (ret)
297 return ret; 395 return ret;
298 396
397 skl->cores.count = 2;
299 skl->boot_complete = false; 398 skl->boot_complete = false;
300 init_waitqueue_head(&skl->boot_wait); 399 init_waitqueue_head(&skl->boot_wait);
301 400
@@ -305,6 +404,8 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
305 return ret; 404 return ret;
306 } 405 }
307 406
407 skl_dsp_init_core_state(sst);
408
308 if (dsp) 409 if (dsp)
309 *dsp = skl; 410 *dsp = skl;
310 411
@@ -315,6 +416,7 @@ EXPORT_SYMBOL_GPL(bxt_sst_dsp_init);
315 416
316void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) 417void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx)
317{ 418{
419 skl_freeup_uuid_list(ctx);
318 skl_ipc_free(&ctx->ipc); 420 skl_ipc_free(&ctx->ipc);
319 ctx->dsp->cl_dev.ops.cl_cleanup_controller(ctx->dsp); 421 ctx->dsp->cl_dev.ops.cl_cleanup_controller(ctx->dsp);
320 422
diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c
index 226db84ba20f..44ab595ce21a 100644
--- a/sound/soc/intel/skylake/skl-messages.c
+++ b/sound/soc/intel/skylake/skl-messages.c
@@ -206,6 +206,12 @@ static const struct skl_dsp_ops dsp_ops[] = {
206 .cleanup = skl_sst_dsp_cleanup 206 .cleanup = skl_sst_dsp_cleanup
207 }, 207 },
208 { 208 {
209 .id = 0x9d71,
210 .loader_ops = skl_get_loader_ops,
211 .init = skl_sst_dsp_init,
212 .cleanup = skl_sst_dsp_cleanup
213 },
214 {
209 .id = 0x5a98, 215 .id = 0x5a98,
210 .loader_ops = bxt_get_loader_ops, 216 .loader_ops = bxt_get_loader_ops,
211 .init = bxt_sst_dsp_init, 217 .init = bxt_sst_dsp_init,
@@ -730,7 +736,7 @@ static int skl_set_module_format(struct skl_sst *ctx,
730 736
731 dev_dbg(ctx->dev, "Module type=%d config size: %d bytes\n", 737 dev_dbg(ctx->dev, "Module type=%d config size: %d bytes\n",
732 module_config->id.module_id, param_size); 738 module_config->id.module_id, param_size);
733 print_hex_dump(KERN_DEBUG, "Module params:", DUMP_PREFIX_OFFSET, 8, 4, 739 print_hex_dump_debug("Module params:", DUMP_PREFIX_OFFSET, 8, 4,
734 *param_data, param_size, false); 740 *param_data, param_size, false);
735 return 0; 741 return 0;
736} 742}
@@ -1046,7 +1052,7 @@ int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe)
1046 1052
1047 dev_dbg(ctx->dev, "%s: pipe = %d\n", __func__, pipe->ppl_id); 1053 dev_dbg(ctx->dev, "%s: pipe = %d\n", __func__, pipe->ppl_id);
1048 1054
1049 /* If pipe is not started, do not try to stop the pipe in FW. */ 1055 /* If pipe is started, do stop the pipe in FW. */
1050 if (pipe->state > SKL_PIPE_STARTED) { 1056 if (pipe->state > SKL_PIPE_STARTED) {
1051 ret = skl_set_pipe_state(ctx, pipe, PPL_PAUSED); 1057 ret = skl_set_pipe_state(ctx, pipe, PPL_PAUSED);
1052 if (ret < 0) { 1058 if (ret < 0) {
@@ -1055,18 +1061,20 @@ int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe)
1055 } 1061 }
1056 1062
1057 pipe->state = SKL_PIPE_PAUSED; 1063 pipe->state = SKL_PIPE_PAUSED;
1058 } else { 1064 }
1059 /* If pipe was not created in FW, do not try to delete it */
1060 if (pipe->state < SKL_PIPE_CREATED)
1061 return 0;
1062 1065
1063 ret = skl_ipc_delete_pipeline(&ctx->ipc, pipe->ppl_id); 1066 /* If pipe was not created in FW, do not try to delete it */
1064 if (ret < 0) 1067 if (pipe->state < SKL_PIPE_CREATED)
1065 dev_err(ctx->dev, "Failed to delete pipeline\n"); 1068 return 0;
1066 1069
1067 pipe->state = SKL_PIPE_INVALID; 1070 ret = skl_ipc_delete_pipeline(&ctx->ipc, pipe->ppl_id);
1071 if (ret < 0) {
1072 dev_err(ctx->dev, "Failed to delete pipeline\n");
1073 return ret;
1068 } 1074 }
1069 1075
1076 pipe->state = SKL_PIPE_INVALID;
1077
1070 return ret; 1078 return ret;
1071} 1079}
1072 1080
@@ -1125,7 +1133,30 @@ int skl_stop_pipe(struct skl_sst *ctx, struct skl_pipe *pipe)
1125 return ret; 1133 return ret;
1126 } 1134 }
1127 1135
1128 pipe->state = SKL_PIPE_CREATED; 1136 pipe->state = SKL_PIPE_PAUSED;
1137
1138 return 0;
1139}
1140
1141/*
1142 * Reset the pipeline by sending set pipe state IPC this will reset the DMA
1143 * from the DSP side
1144 */
1145int skl_reset_pipe(struct skl_sst *ctx, struct skl_pipe *pipe)
1146{
1147 int ret;
1148
1149 /* If pipe was not created in FW, do not try to pause or delete */
1150 if (pipe->state < SKL_PIPE_PAUSED)
1151 return 0;
1152
1153 ret = skl_set_pipe_state(ctx, pipe, PPL_RESET);
1154 if (ret < 0) {
1155 dev_dbg(ctx->dev, "Failed to reset pipe ret=%d\n", ret);
1156 return ret;
1157 }
1158
1159 pipe->state = SKL_PIPE_RESET;
1129 1160
1130 return 0; 1161 return 0;
1131} 1162}
diff --git a/sound/soc/intel/skylake/skl-nhlt.c b/sound/soc/intel/skylake/skl-nhlt.c
index 7d73648e5f9a..3f8e6f0b7eb5 100644
--- a/sound/soc/intel/skylake/skl-nhlt.c
+++ b/sound/soc/intel/skylake/skl-nhlt.c
@@ -17,6 +17,7 @@
17 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 17 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
18 * 18 *
19 */ 19 */
20#include <linux/pci.h>
20#include "skl.h" 21#include "skl.h"
21 22
22/* Unique identification for getting NHLT blobs */ 23/* Unique identification for getting NHLT blobs */
@@ -149,6 +150,45 @@ struct nhlt_specific_cfg
149 return NULL; 150 return NULL;
150} 151}
151 152
153int skl_get_dmic_geo(struct skl *skl)
154{
155 struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt;
156 struct nhlt_endpoint *epnt;
157 struct nhlt_dmic_array_config *cfg;
158 struct device *dev = &skl->pci->dev;
159 unsigned int dmic_geo = 0;
160 u8 j;
161
162 epnt = (struct nhlt_endpoint *)nhlt->desc;
163
164 for (j = 0; j < nhlt->endpoint_count; j++) {
165 if (epnt->linktype == NHLT_LINK_DMIC) {
166 cfg = (struct nhlt_dmic_array_config *)
167 (epnt->config.caps);
168 switch (cfg->array_type) {
169 case NHLT_MIC_ARRAY_2CH_SMALL:
170 case NHLT_MIC_ARRAY_2CH_BIG:
171 dmic_geo |= MIC_ARRAY_2CH;
172 break;
173
174 case NHLT_MIC_ARRAY_4CH_1ST_GEOM:
175 case NHLT_MIC_ARRAY_4CH_L_SHAPED:
176 case NHLT_MIC_ARRAY_4CH_2ND_GEOM:
177 dmic_geo |= MIC_ARRAY_4CH;
178 break;
179
180 default:
181 dev_warn(dev, "undefined DMIC array_type 0x%0x\n",
182 cfg->array_type);
183
184 }
185 }
186 epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length);
187 }
188
189 return dmic_geo;
190}
191
152static void skl_nhlt_trim_space(struct skl *skl) 192static void skl_nhlt_trim_space(struct skl *skl)
153{ 193{
154 char *s = skl->tplg_name; 194 char *s = skl->tplg_name;
diff --git a/sound/soc/intel/skylake/skl-nhlt.h b/sound/soc/intel/skylake/skl-nhlt.h
index 3769f9fefe2b..116534e7b3c5 100644
--- a/sound/soc/intel/skylake/skl-nhlt.h
+++ b/sound/soc/intel/skylake/skl-nhlt.h
@@ -103,4 +103,26 @@ struct nhlt_resource_desc {
103 u64 length; 103 u64 length;
104} __packed; 104} __packed;
105 105
106#define MIC_ARRAY_2CH 2
107#define MIC_ARRAY_4CH 4
108
109struct nhlt_tdm_config {
110 u8 virtual_slot;
111 u8 config_type;
112} __packed;
113
114struct nhlt_dmic_array_config {
115 struct nhlt_tdm_config tdm_config;
116 u8 array_type;
117} __packed;
118
119enum {
120 NHLT_MIC_ARRAY_2CH_SMALL = 0xa,
121 NHLT_MIC_ARRAY_2CH_BIG = 0xb,
122 NHLT_MIC_ARRAY_4CH_1ST_GEOM = 0xc,
123 NHLT_MIC_ARRAY_4CH_L_SHAPED = 0xd,
124 NHLT_MIC_ARRAY_4CH_2ND_GEOM = 0xe,
125 NHLT_MIC_ARRAY_VENDOR_DEFINED = 0xf,
126};
127
106#endif 128#endif
diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c
index 7c81b31748ff..6e05bf8622f7 100644
--- a/sound/soc/intel/skylake/skl-pcm.c
+++ b/sound/soc/intel/skylake/skl-pcm.c
@@ -227,16 +227,25 @@ static int skl_pcm_prepare(struct snd_pcm_substream *substream,
227 struct snd_soc_dai *dai) 227 struct snd_soc_dai *dai)
228{ 228{
229 struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); 229 struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
230 struct skl *skl = get_skl_ctx(dai->dev);
230 unsigned int format_val; 231 unsigned int format_val;
231 int err; 232 int err;
233 struct skl_module_cfg *mconfig;
232 234
233 dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); 235 dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
234 236
237 mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
238
235 format_val = skl_get_format(substream, dai); 239 format_val = skl_get_format(substream, dai);
236 dev_dbg(dai->dev, "stream_tag=%d formatvalue=%d\n", 240 dev_dbg(dai->dev, "stream_tag=%d formatvalue=%d\n",
237 hdac_stream(stream)->stream_tag, format_val); 241 hdac_stream(stream)->stream_tag, format_val);
238 snd_hdac_stream_reset(hdac_stream(stream)); 242 snd_hdac_stream_reset(hdac_stream(stream));
239 243
244 /* In case of XRUN recovery, reset the FW pipe to clean state */
245 if (mconfig && (substream->runtime->status->state ==
246 SNDRV_PCM_STATE_XRUN))
247 skl_reset_pipe(skl->skl_sst, mconfig->pipe);
248
240 err = snd_hdac_stream_set_params(hdac_stream(stream), format_val); 249 err = snd_hdac_stream_set_params(hdac_stream(stream), format_val);
241 if (err < 0) 250 if (err < 0)
242 return err; 251 return err;
@@ -521,6 +530,8 @@ static int skl_link_pcm_prepare(struct snd_pcm_substream *substream,
521 struct skl_dma_params *dma_params; 530 struct skl_dma_params *dma_params;
522 struct snd_soc_dai *codec_dai = rtd->codec_dai; 531 struct snd_soc_dai *codec_dai = rtd->codec_dai;
523 struct hdac_ext_link *link; 532 struct hdac_ext_link *link;
533 struct skl *skl = get_skl_ctx(dai->dev);
534 struct skl_module_cfg *mconfig = NULL;
524 535
525 dma_params = (struct skl_dma_params *) 536 dma_params = (struct skl_dma_params *)
526 snd_soc_dai_get_dma_data(codec_dai, substream); 537 snd_soc_dai_get_dma_data(codec_dai, substream);
@@ -535,6 +546,12 @@ static int skl_link_pcm_prepare(struct snd_pcm_substream *substream,
535 546
536 snd_hdac_ext_link_stream_reset(link_dev); 547 snd_hdac_ext_link_stream_reset(link_dev);
537 548
549 /* In case of XRUN recovery, reset the FW pipe to clean state */
550 mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream);
551 if (mconfig && (substream->runtime->status->state ==
552 SNDRV_PCM_STATE_XRUN))
553 skl_reset_pipe(skl->skl_sst, mconfig->pipe);
554
538 snd_hdac_ext_link_stream_setup(link_dev, format_val); 555 snd_hdac_ext_link_stream_setup(link_dev, format_val);
539 556
540 snd_hdac_ext_link_set_stream_id(link, hdac_stream(link_dev)->stream_tag); 557 snd_hdac_ext_link_set_stream_id(link, hdac_stream(link_dev)->stream_tag);
@@ -1009,51 +1026,11 @@ static int skl_platform_pcm_trigger(struct snd_pcm_substream *substream,
1009 return 0; 1026 return 0;
1010} 1027}
1011 1028
1012/* calculate runtime delay from LPIB */ 1029static snd_pcm_uframes_t skl_platform_pcm_pointer
1013static int skl_get_delay_from_lpib(struct hdac_ext_bus *ebus, 1030 (struct snd_pcm_substream *substream)
1014 struct hdac_ext_stream *sstream,
1015 unsigned int pos)
1016{
1017 struct hdac_bus *bus = ebus_to_hbus(ebus);
1018 struct hdac_stream *hstream = hdac_stream(sstream);
1019 struct snd_pcm_substream *substream = hstream->substream;
1020 int stream = substream->stream;
1021 unsigned int lpib_pos = snd_hdac_stream_get_pos_lpib(hstream);
1022 int delay;
1023
1024 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
1025 delay = pos - lpib_pos;
1026 else
1027 delay = lpib_pos - pos;
1028
1029 if (delay < 0) {
1030 if (delay >= hstream->delay_negative_threshold)
1031 delay = 0;
1032 else
1033 delay += hstream->bufsize;
1034 }
1035
1036 if (hstream->bufsize == delay)
1037 delay = 0;
1038
1039 if (delay >= hstream->period_bytes) {
1040 dev_info(bus->dev,
1041 "Unstable LPIB (%d >= %d); disabling LPIB delay counting\n",
1042 delay, hstream->period_bytes);
1043 delay = 0;
1044 }
1045
1046 return bytes_to_frames(substream->runtime, delay);
1047}
1048
1049static unsigned int skl_get_position(struct hdac_ext_stream *hstream,
1050 int codec_delay)
1051{ 1031{
1052 struct hdac_stream *hstr = hdac_stream(hstream); 1032 struct hdac_ext_stream *hstream = get_hdac_ext_stream(substream);
1053 struct snd_pcm_substream *substream = hstr->substream;
1054 struct hdac_ext_bus *ebus;
1055 unsigned int pos; 1033 unsigned int pos;
1056 int delay;
1057 1034
1058 /* use the position buffer as default */ 1035 /* use the position buffer as default */
1059 pos = snd_hdac_stream_get_pos_posbuf(hdac_stream(hstream)); 1036 pos = snd_hdac_stream_get_pos_posbuf(hdac_stream(hstream));
@@ -1061,23 +1038,7 @@ static unsigned int skl_get_position(struct hdac_ext_stream *hstream,
1061 if (pos >= hdac_stream(hstream)->bufsize) 1038 if (pos >= hdac_stream(hstream)->bufsize)
1062 pos = 0; 1039 pos = 0;
1063 1040
1064 if (substream->runtime) { 1041 return bytes_to_frames(substream->runtime, pos);
1065 ebus = get_bus_ctx(substream);
1066 delay = skl_get_delay_from_lpib(ebus, hstream, pos)
1067 + codec_delay;
1068 substream->runtime->delay += delay;
1069 }
1070
1071 return pos;
1072}
1073
1074static snd_pcm_uframes_t skl_platform_pcm_pointer
1075 (struct snd_pcm_substream *substream)
1076{
1077 struct hdac_ext_stream *hstream = get_hdac_ext_stream(substream);
1078
1079 return bytes_to_frames(substream->runtime,
1080 skl_get_position(hstream, 0));
1081} 1042}
1082 1043
1083static u64 skl_adjust_codec_delay(struct snd_pcm_substream *substream, 1044static u64 skl_adjust_codec_delay(struct snd_pcm_substream *substream,
@@ -1180,9 +1141,17 @@ static int skl_pcm_new(struct snd_soc_pcm_runtime *rtd)
1180static int skl_platform_soc_probe(struct snd_soc_platform *platform) 1141static int skl_platform_soc_probe(struct snd_soc_platform *platform)
1181{ 1142{
1182 struct hdac_ext_bus *ebus = dev_get_drvdata(platform->dev); 1143 struct hdac_ext_bus *ebus = dev_get_drvdata(platform->dev);
1144 struct skl *skl = ebus_to_skl(ebus);
1145 int ret;
1183 1146
1184 if (ebus->ppcap) 1147 if (ebus->ppcap) {
1185 return skl_tplg_init(platform, ebus); 1148 ret = skl_tplg_init(platform, ebus);
1149 if (ret < 0) {
1150 dev_err(platform->dev, "Failed to init topology!\n");
1151 return ret;
1152 }
1153 skl->platform = platform;
1154 }
1186 1155
1187 return 0; 1156 return 0;
1188} 1157}
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.c b/sound/soc/intel/skylake/skl-sst-dsp.c
index 13c19855ee1a..c3deefab65d6 100644
--- a/sound/soc/intel/skylake/skl-sst-dsp.c
+++ b/sound/soc/intel/skylake/skl-sst-dsp.c
@@ -34,33 +34,84 @@ void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state)
34 mutex_unlock(&ctx->mutex); 34 mutex_unlock(&ctx->mutex);
35} 35}
36 36
37static int skl_dsp_core_set_reset_state(struct sst_dsp *ctx) 37/*
38 * Initialize core power state and usage count. To be called after
39 * successful first boot. Hence core 0 will be running and other cores
40 * will be reset
41 */
42void skl_dsp_init_core_state(struct sst_dsp *ctx)
43{
44 struct skl_sst *skl = ctx->thread_context;
45 int i;
46
47 skl->cores.state[SKL_DSP_CORE0_ID] = SKL_DSP_RUNNING;
48 skl->cores.usage_count[SKL_DSP_CORE0_ID] = 1;
49
50 for (i = SKL_DSP_CORE0_ID + 1; i < SKL_DSP_CORES_MAX; i++) {
51 skl->cores.state[i] = SKL_DSP_RESET;
52 skl->cores.usage_count[i] = 0;
53 }
54}
55
56/* Get the mask for all enabled cores */
57unsigned int skl_dsp_get_enabled_cores(struct sst_dsp *ctx)
58{
59 struct skl_sst *skl = ctx->thread_context;
60 unsigned int core_mask, en_cores_mask;
61 u32 val;
62
63 core_mask = SKL_DSP_CORES_MASK(skl->cores.count);
64
65 val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS);
66
67 /* Cores having CPA bit set */
68 en_cores_mask = (val & SKL_ADSPCS_CPA_MASK(core_mask)) >>
69 SKL_ADSPCS_CPA_SHIFT;
70
71 /* And cores having CRST bit cleared */
72 en_cores_mask &= (~val & SKL_ADSPCS_CRST_MASK(core_mask)) >>
73 SKL_ADSPCS_CRST_SHIFT;
74
75 /* And cores having CSTALL bit cleared */
76 en_cores_mask &= (~val & SKL_ADSPCS_CSTALL_MASK(core_mask)) >>
77 SKL_ADSPCS_CSTALL_SHIFT;
78 en_cores_mask &= core_mask;
79
80 dev_dbg(ctx->dev, "DSP enabled cores mask = %x\n", en_cores_mask);
81
82 return en_cores_mask;
83}
84
85static int
86skl_dsp_core_set_reset_state(struct sst_dsp *ctx, unsigned int core_mask)
38{ 87{
39 int ret; 88 int ret;
40 89
41 /* update bits */ 90 /* update bits */
42 sst_dsp_shim_update_bits_unlocked(ctx, 91 sst_dsp_shim_update_bits_unlocked(ctx,
43 SKL_ADSP_REG_ADSPCS, SKL_ADSPCS_CRST_MASK, 92 SKL_ADSP_REG_ADSPCS, SKL_ADSPCS_CRST_MASK(core_mask),
44 SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)); 93 SKL_ADSPCS_CRST_MASK(core_mask));
45 94
46 /* poll with timeout to check if operation successful */ 95 /* poll with timeout to check if operation successful */
47 ret = sst_dsp_register_poll(ctx, 96 ret = sst_dsp_register_poll(ctx,
48 SKL_ADSP_REG_ADSPCS, 97 SKL_ADSP_REG_ADSPCS,
49 SKL_ADSPCS_CRST_MASK, 98 SKL_ADSPCS_CRST_MASK(core_mask),
50 SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK), 99 SKL_ADSPCS_CRST_MASK(core_mask),
51 SKL_DSP_RESET_TO, 100 SKL_DSP_RESET_TO,
52 "Set reset"); 101 "Set reset");
53 if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & 102 if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
54 SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) != 103 SKL_ADSPCS_CRST_MASK(core_mask)) !=
55 SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) { 104 SKL_ADSPCS_CRST_MASK(core_mask)) {
56 dev_err(ctx->dev, "Set reset state failed\n"); 105 dev_err(ctx->dev, "Set reset state failed: core_mask %x\n",
106 core_mask);
57 ret = -EIO; 107 ret = -EIO;
58 } 108 }
59 109
60 return ret; 110 return ret;
61} 111}
62 112
63static int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx) 113int skl_dsp_core_unset_reset_state(
114 struct sst_dsp *ctx, unsigned int core_mask)
64{ 115{
65 int ret; 116 int ret;
66 117
@@ -68,152 +119,160 @@ static int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx)
68 119
69 /* update bits */ 120 /* update bits */
70 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 121 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
71 SKL_ADSPCS_CRST_MASK, 0); 122 SKL_ADSPCS_CRST_MASK(core_mask), 0);
72 123
73 /* poll with timeout to check if operation successful */ 124 /* poll with timeout to check if operation successful */
74 ret = sst_dsp_register_poll(ctx, 125 ret = sst_dsp_register_poll(ctx,
75 SKL_ADSP_REG_ADSPCS, 126 SKL_ADSP_REG_ADSPCS,
76 SKL_ADSPCS_CRST_MASK, 127 SKL_ADSPCS_CRST_MASK(core_mask),
77 0, 128 0,
78 SKL_DSP_RESET_TO, 129 SKL_DSP_RESET_TO,
79 "Unset reset"); 130 "Unset reset");
80 131
81 if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & 132 if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
82 SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) != 0) { 133 SKL_ADSPCS_CRST_MASK(core_mask)) != 0) {
83 dev_err(ctx->dev, "Unset reset state failed\n"); 134 dev_err(ctx->dev, "Unset reset state failed: core_mask %x\n",
135 core_mask);
84 ret = -EIO; 136 ret = -EIO;
85 } 137 }
86 138
87 return ret; 139 return ret;
88} 140}
89 141
90static bool is_skl_dsp_core_enable(struct sst_dsp *ctx) 142static bool
143is_skl_dsp_core_enable(struct sst_dsp *ctx, unsigned int core_mask)
91{ 144{
92 int val; 145 int val;
93 bool is_enable; 146 bool is_enable;
94 147
95 val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS); 148 val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS);
96 149
97 is_enable = ((val & SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK)) && 150 is_enable = ((val & SKL_ADSPCS_CPA_MASK(core_mask)) &&
98 (val & SKL_ADSPCS_SPA(SKL_DSP_CORES_MASK)) && 151 (val & SKL_ADSPCS_SPA_MASK(core_mask)) &&
99 !(val & SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) && 152 !(val & SKL_ADSPCS_CRST_MASK(core_mask)) &&
100 !(val & SKL_ADSPCS_CSTALL(SKL_DSP_CORES_MASK))); 153 !(val & SKL_ADSPCS_CSTALL_MASK(core_mask)));
154
155 dev_dbg(ctx->dev, "DSP core(s) enabled? %d : core_mask %x\n",
156 is_enable, core_mask);
101 157
102 dev_dbg(ctx->dev, "DSP core is enabled=%d\n", is_enable);
103 return is_enable; 158 return is_enable;
104} 159}
105 160
106static int skl_dsp_reset_core(struct sst_dsp *ctx) 161static int skl_dsp_reset_core(struct sst_dsp *ctx, unsigned int core_mask)
107{ 162{
108 /* stall core */ 163 /* stall core */
109 sst_dsp_shim_write_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 164 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
110 sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & 165 SKL_ADSPCS_CSTALL_MASK(core_mask),
111 SKL_ADSPCS_CSTALL(SKL_DSP_CORES_MASK)); 166 SKL_ADSPCS_CSTALL_MASK(core_mask));
112 167
113 /* set reset state */ 168 /* set reset state */
114 return skl_dsp_core_set_reset_state(ctx); 169 return skl_dsp_core_set_reset_state(ctx, core_mask);
115} 170}
116 171
117static int skl_dsp_start_core(struct sst_dsp *ctx) 172int skl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask)
118{ 173{
119 int ret; 174 int ret;
120 175
121 /* unset reset state */ 176 /* unset reset state */
122 ret = skl_dsp_core_unset_reset_state(ctx); 177 ret = skl_dsp_core_unset_reset_state(ctx, core_mask);
123 if (ret < 0) { 178 if (ret < 0)
124 dev_dbg(ctx->dev, "dsp unset reset fails\n");
125 return ret; 179 return ret;
126 }
127 180
128 /* run core */ 181 /* run core */
129 dev_dbg(ctx->dev, "run core...\n"); 182 dev_dbg(ctx->dev, "unstall/run core: core_mask = %x\n", core_mask);
130 sst_dsp_shim_write_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 183 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
131 sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & 184 SKL_ADSPCS_CSTALL_MASK(core_mask), 0);
132 ~SKL_ADSPCS_CSTALL(SKL_DSP_CORES_MASK)); 185
133 186 if (!is_skl_dsp_core_enable(ctx, core_mask)) {
134 if (!is_skl_dsp_core_enable(ctx)) { 187 skl_dsp_reset_core(ctx, core_mask);
135 skl_dsp_reset_core(ctx); 188 dev_err(ctx->dev, "DSP start core failed: core_mask %x\n",
136 dev_err(ctx->dev, "DSP core enable failed\n"); 189 core_mask);
137 ret = -EIO; 190 ret = -EIO;
138 } 191 }
139 192
140 return ret; 193 return ret;
141} 194}
142 195
143static int skl_dsp_core_power_up(struct sst_dsp *ctx) 196int skl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask)
144{ 197{
145 int ret; 198 int ret;
146 199
147 /* update bits */ 200 /* update bits */
148 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 201 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
149 SKL_ADSPCS_SPA_MASK, SKL_ADSPCS_SPA(SKL_DSP_CORES_MASK)); 202 SKL_ADSPCS_SPA_MASK(core_mask),
203 SKL_ADSPCS_SPA_MASK(core_mask));
150 204
151 /* poll with timeout to check if operation successful */ 205 /* poll with timeout to check if operation successful */
152 ret = sst_dsp_register_poll(ctx, 206 ret = sst_dsp_register_poll(ctx,
153 SKL_ADSP_REG_ADSPCS, 207 SKL_ADSP_REG_ADSPCS,
154 SKL_ADSPCS_CPA_MASK, 208 SKL_ADSPCS_CPA_MASK(core_mask),
155 SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK), 209 SKL_ADSPCS_CPA_MASK(core_mask),
156 SKL_DSP_PU_TO, 210 SKL_DSP_PU_TO,
157 "Power up"); 211 "Power up");
158 212
159 if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & 213 if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
160 SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK)) != 214 SKL_ADSPCS_CPA_MASK(core_mask)) !=
161 SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK)) { 215 SKL_ADSPCS_CPA_MASK(core_mask)) {
162 dev_err(ctx->dev, "DSP core power up failed\n"); 216 dev_err(ctx->dev, "DSP core power up failed: core_mask %x\n",
217 core_mask);
163 ret = -EIO; 218 ret = -EIO;
164 } 219 }
165 220
166 return ret; 221 return ret;
167} 222}
168 223
169static int skl_dsp_core_power_down(struct sst_dsp *ctx) 224int skl_dsp_core_power_down(struct sst_dsp *ctx, unsigned int core_mask)
170{ 225{
171 /* update bits */ 226 /* update bits */
172 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 227 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
173 SKL_ADSPCS_SPA_MASK, 0); 228 SKL_ADSPCS_SPA_MASK(core_mask), 0);
174 229
175 /* poll with timeout to check if operation successful */ 230 /* poll with timeout to check if operation successful */
176 return sst_dsp_register_poll(ctx, 231 return sst_dsp_register_poll(ctx,
177 SKL_ADSP_REG_ADSPCS, 232 SKL_ADSP_REG_ADSPCS,
178 SKL_ADSPCS_CPA_MASK, 233 SKL_ADSPCS_CPA_MASK(core_mask),
179 0, 234 0,
180 SKL_DSP_PD_TO, 235 SKL_DSP_PD_TO,
181 "Power down"); 236 "Power down");
182} 237}
183 238
184int skl_dsp_enable_core(struct sst_dsp *ctx) 239int skl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask)
185{ 240{
186 int ret; 241 int ret;
187 242
188 /* power up */ 243 /* power up */
189 ret = skl_dsp_core_power_up(ctx); 244 ret = skl_dsp_core_power_up(ctx, core_mask);
190 if (ret < 0) { 245 if (ret < 0) {
191 dev_dbg(ctx->dev, "dsp core power up failed\n"); 246 dev_err(ctx->dev, "dsp core power up failed: core_mask %x\n",
247 core_mask);
192 return ret; 248 return ret;
193 } 249 }
194 250
195 return skl_dsp_start_core(ctx); 251 return skl_dsp_start_core(ctx, core_mask);
196} 252}
197 253
198int skl_dsp_disable_core(struct sst_dsp *ctx) 254int skl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask)
199{ 255{
200 int ret; 256 int ret;
201 257
202 ret = skl_dsp_reset_core(ctx); 258 ret = skl_dsp_reset_core(ctx, core_mask);
203 if (ret < 0) { 259 if (ret < 0) {
204 dev_err(ctx->dev, "dsp core reset failed\n"); 260 dev_err(ctx->dev, "dsp core reset failed: core_mask %x\n",
261 core_mask);
205 return ret; 262 return ret;
206 } 263 }
207 264
208 /* power down core*/ 265 /* power down core*/
209 ret = skl_dsp_core_power_down(ctx); 266 ret = skl_dsp_core_power_down(ctx, core_mask);
210 if (ret < 0) { 267 if (ret < 0) {
211 dev_err(ctx->dev, "dsp core power down failed\n"); 268 dev_err(ctx->dev, "dsp core power down fail mask %x: %d\n",
269 core_mask, ret);
212 return ret; 270 return ret;
213 } 271 }
214 272
215 if (is_skl_dsp_core_enable(ctx)) { 273 if (is_skl_dsp_core_enable(ctx, core_mask)) {
216 dev_err(ctx->dev, "DSP core disable failed\n"); 274 dev_err(ctx->dev, "dsp core disable fail mask %x: %d\n",
275 core_mask, ret);
217 ret = -EIO; 276 ret = -EIO;
218 } 277 }
219 278
@@ -224,28 +283,25 @@ int skl_dsp_boot(struct sst_dsp *ctx)
224{ 283{
225 int ret; 284 int ret;
226 285
227 if (is_skl_dsp_core_enable(ctx)) { 286 if (is_skl_dsp_core_enable(ctx, SKL_DSP_CORE0_MASK)) {
228 dev_dbg(ctx->dev, "dsp core is already enabled, so reset the dap core\n"); 287 ret = skl_dsp_reset_core(ctx, SKL_DSP_CORE0_MASK);
229 ret = skl_dsp_reset_core(ctx);
230 if (ret < 0) { 288 if (ret < 0) {
231 dev_err(ctx->dev, "dsp reset failed\n"); 289 dev_err(ctx->dev, "dsp core0 reset fail: %d\n", ret);
232 return ret; 290 return ret;
233 } 291 }
234 292
235 ret = skl_dsp_start_core(ctx); 293 ret = skl_dsp_start_core(ctx, SKL_DSP_CORE0_MASK);
236 if (ret < 0) { 294 if (ret < 0) {
237 dev_err(ctx->dev, "dsp start failed\n"); 295 dev_err(ctx->dev, "dsp core0 start fail: %d\n", ret);
238 return ret; 296 return ret;
239 } 297 }
240 } else { 298 } else {
241 dev_dbg(ctx->dev, "disable and enable to make sure DSP is invalid state\n"); 299 ret = skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
242 ret = skl_dsp_disable_core(ctx);
243
244 if (ret < 0) { 300 if (ret < 0) {
245 dev_err(ctx->dev, "dsp disable core failes\n"); 301 dev_err(ctx->dev, "dsp core0 disable fail: %d\n", ret);
246 return ret; 302 return ret;
247 } 303 }
248 ret = skl_dsp_enable_core(ctx); 304 ret = skl_dsp_enable_core(ctx, SKL_DSP_CORE0_MASK);
249 } 305 }
250 306
251 return ret; 307 return ret;
@@ -281,16 +337,74 @@ irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id)
281 337
282 return result; 338 return result;
283} 339}
340/*
341 * skl_dsp_get_core/skl_dsp_put_core will be called inside DAPM context
342 * within the dapm mutex. Hence no separate lock is used.
343 */
344int skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id)
345{
346 struct skl_sst *skl = ctx->thread_context;
347 int ret = 0;
348
349 if (core_id >= skl->cores.count) {
350 dev_err(ctx->dev, "invalid core id: %d\n", core_id);
351 return -EINVAL;
352 }
353
354 if (skl->cores.state[core_id] == SKL_DSP_RESET) {
355 ret = ctx->fw_ops.set_state_D0(ctx, core_id);
356 if (ret < 0) {
357 dev_err(ctx->dev, "unable to get core%d\n", core_id);
358 return ret;
359 }
360 }
361
362 skl->cores.usage_count[core_id]++;
363
364 dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n",
365 core_id, skl->cores.state[core_id],
366 skl->cores.usage_count[core_id]);
367
368 return ret;
369}
370EXPORT_SYMBOL_GPL(skl_dsp_get_core);
371
372int skl_dsp_put_core(struct sst_dsp *ctx, unsigned int core_id)
373{
374 struct skl_sst *skl = ctx->thread_context;
375 int ret = 0;
376
377 if (core_id >= skl->cores.count) {
378 dev_err(ctx->dev, "invalid core id: %d\n", core_id);
379 return -EINVAL;
380 }
381
382 if (--skl->cores.usage_count[core_id] == 0) {
383 ret = ctx->fw_ops.set_state_D3(ctx, core_id);
384 if (ret < 0) {
385 dev_err(ctx->dev, "unable to put core %d: %d\n",
386 core_id, ret);
387 skl->cores.usage_count[core_id]++;
388 }
389 }
390
391 dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n",
392 core_id, skl->cores.state[core_id],
393 skl->cores.usage_count[core_id]);
394
395 return ret;
396}
397EXPORT_SYMBOL_GPL(skl_dsp_put_core);
284 398
285int skl_dsp_wake(struct sst_dsp *ctx) 399int skl_dsp_wake(struct sst_dsp *ctx)
286{ 400{
287 return ctx->fw_ops.set_state_D0(ctx); 401 return skl_dsp_get_core(ctx, SKL_DSP_CORE0_ID);
288} 402}
289EXPORT_SYMBOL_GPL(skl_dsp_wake); 403EXPORT_SYMBOL_GPL(skl_dsp_wake);
290 404
291int skl_dsp_sleep(struct sst_dsp *ctx) 405int skl_dsp_sleep(struct sst_dsp *ctx)
292{ 406{
293 return ctx->fw_ops.set_state_D3(ctx); 407 return skl_dsp_put_core(ctx, SKL_DSP_CORE0_ID);
294} 408}
295EXPORT_SYMBOL_GPL(skl_dsp_sleep); 409EXPORT_SYMBOL_GPL(skl_dsp_sleep);
296 410
@@ -337,9 +451,7 @@ void skl_dsp_free(struct sst_dsp *dsp)
337 451
338 free_irq(dsp->irq, dsp); 452 free_irq(dsp->irq, dsp);
339 skl_ipc_op_int_disable(dsp); 453 skl_ipc_op_int_disable(dsp);
340 skl_ipc_int_disable(dsp); 454 skl_dsp_disable_core(dsp, SKL_DSP_CORE0_MASK);
341
342 skl_dsp_disable_core(dsp);
343} 455}
344EXPORT_SYMBOL_GPL(skl_dsp_free); 456EXPORT_SYMBOL_GPL(skl_dsp_free);
345 457
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h
index deabe7308d3b..0f8629ef79ac 100644
--- a/sound/soc/intel/skylake/skl-sst-dsp.h
+++ b/sound/soc/intel/skylake/skl-sst-dsp.h
@@ -19,6 +19,7 @@
19#include <linux/interrupt.h> 19#include <linux/interrupt.h>
20#include <sound/memalloc.h> 20#include <sound/memalloc.h>
21#include "skl-sst-cldma.h" 21#include "skl-sst-cldma.h"
22#include "skl-tplg-interface.h"
22 23
23struct sst_dsp; 24struct sst_dsp;
24struct skl_sst; 25struct skl_sst;
@@ -76,35 +77,53 @@ struct sst_dsp_device;
76#define SKL_ADSPIC_IPC 1 77#define SKL_ADSPIC_IPC 1
77#define SKL_ADSPIS_IPC 1 78#define SKL_ADSPIS_IPC 1
78 79
80/* Core ID of core0 */
81#define SKL_DSP_CORE0_ID 0
82
83/* Mask for a given core index, c = 0.. number of supported cores - 1 */
84#define SKL_DSP_CORE_MASK(c) BIT(c)
85
86/*
87 * Core 0 mask = SKL_DSP_CORE_MASK(0); Defined separately
88 * since Core0 is primary core and it is used often
89 */
90#define SKL_DSP_CORE0_MASK BIT(0)
91
92/*
93 * Mask for a given number of cores
94 * nc = number of supported cores
95 */
96#define SKL_DSP_CORES_MASK(nc) GENMASK((nc - 1), 0)
97
79/* ADSPCS - Audio DSP Control & Status */ 98/* ADSPCS - Audio DSP Control & Status */
80#define SKL_DSP_CORES 1 99
81#define SKL_DSP_CORE0_MASK 1 100/*
82#define SKL_DSP_CORES_MASK ((1 << SKL_DSP_CORES) - 1) 101 * Core Reset - asserted high
83 102 * CRST Mask for a given core mask pattern, cm
84/* Core Reset - asserted high */ 103 */
85#define SKL_ADSPCS_CRST_SHIFT 0 104#define SKL_ADSPCS_CRST_SHIFT 0
86#define SKL_ADSPCS_CRST_MASK (SKL_DSP_CORES_MASK << SKL_ADSPCS_CRST_SHIFT) 105#define SKL_ADSPCS_CRST_MASK(cm) ((cm) << SKL_ADSPCS_CRST_SHIFT)
87#define SKL_ADSPCS_CRST(x) ((x << SKL_ADSPCS_CRST_SHIFT) & SKL_ADSPCS_CRST_MASK) 106
88 107/*
89/* Core run/stall - when set to '1' core is stalled */ 108 * Core run/stall - when set to '1' core is stalled
90#define SKL_ADSPCS_CSTALL_SHIFT 8 109 * CSTALL Mask for a given core mask pattern, cm
91#define SKL_ADSPCS_CSTALL_MASK (SKL_DSP_CORES_MASK << \ 110 */
92 SKL_ADSPCS_CSTALL_SHIFT) 111#define SKL_ADSPCS_CSTALL_SHIFT 8
93#define SKL_ADSPCS_CSTALL(x) ((x << SKL_ADSPCS_CSTALL_SHIFT) & \ 112#define SKL_ADSPCS_CSTALL_MASK(cm) ((cm) << SKL_ADSPCS_CSTALL_SHIFT)
94 SKL_ADSPCS_CSTALL_MASK) 113
95 114/*
96/* Set Power Active - when set to '1' turn cores on */ 115 * Set Power Active - when set to '1' turn cores on
97#define SKL_ADSPCS_SPA_SHIFT 16 116 * SPA Mask for a given core mask pattern, cm
98#define SKL_ADSPCS_SPA_MASK (SKL_DSP_CORES_MASK << SKL_ADSPCS_SPA_SHIFT) 117 */
99#define SKL_ADSPCS_SPA(x) ((x << SKL_ADSPCS_SPA_SHIFT) & SKL_ADSPCS_SPA_MASK) 118#define SKL_ADSPCS_SPA_SHIFT 16
100 119#define SKL_ADSPCS_SPA_MASK(cm) ((cm) << SKL_ADSPCS_SPA_SHIFT)
101/* Current Power Active - power status of cores, set by hardware */ 120
102#define SKL_ADSPCS_CPA_SHIFT 24 121/*
103#define SKL_ADSPCS_CPA_MASK (SKL_DSP_CORES_MASK << SKL_ADSPCS_CPA_SHIFT) 122 * Current Power Active - power status of cores, set by hardware
104#define SKL_ADSPCS_CPA(x) ((x << SKL_ADSPCS_CPA_SHIFT) & SKL_ADSPCS_CPA_MASK) 123 * CPA Mask for a given core mask pattern, cm
105 124 */
106#define SST_DSP_POWER_D0 0x0 /* full On */ 125#define SKL_ADSPCS_CPA_SHIFT 24
107#define SST_DSP_POWER_D3 0x3 /* Off */ 126#define SKL_ADSPCS_CPA_MASK(cm) ((cm) << SKL_ADSPCS_CPA_SHIFT)
108 127
109enum skl_dsp_states { 128enum skl_dsp_states {
110 SKL_DSP_RUNNING = 1, 129 SKL_DSP_RUNNING = 1,
@@ -115,8 +134,8 @@ struct skl_dsp_fw_ops {
115 int (*load_fw)(struct sst_dsp *ctx); 134 int (*load_fw)(struct sst_dsp *ctx);
116 /* FW module parser/loader */ 135 /* FW module parser/loader */
117 int (*parse_fw)(struct sst_dsp *ctx); 136 int (*parse_fw)(struct sst_dsp *ctx);
118 int (*set_state_D0)(struct sst_dsp *ctx); 137 int (*set_state_D0)(struct sst_dsp *ctx, unsigned int core_id);
119 int (*set_state_D3)(struct sst_dsp *ctx); 138 int (*set_state_D3)(struct sst_dsp *ctx, unsigned int core_id);
120 unsigned int (*get_fw_errcode)(struct sst_dsp *ctx); 139 unsigned int (*get_fw_errcode)(struct sst_dsp *ctx);
121 int (*load_mod)(struct sst_dsp *ctx, u16 mod_id, u8 *mod_name); 140 int (*load_mod)(struct sst_dsp *ctx, u16 mod_id, u8 *mod_name);
122 int (*unload_mod)(struct sst_dsp *ctx, u16 mod_id); 141 int (*unload_mod)(struct sst_dsp *ctx, u16 mod_id);
@@ -157,14 +176,26 @@ int skl_cldma_prepare(struct sst_dsp *ctx);
157void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state); 176void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state);
158struct sst_dsp *skl_dsp_ctx_init(struct device *dev, 177struct sst_dsp *skl_dsp_ctx_init(struct device *dev,
159 struct sst_dsp_device *sst_dev, int irq); 178 struct sst_dsp_device *sst_dev, int irq);
160int skl_dsp_enable_core(struct sst_dsp *ctx);
161int skl_dsp_disable_core(struct sst_dsp *ctx);
162bool is_skl_dsp_running(struct sst_dsp *ctx); 179bool is_skl_dsp_running(struct sst_dsp *ctx);
180
181unsigned int skl_dsp_get_enabled_cores(struct sst_dsp *ctx);
182void skl_dsp_init_core_state(struct sst_dsp *ctx);
183int skl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask);
184int skl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask);
185int skl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask);
186int skl_dsp_core_power_down(struct sst_dsp *ctx, unsigned int core_mask);
187int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx,
188 unsigned int core_mask);
189int skl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask);
190
163irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id); 191irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id);
164int skl_dsp_wake(struct sst_dsp *ctx); 192int skl_dsp_wake(struct sst_dsp *ctx);
165int skl_dsp_sleep(struct sst_dsp *ctx); 193int skl_dsp_sleep(struct sst_dsp *ctx);
166void skl_dsp_free(struct sst_dsp *dsp); 194void skl_dsp_free(struct sst_dsp *dsp);
167 195
196int skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id);
197int skl_dsp_put_core(struct sst_dsp *ctx, unsigned int core_id);
198
168int skl_dsp_boot(struct sst_dsp *ctx); 199int skl_dsp_boot(struct sst_dsp *ctx);
169int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, 200int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
170 const char *fw_name, struct skl_dsp_loader_ops dsp_ops, 201 const char *fw_name, struct skl_dsp_loader_ops dsp_ops,
@@ -175,4 +206,11 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
175void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx); 206void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx);
176void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx); 207void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx);
177 208
209int snd_skl_get_module_info(struct skl_sst *ctx, u8 *uuid,
210 struct skl_dfw_module *dfw_config);
211int snd_skl_parse_uuids(struct sst_dsp *ctx, unsigned int offset);
212void skl_freeup_uuid_list(struct skl_sst *ctx);
213
214int skl_dsp_strip_extended_manifest(struct firmware *fw);
215
178#endif /*__SKL_SST_DSP_H__*/ 216#endif /*__SKL_SST_DSP_H__*/
diff --git a/sound/soc/intel/skylake/skl-sst-ipc.c b/sound/soc/intel/skylake/skl-sst-ipc.c
index 543460293b00..96f2f6889b18 100644
--- a/sound/soc/intel/skylake/skl-sst-ipc.c
+++ b/sound/soc/intel/skylake/skl-sst-ipc.c
@@ -363,7 +363,7 @@ static void skl_ipc_process_reply(struct sst_generic_ipc *ipc,
363 /* first process the header */ 363 /* first process the header */
364 switch (reply) { 364 switch (reply) {
365 case IPC_GLB_REPLY_SUCCESS: 365 case IPC_GLB_REPLY_SUCCESS:
366 dev_info(ipc->dev, "ipc FW reply %x: success\n", header.primary); 366 dev_dbg(ipc->dev, "ipc FW reply %x: success\n", header.primary);
367 /* copy the rx data from the mailbox */ 367 /* copy the rx data from the mailbox */
368 sst_dsp_inbox_read(ipc->dsp, msg->rx_data, msg->rx_size); 368 sst_dsp_inbox_read(ipc->dsp, msg->rx_data, msg->rx_size);
369 break; 369 break;
@@ -692,7 +692,7 @@ int skl_ipc_init_instance(struct sst_generic_ipc *ipc,
692 /* param_block_size must be in dwords */ 692 /* param_block_size must be in dwords */
693 u16 param_block_size = msg->param_data_size / sizeof(u32); 693 u16 param_block_size = msg->param_data_size / sizeof(u32);
694 694
695 print_hex_dump(KERN_DEBUG, NULL, DUMP_PREFIX_NONE, 695 print_hex_dump_debug("Param data:", DUMP_PREFIX_NONE,
696 16, 4, buffer, param_block_size, false); 696 16, 4, buffer, param_block_size, false);
697 697
698 header.primary = IPC_MSG_TARGET(IPC_MOD_MSG); 698 header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h
index d59d1ba62a43..2e3d4e80ef97 100644
--- a/sound/soc/intel/skylake/skl-sst-ipc.h
+++ b/sound/soc/intel/skylake/skl-sst-ipc.h
@@ -45,6 +45,14 @@ struct skl_ipc_header {
45 u32 extension; 45 u32 extension;
46}; 46};
47 47
48#define SKL_DSP_CORES_MAX 2
49
50struct skl_dsp_cores {
51 unsigned int count;
52 enum skl_dsp_states state[SKL_DSP_CORES_MAX];
53 int usage_count[SKL_DSP_CORES_MAX];
54};
55
48struct skl_sst { 56struct skl_sst {
49 struct device *dev; 57 struct device *dev;
50 struct sst_dsp *dsp; 58 struct sst_dsp *dsp;
@@ -60,6 +68,15 @@ struct skl_sst {
60 void (*enable_miscbdcge)(struct device *dev, bool enable); 68 void (*enable_miscbdcge)(struct device *dev, bool enable);
61 /*Is CGCTL.MISCBDCGE disabled*/ 69 /*Is CGCTL.MISCBDCGE disabled*/
62 bool miscbdcg_disabled; 70 bool miscbdcg_disabled;
71
72 /* Populate module information */
73 struct list_head uuid_list;
74
75 /* Is firmware loaded */
76 bool fw_loaded;
77
78 /* multi-core */
79 struct skl_dsp_cores cores;
63}; 80};
64 81
65struct skl_ipc_init_instance_msg { 82struct skl_ipc_init_instance_msg {
@@ -136,5 +153,6 @@ void skl_ipc_int_disable(struct sst_dsp *dsp);
136bool skl_ipc_int_status(struct sst_dsp *dsp); 153bool skl_ipc_int_status(struct sst_dsp *dsp);
137void skl_ipc_free(struct sst_generic_ipc *ipc); 154void skl_ipc_free(struct sst_generic_ipc *ipc);
138int skl_ipc_init(struct device *dev, struct skl_sst *skl); 155int skl_ipc_init(struct device *dev, struct skl_sst *skl);
156void skl_clear_module_cnt(struct sst_dsp *ctx);
139 157
140#endif /* __SKL_IPC_H */ 158#endif /* __SKL_IPC_H */
diff --git a/sound/soc/intel/skylake/skl-sst-utils.c b/sound/soc/intel/skylake/skl-sst-utils.c
new file mode 100644
index 000000000000..25fcb796bd86
--- /dev/null
+++ b/sound/soc/intel/skylake/skl-sst-utils.c
@@ -0,0 +1,256 @@
1/*
2 * skl-sst-utils.c - SKL sst utils functions
3 *
4 * Copyright (C) 2016 Intel Corp
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 */
15
16#include <linux/device.h>
17#include <linux/slab.h>
18#include <linux/uuid.h>
19#include "skl-sst-dsp.h"
20#include "../common/sst-dsp.h"
21#include "../common/sst-dsp-priv.h"
22#include "skl-sst-ipc.h"
23
24
25#define UUID_STR_SIZE 37
26#define DEFAULT_HASH_SHA256_LEN 32
27
28/* FW Extended Manifest Header id = $AE1 */
29#define SKL_EXT_MANIFEST_HEADER_MAGIC 0x31454124
30
31struct skl_dfw_module_mod {
32 char name[100];
33 struct skl_dfw_module skl_dfw_mod;
34};
35
36struct UUID {
37 u8 id[16];
38};
39
40union seg_flags {
41 u32 ul;
42 struct {
43 u32 contents : 1;
44 u32 alloc : 1;
45 u32 load : 1;
46 u32 read_only : 1;
47 u32 code : 1;
48 u32 data : 1;
49 u32 _rsvd0 : 2;
50 u32 type : 4;
51 u32 _rsvd1 : 4;
52 u32 length : 16;
53 } r;
54} __packed;
55
56struct segment_desc {
57 union seg_flags flags;
58 u32 v_base_addr;
59 u32 file_offset;
60};
61
62struct module_type {
63 u32 load_type : 4;
64 u32 auto_start : 1;
65 u32 domain_ll : 1;
66 u32 domain_dp : 1;
67 u32 rsvd : 25;
68} __packed;
69
70struct adsp_module_entry {
71 u32 struct_id;
72 u8 name[8];
73 struct UUID uuid;
74 struct module_type type;
75 u8 hash1[DEFAULT_HASH_SHA256_LEN];
76 u32 entry_point;
77 u16 cfg_offset;
78 u16 cfg_count;
79 u32 affinity_mask;
80 u16 instance_max_count;
81 u16 instance_bss_size;
82 struct segment_desc segments[3];
83} __packed;
84
85struct adsp_fw_hdr {
86 u32 id;
87 u32 len;
88 u8 name[8];
89 u32 preload_page_count;
90 u32 fw_image_flags;
91 u32 feature_mask;
92 u16 major;
93 u16 minor;
94 u16 hotfix;
95 u16 build;
96 u32 num_modules;
97 u32 hw_buf_base;
98 u32 hw_buf_length;
99 u32 load_offset;
100} __packed;
101
102struct uuid_module {
103 uuid_le uuid;
104 int id;
105 int is_loadable;
106
107 struct list_head list;
108};
109
110struct skl_ext_manifest_hdr {
111 u32 id;
112 u32 len;
113 u16 version_major;
114 u16 version_minor;
115 u32 entries;
116};
117
118int snd_skl_get_module_info(struct skl_sst *ctx, u8 *uuid,
119 struct skl_dfw_module *dfw_config)
120{
121 struct uuid_module *module;
122 uuid_le *uuid_mod;
123
124 uuid_mod = (uuid_le *)uuid;
125
126 list_for_each_entry(module, &ctx->uuid_list, list) {
127 if (uuid_le_cmp(*uuid_mod, module->uuid) == 0) {
128 dfw_config->module_id = module->id;
129 dfw_config->is_loadable = module->is_loadable;
130
131 return 0;
132 }
133 }
134
135 return -EINVAL;
136}
137EXPORT_SYMBOL_GPL(snd_skl_get_module_info);
138
139/*
140 * Parse the firmware binary to get the UUID, module id
141 * and loadable flags
142 */
143int snd_skl_parse_uuids(struct sst_dsp *ctx, unsigned int offset)
144{
145 struct adsp_fw_hdr *adsp_hdr;
146 struct adsp_module_entry *mod_entry;
147 int i, num_entry;
148 uuid_le *uuid_bin;
149 const char *buf;
150 struct skl_sst *skl = ctx->thread_context;
151 struct uuid_module *module;
152 struct firmware stripped_fw;
153 unsigned int safe_file;
154
155 /* Get the FW pointer to derive ADSP header */
156 stripped_fw.data = ctx->fw->data;
157 stripped_fw.size = ctx->fw->size;
158
159 skl_dsp_strip_extended_manifest(&stripped_fw);
160
161 buf = stripped_fw.data;
162
163 /* check if we have enough space in file to move to header */
164 safe_file = sizeof(*adsp_hdr) + offset;
165 if (stripped_fw.size <= safe_file) {
166 dev_err(ctx->dev, "Small fw file size, No space for hdr\n");
167 return -EINVAL;
168 }
169
170 adsp_hdr = (struct adsp_fw_hdr *)(buf + offset);
171
172 /* check 1st module entry is in file */
173 safe_file += adsp_hdr->len + sizeof(*mod_entry);
174 if (stripped_fw.size <= safe_file) {
175 dev_err(ctx->dev, "Small fw file size, No module entry\n");
176 return -EINVAL;
177 }
178
179 mod_entry = (struct adsp_module_entry *)
180 (buf + offset + adsp_hdr->len);
181
182 num_entry = adsp_hdr->num_modules;
183
184 /* check all entries are in file */
185 safe_file += num_entry * sizeof(*mod_entry);
186 if (stripped_fw.size <= safe_file) {
187 dev_err(ctx->dev, "Small fw file size, No modules\n");
188 return -EINVAL;
189 }
190
191
192 /*
193 * Read the UUID(GUID) from FW Manifest.
194 *
195 * The 16 byte UUID format is: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX
196 * Populate the UUID table to store module_id and loadable flags
197 * for the module.
198 */
199
200 for (i = 0; i < num_entry; i++, mod_entry++) {
201 module = kzalloc(sizeof(*module), GFP_KERNEL);
202 if (!module)
203 return -ENOMEM;
204
205 uuid_bin = (uuid_le *)mod_entry->uuid.id;
206 memcpy(&module->uuid, uuid_bin, sizeof(module->uuid));
207
208 module->id = i;
209 module->is_loadable = mod_entry->type.load_type;
210
211 list_add_tail(&module->list, &skl->uuid_list);
212
213 dev_dbg(ctx->dev,
214 "Adding uuid :%pUL mod id: %d Loadable: %d\n",
215 &module->uuid, module->id, module->is_loadable);
216 }
217
218 return 0;
219}
220
221void skl_freeup_uuid_list(struct skl_sst *ctx)
222{
223 struct uuid_module *uuid, *_uuid;
224
225 list_for_each_entry_safe(uuid, _uuid, &ctx->uuid_list, list) {
226 list_del(&uuid->list);
227 kfree(uuid);
228 }
229}
230
231/*
232 * some firmware binary contains some extended manifest. This needs
233 * to be stripped in that case before we load and use that image.
234 *
235 * Get the module id for the module by checking
236 * the table for the UUID for the module
237 */
238int skl_dsp_strip_extended_manifest(struct firmware *fw)
239{
240 struct skl_ext_manifest_hdr *hdr;
241
242 /* check if fw file is greater than header we are looking */
243 if (fw->size < sizeof(hdr)) {
244 pr_err("%s: Firmware file small, no hdr\n", __func__);
245 return -EINVAL;
246 }
247
248 hdr = (struct skl_ext_manifest_hdr *)fw->data;
249
250 if (hdr->id == SKL_EXT_MANIFEST_HEADER_MAGIC) {
251 fw->size -= hdr->len;
252 fw->data += hdr->len;
253 }
254
255 return 0;
256}
diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c
index 13ec8d53b526..588f899ceb65 100644
--- a/sound/soc/intel/skylake/skl-sst.c
+++ b/sound/soc/intel/skylake/skl-sst.c
@@ -68,10 +68,13 @@ static int skl_transfer_firmware(struct sst_dsp *ctx,
68 return ret; 68 return ret;
69} 69}
70 70
71#define SKL_ADSP_FW_BIN_HDR_OFFSET 0x284
72
71static int skl_load_base_firmware(struct sst_dsp *ctx) 73static int skl_load_base_firmware(struct sst_dsp *ctx)
72{ 74{
73 int ret = 0, i; 75 int ret = 0, i;
74 struct skl_sst *skl = ctx->thread_context; 76 struct skl_sst *skl = ctx->thread_context;
77 struct firmware stripped_fw;
75 u32 reg; 78 u32 reg;
76 79
77 skl->boot_complete = false; 80 skl->boot_complete = false;
@@ -81,11 +84,25 @@ static int skl_load_base_firmware(struct sst_dsp *ctx)
81 ret = request_firmware(&ctx->fw, ctx->fw_name, ctx->dev); 84 ret = request_firmware(&ctx->fw, ctx->fw_name, ctx->dev);
82 if (ret < 0) { 85 if (ret < 0) {
83 dev_err(ctx->dev, "Request firmware failed %d\n", ret); 86 dev_err(ctx->dev, "Request firmware failed %d\n", ret);
84 skl_dsp_disable_core(ctx);
85 return -EIO; 87 return -EIO;
86 } 88 }
87 } 89 }
88 90
91 ret = snd_skl_parse_uuids(ctx, SKL_ADSP_FW_BIN_HDR_OFFSET);
92 if (ret < 0) {
93 dev_err(ctx->dev,
94 "UUID parsing err: %d\n", ret);
95 release_firmware(ctx->fw);
96 skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
97 return ret;
98 }
99
100 /* check for extended manifest */
101 stripped_fw.data = ctx->fw->data;
102 stripped_fw.size = ctx->fw->size;
103
104 skl_dsp_strip_extended_manifest(&stripped_fw);
105
89 ret = skl_dsp_boot(ctx); 106 ret = skl_dsp_boot(ctx);
90 if (ret < 0) { 107 if (ret < 0) {
91 dev_err(ctx->dev, "Boot dsp core failed ret: %d", ret); 108 dev_err(ctx->dev, "Boot dsp core failed ret: %d", ret);
@@ -119,7 +136,7 @@ static int skl_load_base_firmware(struct sst_dsp *ctx)
119 goto transfer_firmware_failed; 136 goto transfer_firmware_failed;
120 } 137 }
121 138
122 ret = skl_transfer_firmware(ctx, ctx->fw->data, ctx->fw->size); 139 ret = skl_transfer_firmware(ctx, stripped_fw.data, stripped_fw.size);
123 if (ret < 0) { 140 if (ret < 0) {
124 dev_err(ctx->dev, "Transfer firmware failed%d\n", ret); 141 dev_err(ctx->dev, "Transfer firmware failed%d\n", ret);
125 goto transfer_firmware_failed; 142 goto transfer_firmware_failed;
@@ -133,67 +150,87 @@ static int skl_load_base_firmware(struct sst_dsp *ctx)
133 } 150 }
134 151
135 dev_dbg(ctx->dev, "Download firmware successful%d\n", ret); 152 dev_dbg(ctx->dev, "Download firmware successful%d\n", ret);
136 skl_dsp_set_state_locked(ctx, SKL_DSP_RUNNING); 153 skl->fw_loaded = true;
137 } 154 }
138 return 0; 155 return 0;
139transfer_firmware_failed: 156transfer_firmware_failed:
140 ctx->cl_dev.ops.cl_cleanup_controller(ctx); 157 ctx->cl_dev.ops.cl_cleanup_controller(ctx);
141skl_load_base_firmware_failed: 158skl_load_base_firmware_failed:
142 skl_dsp_disable_core(ctx); 159 skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
143 release_firmware(ctx->fw); 160 release_firmware(ctx->fw);
144 ctx->fw = NULL; 161 ctx->fw = NULL;
145 return ret; 162 return ret;
146} 163}
147 164
148static int skl_set_dsp_D0(struct sst_dsp *ctx) 165static int skl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id)
149{ 166{
150 int ret; 167 int ret;
168 struct skl_ipc_dxstate_info dx;
169 struct skl_sst *skl = ctx->thread_context;
170 unsigned int core_mask = SKL_DSP_CORE_MASK(core_id);
151 171
152 ret = skl_load_base_firmware(ctx); 172 /* If core0 is being turned on, we need to load the FW */
153 if (ret < 0) { 173 if (core_id == SKL_DSP_CORE0_ID) {
154 dev_err(ctx->dev, "unable to load firmware\n"); 174 ret = skl_load_base_firmware(ctx);
155 return ret; 175 if (ret < 0) {
176 dev_err(ctx->dev, "unable to load firmware\n");
177 return ret;
178 }
156 } 179 }
157 180
158 skl_dsp_set_state_locked(ctx, SKL_DSP_RUNNING); 181 /*
182 * If any core other than core 0 is being moved to D0, enable the
183 * core and send the set dx IPC for the core.
184 */
185 if (core_id != SKL_DSP_CORE0_ID) {
186 ret = skl_dsp_enable_core(ctx, core_mask);
187 if (ret < 0)
188 return ret;
189
190 dx.core_mask = core_mask;
191 dx.dx_mask = core_mask;
192
193 ret = skl_ipc_set_dx(&skl->ipc, SKL_INSTANCE_ID,
194 SKL_BASE_FW_MODULE_ID, &dx);
195 if (ret < 0) {
196 dev_err(ctx->dev, "Failed to set dsp to D0:core id= %d\n",
197 core_id);
198 skl_dsp_disable_core(ctx, core_mask);
199 }
200 }
201
202 skl->cores.state[core_id] = SKL_DSP_RUNNING;
159 203
160 return ret; 204 return ret;
161} 205}
162 206
163static int skl_set_dsp_D3(struct sst_dsp *ctx) 207static int skl_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id)
164{ 208{
165 int ret; 209 int ret;
166 struct skl_ipc_dxstate_info dx; 210 struct skl_ipc_dxstate_info dx;
167 struct skl_sst *skl = ctx->thread_context; 211 struct skl_sst *skl = ctx->thread_context;
212 unsigned int core_mask = SKL_DSP_CORE_MASK(core_id);
168 213
169 dev_dbg(ctx->dev, "In %s:\n", __func__); 214 dx.core_mask = core_mask;
170 mutex_lock(&ctx->mutex);
171 if (!is_skl_dsp_running(ctx)) {
172 mutex_unlock(&ctx->mutex);
173 return 0;
174 }
175 mutex_unlock(&ctx->mutex);
176
177 dx.core_mask = SKL_DSP_CORE0_MASK;
178 dx.dx_mask = SKL_IPC_D3_MASK; 215 dx.dx_mask = SKL_IPC_D3_MASK;
216
179 ret = skl_ipc_set_dx(&skl->ipc, SKL_INSTANCE_ID, SKL_BASE_FW_MODULE_ID, &dx); 217 ret = skl_ipc_set_dx(&skl->ipc, SKL_INSTANCE_ID, SKL_BASE_FW_MODULE_ID, &dx);
180 if (ret < 0) 218 if (ret < 0)
181 dev_err(ctx->dev, 219 dev_err(ctx->dev, "set Dx core %d fail: %d\n", core_id, ret);
182 "D3 request to FW failed, continuing reset: %d", ret); 220
183 221 if (core_id == SKL_DSP_CORE0_ID) {
184 /* disable Interrupt */ 222 /* disable Interrupt */
185 ctx->cl_dev.ops.cl_cleanup_controller(ctx); 223 ctx->cl_dev.ops.cl_cleanup_controller(ctx);
186 skl_cldma_int_disable(ctx); 224 skl_cldma_int_disable(ctx);
187 skl_ipc_op_int_disable(ctx); 225 skl_ipc_op_int_disable(ctx);
188 skl_ipc_int_disable(ctx); 226 skl_ipc_int_disable(ctx);
189
190 ret = skl_dsp_disable_core(ctx);
191 if (ret < 0) {
192 dev_err(ctx->dev, "disable dsp core failed ret: %d\n", ret);
193 ret = -EIO;
194 } 227 }
195 skl_dsp_set_state_locked(ctx, SKL_DSP_RESET);
196 228
229 ret = skl_dsp_disable_core(ctx, core_mask);
230 if (ret < 0)
231 return ret;
232
233 skl->cores.state[core_id] = SKL_DSP_RESET;
197 return ret; 234 return ret;
198} 235}
199 236
@@ -360,6 +397,19 @@ static int skl_unload_module(struct sst_dsp *ctx, u16 mod_id)
360 return ret; 397 return ret;
361} 398}
362 399
400void skl_clear_module_cnt(struct sst_dsp *ctx)
401{
402 struct skl_module_table *module;
403
404 if (list_empty(&ctx->module_list))
405 return;
406
407 list_for_each_entry(module, &ctx->module_list, list) {
408 module->usage_cnt = 0;
409 }
410}
411EXPORT_SYMBOL_GPL(skl_clear_module_cnt);
412
363static void skl_clear_module_table(struct sst_dsp *ctx) 413static void skl_clear_module_table(struct sst_dsp *ctx)
364{ 414{
365 struct skl_module_table *module, *tmp; 415 struct skl_module_table *module, *tmp;
@@ -409,6 +459,7 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
409 459
410 skl->dev = dev; 460 skl->dev = dev;
411 skl_dev.thread_context = skl; 461 skl_dev.thread_context = skl;
462 INIT_LIST_HEAD(&skl->uuid_list);
412 463
413 skl->dsp = skl_dsp_ctx_init(dev, &skl_dev, irq); 464 skl->dsp = skl_dsp_ctx_init(dev, &skl_dev, irq);
414 if (!skl->dsp) { 465 if (!skl->dsp) {
@@ -432,12 +483,16 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
432 if (ret) 483 if (ret)
433 return ret; 484 return ret;
434 485
486 skl->cores.count = 2;
487
435 ret = sst->fw_ops.load_fw(sst); 488 ret = sst->fw_ops.load_fw(sst);
436 if (ret < 0) { 489 if (ret < 0) {
437 dev_err(dev, "Load base fw failed : %d", ret); 490 dev_err(dev, "Load base fw failed : %d", ret);
438 goto cleanup; 491 goto cleanup;
439 } 492 }
440 493
494 skl_dsp_init_core_state(sst);
495
441 if (dsp) 496 if (dsp)
442 *dsp = skl; 497 *dsp = skl;
443 498
@@ -452,6 +507,7 @@ EXPORT_SYMBOL_GPL(skl_sst_dsp_init);
452void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) 507void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx)
453{ 508{
454 skl_clear_module_table(ctx->dsp); 509 skl_clear_module_table(ctx->dsp);
510 skl_freeup_uuid_list(ctx);
455 skl_ipc_free(&ctx->ipc); 511 skl_ipc_free(&ctx->ipc);
456 ctx->dsp->ops->free(ctx->dsp); 512 ctx->dsp->ops->free(ctx->dsp);
457 if (ctx->boot_complete) { 513 if (ctx->boot_complete) {
diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c
index c15b7f8962b3..cc0150fc2601 100644
--- a/sound/soc/intel/skylake/skl-topology.c
+++ b/sound/soc/intel/skylake/skl-topology.c
@@ -379,43 +379,6 @@ static void skl_tplg_update_module_params(struct snd_soc_dapm_widget *w,
379} 379}
380 380
381/* 381/*
382 * A pipe can have multiple modules, each of them will be a DAPM widget as
383 * well. While managing a pipeline we need to get the list of all the
384 * widgets in a pipelines, so this helper - skl_tplg_get_pipe_widget() helps
385 * to get the SKL type widgets in that pipeline
386 */
387static int skl_tplg_alloc_pipe_widget(struct device *dev,
388 struct snd_soc_dapm_widget *w, struct skl_pipe *pipe)
389{
390 struct skl_module_cfg *src_module = NULL;
391 struct snd_soc_dapm_path *p = NULL;
392 struct skl_pipe_module *p_module = NULL;
393
394 p_module = devm_kzalloc(dev, sizeof(*p_module), GFP_KERNEL);
395 if (!p_module)
396 return -ENOMEM;
397
398 p_module->w = w;
399 list_add_tail(&p_module->node, &pipe->w_list);
400
401 snd_soc_dapm_widget_for_each_sink_path(w, p) {
402 if ((p->sink->priv == NULL)
403 && (!is_skl_dsp_widget_type(w)))
404 continue;
405
406 if ((p->sink->priv != NULL) && p->connect
407 && is_skl_dsp_widget_type(p->sink)) {
408
409 src_module = p->sink->priv;
410 if (pipe->ppl_id == src_module->pipe->ppl_id)
411 skl_tplg_alloc_pipe_widget(dev,
412 p->sink, pipe);
413 }
414 }
415 return 0;
416}
417
418/*
419 * some modules can have multiple params set from user control and 382 * some modules can have multiple params set from user control and
420 * need to be set after module is initialized. If set_param flag is 383 * need to be set after module is initialized. If set_param flag is
421 * set module params will be done after module is initialised. 384 * set module params will be done after module is initialised.
@@ -514,8 +477,6 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe)
514 if (!skl_is_pipe_mcps_avail(skl, mconfig)) 477 if (!skl_is_pipe_mcps_avail(skl, mconfig))
515 return -ENOMEM; 478 return -ENOMEM;
516 479
517 skl_tplg_alloc_pipe_mcps(skl, mconfig);
518
519 if (mconfig->is_loadable && ctx->dsp->fw_ops.load_mod) { 480 if (mconfig->is_loadable && ctx->dsp->fw_ops.load_mod) {
520 ret = ctx->dsp->fw_ops.load_mod(ctx->dsp, 481 ret = ctx->dsp->fw_ops.load_mod(ctx->dsp,
521 mconfig->id.module_id, mconfig->guid); 482 mconfig->id.module_id, mconfig->guid);
@@ -539,6 +500,7 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe)
539 if (ret < 0) 500 if (ret < 0)
540 return ret; 501 return ret;
541 502
503 skl_tplg_alloc_pipe_mcps(skl, mconfig);
542 ret = skl_tplg_set_module_params(w, ctx); 504 ret = skl_tplg_set_module_params(w, ctx);
543 if (ret < 0) 505 if (ret < 0)
544 return ret; 506 return ret;
@@ -591,9 +553,6 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
591 if (!skl_is_pipe_mem_avail(skl, mconfig)) 553 if (!skl_is_pipe_mem_avail(skl, mconfig))
592 return -ENOMEM; 554 return -ENOMEM;
593 555
594 skl_tplg_alloc_pipe_mem(skl, mconfig);
595 skl_tplg_alloc_pipe_mcps(skl, mconfig);
596
597 /* 556 /*
598 * Create a list of modules for pipe. 557 * Create a list of modules for pipe.
599 * This list contains modules from source to sink 558 * This list contains modules from source to sink
@@ -602,19 +561,8 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
602 if (ret < 0) 561 if (ret < 0)
603 return ret; 562 return ret;
604 563
605 /* 564 skl_tplg_alloc_pipe_mem(skl, mconfig);
606 * we create a w_list of all widgets in that pipe. This list is not 565 skl_tplg_alloc_pipe_mcps(skl, mconfig);
607 * freed on PMD event as widgets within a pipe are static. This
608 * saves us cycles to get widgets in pipe every time.
609 *
610 * So if we have already initialized all the widgets of a pipeline
611 * we skip, so check for list_empty and create the list if empty
612 */
613 if (list_empty(&s_pipe->w_list)) {
614 ret = skl_tplg_alloc_pipe_widget(ctx->dev, w, s_pipe);
615 if (ret < 0)
616 return ret;
617 }
618 566
619 /* Init all pipe modules from source to sink */ 567 /* Init all pipe modules from source to sink */
620 ret = skl_tplg_init_pipe_modules(skl, s_pipe); 568 ret = skl_tplg_init_pipe_modules(skl, s_pipe);
@@ -949,13 +897,17 @@ static int skl_tplg_mixer_dapm_post_pmd_event(struct snd_soc_dapm_widget *w,
949 struct skl_pipe *s_pipe = mconfig->pipe; 897 struct skl_pipe *s_pipe = mconfig->pipe;
950 int ret = 0; 898 int ret = 0;
951 899
900 if (s_pipe->state == SKL_PIPE_INVALID)
901 return -EINVAL;
902
952 skl_tplg_free_pipe_mcps(skl, mconfig); 903 skl_tplg_free_pipe_mcps(skl, mconfig);
953 skl_tplg_free_pipe_mem(skl, mconfig); 904 skl_tplg_free_pipe_mem(skl, mconfig);
954 905
955 list_for_each_entry(w_module, &s_pipe->w_list, node) { 906 list_for_each_entry(w_module, &s_pipe->w_list, node) {
956 dst_module = w_module->w->priv; 907 dst_module = w_module->w->priv;
957 908
958 skl_tplg_free_pipe_mcps(skl, dst_module); 909 if (mconfig->m_state >= SKL_MODULE_INIT_DONE)
910 skl_tplg_free_pipe_mcps(skl, dst_module);
959 if (src_module == NULL) { 911 if (src_module == NULL) {
960 src_module = dst_module; 912 src_module = dst_module;
961 continue; 913 continue;
@@ -1163,6 +1115,39 @@ static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol,
1163} 1115}
1164 1116
1165/* 1117/*
1118 * Fill the dma id for host and link. In case of passthrough
1119 * pipeline, this will both host and link in the same
1120 * pipeline, so need to copy the link and host based on dev_type
1121 */
1122static void skl_tplg_fill_dma_id(struct skl_module_cfg *mcfg,
1123 struct skl_pipe_params *params)
1124{
1125 struct skl_pipe *pipe = mcfg->pipe;
1126
1127 if (pipe->passthru) {
1128 switch (mcfg->dev_type) {
1129 case SKL_DEVICE_HDALINK:
1130 pipe->p_params->link_dma_id = params->link_dma_id;
1131 break;
1132
1133 case SKL_DEVICE_HDAHOST:
1134 pipe->p_params->host_dma_id = params->host_dma_id;
1135 break;
1136
1137 default:
1138 break;
1139 }
1140 pipe->p_params->s_fmt = params->s_fmt;
1141 pipe->p_params->ch = params->ch;
1142 pipe->p_params->s_freq = params->s_freq;
1143 pipe->p_params->stream = params->stream;
1144
1145 } else {
1146 memcpy(pipe->p_params, params, sizeof(*params));
1147 }
1148}
1149
1150/*
1166 * The FE params are passed by hw_params of the DAI. 1151 * The FE params are passed by hw_params of the DAI.
1167 * On hw_params, the params are stored in Gateway module of the FE and we 1152 * On hw_params, the params are stored in Gateway module of the FE and we
1168 * need to calculate the format in DSP module configuration, that 1153 * need to calculate the format in DSP module configuration, that
@@ -1172,10 +1157,9 @@ int skl_tplg_update_pipe_params(struct device *dev,
1172 struct skl_module_cfg *mconfig, 1157 struct skl_module_cfg *mconfig,
1173 struct skl_pipe_params *params) 1158 struct skl_pipe_params *params)
1174{ 1159{
1175 struct skl_pipe *pipe = mconfig->pipe;
1176 struct skl_module_fmt *format = NULL; 1160 struct skl_module_fmt *format = NULL;
1177 1161
1178 memcpy(pipe->p_params, params, sizeof(*params)); 1162 skl_tplg_fill_dma_id(mconfig, params);
1179 1163
1180 if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) 1164 if (params->stream == SNDRV_PCM_STREAM_PLAYBACK)
1181 format = &mconfig->in_fmt[0]; 1165 format = &mconfig->in_fmt[0];
@@ -1362,12 +1346,11 @@ static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai,
1362 struct skl_module_cfg *mconfig, 1346 struct skl_module_cfg *mconfig,
1363 struct skl_pipe_params *params) 1347 struct skl_pipe_params *params)
1364{ 1348{
1365 struct skl_pipe *pipe = mconfig->pipe;
1366 struct nhlt_specific_cfg *cfg; 1349 struct nhlt_specific_cfg *cfg;
1367 struct skl *skl = get_skl_ctx(dai->dev); 1350 struct skl *skl = get_skl_ctx(dai->dev);
1368 int link_type = skl_tplg_be_link_type(mconfig->dev_type); 1351 int link_type = skl_tplg_be_link_type(mconfig->dev_type);
1369 1352
1370 memcpy(pipe->p_params, params, sizeof(*params)); 1353 skl_tplg_fill_dma_id(mconfig, params);
1371 1354
1372 if (link_type == NHLT_LINK_HDA) 1355 if (link_type == NHLT_LINK_HDA)
1373 return 0; 1356 return 0;
@@ -1558,6 +1541,55 @@ static void skl_tplg_fill_fmt(struct skl_module_fmt *dst_fmt,
1558 } 1541 }
1559} 1542}
1560 1543
1544static void skl_clear_pin_config(struct snd_soc_platform *platform,
1545 struct snd_soc_dapm_widget *w)
1546{
1547 int i;
1548 struct skl_module_cfg *mconfig;
1549 struct skl_pipe *pipe;
1550
1551 if (!strncmp(w->dapm->component->name, platform->component.name,
1552 strlen(platform->component.name))) {
1553 mconfig = w->priv;
1554 pipe = mconfig->pipe;
1555 for (i = 0; i < mconfig->max_in_queue; i++) {
1556 mconfig->m_in_pin[i].in_use = false;
1557 mconfig->m_in_pin[i].pin_state = SKL_PIN_UNBIND;
1558 }
1559 for (i = 0; i < mconfig->max_out_queue; i++) {
1560 mconfig->m_out_pin[i].in_use = false;
1561 mconfig->m_out_pin[i].pin_state = SKL_PIN_UNBIND;
1562 }
1563 pipe->state = SKL_PIPE_INVALID;
1564 mconfig->m_state = SKL_MODULE_UNINIT;
1565 }
1566}
1567
1568void skl_cleanup_resources(struct skl *skl)
1569{
1570 struct skl_sst *ctx = skl->skl_sst;
1571 struct snd_soc_platform *soc_platform = skl->platform;
1572 struct snd_soc_dapm_widget *w;
1573 struct snd_soc_card *card;
1574
1575 if (soc_platform == NULL)
1576 return;
1577
1578 card = soc_platform->component.card;
1579 if (!card || !card->instantiated)
1580 return;
1581
1582 skl->resource.mem = 0;
1583 skl->resource.mcps = 0;
1584
1585 list_for_each_entry(w, &card->widgets, list) {
1586 if (is_skl_dsp_widget_type(w) && (w->priv != NULL))
1587 skl_clear_pin_config(soc_platform, w);
1588 }
1589
1590 skl_clear_module_cnt(ctx->dsp);
1591}
1592
1561/* 1593/*
1562 * Topology core widget load callback 1594 * Topology core widget load callback
1563 * 1595 *
@@ -1589,6 +1621,10 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt,
1589 w->priv = mconfig; 1621 w->priv = mconfig;
1590 memcpy(&mconfig->guid, &dfw_config->uuid, 16); 1622 memcpy(&mconfig->guid, &dfw_config->uuid, 16);
1591 1623
1624 ret = snd_skl_get_module_info(skl->skl_sst, mconfig->guid, dfw_config);
1625 if (ret < 0)
1626 return ret;
1627
1592 mconfig->id.module_id = dfw_config->module_id; 1628 mconfig->id.module_id = dfw_config->module_id;
1593 mconfig->id.instance_id = dfw_config->instance_id; 1629 mconfig->id.instance_id = dfw_config->instance_id;
1594 mconfig->mcps = dfw_config->max_mcps; 1630 mconfig->mcps = dfw_config->max_mcps;
@@ -1738,6 +1774,60 @@ static struct snd_soc_tplg_ops skl_tplg_ops = {
1738 .bytes_ext_ops_count = ARRAY_SIZE(skl_tlv_ops), 1774 .bytes_ext_ops_count = ARRAY_SIZE(skl_tlv_ops),
1739}; 1775};
1740 1776
1777/*
1778 * A pipe can have multiple modules, each of them will be a DAPM widget as
1779 * well. While managing a pipeline we need to get the list of all the
1780 * widgets in a pipelines, so this helper - skl_tplg_create_pipe_widget_list()
1781 * helps to get the SKL type widgets in that pipeline
1782 */
1783static int skl_tplg_create_pipe_widget_list(struct snd_soc_platform *platform)
1784{
1785 struct snd_soc_dapm_widget *w;
1786 struct skl_module_cfg *mcfg = NULL;
1787 struct skl_pipe_module *p_module = NULL;
1788 struct skl_pipe *pipe;
1789
1790 list_for_each_entry(w, &platform->component.card->widgets, list) {
1791 if (is_skl_dsp_widget_type(w) && w->priv != NULL) {
1792 mcfg = w->priv;
1793 pipe = mcfg->pipe;
1794
1795 p_module = devm_kzalloc(platform->dev,
1796 sizeof(*p_module), GFP_KERNEL);
1797 if (!p_module)
1798 return -ENOMEM;
1799
1800 p_module->w = w;
1801 list_add_tail(&p_module->node, &pipe->w_list);
1802 }
1803 }
1804
1805 return 0;
1806}
1807
1808static void skl_tplg_set_pipe_type(struct skl *skl, struct skl_pipe *pipe)
1809{
1810 struct skl_pipe_module *w_module;
1811 struct snd_soc_dapm_widget *w;
1812 struct skl_module_cfg *mconfig;
1813 bool host_found = false, link_found = false;
1814
1815 list_for_each_entry(w_module, &pipe->w_list, node) {
1816 w = w_module->w;
1817 mconfig = w->priv;
1818
1819 if (mconfig->dev_type == SKL_DEVICE_HDAHOST)
1820 host_found = true;
1821 else if (mconfig->dev_type != SKL_DEVICE_NONE)
1822 link_found = true;
1823 }
1824
1825 if (host_found && link_found)
1826 pipe->passthru = true;
1827 else
1828 pipe->passthru = false;
1829}
1830
1741/* This will be read from topology manifest, currently defined here */ 1831/* This will be read from topology manifest, currently defined here */
1742#define SKL_MAX_MCPS 30000000 1832#define SKL_MAX_MCPS 30000000
1743#define SKL_FW_MAX_MEM 1000000 1833#define SKL_FW_MAX_MEM 1000000
@@ -1751,6 +1841,7 @@ int skl_tplg_init(struct snd_soc_platform *platform, struct hdac_ext_bus *ebus)
1751 const struct firmware *fw; 1841 const struct firmware *fw;
1752 struct hdac_bus *bus = ebus_to_hbus(ebus); 1842 struct hdac_bus *bus = ebus_to_hbus(ebus);
1753 struct skl *skl = ebus_to_skl(ebus); 1843 struct skl *skl = ebus_to_skl(ebus);
1844 struct skl_pipeline *ppl;
1754 1845
1755 ret = request_firmware(&fw, skl->tplg_name, bus->dev); 1846 ret = request_firmware(&fw, skl->tplg_name, bus->dev);
1756 if (ret < 0) { 1847 if (ret < 0) {
@@ -1780,6 +1871,12 @@ int skl_tplg_init(struct snd_soc_platform *platform, struct hdac_ext_bus *ebus)
1780 skl->resource.max_mem = SKL_FW_MAX_MEM; 1871 skl->resource.max_mem = SKL_FW_MAX_MEM;
1781 1872
1782 skl->tplg = fw; 1873 skl->tplg = fw;
1874 ret = skl_tplg_create_pipe_widget_list(platform);
1875 if (ret < 0)
1876 return ret;
1877
1878 list_for_each_entry(ppl, &skl->ppl_list, node)
1879 skl_tplg_set_pipe_type(skl, ppl->pipe);
1783 1880
1784 return 0; 1881 return 0;
1785} 1882}
diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h
index 28d1d2c68528..22d3ef83817d 100644
--- a/sound/soc/intel/skylake/skl-topology.h
+++ b/sound/soc/intel/skylake/skl-topology.h
@@ -244,7 +244,8 @@ enum skl_pipe_state {
244 SKL_PIPE_INVALID = 0, 244 SKL_PIPE_INVALID = 0,
245 SKL_PIPE_CREATED = 1, 245 SKL_PIPE_CREATED = 1,
246 SKL_PIPE_PAUSED = 2, 246 SKL_PIPE_PAUSED = 2,
247 SKL_PIPE_STARTED = 3 247 SKL_PIPE_STARTED = 3,
248 SKL_PIPE_RESET = 4
248}; 249};
249 250
250struct skl_pipe_module { 251struct skl_pipe_module {
@@ -270,6 +271,7 @@ struct skl_pipe {
270 struct skl_pipe_params *p_params; 271 struct skl_pipe_params *p_params;
271 enum skl_pipe_state state; 272 enum skl_pipe_state state;
272 struct list_head w_list; 273 struct list_head w_list;
274 bool passthru;
273}; 275};
274 276
275enum skl_module_state { 277enum skl_module_state {
@@ -358,6 +360,8 @@ int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe);
358 360
359int skl_stop_pipe(struct skl_sst *ctx, struct skl_pipe *pipe); 361int skl_stop_pipe(struct skl_sst *ctx, struct skl_pipe *pipe);
360 362
363int skl_reset_pipe(struct skl_sst *ctx, struct skl_pipe *pipe);
364
361int skl_init_module(struct skl_sst *ctx, struct skl_module_cfg *module_config); 365int skl_init_module(struct skl_sst *ctx, struct skl_module_cfg *module_config);
362 366
363int skl_bind_modules(struct skl_sst *ctx, struct skl_module_cfg 367int skl_bind_modules(struct skl_sst *ctx, struct skl_module_cfg
diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c
index 06d8c263c68f..cd59536a761d 100644
--- a/sound/soc/intel/skylake/skl.c
+++ b/sound/soc/intel/skylake/skl.c
@@ -35,6 +35,8 @@
35#include "skl-sst-dsp.h" 35#include "skl-sst-dsp.h"
36#include "skl-sst-ipc.h" 36#include "skl-sst-ipc.h"
37 37
38static struct skl_machine_pdata skl_dmic_data;
39
38/* 40/*
39 * initialize the PCI registers 41 * initialize the PCI registers
40 */ 42 */
@@ -184,6 +186,7 @@ static int _skl_suspend(struct hdac_ext_bus *ebus)
184{ 186{
185 struct skl *skl = ebus_to_skl(ebus); 187 struct skl *skl = ebus_to_skl(ebus);
186 struct hdac_bus *bus = ebus_to_hbus(ebus); 188 struct hdac_bus *bus = ebus_to_hbus(ebus);
189 struct pci_dev *pci = to_pci_dev(bus->dev);
187 int ret; 190 int ret;
188 191
189 snd_hdac_ext_bus_link_power_down_all(ebus); 192 snd_hdac_ext_bus_link_power_down_all(ebus);
@@ -193,9 +196,12 @@ static int _skl_suspend(struct hdac_ext_bus *ebus)
193 return ret; 196 return ret;
194 197
195 snd_hdac_bus_stop_chip(bus); 198 snd_hdac_bus_stop_chip(bus);
199 update_pci_dword(pci, AZX_PCIREG_PGCTL,
200 AZX_PGCTL_LSRMD_MASK, AZX_PGCTL_LSRMD_MASK);
196 skl_enable_miscbdcge(bus->dev, false); 201 skl_enable_miscbdcge(bus->dev, false);
197 snd_hdac_bus_enter_link_reset(bus); 202 snd_hdac_bus_enter_link_reset(bus);
198 skl_enable_miscbdcge(bus->dev, true); 203 skl_enable_miscbdcge(bus->dev, true);
204 skl_cleanup_resources(skl);
199 205
200 return 0; 206 return 0;
201} 207}
@@ -242,6 +248,7 @@ static int skl_suspend(struct device *dev)
242 ret = _skl_suspend(ebus); 248 ret = _skl_suspend(ebus);
243 if (ret < 0) 249 if (ret < 0)
244 return ret; 250 return ret;
251 skl->skl_sst->fw_loaded = false;
245 } 252 }
246 253
247 if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { 254 if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
@@ -397,6 +404,10 @@ static int skl_machine_device_register(struct skl *skl, void *driver_data)
397 platform_device_put(pdev); 404 platform_device_put(pdev);
398 return -EIO; 405 return -EIO;
399 } 406 }
407
408 if (mach->pdata)
409 dev_set_drvdata(&pdev->dev, mach->pdata);
410
400 skl->i2s_dev = pdev; 411 skl->i2s_dev = pdev;
401 412
402 return 0; 413 return 0;
@@ -657,6 +668,8 @@ static int skl_probe(struct pci_dev *pci,
657 668
658 skl->pci_id = pci->device; 669 skl->pci_id = pci->device;
659 670
671 device_disable_async_suspend(bus->dev);
672
660 skl->nhlt = skl_nhlt_init(bus->dev); 673 skl->nhlt = skl_nhlt_init(bus->dev);
661 674
662 if (skl->nhlt == NULL) 675 if (skl->nhlt == NULL)
@@ -666,6 +679,8 @@ static int skl_probe(struct pci_dev *pci,
666 679
667 pci_set_drvdata(skl->pci, ebus); 680 pci_set_drvdata(skl->pci, ebus);
668 681
682 skl_dmic_data.dmic_num = skl_get_dmic_geo(skl);
683
669 /* check if dsp is there */ 684 /* check if dsp is there */
670 if (ebus->ppcap) { 685 if (ebus->ppcap) {
671 err = skl_machine_device_register(skl, 686 err = skl_machine_device_register(skl,
@@ -713,7 +728,7 @@ static int skl_probe(struct pci_dev *pci,
713 list_for_each_entry(hlink, &ebus->hlink_list, list) 728 list_for_each_entry(hlink, &ebus->hlink_list, list)
714 snd_hdac_ext_bus_link_put(ebus, hlink); 729 snd_hdac_ext_bus_link_put(ebus, hlink);
715 730
716 /*configure PM */ 731 /* configure PM */
717 pm_runtime_put_noidle(bus->dev); 732 pm_runtime_put_noidle(bus->dev);
718 pm_runtime_allow(bus->dev); 733 pm_runtime_allow(bus->dev);
719 734
@@ -766,8 +781,7 @@ static void skl_remove(struct pci_dev *pci)
766 struct hdac_ext_bus *ebus = pci_get_drvdata(pci); 781 struct hdac_ext_bus *ebus = pci_get_drvdata(pci);
767 struct skl *skl = ebus_to_skl(ebus); 782 struct skl *skl = ebus_to_skl(ebus);
768 783
769 if (skl->tplg) 784 release_firmware(skl->tplg);
770 release_firmware(skl->tplg);
771 785
772 if (pci_dev_run_wake(pci)) 786 if (pci_dev_run_wake(pci))
773 pm_runtime_get_noresume(&pci->dev); 787 pm_runtime_get_noresume(&pci->dev);
@@ -786,15 +800,23 @@ static void skl_remove(struct pci_dev *pci)
786 800
787static struct sst_acpi_mach sst_skl_devdata[] = { 801static struct sst_acpi_mach sst_skl_devdata[] = {
788 { "INT343A", "skl_alc286s_i2s", "intel/dsp_fw_release.bin", NULL, NULL, NULL }, 802 { "INT343A", "skl_alc286s_i2s", "intel/dsp_fw_release.bin", NULL, NULL, NULL },
789 { "INT343B", "skl_nau88l25_ssm4567_i2s", "intel/dsp_fw_release.bin", 803 { "INT343B", "skl_n88l25_s4567", "intel/dsp_fw_release.bin",
790 NULL, NULL, NULL }, 804 NULL, NULL, &skl_dmic_data },
791 { "MX98357A", "skl_nau88l25_max98357a_i2s", "intel/dsp_fw_release.bin", 805 { "MX98357A", "skl_n88l25_m98357a", "intel/dsp_fw_release.bin",
792 NULL, NULL, NULL }, 806 NULL, NULL, &skl_dmic_data },
793 {} 807 {}
794}; 808};
795 809
796static struct sst_acpi_mach sst_bxtp_devdata[] = { 810static struct sst_acpi_mach sst_bxtp_devdata[] = {
797 { "INT343A", "bxt_alc298s_i2s", "intel/dsp_fw_bxtn.bin", NULL, NULL, NULL }, 811 { "INT343A", "bxt_alc298s_i2s", "intel/dsp_fw_bxtn.bin", NULL, NULL, NULL },
812 { "DLGS7219", "bxt_da7219_max98357a_i2s", "intel/dsp_fw_bxtn.bin", NULL, NULL, NULL },
813};
814
815static struct sst_acpi_mach sst_kbl_devdata[] = {
816 { "INT343A", "kbl_alc286s_i2s", "intel/dsp_fw_kbl.bin", NULL, NULL, NULL },
817 { "INT343B", "kbl_n88l25_s4567", "intel/dsp_fw_kbl.bin", NULL, NULL, &skl_dmic_data },
818 { "MX98357A", "kbl_n88l25_m98357a", "intel/dsp_fw_kbl.bin", NULL, NULL, &skl_dmic_data },
819 {}
798}; 820};
799 821
800/* PCI IDs */ 822/* PCI IDs */
@@ -805,6 +827,9 @@ static const struct pci_device_id skl_ids[] = {
805 /* BXT-P */ 827 /* BXT-P */
806 { PCI_DEVICE(0x8086, 0x5a98), 828 { PCI_DEVICE(0x8086, 0x5a98),
807 .driver_data = (unsigned long)&sst_bxtp_devdata}, 829 .driver_data = (unsigned long)&sst_bxtp_devdata},
830 /* KBL */
831 { PCI_DEVICE(0x8086, 0x9D71),
832 .driver_data = (unsigned long)&sst_kbl_devdata},
808 { 0, } 833 { 0, }
809}; 834};
810MODULE_DEVICE_TABLE(pci, skl_ids); 835MODULE_DEVICE_TABLE(pci, skl_ids);
diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h
index 4b4b3876aea9..9064e5b0d676 100644
--- a/sound/soc/intel/skylake/skl.h
+++ b/sound/soc/intel/skylake/skl.h
@@ -48,6 +48,8 @@
48#define AZX_REG_VS_SDXEFIFOS_XBASE 0x1094 48#define AZX_REG_VS_SDXEFIFOS_XBASE 0x1094
49#define AZX_REG_VS_SDXEFIFOS_XINTERVAL 0x20 49#define AZX_REG_VS_SDXEFIFOS_XINTERVAL 0x20
50 50
51#define AZX_PCIREG_PGCTL 0x44
52#define AZX_PGCTL_LSRMD_MASK (1 << 4)
51#define AZX_PCIREG_CGCTL 0x48 53#define AZX_PCIREG_CGCTL 0x48
52#define AZX_CGCTL_MISCBDCGE_MASK (1 << 6) 54#define AZX_CGCTL_MISCBDCGE_MASK (1 << 6)
53 55
@@ -65,6 +67,7 @@ struct skl {
65 unsigned int init_failed:1; /* delayed init failed */ 67 unsigned int init_failed:1; /* delayed init failed */
66 struct platform_device *dmic_dev; 68 struct platform_device *dmic_dev;
67 struct platform_device *i2s_dev; 69 struct platform_device *i2s_dev;
70 struct snd_soc_platform *platform;
68 71
69 struct nhlt_acpi_table *nhlt; /* nhlt ptr */ 72 struct nhlt_acpi_table *nhlt; /* nhlt ptr */
70 struct skl_sst *skl_sst; /* sst skl ctx */ 73 struct skl_sst *skl_sst; /* sst skl ctx */
@@ -90,6 +93,11 @@ struct skl_dma_params {
90 u8 stream_tag; 93 u8 stream_tag;
91}; 94};
92 95
96/* to pass dmic data */
97struct skl_machine_pdata {
98 u32 dmic_num;
99};
100
93struct skl_dsp_ops { 101struct skl_dsp_ops {
94 int id; 102 int id;
95 struct skl_dsp_loader_ops (*loader_ops)(void); 103 struct skl_dsp_loader_ops (*loader_ops)(void);
@@ -108,9 +116,11 @@ void skl_nhlt_free(struct nhlt_acpi_table *addr);
108struct nhlt_specific_cfg *skl_get_ep_blob(struct skl *skl, u32 instance, 116struct nhlt_specific_cfg *skl_get_ep_blob(struct skl *skl, u32 instance,
109 u8 link_type, u8 s_fmt, u8 no_ch, u32 s_rate, u8 dirn); 117 u8 link_type, u8 s_fmt, u8 no_ch, u32 s_rate, u8 dirn);
110 118
119int skl_get_dmic_geo(struct skl *skl);
111int skl_nhlt_update_topology_bin(struct skl *skl); 120int skl_nhlt_update_topology_bin(struct skl *skl);
112int skl_init_dsp(struct skl *skl); 121int skl_init_dsp(struct skl *skl);
113int skl_free_dsp(struct skl *skl); 122int skl_free_dsp(struct skl *skl);
114int skl_suspend_dsp(struct skl *skl); 123int skl_suspend_dsp(struct skl *skl);
115int skl_resume_dsp(struct skl *skl); 124int skl_resume_dsp(struct skl *skl);
125void skl_cleanup_resources(struct skl *skl);
116#endif /* __SOUND_SOC_SKL_H */ 126#endif /* __SOUND_SOC_SKL_H */