18e8e69d6SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2d8c2dab8SJeeja KP /*
3d8c2dab8SJeeja KP * skl.c - Implementation of ASoC Intel SKL HD Audio driver
4d8c2dab8SJeeja KP *
5d8c2dab8SJeeja KP * Copyright (C) 2014-2015 Intel Corp
6d8c2dab8SJeeja KP * Author: Jeeja KP <jeeja.kp@intel.com>
7d8c2dab8SJeeja KP *
8d8c2dab8SJeeja KP * Derived mostly from Intel HDA driver with following copyrights:
9d8c2dab8SJeeja KP * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
10d8c2dab8SJeeja KP * PeiSen Hou <pshou@realtek.com.tw>
11d8c2dab8SJeeja KP * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12d8c2dab8SJeeja KP *
13d8c2dab8SJeeja KP * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
14d8c2dab8SJeeja KP */
15d8c2dab8SJeeja KP
16d8c2dab8SJeeja KP #include <linux/module.h>
17d8c2dab8SJeeja KP #include <linux/pci.h>
18d8c2dab8SJeeja KP #include <linux/pm_runtime.h>
19d8c2dab8SJeeja KP #include <linux/platform_device.h>
20d8018361SVinod Koul #include <linux/firmware.h>
21a26a3f53SPardha Saradhi K #include <linux/delay.h>
22d8c2dab8SJeeja KP #include <sound/pcm.h>
237feb2f78SPierre-Louis Bossart #include <sound/soc-acpi.h>
24cbaa7f0bSPierre-Louis Bossart #include <sound/soc-acpi-intel-match.h>
256980c057SVinod Koul #include <sound/hda_register.h>
266980c057SVinod Koul #include <sound/hdaudio.h>
276980c057SVinod Koul #include <sound/hda_i915.h>
2800deadb5SRakesh Ughreja #include <sound/hda_codec.h>
291169cbf6SPierre-Louis Bossart #include <sound/intel-nhlt.h>
3082d9d54aSJaroslav Kysela #include <sound/intel-dsp-config.h>
31d8c2dab8SJeeja KP #include "skl.h"
320c8ba9d2SJayachandran B #include "skl-sst-dsp.h"
330c8ba9d2SJayachandran B #include "skl-sst-ipc.h"
341169cbf6SPierre-Louis Bossart
358c4e7c2eSPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
366bae5ea9SRakesh Ughreja #include "../../../soc/codecs/hdac_hda.h"
378c4e7c2eSPierre-Louis Bossart #endif
38d82b51c8SPierre-Louis Bossart static int skl_pci_binding;
39d82b51c8SPierre-Louis Bossart module_param_named(pci_binding, skl_pci_binding, int, 0444);
40d82b51c8SPierre-Louis Bossart MODULE_PARM_DESC(pci_binding, "PCI binding (0=auto, 1=only legacy, 2=only asoc");
41d8c2dab8SJeeja KP
42d8c2dab8SJeeja KP /*
43d8c2dab8SJeeja KP * initialize the PCI registers
44d8c2dab8SJeeja KP */
skl_update_pci_byte(struct pci_dev * pci,unsigned int reg,unsigned char mask,unsigned char val)45d8c2dab8SJeeja KP static void skl_update_pci_byte(struct pci_dev *pci, unsigned int reg,
46d8c2dab8SJeeja KP unsigned char mask, unsigned char val)
47d8c2dab8SJeeja KP {
48d8c2dab8SJeeja KP unsigned char data;
49d8c2dab8SJeeja KP
50d8c2dab8SJeeja KP pci_read_config_byte(pci, reg, &data);
51d8c2dab8SJeeja KP data &= ~mask;
52d8c2dab8SJeeja KP data |= (val & mask);
53d8c2dab8SJeeja KP pci_write_config_byte(pci, reg, data);
54d8c2dab8SJeeja KP }
55d8c2dab8SJeeja KP
skl_init_pci(struct skl_dev * skl)56bcc2a2dcSCezary Rojewski static void skl_init_pci(struct skl_dev *skl)
57d8c2dab8SJeeja KP {
5876f56faeSRakesh Ughreja struct hdac_bus *bus = skl_to_bus(skl);
59d8c2dab8SJeeja KP
60d8c2dab8SJeeja KP /*
61d8c2dab8SJeeja KP * Clear bits 0-2 of PCI register TCSEL (at offset 0x44)
62d8c2dab8SJeeja KP * TCSEL == Traffic Class Select Register, which sets PCI express QOS
63d8c2dab8SJeeja KP * Ensuring these bits are 0 clears playback static on some HD Audio
64d8c2dab8SJeeja KP * codecs.
65d8c2dab8SJeeja KP * The PCI register TCSEL is defined in the Intel manuals.
66d8c2dab8SJeeja KP */
6776f56faeSRakesh Ughreja dev_dbg(bus->dev, "Clearing TCSEL\n");
68d8c2dab8SJeeja KP skl_update_pci_byte(skl->pci, AZX_PCIREG_TCSEL, 0x07, 0);
69d8c2dab8SJeeja KP }
70d8c2dab8SJeeja KP
update_pci_dword(struct pci_dev * pci,unsigned int reg,u32 mask,u32 val)710c8ba9d2SJayachandran B static void update_pci_dword(struct pci_dev *pci,
720c8ba9d2SJayachandran B unsigned int reg, u32 mask, u32 val)
730c8ba9d2SJayachandran B {
740c8ba9d2SJayachandran B u32 data = 0;
750c8ba9d2SJayachandran B
760c8ba9d2SJayachandran B pci_read_config_dword(pci, reg, &data);
770c8ba9d2SJayachandran B data &= ~mask;
780c8ba9d2SJayachandran B data |= (val & mask);
790c8ba9d2SJayachandran B pci_write_config_dword(pci, reg, data);
800c8ba9d2SJayachandran B }
810c8ba9d2SJayachandran B
820c8ba9d2SJayachandran B /*
830c8ba9d2SJayachandran B * skl_enable_miscbdcge - enable/dsiable CGCTL.MISCBDCGE bits
840c8ba9d2SJayachandran B *
850c8ba9d2SJayachandran B * @dev: device pointer
860c8ba9d2SJayachandran B * @enable: enable/disable flag
870c8ba9d2SJayachandran B */
skl_enable_miscbdcge(struct device * dev,bool enable)880c8ba9d2SJayachandran B static void skl_enable_miscbdcge(struct device *dev, bool enable)
890c8ba9d2SJayachandran B {
900c8ba9d2SJayachandran B struct pci_dev *pci = to_pci_dev(dev);
910c8ba9d2SJayachandran B u32 val;
920c8ba9d2SJayachandran B
930c8ba9d2SJayachandran B val = enable ? AZX_CGCTL_MISCBDCGE_MASK : 0;
940c8ba9d2SJayachandran B
950c8ba9d2SJayachandran B update_pci_dword(pci, AZX_PCIREG_CGCTL, AZX_CGCTL_MISCBDCGE_MASK, val);
960c8ba9d2SJayachandran B }
970c8ba9d2SJayachandran B
98fc9fdd61SSanyog Kale /**
99fc9fdd61SSanyog Kale * skl_clock_power_gating: Enable/Disable clock and power gating
100fc9fdd61SSanyog Kale *
101fc9fdd61SSanyog Kale * @dev: Device pointer
102fc9fdd61SSanyog Kale * @enable: Enable/Disable flag
103fc9fdd61SSanyog Kale */
skl_clock_power_gating(struct device * dev,bool enable)104fc9fdd61SSanyog Kale static void skl_clock_power_gating(struct device *dev, bool enable)
105fc9fdd61SSanyog Kale {
106fc9fdd61SSanyog Kale struct pci_dev *pci = to_pci_dev(dev);
10776f56faeSRakesh Ughreja struct hdac_bus *bus = pci_get_drvdata(pci);
108fc9fdd61SSanyog Kale u32 val;
109fc9fdd61SSanyog Kale
110fc9fdd61SSanyog Kale /* Update PDCGE bit of CGCTL register */
111fc9fdd61SSanyog Kale val = enable ? AZX_CGCTL_ADSPDCGE : 0;
112fc9fdd61SSanyog Kale update_pci_dword(pci, AZX_PCIREG_CGCTL, AZX_CGCTL_ADSPDCGE, val);
113fc9fdd61SSanyog Kale
114fc9fdd61SSanyog Kale /* Update L1SEN bit of EM2 register */
115fc9fdd61SSanyog Kale val = enable ? AZX_REG_VS_EM2_L1SEN : 0;
116fc9fdd61SSanyog Kale snd_hdac_chip_updatel(bus, VS_EM2, AZX_REG_VS_EM2_L1SEN, val);
117fc9fdd61SSanyog Kale
118fc9fdd61SSanyog Kale /* Update ADSPPGD bit of PGCTL register */
119fc9fdd61SSanyog Kale val = enable ? 0 : AZX_PGCTL_ADSPPGD;
120fc9fdd61SSanyog Kale update_pci_dword(pci, AZX_PCIREG_PGCTL, AZX_PGCTL_ADSPPGD, val);
121fc9fdd61SSanyog Kale }
122fc9fdd61SSanyog Kale
1230c8ba9d2SJayachandran B /*
1240c8ba9d2SJayachandran B * While performing reset, controller may not come back properly causing
1250c8ba9d2SJayachandran B * issues, so recommendation is to set CGCTL.MISCBDCGE to 0 then do reset
1260c8ba9d2SJayachandran B * (init chip) and then again set CGCTL.MISCBDCGE to 1
1270c8ba9d2SJayachandran B */
skl_init_chip(struct hdac_bus * bus,bool full_reset)1280c8ba9d2SJayachandran B static int skl_init_chip(struct hdac_bus *bus, bool full_reset)
1290c8ba9d2SJayachandran B {
130112c60b3SRakesh Ughreja struct hdac_ext_link *hlink;
1310c8ba9d2SJayachandran B int ret;
1320c8ba9d2SJayachandran B
133e603f11dSCezary Rojewski snd_hdac_set_codec_wakeup(bus, true);
1340c8ba9d2SJayachandran B skl_enable_miscbdcge(bus->dev, false);
1350c8ba9d2SJayachandran B ret = snd_hdac_bus_init_chip(bus, full_reset);
136112c60b3SRakesh Ughreja
137112c60b3SRakesh Ughreja /* Reset stream-to-link mapping */
13876f56faeSRakesh Ughreja list_for_each_entry(hlink, &bus->hlink_list, list)
13919abfefdSTakashi Iwai writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV);
140112c60b3SRakesh Ughreja
1410c8ba9d2SJayachandran B skl_enable_miscbdcge(bus->dev, true);
142e603f11dSCezary Rojewski snd_hdac_set_codec_wakeup(bus, false);
1430c8ba9d2SJayachandran B
1440c8ba9d2SJayachandran B return ret;
1450c8ba9d2SJayachandran B }
1460c8ba9d2SJayachandran B
skl_update_d0i3c(struct device * dev,bool enable)147a26a3f53SPardha Saradhi K void skl_update_d0i3c(struct device *dev, bool enable)
148a26a3f53SPardha Saradhi K {
149a26a3f53SPardha Saradhi K struct pci_dev *pci = to_pci_dev(dev);
15076f56faeSRakesh Ughreja struct hdac_bus *bus = pci_get_drvdata(pci);
151a26a3f53SPardha Saradhi K u8 reg;
152a26a3f53SPardha Saradhi K int timeout = 50;
153a26a3f53SPardha Saradhi K
154a26a3f53SPardha Saradhi K reg = snd_hdac_chip_readb(bus, VS_D0I3C);
155a26a3f53SPardha Saradhi K /* Do not write to D0I3C until command in progress bit is cleared */
156a26a3f53SPardha Saradhi K while ((reg & AZX_REG_VS_D0I3C_CIP) && --timeout) {
157a26a3f53SPardha Saradhi K udelay(10);
158a26a3f53SPardha Saradhi K reg = snd_hdac_chip_readb(bus, VS_D0I3C);
159a26a3f53SPardha Saradhi K }
160a26a3f53SPardha Saradhi K
161a26a3f53SPardha Saradhi K /* Highly unlikely. But if it happens, flag error explicitly */
162a26a3f53SPardha Saradhi K if (!timeout) {
163a26a3f53SPardha Saradhi K dev_err(bus->dev, "Before D0I3C update: D0I3C CIP timeout\n");
164a26a3f53SPardha Saradhi K return;
165a26a3f53SPardha Saradhi K }
166a26a3f53SPardha Saradhi K
167a26a3f53SPardha Saradhi K if (enable)
168a26a3f53SPardha Saradhi K reg = reg | AZX_REG_VS_D0I3C_I3;
169a26a3f53SPardha Saradhi K else
170a26a3f53SPardha Saradhi K reg = reg & (~AZX_REG_VS_D0I3C_I3);
171a26a3f53SPardha Saradhi K
172a26a3f53SPardha Saradhi K snd_hdac_chip_writeb(bus, VS_D0I3C, reg);
173a26a3f53SPardha Saradhi K
174a26a3f53SPardha Saradhi K timeout = 50;
175a26a3f53SPardha Saradhi K /* Wait for cmd in progress to be cleared before exiting the function */
176a26a3f53SPardha Saradhi K reg = snd_hdac_chip_readb(bus, VS_D0I3C);
177a26a3f53SPardha Saradhi K while ((reg & AZX_REG_VS_D0I3C_CIP) && --timeout) {
178a26a3f53SPardha Saradhi K udelay(10);
179a26a3f53SPardha Saradhi K reg = snd_hdac_chip_readb(bus, VS_D0I3C);
180a26a3f53SPardha Saradhi K }
181a26a3f53SPardha Saradhi K
182a26a3f53SPardha Saradhi K /* Highly unlikely. But if it happens, flag error explicitly */
183a26a3f53SPardha Saradhi K if (!timeout) {
184a26a3f53SPardha Saradhi K dev_err(bus->dev, "After D0I3C update: D0I3C CIP timeout\n");
185a26a3f53SPardha Saradhi K return;
186a26a3f53SPardha Saradhi K }
187a26a3f53SPardha Saradhi K
188a26a3f53SPardha Saradhi K dev_dbg(bus->dev, "D0I3C register = 0x%x\n",
189a26a3f53SPardha Saradhi K snd_hdac_chip_readb(bus, VS_D0I3C));
190a26a3f53SPardha Saradhi K }
191a26a3f53SPardha Saradhi K
1927a1954deSCezary Rojewski /**
1937a1954deSCezary Rojewski * skl_dum_set - set DUM bit in EM2 register
1947a1954deSCezary Rojewski * @bus: HD-audio core bus
1957a1954deSCezary Rojewski *
1967a1954deSCezary Rojewski * Addresses incorrect position reporting for capture streams.
1977a1954deSCezary Rojewski * Used on device power up.
1987a1954deSCezary Rojewski */
skl_dum_set(struct hdac_bus * bus)1997a1954deSCezary Rojewski static void skl_dum_set(struct hdac_bus *bus)
2007a1954deSCezary Rojewski {
2017a1954deSCezary Rojewski /* For the DUM bit to be set, CRST needs to be out of reset state */
2027a1954deSCezary Rojewski if (!(snd_hdac_chip_readb(bus, GCTL) & AZX_GCTL_RESET)) {
2037a1954deSCezary Rojewski skl_enable_miscbdcge(bus->dev, false);
2047a1954deSCezary Rojewski snd_hdac_bus_exit_link_reset(bus);
2057a1954deSCezary Rojewski skl_enable_miscbdcge(bus->dev, true);
2067a1954deSCezary Rojewski }
2077a1954deSCezary Rojewski
2087a1954deSCezary Rojewski snd_hdac_chip_updatel(bus, VS_EM2, AZX_VS_EM2_DUM, AZX_VS_EM2_DUM);
2097a1954deSCezary Rojewski }
2107a1954deSCezary Rojewski
211d8c2dab8SJeeja KP /* called from IRQ */
skl_stream_update(struct hdac_bus * bus,struct hdac_stream * hstr)212d8c2dab8SJeeja KP static void skl_stream_update(struct hdac_bus *bus, struct hdac_stream *hstr)
213d8c2dab8SJeeja KP {
214d8c2dab8SJeeja KP snd_pcm_period_elapsed(hstr->substream);
215d8c2dab8SJeeja KP }
216d8c2dab8SJeeja KP
skl_interrupt(int irq,void * dev_id)217d8c2dab8SJeeja KP static irqreturn_t skl_interrupt(int irq, void *dev_id)
218d8c2dab8SJeeja KP {
21976f56faeSRakesh Ughreja struct hdac_bus *bus = dev_id;
220d8c2dab8SJeeja KP u32 status;
221d8c2dab8SJeeja KP
222d8c2dab8SJeeja KP if (!pm_runtime_active(bus->dev))
223d8c2dab8SJeeja KP return IRQ_NONE;
224d8c2dab8SJeeja KP
225d8c2dab8SJeeja KP spin_lock(&bus->reg_lock);
226d8c2dab8SJeeja KP
227d8c2dab8SJeeja KP status = snd_hdac_chip_readl(bus, INTSTS);
228d8c2dab8SJeeja KP if (status == 0 || status == 0xffffffff) {
229d8c2dab8SJeeja KP spin_unlock(&bus->reg_lock);
230d8c2dab8SJeeja KP return IRQ_NONE;
231d8c2dab8SJeeja KP }
232d8c2dab8SJeeja KP
233d8c2dab8SJeeja KP /* clear rirb int */
234d8c2dab8SJeeja KP status = snd_hdac_chip_readb(bus, RIRBSTS);
235d8c2dab8SJeeja KP if (status & RIRB_INT_MASK) {
236d8c2dab8SJeeja KP if (status & RIRB_INT_RESPONSE)
237d8c2dab8SJeeja KP snd_hdac_bus_update_rirb(bus);
238d8c2dab8SJeeja KP snd_hdac_chip_writeb(bus, RIRBSTS, RIRB_INT_MASK);
239d8c2dab8SJeeja KP }
240d8c2dab8SJeeja KP
241d8c2dab8SJeeja KP spin_unlock(&bus->reg_lock);
242d8c2dab8SJeeja KP
243d8c2dab8SJeeja KP return snd_hdac_chip_readl(bus, INTSTS) ? IRQ_WAKE_THREAD : IRQ_HANDLED;
244d8c2dab8SJeeja KP }
245d8c2dab8SJeeja KP
skl_threaded_handler(int irq,void * dev_id)246d8c2dab8SJeeja KP static irqreturn_t skl_threaded_handler(int irq, void *dev_id)
247d8c2dab8SJeeja KP {
24876f56faeSRakesh Ughreja struct hdac_bus *bus = dev_id;
249d8c2dab8SJeeja KP u32 status;
250d8c2dab8SJeeja KP
251d8c2dab8SJeeja KP status = snd_hdac_chip_readl(bus, INTSTS);
252d8c2dab8SJeeja KP
253d8c2dab8SJeeja KP snd_hdac_bus_handle_stream_irq(bus, status, skl_stream_update);
254d8c2dab8SJeeja KP
255d8c2dab8SJeeja KP return IRQ_HANDLED;
256d8c2dab8SJeeja KP }
257d8c2dab8SJeeja KP
skl_acquire_irq(struct hdac_bus * bus,int do_disconnect)25876f56faeSRakesh Ughreja static int skl_acquire_irq(struct hdac_bus *bus, int do_disconnect)
259d8c2dab8SJeeja KP {
260bcc2a2dcSCezary Rojewski struct skl_dev *skl = bus_to_skl(bus);
261d8c2dab8SJeeja KP int ret;
262d8c2dab8SJeeja KP
263d8c2dab8SJeeja KP ret = request_threaded_irq(skl->pci->irq, skl_interrupt,
264d8c2dab8SJeeja KP skl_threaded_handler,
265d8c2dab8SJeeja KP IRQF_SHARED,
26676f56faeSRakesh Ughreja KBUILD_MODNAME, bus);
267d8c2dab8SJeeja KP if (ret) {
268d8c2dab8SJeeja KP dev_err(bus->dev,
269d8c2dab8SJeeja KP "unable to grab IRQ %d, disabling device\n",
270d8c2dab8SJeeja KP skl->pci->irq);
271d8c2dab8SJeeja KP return ret;
272d8c2dab8SJeeja KP }
273d8c2dab8SJeeja KP
274d8c2dab8SJeeja KP bus->irq = skl->pci->irq;
275d8c2dab8SJeeja KP pci_intx(skl->pci, 1);
276d8c2dab8SJeeja KP
277d8c2dab8SJeeja KP return 0;
278d8c2dab8SJeeja KP }
279d8c2dab8SJeeja KP
skl_suspend_late(struct device * dev)2808b4a133cSJayachandran B static int skl_suspend_late(struct device *dev)
2818b4a133cSJayachandran B {
2828b4a133cSJayachandran B struct pci_dev *pci = to_pci_dev(dev);
28376f56faeSRakesh Ughreja struct hdac_bus *bus = pci_get_drvdata(pci);
284bcc2a2dcSCezary Rojewski struct skl_dev *skl = bus_to_skl(bus);
2858b4a133cSJayachandran B
2868b4a133cSJayachandran B return skl_suspend_late_dsp(skl);
2878b4a133cSJayachandran B }
2888b4a133cSJayachandran B
289d8c2dab8SJeeja KP #ifdef CONFIG_PM
_skl_suspend(struct hdac_bus * bus)29076f56faeSRakesh Ughreja static int _skl_suspend(struct hdac_bus *bus)
291d8c2dab8SJeeja KP {
292bcc2a2dcSCezary Rojewski struct skl_dev *skl = bus_to_skl(bus);
29351a01b8cSDharageswari R struct pci_dev *pci = to_pci_dev(bus->dev);
2942a29b200SJeeja KP int ret;
295d8c2dab8SJeeja KP
29676f56faeSRakesh Ughreja snd_hdac_ext_bus_link_power_down_all(bus);
29701bb84b5SJeeja KP
2982a29b200SJeeja KP ret = skl_suspend_dsp(skl);
2992a29b200SJeeja KP if (ret < 0)
3002a29b200SJeeja KP return ret;
301d8c2dab8SJeeja KP
302d8c2dab8SJeeja KP snd_hdac_bus_stop_chip(bus);
30351a01b8cSDharageswari R update_pci_dword(pci, AZX_PCIREG_PGCTL,
30451a01b8cSDharageswari R AZX_PGCTL_LSRMD_MASK, AZX_PGCTL_LSRMD_MASK);
3050c8ba9d2SJayachandran B skl_enable_miscbdcge(bus->dev, false);
306d8c2dab8SJeeja KP snd_hdac_bus_enter_link_reset(bus);
3070c8ba9d2SJayachandran B skl_enable_miscbdcge(bus->dev, true);
308fe3f4442SDharageswari R skl_cleanup_resources(skl);
309d8c2dab8SJeeja KP
310d8c2dab8SJeeja KP return 0;
311d8c2dab8SJeeja KP }
312d8c2dab8SJeeja KP
_skl_resume(struct hdac_bus * bus)31376f56faeSRakesh Ughreja static int _skl_resume(struct hdac_bus *bus)
31461722f44SJeeja KP {
315bcc2a2dcSCezary Rojewski struct skl_dev *skl = bus_to_skl(bus);
31661722f44SJeeja KP
31761722f44SJeeja KP skl_init_pci(skl);
3187a1954deSCezary Rojewski skl_dum_set(bus);
3190c8ba9d2SJayachandran B skl_init_chip(bus, true);
32061722f44SJeeja KP
32161722f44SJeeja KP return skl_resume_dsp(skl);
32261722f44SJeeja KP }
32361722f44SJeeja KP #endif
32461722f44SJeeja KP
32561722f44SJeeja KP #ifdef CONFIG_PM_SLEEP
32661722f44SJeeja KP /*
32761722f44SJeeja KP * power management
32861722f44SJeeja KP */
skl_suspend(struct device * dev)32961722f44SJeeja KP static int skl_suspend(struct device *dev)
33061722f44SJeeja KP {
33161722f44SJeeja KP struct pci_dev *pci = to_pci_dev(dev);
33276f56faeSRakesh Ughreja struct hdac_bus *bus = pci_get_drvdata(pci);
333bcc2a2dcSCezary Rojewski struct skl_dev *skl = bus_to_skl(bus);
3344f799e73STakashi Iwai int ret;
33561722f44SJeeja KP
3364557c305SJeeja KP /*
3374557c305SJeeja KP * Do not suspend if streams which are marked ignore suspend are
3384557c305SJeeja KP * running, we need to save the state for these and continue
3394557c305SJeeja KP */
3404557c305SJeeja KP if (skl->supend_active) {
341cce6c149SVinod Koul /* turn off the links and stop the CORB/RIRB DMA if it is On */
34276f56faeSRakesh Ughreja snd_hdac_ext_bus_link_power_down_all(bus);
343cce6c149SVinod Koul
34476f56faeSRakesh Ughreja if (bus->cmd_dma_state)
34576f56faeSRakesh Ughreja snd_hdac_bus_stop_cmd_io(bus);
346cce6c149SVinod Koul
3471f4956fdSJeeja KP enable_irq_wake(bus->irq);
3484557c305SJeeja KP pci_save_state(pci);
3494557c305SJeeja KP } else {
35076f56faeSRakesh Ughreja ret = _skl_suspend(bus);
351af037412SSubhransu S. Prusty if (ret < 0)
352af037412SSubhransu S. Prusty return ret;
353bcc2a2dcSCezary Rojewski skl->fw_loaded = false;
35461722f44SJeeja KP }
355af037412SSubhransu S. Prusty
3564f799e73STakashi Iwai return 0;
3574557c305SJeeja KP }
35861722f44SJeeja KP
skl_resume(struct device * dev)35961722f44SJeeja KP static int skl_resume(struct device *dev)
36061722f44SJeeja KP {
36161722f44SJeeja KP struct pci_dev *pci = to_pci_dev(dev);
36276f56faeSRakesh Ughreja struct hdac_bus *bus = pci_get_drvdata(pci);
363bcc2a2dcSCezary Rojewski struct skl_dev *skl = bus_to_skl(bus);
364ca841843SGuennadi Liakhovetski struct hdac_ext_link *hlink;
3654557c305SJeeja KP int ret;
36661722f44SJeeja KP
3674557c305SJeeja KP /*
3684557c305SJeeja KP * resume only when we are not in suspend active, otherwise need to
3694557c305SJeeja KP * restore the device
3704557c305SJeeja KP */
3714557c305SJeeja KP if (skl->supend_active) {
3724557c305SJeeja KP pci_restore_state(pci);
37376f56faeSRakesh Ughreja snd_hdac_ext_bus_link_power_up_all(bus);
3741f4956fdSJeeja KP disable_irq_wake(bus->irq);
375cce6c149SVinod Koul /*
376cce6c149SVinod Koul * turn On the links which are On before active suspend
377cce6c149SVinod Koul * and start the CORB/RIRB DMA if On before
378cce6c149SVinod Koul * active suspend.
379cce6c149SVinod Koul */
38076f56faeSRakesh Ughreja list_for_each_entry(hlink, &bus->hlink_list, list) {
381cce6c149SVinod Koul if (hlink->ref_count)
382cce6c149SVinod Koul snd_hdac_ext_bus_link_power_up(hlink);
383cce6c149SVinod Koul }
384cce6c149SVinod Koul
385cc20c4dfSArnd Bergmann ret = 0;
38676f56faeSRakesh Ughreja if (bus->cmd_dma_state)
38776f56faeSRakesh Ughreja snd_hdac_bus_init_cmd_io(bus);
3884557c305SJeeja KP } else {
38976f56faeSRakesh Ughreja ret = _skl_resume(bus);
3904557c305SJeeja KP }
3914557c305SJeeja KP
3924557c305SJeeja KP return ret;
39361722f44SJeeja KP }
39461722f44SJeeja KP #endif /* CONFIG_PM_SLEEP */
39561722f44SJeeja KP
39661722f44SJeeja KP #ifdef CONFIG_PM
skl_runtime_suspend(struct device * dev)39761722f44SJeeja KP static int skl_runtime_suspend(struct device *dev)
39861722f44SJeeja KP {
39961722f44SJeeja KP struct pci_dev *pci = to_pci_dev(dev);
40076f56faeSRakesh Ughreja struct hdac_bus *bus = pci_get_drvdata(pci);
40161722f44SJeeja KP
40261722f44SJeeja KP dev_dbg(bus->dev, "in %s\n", __func__);
40361722f44SJeeja KP
40476f56faeSRakesh Ughreja return _skl_suspend(bus);
40561722f44SJeeja KP }
40661722f44SJeeja KP
skl_runtime_resume(struct device * dev)407d8c2dab8SJeeja KP static int skl_runtime_resume(struct device *dev)
408d8c2dab8SJeeja KP {
409d8c2dab8SJeeja KP struct pci_dev *pci = to_pci_dev(dev);
41076f56faeSRakesh Ughreja struct hdac_bus *bus = pci_get_drvdata(pci);
411d8c2dab8SJeeja KP
412d8c2dab8SJeeja KP dev_dbg(bus->dev, "in %s\n", __func__);
413d8c2dab8SJeeja KP
41476f56faeSRakesh Ughreja return _skl_resume(bus);
415d8c2dab8SJeeja KP }
416d8c2dab8SJeeja KP #endif /* CONFIG_PM */
417d8c2dab8SJeeja KP
418d8c2dab8SJeeja KP static const struct dev_pm_ops skl_pm = {
419d8c2dab8SJeeja KP SET_SYSTEM_SLEEP_PM_OPS(skl_suspend, skl_resume)
420d8c2dab8SJeeja KP SET_RUNTIME_PM_OPS(skl_runtime_suspend, skl_runtime_resume, NULL)
4218b4a133cSJayachandran B .suspend_late = skl_suspend_late,
422d8c2dab8SJeeja KP };
423d8c2dab8SJeeja KP
424d8c2dab8SJeeja KP /*
425d8c2dab8SJeeja KP * destructor
426d8c2dab8SJeeja KP */
skl_free(struct hdac_bus * bus)42776f56faeSRakesh Ughreja static int skl_free(struct hdac_bus *bus)
428d8c2dab8SJeeja KP {
429bcc2a2dcSCezary Rojewski struct skl_dev *skl = bus_to_skl(bus);
430d8c2dab8SJeeja KP
431ab1b732dSVinod Koul skl->init_done = 0; /* to be sure */
432d8c2dab8SJeeja KP
43312054f0cSPierre-Louis Bossart snd_hdac_stop_streams_and_chip(bus);
434d8c2dab8SJeeja KP
435d8c2dab8SJeeja KP if (bus->irq >= 0)
43676f56faeSRakesh Ughreja free_irq(bus->irq, (void *)bus);
437d8c2dab8SJeeja KP snd_hdac_bus_free_stream_pages(bus);
4380839a04eSPierre-Louis Bossart snd_hdac_ext_stream_free_all(bus);
4397f05ca9aSPierre-Louis Bossart snd_hdac_ext_link_free_all(bus);
440077411e5SVinod Koul
441077411e5SVinod Koul if (bus->remap_addr)
442077411e5SVinod Koul iounmap(bus->remap_addr);
443077411e5SVinod Koul
444d8c2dab8SJeeja KP pci_release_regions(skl->pci);
445d8c2dab8SJeeja KP pci_disable_device(skl->pci);
446d8c2dab8SJeeja KP
44776f56faeSRakesh Ughreja snd_hdac_ext_bus_exit(bus);
448d8c2dab8SJeeja KP
449687ae9e2STakashi Iwai if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
450687ae9e2STakashi Iwai snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
45176f56faeSRakesh Ughreja snd_hdac_i915_exit(bus);
452687ae9e2STakashi Iwai }
453ab1b732dSVinod Koul
454d8c2dab8SJeeja KP return 0;
455d8c2dab8SJeeja KP }
456d8c2dab8SJeeja KP
457bc2bd45bSSriram Periyasamy /*
458bc2bd45bSSriram Periyasamy * For each ssp there are 3 clocks (mclk/sclk/sclkfs).
459bc2bd45bSSriram Periyasamy * e.g. for ssp0, clocks will be named as
460bc2bd45bSSriram Periyasamy * "ssp0_mclk", "ssp0_sclk", "ssp0_sclkfs"
461bc2bd45bSSriram Periyasamy * So for skl+, there are 6 ssps, so 18 clocks will be created.
462bc2bd45bSSriram Periyasamy */
463bc2bd45bSSriram Periyasamy static struct skl_ssp_clk skl_ssp_clks[] = {
464bc2bd45bSSriram Periyasamy {.name = "ssp0_mclk"}, {.name = "ssp1_mclk"}, {.name = "ssp2_mclk"},
465bc2bd45bSSriram Periyasamy {.name = "ssp3_mclk"}, {.name = "ssp4_mclk"}, {.name = "ssp5_mclk"},
466bc2bd45bSSriram Periyasamy {.name = "ssp0_sclk"}, {.name = "ssp1_sclk"}, {.name = "ssp2_sclk"},
467bc2bd45bSSriram Periyasamy {.name = "ssp3_sclk"}, {.name = "ssp4_sclk"}, {.name = "ssp5_sclk"},
468bc2bd45bSSriram Periyasamy {.name = "ssp0_sclkfs"}, {.name = "ssp1_sclkfs"},
469bc2bd45bSSriram Periyasamy {.name = "ssp2_sclkfs"},
470bc2bd45bSSriram Periyasamy {.name = "ssp3_sclkfs"}, {.name = "ssp4_sclkfs"},
471bc2bd45bSSriram Periyasamy {.name = "ssp5_sclkfs"},
472bc2bd45bSSriram Periyasamy };
473bc2bd45bSSriram Periyasamy
skl_find_hda_machine(struct skl_dev * skl,struct snd_soc_acpi_mach * machines)474bcc2a2dcSCezary Rojewski static struct snd_soc_acpi_mach *skl_find_hda_machine(struct skl_dev *skl,
4759cdae435SRakesh Ughreja struct snd_soc_acpi_mach *machines)
4769cdae435SRakesh Ughreja {
4779cdae435SRakesh Ughreja struct snd_soc_acpi_mach *mach;
4789cdae435SRakesh Ughreja
4799cdae435SRakesh Ughreja /* point to common table */
4809cdae435SRakesh Ughreja mach = snd_soc_acpi_intel_hda_machines;
4819cdae435SRakesh Ughreja
4829cdae435SRakesh Ughreja /* all entries in the machine table use the same firmware */
4839cdae435SRakesh Ughreja mach->fw_filename = machines->fw_filename;
4849cdae435SRakesh Ughreja
4859cdae435SRakesh Ughreja return mach;
4869cdae435SRakesh Ughreja }
4879cdae435SRakesh Ughreja
skl_find_machine(struct skl_dev * skl,void * driver_data)488bcc2a2dcSCezary Rojewski static int skl_find_machine(struct skl_dev *skl, void *driver_data)
489cc18c5fdSVinod Koul {
49076f56faeSRakesh Ughreja struct hdac_bus *bus = skl_to_bus(skl);
4917feb2f78SPierre-Louis Bossart struct snd_soc_acpi_mach *mach = driver_data;
492752c93aaSPankaj Bharadiya struct skl_machine_pdata *pdata;
493cc18c5fdSVinod Koul
4947feb2f78SPierre-Louis Bossart mach = snd_soc_acpi_find_machine(mach);
4959cdae435SRakesh Ughreja if (!mach) {
4969cdae435SRakesh Ughreja dev_dbg(bus->dev, "No matching I2S machine driver found\n");
4979cdae435SRakesh Ughreja mach = skl_find_hda_machine(skl, driver_data);
4989cdae435SRakesh Ughreja if (!mach) {
499cc18c5fdSVinod Koul dev_err(bus->dev, "No matching machine driver found\n");
500cc18c5fdSVinod Koul return -ENODEV;
501cc18c5fdSVinod Koul }
5029cdae435SRakesh Ughreja }
503752c93aaSPankaj Bharadiya
504752c93aaSPankaj Bharadiya skl->mach = mach;
505aecf6fd8SVinod Koul skl->fw_name = mach->fw_filename;
5065f15f267SPierre-Louis Bossart pdata = mach->pdata;
507752c93aaSPankaj Bharadiya
5085f15f267SPierre-Louis Bossart if (pdata) {
509752c93aaSPankaj Bharadiya skl->use_tplg_pcm = pdata->use_tplg_pcm;
5101169cbf6SPierre-Louis Bossart mach->mach_params.dmic_num =
5111169cbf6SPierre-Louis Bossart intel_nhlt_get_dmic_geo(&skl->pci->dev,
5121169cbf6SPierre-Louis Bossart skl->nhlt);
5135f15f267SPierre-Louis Bossart }
514752c93aaSPankaj Bharadiya
515752c93aaSPankaj Bharadiya return 0;
516752c93aaSPankaj Bharadiya }
517752c93aaSPankaj Bharadiya
skl_machine_device_register(struct skl_dev * skl)518bcc2a2dcSCezary Rojewski static int skl_machine_device_register(struct skl_dev *skl)
519752c93aaSPankaj Bharadiya {
520752c93aaSPankaj Bharadiya struct snd_soc_acpi_mach *mach = skl->mach;
5219cdae435SRakesh Ughreja struct hdac_bus *bus = skl_to_bus(skl);
522752c93aaSPankaj Bharadiya struct platform_device *pdev;
523752c93aaSPankaj Bharadiya int ret;
524cc18c5fdSVinod Koul
525cc18c5fdSVinod Koul pdev = platform_device_alloc(mach->drv_name, -1);
526cc18c5fdSVinod Koul if (pdev == NULL) {
527cc18c5fdSVinod Koul dev_err(bus->dev, "platform device alloc failed\n");
528cc18c5fdSVinod Koul return -EIO;
529cc18c5fdSVinod Koul }
530cc18c5fdSVinod Koul
5315a619b9eSPierre-Louis Bossart mach->mach_params.platform = dev_name(bus->dev);
5325a619b9eSPierre-Louis Bossart mach->mach_params.codec_mask = bus->codec_mask;
5335a619b9eSPierre-Louis Bossart
5345a619b9eSPierre-Louis Bossart ret = platform_device_add_data(pdev, (const void *)mach, sizeof(*mach));
5355a619b9eSPierre-Louis Bossart if (ret) {
5365a619b9eSPierre-Louis Bossart dev_err(bus->dev, "failed to add machine device platform data\n");
5375a619b9eSPierre-Louis Bossart platform_device_put(pdev);
5385a619b9eSPierre-Louis Bossart return ret;
5395a619b9eSPierre-Louis Bossart }
5405a619b9eSPierre-Louis Bossart
541cc18c5fdSVinod Koul ret = platform_device_add(pdev);
542cc18c5fdSVinod Koul if (ret) {
543cc18c5fdSVinod Koul dev_err(bus->dev, "failed to add machine device\n");
544cc18c5fdSVinod Koul platform_device_put(pdev);
545cc18c5fdSVinod Koul return -EIO;
546cc18c5fdSVinod Koul }
547f65cf7d6SYong Zhi
548f65cf7d6SYong Zhi
549cc18c5fdSVinod Koul skl->i2s_dev = pdev;
550cc18c5fdSVinod Koul
551cc18c5fdSVinod Koul return 0;
552cc18c5fdSVinod Koul }
553cc18c5fdSVinod Koul
skl_machine_device_unregister(struct skl_dev * skl)554bcc2a2dcSCezary Rojewski static void skl_machine_device_unregister(struct skl_dev *skl)
555cc18c5fdSVinod Koul {
556cc18c5fdSVinod Koul if (skl->i2s_dev)
557cc18c5fdSVinod Koul platform_device_unregister(skl->i2s_dev);
558cc18c5fdSVinod Koul }
559cc18c5fdSVinod Koul
skl_dmic_device_register(struct skl_dev * skl)560bcc2a2dcSCezary Rojewski static int skl_dmic_device_register(struct skl_dev *skl)
561d8c2dab8SJeeja KP {
56276f56faeSRakesh Ughreja struct hdac_bus *bus = skl_to_bus(skl);
563d8c2dab8SJeeja KP struct platform_device *pdev;
564d8c2dab8SJeeja KP int ret;
565d8c2dab8SJeeja KP
566d8c2dab8SJeeja KP /* SKL has one dmic port, so allocate dmic device for this */
567d8c2dab8SJeeja KP pdev = platform_device_alloc("dmic-codec", -1);
568d8c2dab8SJeeja KP if (!pdev) {
569d8c2dab8SJeeja KP dev_err(bus->dev, "failed to allocate dmic device\n");
570d8c2dab8SJeeja KP return -ENOMEM;
571d8c2dab8SJeeja KP }
572d8c2dab8SJeeja KP
573d8c2dab8SJeeja KP ret = platform_device_add(pdev);
574d8c2dab8SJeeja KP if (ret) {
575d8c2dab8SJeeja KP dev_err(bus->dev, "failed to add dmic device: %d\n", ret);
576d8c2dab8SJeeja KP platform_device_put(pdev);
577d8c2dab8SJeeja KP return ret;
578d8c2dab8SJeeja KP }
579d8c2dab8SJeeja KP skl->dmic_dev = pdev;
580d8c2dab8SJeeja KP
581d8c2dab8SJeeja KP return 0;
582d8c2dab8SJeeja KP }
583d8c2dab8SJeeja KP
skl_dmic_device_unregister(struct skl_dev * skl)584bcc2a2dcSCezary Rojewski static void skl_dmic_device_unregister(struct skl_dev *skl)
585d8c2dab8SJeeja KP {
586d8c2dab8SJeeja KP if (skl->dmic_dev)
587d8c2dab8SJeeja KP platform_device_unregister(skl->dmic_dev);
588d8c2dab8SJeeja KP }
589d8c2dab8SJeeja KP
590bc2bd45bSSriram Periyasamy static struct skl_clk_parent_src skl_clk_src[] = {
591bc2bd45bSSriram Periyasamy { .clk_id = SKL_XTAL, .name = "xtal" },
592bc2bd45bSSriram Periyasamy { .clk_id = SKL_CARDINAL, .name = "cardinal", .rate = 24576000 },
593bc2bd45bSSriram Periyasamy { .clk_id = SKL_PLL, .name = "pll", .rate = 96000000 },
594bc2bd45bSSriram Periyasamy };
595bc2bd45bSSriram Periyasamy
skl_get_parent_clk(u8 clk_id)596bc2bd45bSSriram Periyasamy struct skl_clk_parent_src *skl_get_parent_clk(u8 clk_id)
597bc2bd45bSSriram Periyasamy {
598bc2bd45bSSriram Periyasamy unsigned int i;
599bc2bd45bSSriram Periyasamy
600bc2bd45bSSriram Periyasamy for (i = 0; i < ARRAY_SIZE(skl_clk_src); i++) {
601bc2bd45bSSriram Periyasamy if (skl_clk_src[i].clk_id == clk_id)
602bc2bd45bSSriram Periyasamy return &skl_clk_src[i];
603bc2bd45bSSriram Periyasamy }
604bc2bd45bSSriram Periyasamy
605bc2bd45bSSriram Periyasamy return NULL;
606bc2bd45bSSriram Periyasamy }
607bc2bd45bSSriram Periyasamy
init_skl_xtal_rate(int pci_id)6088e79ec98SGuneshwor Singh static void init_skl_xtal_rate(int pci_id)
609bc2bd45bSSriram Periyasamy {
610bc2bd45bSSriram Periyasamy switch (pci_id) {
611*a2db8743SAmadeusz Sławiński case PCI_DEVICE_ID_INTEL_HDA_SKL_LP:
612*a2db8743SAmadeusz Sławiński case PCI_DEVICE_ID_INTEL_HDA_KBL_LP:
613bc2bd45bSSriram Periyasamy skl_clk_src[0].rate = 24000000;
614bc2bd45bSSriram Periyasamy return;
615bc2bd45bSSriram Periyasamy
616bc2bd45bSSriram Periyasamy default:
617bc2bd45bSSriram Periyasamy skl_clk_src[0].rate = 19200000;
618bc2bd45bSSriram Periyasamy return;
619bc2bd45bSSriram Periyasamy }
620bc2bd45bSSriram Periyasamy }
621bc2bd45bSSriram Periyasamy
skl_clock_device_register(struct skl_dev * skl)622bcc2a2dcSCezary Rojewski static int skl_clock_device_register(struct skl_dev *skl)
623bc2bd45bSSriram Periyasamy {
624bc2bd45bSSriram Periyasamy struct platform_device_info pdevinfo = {NULL};
625bc2bd45bSSriram Periyasamy struct skl_clk_pdata *clk_pdata;
626bc2bd45bSSriram Periyasamy
6279e6c382fSCezary Rojewski if (!skl->nhlt)
6289e6c382fSCezary Rojewski return 0;
6299e6c382fSCezary Rojewski
630bc2bd45bSSriram Periyasamy clk_pdata = devm_kzalloc(&skl->pci->dev, sizeof(*clk_pdata),
631bc2bd45bSSriram Periyasamy GFP_KERNEL);
632bc2bd45bSSriram Periyasamy if (!clk_pdata)
633bc2bd45bSSriram Periyasamy return -ENOMEM;
634bc2bd45bSSriram Periyasamy
635bc2bd45bSSriram Periyasamy init_skl_xtal_rate(skl->pci->device);
636bc2bd45bSSriram Periyasamy
637bc2bd45bSSriram Periyasamy clk_pdata->parent_clks = skl_clk_src;
638bc2bd45bSSriram Periyasamy clk_pdata->ssp_clks = skl_ssp_clks;
639bc2bd45bSSriram Periyasamy clk_pdata->num_clks = ARRAY_SIZE(skl_ssp_clks);
640bc2bd45bSSriram Periyasamy
641bc2bd45bSSriram Periyasamy /* Query NHLT to fill the rates and parent */
642bc2bd45bSSriram Periyasamy skl_get_clks(skl, clk_pdata->ssp_clks);
643bc2bd45bSSriram Periyasamy clk_pdata->pvt_data = skl;
644bc2bd45bSSriram Periyasamy
645bc2bd45bSSriram Periyasamy /* Register Platform device */
646bc2bd45bSSriram Periyasamy pdevinfo.parent = &skl->pci->dev;
647bc2bd45bSSriram Periyasamy pdevinfo.id = -1;
648bc2bd45bSSriram Periyasamy pdevinfo.name = "skl-ssp-clk";
649bc2bd45bSSriram Periyasamy pdevinfo.data = clk_pdata;
650bc2bd45bSSriram Periyasamy pdevinfo.size_data = sizeof(*clk_pdata);
651bc2bd45bSSriram Periyasamy skl->clk_dev = platform_device_register_full(&pdevinfo);
652bc2bd45bSSriram Periyasamy return PTR_ERR_OR_ZERO(skl->clk_dev);
653bc2bd45bSSriram Periyasamy }
654bc2bd45bSSriram Periyasamy
skl_clock_device_unregister(struct skl_dev * skl)655bcc2a2dcSCezary Rojewski static void skl_clock_device_unregister(struct skl_dev *skl)
656bc2bd45bSSriram Periyasamy {
657bc2bd45bSSriram Periyasamy if (skl->clk_dev)
658bc2bd45bSSriram Periyasamy platform_device_unregister(skl->clk_dev);
659bc2bd45bSSriram Periyasamy }
660bc2bd45bSSriram Periyasamy
6618c4e7c2eSPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
6628c4e7c2eSPierre-Louis Bossart
6636bae5ea9SRakesh Ughreja #define IDISP_INTEL_VENDOR_ID 0x80860000
6646bae5ea9SRakesh Ughreja
6656bae5ea9SRakesh Ughreja /*
6666bae5ea9SRakesh Ughreja * load the legacy codec driver
6676bae5ea9SRakesh Ughreja */
load_codec_module(struct hda_codec * codec)6686bae5ea9SRakesh Ughreja static void load_codec_module(struct hda_codec *codec)
6696bae5ea9SRakesh Ughreja {
6706bae5ea9SRakesh Ughreja #ifdef MODULE
6716bae5ea9SRakesh Ughreja char modalias[MODULE_NAME_LEN];
6726bae5ea9SRakesh Ughreja const char *mod = NULL;
6736bae5ea9SRakesh Ughreja
6746bae5ea9SRakesh Ughreja snd_hdac_codec_modalias(&codec->core, modalias, sizeof(modalias));
6756bae5ea9SRakesh Ughreja mod = modalias;
6766bae5ea9SRakesh Ughreja dev_dbg(&codec->core.dev, "loading %s codec module\n", mod);
6776bae5ea9SRakesh Ughreja request_module(mod);
6786bae5ea9SRakesh Ughreja #endif
6796bae5ea9SRakesh Ughreja }
6806bae5ea9SRakesh Ughreja
6818c4e7c2eSPierre-Louis Bossart #endif /* CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC */
6828c4e7c2eSPierre-Louis Bossart
skl_codec_device_init(struct hdac_bus * bus,int addr)6833fd63658SCezary Rojewski static struct hda_codec *skl_codec_device_init(struct hdac_bus *bus, int addr)
684e4746d94SCezary Rojewski {
685e4746d94SCezary Rojewski struct hda_codec *codec;
686e4746d94SCezary Rojewski int ret;
687e4746d94SCezary Rojewski
688e4746d94SCezary Rojewski codec = snd_hda_codec_device_init(to_hda_bus(bus), addr, "ehdaudio%dD%d", bus->idx, addr);
689e4746d94SCezary Rojewski if (IS_ERR(codec)) {
690e4746d94SCezary Rojewski dev_err(bus->dev, "device init failed for hdac device\n");
691e4746d94SCezary Rojewski return codec;
692e4746d94SCezary Rojewski }
693e4746d94SCezary Rojewski
694e4746d94SCezary Rojewski codec->core.type = HDA_DEV_ASOC;
695e4746d94SCezary Rojewski
696e4746d94SCezary Rojewski ret = snd_hdac_device_register(&codec->core);
697e4746d94SCezary Rojewski if (ret) {
698e4746d94SCezary Rojewski dev_err(bus->dev, "failed to register hdac device\n");
6990aa60ddcSYang Yingliang put_device(&codec->core.dev);
700e4746d94SCezary Rojewski return ERR_PTR(ret);
701e4746d94SCezary Rojewski }
702e4746d94SCezary Rojewski
703e4746d94SCezary Rojewski return codec;
704e4746d94SCezary Rojewski }
705e4746d94SCezary Rojewski
706d8c2dab8SJeeja KP /*
707d8c2dab8SJeeja KP * Probe the given codec address
708d8c2dab8SJeeja KP */
probe_codec(struct hdac_bus * bus,int addr)70976f56faeSRakesh Ughreja static int probe_codec(struct hdac_bus *bus, int addr)
710d8c2dab8SJeeja KP {
711d8c2dab8SJeeja KP unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) |
712d8c2dab8SJeeja KP (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID;
713e6a33532SDan Carpenter unsigned int res = -1;
7148c4e7c2eSPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
715a74bfc9eSGaosheng Cui struct skl_dev *skl = bus_to_skl(bus);
7166bae5ea9SRakesh Ughreja struct hdac_hda_priv *hda_codec;
7178c4e7c2eSPierre-Louis Bossart #endif
7183fd63658SCezary Rojewski struct hda_codec *codec;
719d8c2dab8SJeeja KP
720d8c2dab8SJeeja KP mutex_lock(&bus->cmd_mutex);
721d8c2dab8SJeeja KP snd_hdac_bus_send_cmd(bus, cmd);
722d8c2dab8SJeeja KP snd_hdac_bus_get_response(bus, addr, &res);
723d8c2dab8SJeeja KP mutex_unlock(&bus->cmd_mutex);
724d8c2dab8SJeeja KP if (res == -1)
725d8c2dab8SJeeja KP return -EIO;
72600deadb5SRakesh Ughreja dev_dbg(bus->dev, "codec #%d probed OK: %x\n", addr, res);
727d8c2dab8SJeeja KP
7288c4e7c2eSPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
7296bae5ea9SRakesh Ughreja hda_codec = devm_kzalloc(&skl->pci->dev, sizeof(*hda_codec),
7306bae5ea9SRakesh Ughreja GFP_KERNEL);
7316bae5ea9SRakesh Ughreja if (!hda_codec)
7326298542fSRakesh Ughreja return -ENOMEM;
7336298542fSRakesh Ughreja
7343fd63658SCezary Rojewski codec = skl_codec_device_init(bus, addr);
7353fd63658SCezary Rojewski if (IS_ERR(codec))
7363fd63658SCezary Rojewski return PTR_ERR(codec);
7376bae5ea9SRakesh Ughreja
7383fd63658SCezary Rojewski hda_codec->codec = codec;
7393fd63658SCezary Rojewski dev_set_drvdata(&codec->core.dev, hda_codec);
7406bae5ea9SRakesh Ughreja
7416bae5ea9SRakesh Ughreja /* use legacy bus only for HDA codecs, idisp uses ext bus */
7426bae5ea9SRakesh Ughreja if ((res & 0xFFFF0000) != IDISP_INTEL_VENDOR_ID) {
7433fd63658SCezary Rojewski codec->core.type = HDA_DEV_LEGACY;
7443fd63658SCezary Rojewski load_codec_module(hda_codec->codec);
7456bae5ea9SRakesh Ughreja }
7466bae5ea9SRakesh Ughreja return 0;
7478c4e7c2eSPierre-Louis Bossart #else
7483fd63658SCezary Rojewski codec = skl_codec_device_init(bus, addr);
7493fd63658SCezary Rojewski return PTR_ERR_OR_ZERO(codec);
7508c4e7c2eSPierre-Louis Bossart #endif /* CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC */
751d8c2dab8SJeeja KP }
752d8c2dab8SJeeja KP
753d8c2dab8SJeeja KP /* Codec initialization */
skl_codec_create(struct hdac_bus * bus)75476f56faeSRakesh Ughreja static void skl_codec_create(struct hdac_bus *bus)
755d8c2dab8SJeeja KP {
756d8c2dab8SJeeja KP int c, max_slots;
757d8c2dab8SJeeja KP
758d8c2dab8SJeeja KP max_slots = HDA_MAX_CODECS;
759d8c2dab8SJeeja KP
760d8c2dab8SJeeja KP /* First try to probe all given codec slots */
761d8c2dab8SJeeja KP for (c = 0; c < max_slots; c++) {
762d8c2dab8SJeeja KP if ((bus->codec_mask & (1 << c))) {
76376f56faeSRakesh Ughreja if (probe_codec(bus, c) < 0) {
764d8c2dab8SJeeja KP /*
765d8c2dab8SJeeja KP * Some BIOSen give you wrong codec addresses
766d8c2dab8SJeeja KP * that don't exist
767d8c2dab8SJeeja KP */
768d8c2dab8SJeeja KP dev_warn(bus->dev,
769d8c2dab8SJeeja KP "Codec #%d probe error; disabling it...\n", c);
770d8c2dab8SJeeja KP bus->codec_mask &= ~(1 << c);
771d8c2dab8SJeeja KP /*
772d8c2dab8SJeeja KP * More badly, accessing to a non-existing
773d8c2dab8SJeeja KP * codec often screws up the controller bus,
774d8c2dab8SJeeja KP * and disturbs the further communications.
775d8c2dab8SJeeja KP * Thus if an error occurs during probing,
776d8c2dab8SJeeja KP * better to reset the controller bus to get
777d8c2dab8SJeeja KP * back to the sanity state.
778d8c2dab8SJeeja KP */
779d8c2dab8SJeeja KP snd_hdac_bus_stop_chip(bus);
7800c8ba9d2SJayachandran B skl_init_chip(bus, true);
781d8c2dab8SJeeja KP }
782d8c2dab8SJeeja KP }
783d8c2dab8SJeeja KP }
784d8c2dab8SJeeja KP }
785d8c2dab8SJeeja KP
skl_i915_init(struct hdac_bus * bus)786ab1b732dSVinod Koul static int skl_i915_init(struct hdac_bus *bus)
787ab1b732dSVinod Koul {
788ab1b732dSVinod Koul int err;
789ab1b732dSVinod Koul
790ab1b732dSVinod Koul /*
791ab1b732dSVinod Koul * The HDMI codec is in GPU so we need to ensure that it is powered
792ab1b732dSVinod Koul * up and ready for probe
793ab1b732dSVinod Koul */
794ab1b732dSVinod Koul err = snd_hdac_i915_init(bus);
795ab1b732dSVinod Koul if (err < 0)
796ab1b732dSVinod Koul return err;
797ab1b732dSVinod Koul
7984f799e73STakashi Iwai snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true);
799ab1b732dSVinod Koul
8004f799e73STakashi Iwai return 0;
801ab1b732dSVinod Koul }
802ab1b732dSVinod Koul
skl_probe_work(struct work_struct * work)803ab1b732dSVinod Koul static void skl_probe_work(struct work_struct *work)
804ab1b732dSVinod Koul {
805bcc2a2dcSCezary Rojewski struct skl_dev *skl = container_of(work, struct skl_dev, probe_work);
80676f56faeSRakesh Ughreja struct hdac_bus *bus = skl_to_bus(skl);
807ca841843SGuennadi Liakhovetski struct hdac_ext_link *hlink;
808ab1b732dSVinod Koul int err;
809ab1b732dSVinod Koul
810ab1b732dSVinod Koul if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
811ab1b732dSVinod Koul err = skl_i915_init(bus);
812ab1b732dSVinod Koul if (err < 0)
813ab1b732dSVinod Koul return;
814ab1b732dSVinod Koul }
815ab1b732dSVinod Koul
8162ef81057SCezary Rojewski skl_init_pci(skl);
8172ef81057SCezary Rojewski skl_dum_set(bus);
8182ef81057SCezary Rojewski
819ab1b732dSVinod Koul err = skl_init_chip(bus, true);
820ab1b732dSVinod Koul if (err < 0) {
821ab1b732dSVinod Koul dev_err(bus->dev, "Init chip failed with err: %d\n", err);
822ab1b732dSVinod Koul goto out_err;
823ab1b732dSVinod Koul }
824ab1b732dSVinod Koul
825ab1b732dSVinod Koul /* codec detection */
826ab1b732dSVinod Koul if (!bus->codec_mask)
827ab1b732dSVinod Koul dev_info(bus->dev, "no hda codecs found!\n");
828ab1b732dSVinod Koul
829ab1b732dSVinod Koul /* create codec instances */
83076f56faeSRakesh Ughreja skl_codec_create(bus);
831ab1b732dSVinod Koul
832752c93aaSPankaj Bharadiya /* register platform dai and controls */
833752c93aaSPankaj Bharadiya err = skl_platform_register(bus->dev);
834752c93aaSPankaj Bharadiya if (err < 0) {
835752c93aaSPankaj Bharadiya dev_err(bus->dev, "platform register failed: %d\n", err);
836687ae9e2STakashi Iwai goto out_err;
837752c93aaSPankaj Bharadiya }
838752c93aaSPankaj Bharadiya
839752c93aaSPankaj Bharadiya err = skl_machine_device_register(skl);
840752c93aaSPankaj Bharadiya if (err < 0) {
841752c93aaSPankaj Bharadiya dev_err(bus->dev, "machine register failed: %d\n", err);
842752c93aaSPankaj Bharadiya goto out_err;
843752c93aaSPankaj Bharadiya }
844752c93aaSPankaj Bharadiya
8454c10473dSPierre-Louis Bossart /*
8464c10473dSPierre-Louis Bossart * we are done probing so decrement link counts
8474c10473dSPierre-Louis Bossart */
8484c10473dSPierre-Louis Bossart list_for_each_entry(hlink, &bus->hlink_list, list)
8494c10473dSPierre-Louis Bossart snd_hdac_ext_bus_link_put(bus, hlink);
8504c10473dSPierre-Louis Bossart
8514f799e73STakashi Iwai if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
8524f799e73STakashi Iwai snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
853ab1b732dSVinod Koul
854ab1b732dSVinod Koul /* configure PM */
855ab1b732dSVinod Koul pm_runtime_put_noidle(bus->dev);
856ab1b732dSVinod Koul pm_runtime_allow(bus->dev);
857ab1b732dSVinod Koul skl->init_done = 1;
858ab1b732dSVinod Koul
859ab1b732dSVinod Koul return;
860ab1b732dSVinod Koul
861ab1b732dSVinod Koul out_err:
862ab1b732dSVinod Koul if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
8634f799e73STakashi Iwai snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
864ab1b732dSVinod Koul }
865ab1b732dSVinod Koul
866d8c2dab8SJeeja KP /*
867d8c2dab8SJeeja KP * constructor
868d8c2dab8SJeeja KP */
skl_create(struct pci_dev * pci,struct skl_dev ** rskl)869d8c2dab8SJeeja KP static int skl_create(struct pci_dev *pci,
870bcc2a2dcSCezary Rojewski struct skl_dev **rskl)
871d8c2dab8SJeeja KP {
8726bae5ea9SRakesh Ughreja struct hdac_ext_bus_ops *ext_ops = NULL;
873bcc2a2dcSCezary Rojewski struct skl_dev *skl;
87476f56faeSRakesh Ughreja struct hdac_bus *bus;
87500deadb5SRakesh Ughreja struct hda_bus *hbus;
876d8c2dab8SJeeja KP int err;
877d8c2dab8SJeeja KP
878d8c2dab8SJeeja KP *rskl = NULL;
879d8c2dab8SJeeja KP
880d8c2dab8SJeeja KP err = pci_enable_device(pci);
881d8c2dab8SJeeja KP if (err < 0)
882d8c2dab8SJeeja KP return err;
883d8c2dab8SJeeja KP
884d8c2dab8SJeeja KP skl = devm_kzalloc(&pci->dev, sizeof(*skl), GFP_KERNEL);
885d8c2dab8SJeeja KP if (!skl) {
886d8c2dab8SJeeja KP pci_disable_device(pci);
887d8c2dab8SJeeja KP return -ENOMEM;
888d8c2dab8SJeeja KP }
88976f56faeSRakesh Ughreja
89000deadb5SRakesh Ughreja hbus = skl_to_hbus(skl);
89176f56faeSRakesh Ughreja bus = skl_to_bus(skl);
8926bae5ea9SRakesh Ughreja
893776cb3b8SAmadeusz Sławiński INIT_LIST_HEAD(&skl->ppl_list);
894776cb3b8SAmadeusz Sławiński INIT_LIST_HEAD(&skl->bind_list);
895776cb3b8SAmadeusz Sławiński
8968c4e7c2eSPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
8976bae5ea9SRakesh Ughreja ext_ops = snd_soc_hdac_hda_get_ops();
8986bae5ea9SRakesh Ughreja #endif
899ae91a189STakashi Iwai snd_hdac_ext_bus_init(bus, &pci->dev, NULL, ext_ops);
90076f56faeSRakesh Ughreja bus->use_posbuf = 1;
901d8c2dab8SJeeja KP skl->pci = pci;
902ab1b732dSVinod Koul INIT_WORK(&skl->probe_work, skl_probe_work);
90376f56faeSRakesh Ughreja bus->bdl_pos_adj = 0;
904d8c2dab8SJeeja KP
90500deadb5SRakesh Ughreja mutex_init(&hbus->prepare_mutex);
90600deadb5SRakesh Ughreja hbus->pci = pci;
90700deadb5SRakesh Ughreja hbus->mixer_assigned = -1;
90800deadb5SRakesh Ughreja hbus->modelname = "sklbus";
90900deadb5SRakesh Ughreja
910d8c2dab8SJeeja KP *rskl = skl;
911d8c2dab8SJeeja KP
912d8c2dab8SJeeja KP return 0;
913d8c2dab8SJeeja KP }
914d8c2dab8SJeeja KP
skl_first_init(struct hdac_bus * bus)91576f56faeSRakesh Ughreja static int skl_first_init(struct hdac_bus *bus)
916d8c2dab8SJeeja KP {
917bcc2a2dcSCezary Rojewski struct skl_dev *skl = bus_to_skl(bus);
918d8c2dab8SJeeja KP struct pci_dev *pci = skl->pci;
919d8c2dab8SJeeja KP int err;
920d8c2dab8SJeeja KP unsigned short gcap;
921d8c2dab8SJeeja KP int cp_streams, pb_streams, start_idx;
922d8c2dab8SJeeja KP
923d8c2dab8SJeeja KP err = pci_request_regions(pci, "Skylake HD audio");
924d8c2dab8SJeeja KP if (err < 0)
925d8c2dab8SJeeja KP return err;
926d8c2dab8SJeeja KP
927d8c2dab8SJeeja KP bus->addr = pci_resource_start(pci, 0);
928d8c2dab8SJeeja KP bus->remap_addr = pci_ioremap_bar(pci, 0);
929d8c2dab8SJeeja KP if (bus->remap_addr == NULL) {
930d8c2dab8SJeeja KP dev_err(bus->dev, "ioremap error\n");
931d8c2dab8SJeeja KP return -ENXIO;
932d8c2dab8SJeeja KP }
933d8c2dab8SJeeja KP
934ec8ae570SVinod Koul snd_hdac_bus_parse_capabilities(bus);
93505057001SJeeja KP
936fa11ab56SPierre-Louis Bossart /* check if PPCAP exists */
937fa11ab56SPierre-Louis Bossart if (!bus->ppcap) {
938135ab457SPierre-Louis Bossart dev_err(bus->dev, "bus ppcap not set, HDAudio or DSP not present?\n");
939fa11ab56SPierre-Louis Bossart return -ENODEV;
940fa11ab56SPierre-Louis Bossart }
941fa11ab56SPierre-Louis Bossart
942542cedecSYu Zhao if (skl_acquire_irq(bus, 0) < 0)
943542cedecSYu Zhao return -EBUSY;
944542cedecSYu Zhao
945d8c2dab8SJeeja KP pci_set_master(pci);
946542cedecSYu Zhao synchronize_irq(bus->irq);
947d8c2dab8SJeeja KP
948d8c2dab8SJeeja KP gcap = snd_hdac_chip_readw(bus, GCAP);
949d8c2dab8SJeeja KP dev_dbg(bus->dev, "chipset global capabilities = 0x%x\n", gcap);
950d8c2dab8SJeeja KP
951fa11ab56SPierre-Louis Bossart /* read number of streams from GCAP register */
952fa11ab56SPierre-Louis Bossart cp_streams = (gcap >> 8) & 0x0f;
953fa11ab56SPierre-Louis Bossart pb_streams = (gcap >> 12) & 0x0f;
954fa11ab56SPierre-Louis Bossart
955fa11ab56SPierre-Louis Bossart if (!pb_streams && !cp_streams) {
956fa11ab56SPierre-Louis Bossart dev_err(bus->dev, "no streams found in GCAP definitions?\n");
957fa11ab56SPierre-Louis Bossart return -EIO;
958fa11ab56SPierre-Louis Bossart }
959fa11ab56SPierre-Louis Bossart
960fa11ab56SPierre-Louis Bossart bus->num_streams = cp_streams + pb_streams;
961fa11ab56SPierre-Louis Bossart
962d8c2dab8SJeeja KP /* allow 64bit DMA address if supported by H/W */
963d3afb002STakashi Iwai if (dma_set_mask_and_coherent(bus->dev, DMA_BIT_MASK(64)))
964d3afb002STakashi Iwai dma_set_mask_and_coherent(bus->dev, DMA_BIT_MASK(32));
965c22a8086STakashi Iwai dma_set_max_seg_size(bus->dev, UINT_MAX);
966d8c2dab8SJeeja KP
967d8c2dab8SJeeja KP /* initialize streams */
968d8c2dab8SJeeja KP snd_hdac_ext_stream_init_all
96976f56faeSRakesh Ughreja (bus, 0, cp_streams, SNDRV_PCM_STREAM_CAPTURE);
970d8c2dab8SJeeja KP start_idx = cp_streams;
971d8c2dab8SJeeja KP snd_hdac_ext_stream_init_all
97276f56faeSRakesh Ughreja (bus, start_idx, pb_streams, SNDRV_PCM_STREAM_PLAYBACK);
973d8c2dab8SJeeja KP
974d8c2dab8SJeeja KP err = snd_hdac_bus_alloc_stream_pages(bus);
975d8c2dab8SJeeja KP if (err < 0)
976d8c2dab8SJeeja KP return err;
977d8c2dab8SJeeja KP
9782ef81057SCezary Rojewski return 0;
979d8c2dab8SJeeja KP }
980d8c2dab8SJeeja KP
skl_probe(struct pci_dev * pci,const struct pci_device_id * pci_id)981d8c2dab8SJeeja KP static int skl_probe(struct pci_dev *pci,
982d8c2dab8SJeeja KP const struct pci_device_id *pci_id)
983d8c2dab8SJeeja KP {
984bcc2a2dcSCezary Rojewski struct skl_dev *skl;
985d8c2dab8SJeeja KP struct hdac_bus *bus = NULL;
986d8c2dab8SJeeja KP int err;
987d8c2dab8SJeeja KP
988d82b51c8SPierre-Louis Bossart switch (skl_pci_binding) {
989d82b51c8SPierre-Louis Bossart case SND_SKL_PCI_BIND_AUTO:
99082d9d54aSJaroslav Kysela err = snd_intel_dsp_driver_probe(pci);
99182d9d54aSJaroslav Kysela if (err != SND_INTEL_DSP_DRIVER_ANY &&
99282d9d54aSJaroslav Kysela err != SND_INTEL_DSP_DRIVER_SST)
993d82b51c8SPierre-Louis Bossart return -ENODEV;
994d82b51c8SPierre-Louis Bossart break;
995d82b51c8SPierre-Louis Bossart case SND_SKL_PCI_BIND_LEGACY:
996135ab457SPierre-Louis Bossart dev_info(&pci->dev, "Module parameter forced binding with HDAudio legacy, aborting probe\n");
997d82b51c8SPierre-Louis Bossart return -ENODEV;
998d82b51c8SPierre-Louis Bossart case SND_SKL_PCI_BIND_ASOC:
999d82b51c8SPierre-Louis Bossart dev_info(&pci->dev, "Module parameter forced binding with SKL driver, bypassed detection logic\n");
1000d82b51c8SPierre-Louis Bossart break;
1001d82b51c8SPierre-Louis Bossart default:
1002d82b51c8SPierre-Louis Bossart dev_err(&pci->dev, "invalid value for skl_pci_binding module parameter, ignored\n");
1003d82b51c8SPierre-Louis Bossart break;
1004d82b51c8SPierre-Louis Bossart }
1005d82b51c8SPierre-Louis Bossart
1006d8c2dab8SJeeja KP /* we use ext core ops, so provide NULL for ops here */
100719abfefdSTakashi Iwai err = skl_create(pci, &skl);
1008d8c2dab8SJeeja KP if (err < 0)
1009d8c2dab8SJeeja KP return err;
1010d8c2dab8SJeeja KP
101176f56faeSRakesh Ughreja bus = skl_to_bus(skl);
1012d8c2dab8SJeeja KP
101376f56faeSRakesh Ughreja err = skl_first_init(bus);
1014f231c34cSPierre-Louis Bossart if (err < 0) {
1015f231c34cSPierre-Louis Bossart dev_err(bus->dev, "skl_first_init failed with err: %d\n", err);
1016d8c2dab8SJeeja KP goto out_free;
1017f231c34cSPierre-Louis Bossart }
1018d8c2dab8SJeeja KP
10194b235c43SVinod Koul skl->pci_id = pci->device;
10204b235c43SVinod Koul
10212e9dc2b6SVinod Koul device_disable_async_suspend(bus->dev);
10222e9dc2b6SVinod Koul
10231169cbf6SPierre-Louis Bossart skl->nhlt = intel_nhlt_init(bus->dev);
102487b2bdf0SJeeja KP
1025979cf59aSWei Yongjun if (skl->nhlt == NULL) {
1026f231c34cSPierre-Louis Bossart #if !IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
1027f231c34cSPierre-Louis Bossart dev_err(bus->dev, "no nhlt info found\n");
1028979cf59aSWei Yongjun err = -ENODEV;
1029ab1b732dSVinod Koul goto out_free;
1030f231c34cSPierre-Louis Bossart #else
1031135ab457SPierre-Louis Bossart dev_warn(bus->dev, "no nhlt info found, continuing to try to enable HDAudio codec\n");
1032f231c34cSPierre-Louis Bossart #endif
1033f231c34cSPierre-Louis Bossart } else {
103487b2bdf0SJeeja KP
10350cf5a171SSubhransu S. Prusty err = skl_nhlt_create_sysfs(skl);
1036f231c34cSPierre-Louis Bossart if (err < 0) {
1037f231c34cSPierre-Louis Bossart dev_err(bus->dev, "skl_nhlt_create_sysfs failed with err: %d\n", err);
10380cf5a171SSubhransu S. Prusty goto out_nhlt_free;
1039f231c34cSPierre-Louis Bossart }
10400cf5a171SSubhransu S. Prusty
10414b235c43SVinod Koul skl_nhlt_update_topology_bin(skl);
10424b235c43SVinod Koul
1043bc2bd45bSSriram Periyasamy /* create device for dsp clk */
1044bc2bd45bSSriram Periyasamy err = skl_clock_device_register(skl);
1045f231c34cSPierre-Louis Bossart if (err < 0) {
1046f231c34cSPierre-Louis Bossart dev_err(bus->dev, "skl_clock_device_register failed with err: %d\n", err);
1047bc2bd45bSSriram Periyasamy goto out_clk_free;
1048f231c34cSPierre-Louis Bossart }
1049f231c34cSPierre-Louis Bossart }
1050f231c34cSPierre-Louis Bossart
1051f231c34cSPierre-Louis Bossart pci_set_drvdata(skl->pci, bus);
1052f231c34cSPierre-Louis Bossart
1053bc2bd45bSSriram Periyasamy
1054752c93aaSPankaj Bharadiya err = skl_find_machine(skl, (void *)pci_id->driver_data);
1055f231c34cSPierre-Louis Bossart if (err < 0) {
1056f231c34cSPierre-Louis Bossart dev_err(bus->dev, "skl_find_machine failed with err: %d\n", err);
1057c286b3f9SJeeja KP goto out_nhlt_free;
1058f231c34cSPierre-Louis Bossart }
1059cc18c5fdSVinod Koul
10602a29b200SJeeja KP err = skl_init_dsp(skl);
10612a29b200SJeeja KP if (err < 0) {
10622a29b200SJeeja KP dev_dbg(bus->dev, "error failed to register dsp\n");
1063752c93aaSPankaj Bharadiya goto out_nhlt_free;
106405057001SJeeja KP }
1065bcc2a2dcSCezary Rojewski skl->enable_miscbdcge = skl_enable_miscbdcge;
1066bcc2a2dcSCezary Rojewski skl->clock_power_gating = skl_clock_power_gating;
10677f981bdcSPierre-Louis Bossart
1068ec8ae570SVinod Koul if (bus->mlcap)
106976f56faeSRakesh Ughreja snd_hdac_ext_bus_get_ml_capabilities(bus);
107005057001SJeeja KP
1071d8c2dab8SJeeja KP /* create device for soc dmic */
1072d8c2dab8SJeeja KP err = skl_dmic_device_register(skl);
1073f231c34cSPierre-Louis Bossart if (err < 0) {
1074f231c34cSPierre-Louis Bossart dev_err(bus->dev, "skl_dmic_device_register failed with err: %d\n", err);
10752a29b200SJeeja KP goto out_dsp_free;
1076f231c34cSPierre-Louis Bossart }
1077d8c2dab8SJeeja KP
1078ab1b732dSVinod Koul schedule_work(&skl->probe_work);
1079d8c2dab8SJeeja KP
1080d8c2dab8SJeeja KP return 0;
1081d8c2dab8SJeeja KP
10822a29b200SJeeja KP out_dsp_free:
10832a29b200SJeeja KP skl_free_dsp(skl);
1084bc2bd45bSSriram Periyasamy out_clk_free:
1085bc2bd45bSSriram Periyasamy skl_clock_device_unregister(skl);
1086c286b3f9SJeeja KP out_nhlt_free:
10879e6c382fSCezary Rojewski if (skl->nhlt)
10881169cbf6SPierre-Louis Bossart intel_nhlt_free(skl->nhlt);
1089d8c2dab8SJeeja KP out_free:
109076f56faeSRakesh Ughreja skl_free(bus);
1091d8c2dab8SJeeja KP
1092d8c2dab8SJeeja KP return err;
1093d8c2dab8SJeeja KP }
1094d8c2dab8SJeeja KP
skl_shutdown(struct pci_dev * pci)1095c5a76a24SJeeja KP static void skl_shutdown(struct pci_dev *pci)
1096c5a76a24SJeeja KP {
109776f56faeSRakesh Ughreja struct hdac_bus *bus = pci_get_drvdata(pci);
1098c5a76a24SJeeja KP struct hdac_stream *s;
1099c5a76a24SJeeja KP struct hdac_ext_stream *stream;
1100bcc2a2dcSCezary Rojewski struct skl_dev *skl;
1101c5a76a24SJeeja KP
110276f56faeSRakesh Ughreja if (!bus)
1103c5a76a24SJeeja KP return;
1104c5a76a24SJeeja KP
110576f56faeSRakesh Ughreja skl = bus_to_skl(bus);
1106c5a76a24SJeeja KP
1107ab1b732dSVinod Koul if (!skl->init_done)
1108c5a76a24SJeeja KP return;
1109c5a76a24SJeeja KP
111017110723SCezary Rojewski snd_hdac_stop_streams(bus);
111117110723SCezary Rojewski snd_hdac_ext_bus_link_power_down_all(bus);
111217110723SCezary Rojewski skl_dsp_sleep(skl->dsp);
111317110723SCezary Rojewski
1114c5a76a24SJeeja KP list_for_each_entry(s, &bus->stream_list, list) {
1115c5a76a24SJeeja KP stream = stream_to_hdac_ext_stream(s);
111676f56faeSRakesh Ughreja snd_hdac_ext_stream_decouple(bus, stream, false);
1117c5a76a24SJeeja KP }
1118c5a76a24SJeeja KP
1119c5a76a24SJeeja KP snd_hdac_bus_stop_chip(bus);
1120c5a76a24SJeeja KP }
1121c5a76a24SJeeja KP
skl_remove(struct pci_dev * pci)1122d8c2dab8SJeeja KP static void skl_remove(struct pci_dev *pci)
1123d8c2dab8SJeeja KP {
112476f56faeSRakesh Ughreja struct hdac_bus *bus = pci_get_drvdata(pci);
1125bcc2a2dcSCezary Rojewski struct skl_dev *skl = bus_to_skl(bus);
1126d8c2dab8SJeeja KP
1127776cb3b8SAmadeusz Sławiński cancel_work_sync(&skl->probe_work);
1128d8018361SVinod Koul
1129d8c2dab8SJeeja KP pm_runtime_get_noresume(&pci->dev);
11307373f481SVinod Koul
11317373f481SVinod Koul /* codec removal, invoke bus_device_remove */
113276f56faeSRakesh Ughreja snd_hdac_ext_bus_device_remove(bus);
11337373f481SVinod Koul
1134d8c2dab8SJeeja KP skl_platform_unregister(&pci->dev);
11352a29b200SJeeja KP skl_free_dsp(skl);
1136cc18c5fdSVinod Koul skl_machine_device_unregister(skl);
1137d8c2dab8SJeeja KP skl_dmic_device_unregister(skl);
1138bc2bd45bSSriram Periyasamy skl_clock_device_unregister(skl);
11390cf5a171SSubhransu S. Prusty skl_nhlt_remove_sysfs(skl);
11409e6c382fSCezary Rojewski if (skl->nhlt)
11411169cbf6SPierre-Louis Bossart intel_nhlt_free(skl->nhlt);
114276f56faeSRakesh Ughreja skl_free(bus);
1143d8c2dab8SJeeja KP }
1144d8c2dab8SJeeja KP
1145d8c2dab8SJeeja KP /* PCI IDs */
1146d8c2dab8SJeeja KP static const struct pci_device_id skl_ids[] = {
114735bc99aaSPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKL)
1148*a2db8743SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_SKL_LP, &snd_soc_acpi_intel_skl_machines) },
114935bc99aaSPierre-Louis Bossart #endif
115035bc99aaSPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_APL)
1151*a2db8743SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_APL, &snd_soc_acpi_intel_bxt_machines) },
115235bc99aaSPierre-Louis Bossart #endif
115335bc99aaSPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_KBL)
1154*a2db8743SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_KBL_LP, &snd_soc_acpi_intel_kbl_machines) },
115535bc99aaSPierre-Louis Bossart #endif
115635bc99aaSPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_GLK)
1157*a2db8743SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_GML, &snd_soc_acpi_intel_glk_machines) },
115835bc99aaSPierre-Louis Bossart #endif
115935bc99aaSPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_CNL)
1160*a2db8743SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_CNL_LP, &snd_soc_acpi_intel_cnl_machines) },
116135bc99aaSPierre-Louis Bossart #endif
116235bc99aaSPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_CFL)
1163*a2db8743SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_CNL_H, &snd_soc_acpi_intel_cnl_machines) },
116435bc99aaSPierre-Louis Bossart #endif
11655f740b24SEvan Green #if IS_ENABLED(CONFIG_SND_SOC_INTEL_CML_LP)
1166*a2db8743SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_CML_LP, &snd_soc_acpi_intel_cnl_machines) },
11675f740b24SEvan Green #endif
11685f740b24SEvan Green #if IS_ENABLED(CONFIG_SND_SOC_INTEL_CML_H)
1169*a2db8743SAmadeusz Sławiński { PCI_DEVICE_DATA(INTEL, HDA_CML_H, &snd_soc_acpi_intel_cnl_machines) },
11705f740b24SEvan Green #endif
1171d8c2dab8SJeeja KP { 0, }
1172d8c2dab8SJeeja KP };
1173d8c2dab8SJeeja KP MODULE_DEVICE_TABLE(pci, skl_ids);
1174d8c2dab8SJeeja KP
1175d8c2dab8SJeeja KP /* pci_driver definition */
1176d8c2dab8SJeeja KP static struct pci_driver skl_driver = {
1177d8c2dab8SJeeja KP .name = KBUILD_MODNAME,
1178d8c2dab8SJeeja KP .id_table = skl_ids,
1179d8c2dab8SJeeja KP .probe = skl_probe,
1180d8c2dab8SJeeja KP .remove = skl_remove,
1181c5a76a24SJeeja KP .shutdown = skl_shutdown,
1182d8c2dab8SJeeja KP .driver = {
1183d8c2dab8SJeeja KP .pm = &skl_pm,
1184d8c2dab8SJeeja KP },
1185d8c2dab8SJeeja KP };
1186d8c2dab8SJeeja KP module_pci_driver(skl_driver);
1187d8c2dab8SJeeja KP
1188d8c2dab8SJeeja KP MODULE_LICENSE("GPL v2");
1189d8c2dab8SJeeja KP MODULE_DESCRIPTION("Intel Skylake ASoC HDA driver");
1190