diff options
author | Mark Brown <broonie@kernel.org> | 2016-07-24 17:07:22 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2016-07-24 17:07:22 -0400 |
commit | 44d624622e57ad60e652da4d7bde43aadab350bf (patch) | |
tree | 30a330c8fa9a051f147f82e336823f800e9d4e11 /sound/soc/intel | |
parent | 0d911262808d07af538c23b1b6d249b3a4a9a431 (diff) | |
parent | 1b00126cb3de017274e899ac559a744d4e3dbd61 (diff) |
Merge remote-tracking branch 'asoc/topic/intel' into asoc-next
Diffstat (limited to 'sound/soc/intel')
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 | ||
13 | config SND_SST_MFLD_PLATFORM | 13 | config 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 | ||
30 | config SND_SOC_INTEL_SST | 29 | config 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 | ||
38 | config SND_SOC_INTEL_SST_FIRMWARE | ||
39 | tristate | ||
40 | |||
36 | config SND_SOC_INTEL_SST_ACPI | 41 | config SND_SOC_INTEL_SST_ACPI |
37 | tristate | 42 | tristate |
38 | 43 | ||
@@ -48,16 +53,33 @@ config SND_SOC_INTEL_BAYTRAIL | |||
48 | config SND_SOC_INTEL_HASWELL_MACH | 53 | config 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 | ||
67 | config 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 | |||
61 | config SND_SOC_INTEL_BXT_RT298_MACH | 83 | config 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 | ||
76 | config SND_SOC_INTEL_BYT_RT5640_MACH | 98 | config 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 | ||
88 | config SND_SOC_INTEL_BYT_MAX98090_MACH | 111 | config 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 | ||
113 | config SND_SOC_INTEL_BYTCR_RT5640_MACH | 138 | config 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 | ||
126 | config SND_SOC_INTEL_BYTCR_RT5651_MACH | 151 | config 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 | ||
139 | config SND_SOC_INTEL_CHT_BSW_RT5672_MACH | 164 | config 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 | ||
152 | config SND_SOC_INTEL_CHT_BSW_RT5645_MACH | 177 | config 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 | ||
164 | config SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH | 189 | config 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 | ||
177 | config SND_SOC_INTEL_SKYLAKE | 202 | config 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 | ||
198 | config SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH | 223 | config 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 | ||
213 | config SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH | 238 | config 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 | ||
327 | static unsigned long cht_machine_id; | ||
328 | |||
329 | #define CHT_SURFACE_MACH 1 | ||
330 | |||
331 | static 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 | |||
338 | static 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 | |||
349 | static 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 | |||
353 | static 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 | |||
323 | static struct sst_acpi_mach sst_acpi_bytcr[] = { | 365 | static 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 | |||
2 | snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o | 2 | snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o |
3 | snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o | 3 | snd-soc-sst-byt-max98090-mach-objs := byt-max98090.o |
4 | snd-soc-sst-broadwell-objs := broadwell.o | 4 | snd-soc-sst-broadwell-objs := broadwell.o |
5 | snd-soc-sst-bxt-da7219_max98357a-objs := bxt_da7219_max98357a.o | ||
5 | snd-soc-sst-bxt-rt298-objs := bxt_rt298.o | 6 | snd-soc-sst-bxt-rt298-objs := bxt_rt298.o |
6 | snd-soc-sst-bytcr-rt5640-objs := bytcr_rt5640.o | 7 | snd-soc-sst-bytcr-rt5640-objs := bytcr_rt5640.o |
7 | snd-soc-sst-bytcr-rt5651-objs := bytcr_rt5651.o | 8 | snd-soc-sst-bytcr-rt5651-objs := bytcr_rt5651.o |
@@ -15,6 +16,7 @@ snd-soc-skl_nau88l25_ssm4567-objs := skl_nau88l25_ssm4567.o | |||
15 | obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o | 16 | obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o |
16 | obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o | 17 | obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o |
17 | obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o | 18 | obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o |
19 | obj-$(CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH) += snd-soc-sst-bxt-da7219_max98357a.o | ||
18 | obj-$(CONFIG_SND_SOC_INTEL_BXT_RT298_MACH) += snd-soc-sst-bxt-rt298.o | 20 | obj-$(CONFIG_SND_SOC_INTEL_BXT_RT298_MACH) += snd-soc-sst-bxt-rt298.o |
19 | obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o | 21 | obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o |
20 | obj-$(CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH) += snd-soc-sst-bytcr-rt5640.o | 22 | obj-$(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 | |||
34 | static struct snd_soc_jack broxton_headset; | ||
35 | |||
36 | enum { | ||
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 | |||
45 | static 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 | |||
51 | static 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 | |||
61 | static 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 | |||
101 | static 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 | |||
121 | static 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 | |||
146 | static 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 | |||
153 | static 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 | |||
164 | static unsigned int rates[] = { | ||
165 | 48000, | ||
166 | }; | ||
167 | |||
168 | static struct snd_pcm_hw_constraint_list constraints_rates = { | ||
169 | .count = ARRAY_SIZE(rates), | ||
170 | .list = rates, | ||
171 | .mask = 0, | ||
172 | }; | ||
173 | |||
174 | static unsigned int channels[] = { | ||
175 | DUAL_CHANNEL, | ||
176 | }; | ||
177 | |||
178 | static struct snd_pcm_hw_constraint_list constraints_channels = { | ||
179 | .count = ARRAY_SIZE(channels), | ||
180 | .list = channels, | ||
181 | .mask = 0, | ||
182 | }; | ||
183 | |||
184 | static 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 | |||
208 | static const struct snd_soc_ops broxton_da7219_fe_ops = { | ||
209 | .startup = bxt_fe_startup, | ||
210 | }; | ||
211 | |||
212 | static 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 | |||
234 | static 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 | |||
250 | static 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 */ | ||
256 | static 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 */ | ||
424 | static 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 | |||
438 | static 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 | |||
444 | static 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 | }; | ||
451 | module_platform_driver(broxton_audio) | ||
452 | |||
453 | /* Module information */ | ||
454 | MODULE_DESCRIPTION("Audio Machine driver-DA7219 & MAX98357A in I2S mode"); | ||
455 | MODULE_AUTHOR("Sathyanarayana Nujella <sathyanarayana.nujella@intel.com>"); | ||
456 | MODULE_AUTHOR("Rohit Ainapure <rohit.m.ainapure@intel.com>"); | ||
457 | MODULE_AUTHOR("Harsha Priya <harshapriya.n@intel.com>"); | ||
458 | MODULE_AUTHOR("Conrad Cooke <conrad.cooke@intel.com>"); | ||
459 | MODULE_LICENSE("GPL v2"); | ||
460 | MODULE_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 | ||
109 | static 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 | |||
107 | static int broxton_rt298_codec_init(struct snd_soc_pcm_runtime *rtd) | 120 | static 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 | ||
188 | static unsigned int rates[] = { | ||
189 | 48000, | ||
190 | }; | ||
191 | |||
192 | static struct snd_pcm_hw_constraint_list constraints_rates = { | ||
193 | .count = ARRAY_SIZE(rates), | ||
194 | .list = rates, | ||
195 | .mask = 0, | ||
196 | }; | ||
197 | |||
198 | static 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 | |||
211 | static unsigned int channels_dmic[] = { | ||
212 | 2, 4, | ||
213 | }; | ||
214 | |||
215 | static struct snd_pcm_hw_constraint_list constraints_dmic_channels = { | ||
216 | .count = ARRAY_SIZE(channels_dmic), | ||
217 | .list = channels_dmic, | ||
218 | .mask = 0, | ||
219 | }; | ||
220 | |||
221 | static 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 | |||
233 | static struct snd_soc_ops broxton_dmic_ops = { | ||
234 | .startup = broxton_dmic_startup, | ||
235 | }; | ||
236 | |||
237 | static unsigned int channels[] = { | ||
238 | 2, | ||
239 | }; | ||
240 | |||
241 | static struct snd_pcm_hw_constraint_list constraints_channels = { | ||
242 | .count = ARRAY_SIZE(channels), | ||
243 | .list = channels, | ||
244 | .mask = 0, | ||
245 | }; | ||
246 | |||
247 | static 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 | |||
267 | static 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 */ |
173 | static struct snd_soc_dai_link broxton_rt298_dais[] = { | 272 | static 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 | }; |
346 | module_platform_driver(broxton_audio) | 464 | module_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 | ||
342 | static struct cht_acpi_card snd_soc_cards[] = { | 343 | static 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 | ||
349 | static char cht_rt5640_codec_name[16]; /* i2c-<HID>:00 with HID being 8 chars */ | ||
350 | |||
347 | static int snd_cht_mc_probe(struct platform_device *pdev) | 351 | static 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 | ||
30 | static struct snd_soc_jack skylake_headset; | 32 | static struct snd_soc_jack skylake_headset; |
31 | static struct snd_soc_card skylake_audio_card; | 33 | static struct snd_soc_card skylake_audio_card; |
34 | static const struct snd_pcm_hw_constraint_list *dmic_constraints; | ||
32 | 35 | ||
33 | struct skl_hdmi_pcm { | 36 | struct 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 | ||
363 | static const unsigned int dmic_2ch[] = { | ||
364 | 2, | ||
365 | }; | ||
366 | |||
367 | static 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 | |||
360 | static int skylake_dmic_startup(struct snd_pcm_substream *substream) | 373 | static 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 | ||
398 | static const unsigned int ch_mono[] = { | ||
399 | 1, | ||
400 | }; | ||
401 | |||
402 | static const struct snd_pcm_hw_constraint_list constraints_refcap = { | ||
403 | .count = ARRAY_SIZE(ch_mono), | ||
404 | .list = ch_mono, | ||
405 | }; | ||
406 | |||
385 | static int skylake_refcap_startup(struct snd_pcm_substream *substream) | 407 | static 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 = { | |||
610 | static int skylake_audio_probe(struct platform_device *pdev) | 637 | static 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 | ||
659 | static const struct platform_device_id skl_board_ids[] = { | ||
660 | { .name = "skl_n88l25_m98357a" }, | ||
661 | { .name = "kbl_n88l25_m98357a" }, | ||
662 | { } | ||
663 | }; | ||
664 | |||
626 | static struct platform_driver skylake_audio = { | 665 | static 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 | ||
634 | module_platform_driver(skylake_audio) | 674 | module_platform_driver(skylake_audio) |
@@ -637,4 +677,5 @@ module_platform_driver(skylake_audio) | |||
637 | MODULE_DESCRIPTION("Audio Machine driver-NAU88L25 & MAX98357A in I2S mode"); | 677 | MODULE_DESCRIPTION("Audio Machine driver-NAU88L25 & MAX98357A in I2S mode"); |
638 | MODULE_AUTHOR("Rohit Ainapure <rohit.m.ainapure@intel.com"); | 678 | MODULE_AUTHOR("Rohit Ainapure <rohit.m.ainapure@intel.com"); |
639 | MODULE_LICENSE("GPL v2"); | 679 | MODULE_LICENSE("GPL v2"); |
640 | MODULE_ALIAS("platform:skl_nau88l25_max98357a_i2s"); | 680 | MODULE_ALIAS("platform:skl_n88l25_m98357a"); |
681 | MODULE_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 | ||
34 | static struct snd_soc_jack skylake_headset; | 36 | static struct snd_soc_jack skylake_headset; |
35 | static struct snd_soc_card skylake_audio_card; | 37 | static struct snd_soc_card skylake_audio_card; |
38 | static const struct snd_pcm_hw_constraint_list *dmic_constraints; | ||
36 | 39 | ||
37 | struct skl_hdmi_pcm { | 40 | struct 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 | ||
411 | static const unsigned int dmic_2ch[] = { | ||
412 | 2, | ||
413 | }; | ||
414 | |||
415 | static 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 | |||
408 | static int skylake_dmic_startup(struct snd_pcm_substream *substream) | 421 | static 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 | ||
446 | static const unsigned int ch_mono[] = { | ||
447 | 1, | ||
448 | }; | ||
449 | |||
450 | static const struct snd_pcm_hw_constraint_list constraints_refcap = { | ||
451 | .count = ARRAY_SIZE(ch_mono), | ||
452 | .list = ch_mono, | ||
453 | }; | ||
454 | |||
433 | static int skylake_refcap_startup(struct snd_pcm_substream *substream) | 455 | static 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 = { | |||
662 | static int skylake_audio_probe(struct platform_device *pdev) | 689 | static 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 | ||
711 | static const struct platform_device_id skl_board_ids[] = { | ||
712 | { .name = "skl_n88l25_s4567" }, | ||
713 | { .name = "kbl_n88l25_s4567" }, | ||
714 | { } | ||
715 | }; | ||
716 | |||
678 | static struct platform_driver skylake_audio = { | 717 | static 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 | ||
686 | module_platform_driver(skylake_audio) | 726 | module_platform_driver(skylake_audio) |
@@ -693,4 +733,5 @@ MODULE_AUTHOR("Sathya Prakash M R <sathya.prakash.m.r@intel.com>"); | |||
693 | MODULE_AUTHOR("Yong Zhi <yong.zhi@intel.com>"); | 733 | MODULE_AUTHOR("Yong Zhi <yong.zhi@intel.com>"); |
694 | MODULE_DESCRIPTION("Intel Audio Machine driver for SKL with NAU88L25 and SSM4567 in I2S Mode"); | 734 | MODULE_DESCRIPTION("Intel Audio Machine driver for SKL with NAU88L25 and SSM4567 in I2S Mode"); |
695 | MODULE_LICENSE("GPL v2"); | 735 | MODULE_LICENSE("GPL v2"); |
696 | MODULE_ALIAS("platform:skl_nau88l25_ssm4567_i2s"); | 736 | MODULE_ALIAS("platform:skl_n88l25_s4567"); |
737 | MODULE_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 | ||
508 | static const struct platform_device_id skl_board_ids[] = { | ||
509 | { .name = "skl_alc286s_i2s" }, | ||
510 | { .name = "kbl_alc286s_i2s" }, | ||
511 | { } | ||
512 | }; | ||
513 | |||
508 | static struct platform_driver skylake_audio = { | 514 | static 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 | ||
516 | module_platform_driver(skylake_audio) | 524 | module_platform_driver(skylake_audio) |
@@ -520,3 +528,4 @@ MODULE_AUTHOR("Omair Mohammed Abdullah <omair.m.abdullah@intel.com>"); | |||
520 | MODULE_DESCRIPTION("Intel SST Audio for Skylake"); | 528 | MODULE_DESCRIPTION("Intel SST Audio for Skylake"); |
521 | MODULE_LICENSE("GPL v2"); | 529 | MODULE_LICENSE("GPL v2"); |
522 | MODULE_ALIAS("platform:skl_alc286s_i2s"); | 530 | MODULE_ALIAS("platform:skl_alc286s_i2s"); |
531 | MODULE_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 | |||
2 | snd-soc-sst-acpi-objs := sst-acpi.o | 2 | snd-soc-sst-acpi-objs := sst-acpi.o |
3 | snd-soc-sst-match-objs := sst-match-acpi.o | 3 | snd-soc-sst-match-objs := sst-match-acpi.o |
4 | snd-soc-sst-ipc-objs := sst-ipc.o | 4 | snd-soc-sst-ipc-objs := sst-ipc.o |
5 | 5 | snd-soc-sst-firmware-objs := sst-firmware.o | |
6 | snd-soc-sst-dsp-$(CONFIG_DW_DMAC_CORE) += sst-firmware.o | ||
7 | 6 | ||
8 | obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o snd-soc-sst-ipc.o | 7 | obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o snd-soc-sst-ipc.o |
9 | obj-$(CONFIG_SND_SOC_INTEL_SST_ACPI) += snd-soc-sst-acpi.o | 8 | obj-$(CONFIG_SND_SOC_INTEL_SST_ACPI) += snd-soc-sst-acpi.o |
10 | obj-$(CONFIG_SND_SOC_INTEL_SST_MATCH) += snd-soc-sst-match.o | 9 | obj-$(CONFIG_SND_SOC_INTEL_SST_MATCH) += snd-soc-sst-match.o |
10 | obj-$(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) |
21 | const char *sst_acpi_find_name_from_hid(const u8 hid[ACPI_ID_LEN]); | 21 | const char *sst_acpi_find_name_from_hid(const u8 hid[ACPI_ID_LEN]); |
22 | #else | 22 | #else |
23 | inline const char *sst_acpi_find_name_from_hid(const u8 hid[ACPI_ID_LEN]) | 23 | static 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); |
384 | void sst_mem_block_unregister_all(struct sst_dsp *dsp); | 384 | void sst_mem_block_unregister_all(struct sst_dsp *dsp); |
385 | 385 | ||
386 | /* Create/Free DMA resources */ | ||
387 | int sst_dma_new(struct sst_dsp *sst); | ||
388 | void sst_dma_free(struct sst_dma *dma); | ||
389 | |||
390 | u32 sst_dsp_get_offset(struct sst_dsp *dsp, u32 offset, | 386 | u32 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 | } |
421 | EXPORT_SYMBOL_GPL(sst_dsp_inbox_read); | 421 | EXPORT_SYMBOL_GPL(sst_dsp_inbox_read); |
422 | 422 | ||
423 | #ifdef CONFIG_DW_DMAC_CORE | ||
424 | struct 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 | |||
471 | irq_err: | ||
472 | if (sst->ops->free) | ||
473 | sst->ops->free(sst); | ||
474 | |||
475 | return NULL; | ||
476 | } | ||
477 | EXPORT_SYMBOL_GPL(sst_dsp_new); | ||
478 | |||
479 | void 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 | } | ||
487 | EXPORT_SYMBOL_GPL(sst_dsp_free); | ||
488 | #endif | ||
489 | |||
490 | /* Module information */ | 423 | /* Module information */ |
491 | MODULE_AUTHOR("Liam Girdwood"); | 424 | MODULE_AUTHOR("Liam Girdwood"); |
492 | MODULE_DESCRIPTION("Intel SST Core"); | 425 | MODULE_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 */ |
221 | struct sst_dsp *sst_dsp_new(struct device *dev, | 221 | struct 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 | } |
1213 | EXPORT_SYMBOL_GPL(sst_dsp_get_offset); | 1213 | EXPORT_SYMBOL_GPL(sst_dsp_get_offset); |
1214 | |||
1215 | struct 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 | |||
1262 | irq_err: | ||
1263 | if (sst->ops->free) | ||
1264 | sst->ops->free(sst); | ||
1265 | |||
1266 | return NULL; | ||
1267 | } | ||
1268 | EXPORT_SYMBOL_GPL(sst_dsp_new); | ||
1269 | |||
1270 | void 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 | } | ||
1278 | EXPORT_SYMBOL_GPL(sst_dsp_free); | ||
1279 | |||
1280 | MODULE_DESCRIPTION("Intel SST Firmware Loader"); | ||
1281 | MODULE_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 |
7 | snd-soc-skl-ipc-objs := skl-sst-ipc.o skl-sst-dsp.o skl-sst-cldma.o \ | 7 | snd-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 | ||
10 | obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl-ipc.o | 10 | obj-$(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 | |||
40 | static unsigned int bxt_get_errorcode(struct sst_dsp *ctx) | 43 | static 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 | */ | ||
45 | static int sst_bxt_prepare_fw(struct sst_dsp *ctx, | 53 | static 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 | ||
113 | base_fw_load_failed: | 139 | base_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 | |||
133 | static int bxt_load_base_firmware(struct sst_dsp *ctx) | 162 | static 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 | ||
177 | sst_load_base_firmware_failed: | 222 | sst_load_base_firmware_failed: |
178 | release_firmware(fw); | 223 | release_firmware(ctx->fw); |
179 | return ret; | 224 | return ret; |
180 | } | 225 | } |
181 | 226 | ||
182 | static int bxt_set_dsp_D0(struct sst_dsp *ctx) | 227 | static 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; |
302 | err: | ||
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 | ||
213 | static int bxt_set_dsp_D3(struct sst_dsp *ctx) | 310 | static 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 | ||
316 | void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) | 417 | void 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 | */ | ||
1145 | int 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 | ||
153 | int 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 | |||
152 | static void skl_nhlt_trim_space(struct skl *skl) | 192 | static 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 | |||
109 | struct nhlt_tdm_config { | ||
110 | u8 virtual_slot; | ||
111 | u8 config_type; | ||
112 | } __packed; | ||
113 | |||
114 | struct nhlt_dmic_array_config { | ||
115 | struct nhlt_tdm_config tdm_config; | ||
116 | u8 array_type; | ||
117 | } __packed; | ||
118 | |||
119 | enum { | ||
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 */ | 1029 | static snd_pcm_uframes_t skl_platform_pcm_pointer |
1013 | static 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 | |||
1049 | static 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 | |||
1074 | static 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 | ||
1083 | static u64 skl_adjust_codec_delay(struct snd_pcm_substream *substream, | 1044 | static 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) | |||
1180 | static int skl_platform_soc_probe(struct snd_soc_platform *platform) | 1141 | static 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 | ||
37 | static 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 | */ | ||
42 | void 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 */ | ||
57 | unsigned 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 | |||
85 | static int | ||
86 | skl_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 | ||
63 | static int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx) | 113 | int 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 | ||
90 | static bool is_skl_dsp_core_enable(struct sst_dsp *ctx) | 142 | static bool |
143 | is_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 | ||
106 | static int skl_dsp_reset_core(struct sst_dsp *ctx) | 161 | static 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 | ||
117 | static int skl_dsp_start_core(struct sst_dsp *ctx) | 172 | int 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 | ||
143 | static int skl_dsp_core_power_up(struct sst_dsp *ctx) | 196 | int 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 | ||
169 | static int skl_dsp_core_power_down(struct sst_dsp *ctx) | 224 | int 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 | ||
184 | int skl_dsp_enable_core(struct sst_dsp *ctx) | 239 | int 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 | ||
198 | int skl_dsp_disable_core(struct sst_dsp *ctx) | 254 | int 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 | */ | ||
344 | int 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 | } | ||
370 | EXPORT_SYMBOL_GPL(skl_dsp_get_core); | ||
371 | |||
372 | int 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 | } | ||
397 | EXPORT_SYMBOL_GPL(skl_dsp_put_core); | ||
284 | 398 | ||
285 | int skl_dsp_wake(struct sst_dsp *ctx) | 399 | int 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 | } |
289 | EXPORT_SYMBOL_GPL(skl_dsp_wake); | 403 | EXPORT_SYMBOL_GPL(skl_dsp_wake); |
290 | 404 | ||
291 | int skl_dsp_sleep(struct sst_dsp *ctx) | 405 | int 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 | } |
295 | EXPORT_SYMBOL_GPL(skl_dsp_sleep); | 409 | EXPORT_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 | } |
344 | EXPORT_SYMBOL_GPL(skl_dsp_free); | 456 | EXPORT_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 | ||
23 | struct sst_dsp; | 24 | struct sst_dsp; |
24 | struct skl_sst; | 25 | struct 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 | ||
109 | enum skl_dsp_states { | 128 | enum 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); | |||
157 | void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state); | 176 | void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state); |
158 | struct sst_dsp *skl_dsp_ctx_init(struct device *dev, | 177 | struct 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); |
160 | int skl_dsp_enable_core(struct sst_dsp *ctx); | ||
161 | int skl_dsp_disable_core(struct sst_dsp *ctx); | ||
162 | bool is_skl_dsp_running(struct sst_dsp *ctx); | 179 | bool is_skl_dsp_running(struct sst_dsp *ctx); |
180 | |||
181 | unsigned int skl_dsp_get_enabled_cores(struct sst_dsp *ctx); | ||
182 | void skl_dsp_init_core_state(struct sst_dsp *ctx); | ||
183 | int skl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask); | ||
184 | int skl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask); | ||
185 | int skl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask); | ||
186 | int skl_dsp_core_power_down(struct sst_dsp *ctx, unsigned int core_mask); | ||
187 | int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx, | ||
188 | unsigned int core_mask); | ||
189 | int skl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask); | ||
190 | |||
163 | irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id); | 191 | irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id); |
164 | int skl_dsp_wake(struct sst_dsp *ctx); | 192 | int skl_dsp_wake(struct sst_dsp *ctx); |
165 | int skl_dsp_sleep(struct sst_dsp *ctx); | 193 | int skl_dsp_sleep(struct sst_dsp *ctx); |
166 | void skl_dsp_free(struct sst_dsp *dsp); | 194 | void skl_dsp_free(struct sst_dsp *dsp); |
167 | 195 | ||
196 | int skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id); | ||
197 | int skl_dsp_put_core(struct sst_dsp *ctx, unsigned int core_id); | ||
198 | |||
168 | int skl_dsp_boot(struct sst_dsp *ctx); | 199 | int skl_dsp_boot(struct sst_dsp *ctx); |
169 | int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, | 200 | int 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, | |||
175 | void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx); | 206 | void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx); |
176 | void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx); | 207 | void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx); |
177 | 208 | ||
209 | int snd_skl_get_module_info(struct skl_sst *ctx, u8 *uuid, | ||
210 | struct skl_dfw_module *dfw_config); | ||
211 | int snd_skl_parse_uuids(struct sst_dsp *ctx, unsigned int offset); | ||
212 | void skl_freeup_uuid_list(struct skl_sst *ctx); | ||
213 | |||
214 | int 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 | |||
50 | struct 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 | |||
48 | struct skl_sst { | 56 | struct 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 | ||
65 | struct skl_ipc_init_instance_msg { | 82 | struct skl_ipc_init_instance_msg { |
@@ -136,5 +153,6 @@ void skl_ipc_int_disable(struct sst_dsp *dsp); | |||
136 | bool skl_ipc_int_status(struct sst_dsp *dsp); | 153 | bool skl_ipc_int_status(struct sst_dsp *dsp); |
137 | void skl_ipc_free(struct sst_generic_ipc *ipc); | 154 | void skl_ipc_free(struct sst_generic_ipc *ipc); |
138 | int skl_ipc_init(struct device *dev, struct skl_sst *skl); | 155 | int skl_ipc_init(struct device *dev, struct skl_sst *skl); |
156 | void 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 | |||
31 | struct skl_dfw_module_mod { | ||
32 | char name[100]; | ||
33 | struct skl_dfw_module skl_dfw_mod; | ||
34 | }; | ||
35 | |||
36 | struct UUID { | ||
37 | u8 id[16]; | ||
38 | }; | ||
39 | |||
40 | union 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 | |||
56 | struct segment_desc { | ||
57 | union seg_flags flags; | ||
58 | u32 v_base_addr; | ||
59 | u32 file_offset; | ||
60 | }; | ||
61 | |||
62 | struct 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 | |||
70 | struct 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 | |||
85 | struct 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 | |||
102 | struct uuid_module { | ||
103 | uuid_le uuid; | ||
104 | int id; | ||
105 | int is_loadable; | ||
106 | |||
107 | struct list_head list; | ||
108 | }; | ||
109 | |||
110 | struct skl_ext_manifest_hdr { | ||
111 | u32 id; | ||
112 | u32 len; | ||
113 | u16 version_major; | ||
114 | u16 version_minor; | ||
115 | u32 entries; | ||
116 | }; | ||
117 | |||
118 | int 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 | } | ||
137 | EXPORT_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 | */ | ||
143 | int 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 | |||
221 | void 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 | */ | ||
238 | int 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 | |||
71 | static int skl_load_base_firmware(struct sst_dsp *ctx) | 73 | static 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; |
139 | transfer_firmware_failed: | 156 | transfer_firmware_failed: |
140 | ctx->cl_dev.ops.cl_cleanup_controller(ctx); | 157 | ctx->cl_dev.ops.cl_cleanup_controller(ctx); |
141 | skl_load_base_firmware_failed: | 158 | skl_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 | ||
148 | static int skl_set_dsp_D0(struct sst_dsp *ctx) | 165 | static 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 | ||
163 | static int skl_set_dsp_D3(struct sst_dsp *ctx) | 207 | static 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 | ||
400 | void 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 | } | ||
411 | EXPORT_SYMBOL_GPL(skl_clear_module_cnt); | ||
412 | |||
363 | static void skl_clear_module_table(struct sst_dsp *ctx) | 413 | static 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); | |||
452 | void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) | 507 | void 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 | */ | ||
387 | static 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 | */ | ||
1122 | static 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 | ||
1544 | static 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 | |||
1568 | void 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 | */ | ||
1783 | static 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 | |||
1808 | static 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 | ||
250 | struct skl_pipe_module { | 251 | struct 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 | ||
275 | enum skl_module_state { | 277 | enum skl_module_state { |
@@ -358,6 +360,8 @@ int skl_delete_pipe(struct skl_sst *ctx, struct skl_pipe *pipe); | |||
358 | 360 | ||
359 | int skl_stop_pipe(struct skl_sst *ctx, struct skl_pipe *pipe); | 361 | int skl_stop_pipe(struct skl_sst *ctx, struct skl_pipe *pipe); |
360 | 362 | ||
363 | int skl_reset_pipe(struct skl_sst *ctx, struct skl_pipe *pipe); | ||
364 | |||
361 | int skl_init_module(struct skl_sst *ctx, struct skl_module_cfg *module_config); | 365 | int skl_init_module(struct skl_sst *ctx, struct skl_module_cfg *module_config); |
362 | 366 | ||
363 | int skl_bind_modules(struct skl_sst *ctx, struct skl_module_cfg | 367 | int 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 | ||
38 | static 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 | ||
787 | static struct sst_acpi_mach sst_skl_devdata[] = { | 801 | static 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 | ||
796 | static struct sst_acpi_mach sst_bxtp_devdata[] = { | 810 | static 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 | |||
815 | static 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 | }; |
810 | MODULE_DEVICE_TABLE(pci, skl_ids); | 835 | MODULE_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 */ | ||
97 | struct skl_machine_pdata { | ||
98 | u32 dmic_num; | ||
99 | }; | ||
100 | |||
93 | struct skl_dsp_ops { | 101 | struct 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); | |||
108 | struct nhlt_specific_cfg *skl_get_ep_blob(struct skl *skl, u32 instance, | 116 | struct 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 | ||
119 | int skl_get_dmic_geo(struct skl *skl); | ||
111 | int skl_nhlt_update_topology_bin(struct skl *skl); | 120 | int skl_nhlt_update_topology_bin(struct skl *skl); |
112 | int skl_init_dsp(struct skl *skl); | 121 | int skl_init_dsp(struct skl *skl); |
113 | int skl_free_dsp(struct skl *skl); | 122 | int skl_free_dsp(struct skl *skl); |
114 | int skl_suspend_dsp(struct skl *skl); | 123 | int skl_suspend_dsp(struct skl *skl); |
115 | int skl_resume_dsp(struct skl *skl); | 124 | int skl_resume_dsp(struct skl *skl); |
125 | void skl_cleanup_resources(struct skl *skl); | ||
116 | #endif /* __SOUND_SOC_SKL_H */ | 126 | #endif /* __SOUND_SOC_SKL_H */ |