diff options
Diffstat (limited to 'sound/soc/intel/skylake/skl.c')
-rw-r--r-- | sound/soc/intel/skylake/skl.c | 158 |
1 files changed, 117 insertions, 41 deletions
diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 5319529aedf7..c38bf99ced10 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/pm_runtime.h> | 26 | #include <linux/pm_runtime.h> |
27 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
28 | #include <sound/pcm.h> | 28 | #include <sound/pcm.h> |
29 | #include "../common/sst-acpi.h" | ||
29 | #include "skl.h" | 30 | #include "skl.h" |
30 | 31 | ||
31 | /* | 32 | /* |
@@ -129,6 +130,37 @@ static int skl_acquire_irq(struct hdac_ext_bus *ebus, int do_disconnect) | |||
129 | return 0; | 130 | return 0; |
130 | } | 131 | } |
131 | 132 | ||
133 | #ifdef CONFIG_PM | ||
134 | static int _skl_suspend(struct hdac_ext_bus *ebus) | ||
135 | { | ||
136 | struct skl *skl = ebus_to_skl(ebus); | ||
137 | struct hdac_bus *bus = ebus_to_hbus(ebus); | ||
138 | int ret; | ||
139 | |||
140 | snd_hdac_ext_bus_link_power_down_all(ebus); | ||
141 | |||
142 | ret = skl_suspend_dsp(skl); | ||
143 | if (ret < 0) | ||
144 | return ret; | ||
145 | |||
146 | snd_hdac_bus_stop_chip(bus); | ||
147 | snd_hdac_bus_enter_link_reset(bus); | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static int _skl_resume(struct hdac_ext_bus *ebus) | ||
153 | { | ||
154 | struct skl *skl = ebus_to_skl(ebus); | ||
155 | struct hdac_bus *bus = ebus_to_hbus(ebus); | ||
156 | |||
157 | skl_init_pci(skl); | ||
158 | snd_hdac_bus_init_chip(bus, true); | ||
159 | |||
160 | return skl_resume_dsp(skl); | ||
161 | } | ||
162 | #endif | ||
163 | |||
132 | #ifdef CONFIG_PM_SLEEP | 164 | #ifdef CONFIG_PM_SLEEP |
133 | /* | 165 | /* |
134 | * power management | 166 | * power management |
@@ -137,26 +169,40 @@ static int skl_suspend(struct device *dev) | |||
137 | { | 169 | { |
138 | struct pci_dev *pci = to_pci_dev(dev); | 170 | struct pci_dev *pci = to_pci_dev(dev); |
139 | struct hdac_ext_bus *ebus = pci_get_drvdata(pci); | 171 | struct hdac_ext_bus *ebus = pci_get_drvdata(pci); |
140 | struct hdac_bus *bus = ebus_to_hbus(ebus); | 172 | struct skl *skl = ebus_to_skl(ebus); |
141 | |||
142 | snd_hdac_bus_stop_chip(bus); | ||
143 | snd_hdac_bus_enter_link_reset(bus); | ||
144 | 173 | ||
145 | return 0; | 174 | /* |
175 | * Do not suspend if streams which are marked ignore suspend are | ||
176 | * running, we need to save the state for these and continue | ||
177 | */ | ||
178 | if (skl->supend_active) { | ||
179 | pci_save_state(pci); | ||
180 | pci_disable_device(pci); | ||
181 | return 0; | ||
182 | } else { | ||
183 | return _skl_suspend(ebus); | ||
184 | } | ||
146 | } | 185 | } |
147 | 186 | ||
148 | static int skl_resume(struct device *dev) | 187 | static int skl_resume(struct device *dev) |
149 | { | 188 | { |
150 | struct pci_dev *pci = to_pci_dev(dev); | 189 | struct pci_dev *pci = to_pci_dev(dev); |
151 | struct hdac_ext_bus *ebus = pci_get_drvdata(pci); | 190 | struct hdac_ext_bus *ebus = pci_get_drvdata(pci); |
152 | struct hdac_bus *bus = ebus_to_hbus(ebus); | 191 | struct skl *skl = ebus_to_skl(ebus); |
153 | struct skl *hda = ebus_to_skl(ebus); | 192 | int ret; |
154 | |||
155 | skl_init_pci(hda); | ||
156 | 193 | ||
157 | snd_hdac_bus_init_chip(bus, 1); | 194 | /* |
195 | * resume only when we are not in suspend active, otherwise need to | ||
196 | * restore the device | ||
197 | */ | ||
198 | if (skl->supend_active) { | ||
199 | pci_restore_state(pci); | ||
200 | ret = pci_enable_device(pci); | ||
201 | } else { | ||
202 | ret = _skl_resume(ebus); | ||
203 | } | ||
158 | 204 | ||
159 | return 0; | 205 | return ret; |
160 | } | 206 | } |
161 | #endif /* CONFIG_PM_SLEEP */ | 207 | #endif /* CONFIG_PM_SLEEP */ |
162 | 208 | ||
@@ -166,24 +212,10 @@ static int skl_runtime_suspend(struct device *dev) | |||
166 | struct pci_dev *pci = to_pci_dev(dev); | 212 | struct pci_dev *pci = to_pci_dev(dev); |
167 | struct hdac_ext_bus *ebus = pci_get_drvdata(pci); | 213 | struct hdac_ext_bus *ebus = pci_get_drvdata(pci); |
168 | struct hdac_bus *bus = ebus_to_hbus(ebus); | 214 | struct hdac_bus *bus = ebus_to_hbus(ebus); |
169 | struct skl *skl = ebus_to_skl(ebus); | ||
170 | int ret; | ||
171 | 215 | ||
172 | dev_dbg(bus->dev, "in %s\n", __func__); | 216 | dev_dbg(bus->dev, "in %s\n", __func__); |
173 | 217 | ||
174 | /* enable controller wake up event */ | 218 | return _skl_suspend(ebus); |
175 | snd_hdac_chip_updatew(bus, WAKEEN, 0, STATESTS_INT_MASK); | ||
176 | |||
177 | snd_hdac_ext_bus_link_power_down_all(ebus); | ||
178 | |||
179 | ret = skl_suspend_dsp(skl); | ||
180 | if (ret < 0) | ||
181 | return ret; | ||
182 | |||
183 | snd_hdac_bus_stop_chip(bus); | ||
184 | snd_hdac_bus_enter_link_reset(bus); | ||
185 | |||
186 | return 0; | ||
187 | } | 219 | } |
188 | 220 | ||
189 | static int skl_runtime_resume(struct device *dev) | 221 | static int skl_runtime_resume(struct device *dev) |
@@ -191,20 +223,10 @@ static int skl_runtime_resume(struct device *dev) | |||
191 | struct pci_dev *pci = to_pci_dev(dev); | 223 | struct pci_dev *pci = to_pci_dev(dev); |
192 | struct hdac_ext_bus *ebus = pci_get_drvdata(pci); | 224 | struct hdac_ext_bus *ebus = pci_get_drvdata(pci); |
193 | struct hdac_bus *bus = ebus_to_hbus(ebus); | 225 | struct hdac_bus *bus = ebus_to_hbus(ebus); |
194 | struct skl *skl = ebus_to_skl(ebus); | ||
195 | int status; | ||
196 | 226 | ||
197 | dev_dbg(bus->dev, "in %s\n", __func__); | 227 | dev_dbg(bus->dev, "in %s\n", __func__); |
198 | 228 | ||
199 | /* Read STATESTS before controller reset */ | 229 | return _skl_resume(ebus); |
200 | status = snd_hdac_chip_readw(bus, STATESTS); | ||
201 | |||
202 | skl_init_pci(skl); | ||
203 | snd_hdac_bus_init_chip(bus, true); | ||
204 | /* disable controller Wake Up event */ | ||
205 | snd_hdac_chip_updatew(bus, WAKEEN, STATESTS_INT_MASK, 0); | ||
206 | |||
207 | return skl_resume_dsp(skl); | ||
208 | } | 230 | } |
209 | #endif /* CONFIG_PM */ | 231 | #endif /* CONFIG_PM */ |
210 | 232 | ||
@@ -241,6 +263,43 @@ static int skl_free(struct hdac_ext_bus *ebus) | |||
241 | return 0; | 263 | return 0; |
242 | } | 264 | } |
243 | 265 | ||
266 | static int skl_machine_device_register(struct skl *skl, void *driver_data) | ||
267 | { | ||
268 | struct hdac_bus *bus = ebus_to_hbus(&skl->ebus); | ||
269 | struct platform_device *pdev; | ||
270 | struct sst_acpi_mach *mach = driver_data; | ||
271 | int ret; | ||
272 | |||
273 | mach = sst_acpi_find_machine(mach); | ||
274 | if (mach == NULL) { | ||
275 | dev_err(bus->dev, "No matching machine driver found\n"); | ||
276 | return -ENODEV; | ||
277 | } | ||
278 | skl->fw_name = mach->fw_filename; | ||
279 | |||
280 | pdev = platform_device_alloc(mach->drv_name, -1); | ||
281 | if (pdev == NULL) { | ||
282 | dev_err(bus->dev, "platform device alloc failed\n"); | ||
283 | return -EIO; | ||
284 | } | ||
285 | |||
286 | ret = platform_device_add(pdev); | ||
287 | if (ret) { | ||
288 | dev_err(bus->dev, "failed to add machine device\n"); | ||
289 | platform_device_put(pdev); | ||
290 | return -EIO; | ||
291 | } | ||
292 | skl->i2s_dev = pdev; | ||
293 | |||
294 | return 0; | ||
295 | } | ||
296 | |||
297 | static void skl_machine_device_unregister(struct skl *skl) | ||
298 | { | ||
299 | if (skl->i2s_dev) | ||
300 | platform_device_unregister(skl->i2s_dev); | ||
301 | } | ||
302 | |||
244 | static int skl_dmic_device_register(struct skl *skl) | 303 | static int skl_dmic_device_register(struct skl *skl) |
245 | { | 304 | { |
246 | struct hdac_bus *bus = ebus_to_hbus(&skl->ebus); | 305 | struct hdac_bus *bus = ebus_to_hbus(&skl->ebus); |
@@ -434,8 +493,7 @@ static int skl_first_init(struct hdac_ext_bus *ebus) | |||
434 | 493 | ||
435 | /* codec detection */ | 494 | /* codec detection */ |
436 | if (!bus->codec_mask) { | 495 | if (!bus->codec_mask) { |
437 | dev_err(bus->dev, "no codecs found!\n"); | 496 | dev_info(bus->dev, "no hda codecs found!\n"); |
438 | return -ENODEV; | ||
439 | } | 497 | } |
440 | 498 | ||
441 | return 0; | 499 | return 0; |
@@ -470,10 +528,15 @@ static int skl_probe(struct pci_dev *pci, | |||
470 | 528 | ||
471 | /* check if dsp is there */ | 529 | /* check if dsp is there */ |
472 | if (ebus->ppcap) { | 530 | if (ebus->ppcap) { |
531 | err = skl_machine_device_register(skl, | ||
532 | (void *)pci_id->driver_data); | ||
533 | if (err < 0) | ||
534 | goto out_free; | ||
535 | |||
473 | err = skl_init_dsp(skl); | 536 | err = skl_init_dsp(skl); |
474 | if (err < 0) { | 537 | if (err < 0) { |
475 | dev_dbg(bus->dev, "error failed to register dsp\n"); | 538 | dev_dbg(bus->dev, "error failed to register dsp\n"); |
476 | goto out_free; | 539 | goto out_mach_free; |
477 | } | 540 | } |
478 | } | 541 | } |
479 | if (ebus->mlcap) | 542 | if (ebus->mlcap) |
@@ -508,6 +571,8 @@ out_dmic_free: | |||
508 | skl_dmic_device_unregister(skl); | 571 | skl_dmic_device_unregister(skl); |
509 | out_dsp_free: | 572 | out_dsp_free: |
510 | skl_free_dsp(skl); | 573 | skl_free_dsp(skl); |
574 | out_mach_free: | ||
575 | skl_machine_device_unregister(skl); | ||
511 | out_free: | 576 | out_free: |
512 | skl->init_failed = 1; | 577 | skl->init_failed = 1; |
513 | skl_free(ebus); | 578 | skl_free(ebus); |
@@ -525,15 +590,26 @@ static void skl_remove(struct pci_dev *pci) | |||
525 | pci_dev_put(pci); | 590 | pci_dev_put(pci); |
526 | skl_platform_unregister(&pci->dev); | 591 | skl_platform_unregister(&pci->dev); |
527 | skl_free_dsp(skl); | 592 | skl_free_dsp(skl); |
593 | skl_machine_device_unregister(skl); | ||
528 | skl_dmic_device_unregister(skl); | 594 | skl_dmic_device_unregister(skl); |
529 | skl_free(ebus); | 595 | skl_free(ebus); |
530 | dev_set_drvdata(&pci->dev, NULL); | 596 | dev_set_drvdata(&pci->dev, NULL); |
531 | } | 597 | } |
532 | 598 | ||
599 | static struct sst_acpi_mach sst_skl_devdata[] = { | ||
600 | { "INT343A", "skl_alc286s_i2s", "intel/dsp_fw_release.bin", NULL, NULL, NULL }, | ||
601 | { "INT343B", "skl_nau88l25_ssm4567_i2s", "intel/dsp_fw_release.bin", | ||
602 | NULL, NULL, NULL }, | ||
603 | { "MX98357A", "skl_nau88l25_max98357a_i2s", "intel/dsp_fw_release.bin", | ||
604 | NULL, NULL, NULL }, | ||
605 | {} | ||
606 | }; | ||
607 | |||
533 | /* PCI IDs */ | 608 | /* PCI IDs */ |
534 | static const struct pci_device_id skl_ids[] = { | 609 | static const struct pci_device_id skl_ids[] = { |
535 | /* Sunrise Point-LP */ | 610 | /* Sunrise Point-LP */ |
536 | { PCI_DEVICE(0x8086, 0x9d70), 0}, | 611 | { PCI_DEVICE(0x8086, 0x9d70), |
612 | .driver_data = (unsigned long)&sst_skl_devdata}, | ||
537 | { 0, } | 613 | { 0, } |
538 | }; | 614 | }; |
539 | MODULE_DEVICE_TABLE(pci, skl_ids); | 615 | MODULE_DEVICE_TABLE(pci, skl_ids); |