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 */ 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 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 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 */ 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 */ 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 */ 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 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 */ 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 */ 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 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 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 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 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 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 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 */ 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 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); 390cce6c149SVinod Koul 391cce6c149SVinod Koul /* turn off the links which are off before suspend */ 39276f56faeSRakesh Ughreja list_for_each_entry(hlink, &bus->hlink_list, list) { 393cce6c149SVinod Koul if (!hlink->ref_count) 394cce6c149SVinod Koul snd_hdac_ext_bus_link_power_down(hlink); 395cce6c149SVinod Koul } 396cce6c149SVinod Koul 39776f56faeSRakesh Ughreja if (!bus->cmd_dma_state) 39876f56faeSRakesh Ughreja snd_hdac_bus_stop_cmd_io(bus); 3994557c305SJeeja KP } 4004557c305SJeeja KP 4014557c305SJeeja KP return ret; 40261722f44SJeeja KP } 40361722f44SJeeja KP #endif /* CONFIG_PM_SLEEP */ 40461722f44SJeeja KP 40561722f44SJeeja KP #ifdef CONFIG_PM 40661722f44SJeeja KP static int skl_runtime_suspend(struct device *dev) 40761722f44SJeeja KP { 40861722f44SJeeja KP struct pci_dev *pci = to_pci_dev(dev); 40976f56faeSRakesh Ughreja struct hdac_bus *bus = pci_get_drvdata(pci); 41061722f44SJeeja KP 41161722f44SJeeja KP dev_dbg(bus->dev, "in %s\n", __func__); 41261722f44SJeeja KP 41376f56faeSRakesh Ughreja return _skl_suspend(bus); 41461722f44SJeeja KP } 41561722f44SJeeja KP 416d8c2dab8SJeeja KP static int skl_runtime_resume(struct device *dev) 417d8c2dab8SJeeja KP { 418d8c2dab8SJeeja KP struct pci_dev *pci = to_pci_dev(dev); 41976f56faeSRakesh Ughreja struct hdac_bus *bus = pci_get_drvdata(pci); 420d8c2dab8SJeeja KP 421d8c2dab8SJeeja KP dev_dbg(bus->dev, "in %s\n", __func__); 422d8c2dab8SJeeja KP 42376f56faeSRakesh Ughreja return _skl_resume(bus); 424d8c2dab8SJeeja KP } 425d8c2dab8SJeeja KP #endif /* CONFIG_PM */ 426d8c2dab8SJeeja KP 427d8c2dab8SJeeja KP static const struct dev_pm_ops skl_pm = { 428d8c2dab8SJeeja KP SET_SYSTEM_SLEEP_PM_OPS(skl_suspend, skl_resume) 429d8c2dab8SJeeja KP SET_RUNTIME_PM_OPS(skl_runtime_suspend, skl_runtime_resume, NULL) 4308b4a133cSJayachandran B .suspend_late = skl_suspend_late, 431d8c2dab8SJeeja KP }; 432d8c2dab8SJeeja KP 433d8c2dab8SJeeja KP /* 434d8c2dab8SJeeja KP * destructor 435d8c2dab8SJeeja KP */ 43676f56faeSRakesh Ughreja static int skl_free(struct hdac_bus *bus) 437d8c2dab8SJeeja KP { 438bcc2a2dcSCezary Rojewski struct skl_dev *skl = bus_to_skl(bus); 439d8c2dab8SJeeja KP 440ab1b732dSVinod Koul skl->init_done = 0; /* to be sure */ 441d8c2dab8SJeeja KP 44212054f0cSPierre-Louis Bossart snd_hdac_stop_streams_and_chip(bus); 443d8c2dab8SJeeja KP 444d8c2dab8SJeeja KP if (bus->irq >= 0) 44576f56faeSRakesh Ughreja free_irq(bus->irq, (void *)bus); 446d8c2dab8SJeeja KP snd_hdac_bus_free_stream_pages(bus); 4470839a04eSPierre-Louis Bossart snd_hdac_ext_stream_free_all(bus); 448*7f05ca9aSPierre-Louis Bossart snd_hdac_ext_link_free_all(bus); 449077411e5SVinod Koul 450077411e5SVinod Koul if (bus->remap_addr) 451077411e5SVinod Koul iounmap(bus->remap_addr); 452077411e5SVinod Koul 453d8c2dab8SJeeja KP pci_release_regions(skl->pci); 454d8c2dab8SJeeja KP pci_disable_device(skl->pci); 455d8c2dab8SJeeja KP 45676f56faeSRakesh Ughreja snd_hdac_ext_bus_exit(bus); 457d8c2dab8SJeeja KP 458687ae9e2STakashi Iwai if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { 459687ae9e2STakashi Iwai snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false); 46076f56faeSRakesh Ughreja snd_hdac_i915_exit(bus); 461687ae9e2STakashi Iwai } 462ab1b732dSVinod Koul 463d8c2dab8SJeeja KP return 0; 464d8c2dab8SJeeja KP } 465d8c2dab8SJeeja KP 466bc2bd45bSSriram Periyasamy /* 467bc2bd45bSSriram Periyasamy * For each ssp there are 3 clocks (mclk/sclk/sclkfs). 468bc2bd45bSSriram Periyasamy * e.g. for ssp0, clocks will be named as 469bc2bd45bSSriram Periyasamy * "ssp0_mclk", "ssp0_sclk", "ssp0_sclkfs" 470bc2bd45bSSriram Periyasamy * So for skl+, there are 6 ssps, so 18 clocks will be created. 471bc2bd45bSSriram Periyasamy */ 472bc2bd45bSSriram Periyasamy static struct skl_ssp_clk skl_ssp_clks[] = { 473bc2bd45bSSriram Periyasamy {.name = "ssp0_mclk"}, {.name = "ssp1_mclk"}, {.name = "ssp2_mclk"}, 474bc2bd45bSSriram Periyasamy {.name = "ssp3_mclk"}, {.name = "ssp4_mclk"}, {.name = "ssp5_mclk"}, 475bc2bd45bSSriram Periyasamy {.name = "ssp0_sclk"}, {.name = "ssp1_sclk"}, {.name = "ssp2_sclk"}, 476bc2bd45bSSriram Periyasamy {.name = "ssp3_sclk"}, {.name = "ssp4_sclk"}, {.name = "ssp5_sclk"}, 477bc2bd45bSSriram Periyasamy {.name = "ssp0_sclkfs"}, {.name = "ssp1_sclkfs"}, 478bc2bd45bSSriram Periyasamy {.name = "ssp2_sclkfs"}, 479bc2bd45bSSriram Periyasamy {.name = "ssp3_sclkfs"}, {.name = "ssp4_sclkfs"}, 480bc2bd45bSSriram Periyasamy {.name = "ssp5_sclkfs"}, 481bc2bd45bSSriram Periyasamy }; 482bc2bd45bSSriram Periyasamy 483bcc2a2dcSCezary Rojewski static struct snd_soc_acpi_mach *skl_find_hda_machine(struct skl_dev *skl, 4849cdae435SRakesh Ughreja struct snd_soc_acpi_mach *machines) 4859cdae435SRakesh Ughreja { 4869cdae435SRakesh Ughreja struct snd_soc_acpi_mach *mach; 4879cdae435SRakesh Ughreja 4889cdae435SRakesh Ughreja /* point to common table */ 4899cdae435SRakesh Ughreja mach = snd_soc_acpi_intel_hda_machines; 4909cdae435SRakesh Ughreja 4919cdae435SRakesh Ughreja /* all entries in the machine table use the same firmware */ 4929cdae435SRakesh Ughreja mach->fw_filename = machines->fw_filename; 4939cdae435SRakesh Ughreja 4949cdae435SRakesh Ughreja return mach; 4959cdae435SRakesh Ughreja } 4969cdae435SRakesh Ughreja 497bcc2a2dcSCezary Rojewski static int skl_find_machine(struct skl_dev *skl, void *driver_data) 498cc18c5fdSVinod Koul { 49976f56faeSRakesh Ughreja struct hdac_bus *bus = skl_to_bus(skl); 5007feb2f78SPierre-Louis Bossart struct snd_soc_acpi_mach *mach = driver_data; 501752c93aaSPankaj Bharadiya struct skl_machine_pdata *pdata; 502cc18c5fdSVinod Koul 5037feb2f78SPierre-Louis Bossart mach = snd_soc_acpi_find_machine(mach); 5049cdae435SRakesh Ughreja if (!mach) { 5059cdae435SRakesh Ughreja dev_dbg(bus->dev, "No matching I2S machine driver found\n"); 5069cdae435SRakesh Ughreja mach = skl_find_hda_machine(skl, driver_data); 5079cdae435SRakesh Ughreja if (!mach) { 508cc18c5fdSVinod Koul dev_err(bus->dev, "No matching machine driver found\n"); 509cc18c5fdSVinod Koul return -ENODEV; 510cc18c5fdSVinod Koul } 5119cdae435SRakesh Ughreja } 512752c93aaSPankaj Bharadiya 513752c93aaSPankaj Bharadiya skl->mach = mach; 514aecf6fd8SVinod Koul skl->fw_name = mach->fw_filename; 5155f15f267SPierre-Louis Bossart pdata = mach->pdata; 516752c93aaSPankaj Bharadiya 5175f15f267SPierre-Louis Bossart if (pdata) { 518752c93aaSPankaj Bharadiya skl->use_tplg_pcm = pdata->use_tplg_pcm; 5191169cbf6SPierre-Louis Bossart mach->mach_params.dmic_num = 5201169cbf6SPierre-Louis Bossart intel_nhlt_get_dmic_geo(&skl->pci->dev, 5211169cbf6SPierre-Louis Bossart skl->nhlt); 5225f15f267SPierre-Louis Bossart } 523752c93aaSPankaj Bharadiya 524752c93aaSPankaj Bharadiya return 0; 525752c93aaSPankaj Bharadiya } 526752c93aaSPankaj Bharadiya 527bcc2a2dcSCezary Rojewski static int skl_machine_device_register(struct skl_dev *skl) 528752c93aaSPankaj Bharadiya { 529752c93aaSPankaj Bharadiya struct snd_soc_acpi_mach *mach = skl->mach; 5309cdae435SRakesh Ughreja struct hdac_bus *bus = skl_to_bus(skl); 531752c93aaSPankaj Bharadiya struct platform_device *pdev; 532752c93aaSPankaj Bharadiya int ret; 533cc18c5fdSVinod Koul 534cc18c5fdSVinod Koul pdev = platform_device_alloc(mach->drv_name, -1); 535cc18c5fdSVinod Koul if (pdev == NULL) { 536cc18c5fdSVinod Koul dev_err(bus->dev, "platform device alloc failed\n"); 537cc18c5fdSVinod Koul return -EIO; 538cc18c5fdSVinod Koul } 539cc18c5fdSVinod Koul 5405a619b9eSPierre-Louis Bossart mach->mach_params.platform = dev_name(bus->dev); 5415a619b9eSPierre-Louis Bossart mach->mach_params.codec_mask = bus->codec_mask; 5425a619b9eSPierre-Louis Bossart 5435a619b9eSPierre-Louis Bossart ret = platform_device_add_data(pdev, (const void *)mach, sizeof(*mach)); 5445a619b9eSPierre-Louis Bossart if (ret) { 5455a619b9eSPierre-Louis Bossart dev_err(bus->dev, "failed to add machine device platform data\n"); 5465a619b9eSPierre-Louis Bossart platform_device_put(pdev); 5475a619b9eSPierre-Louis Bossart return ret; 5485a619b9eSPierre-Louis Bossart } 5495a619b9eSPierre-Louis Bossart 550cc18c5fdSVinod Koul ret = platform_device_add(pdev); 551cc18c5fdSVinod Koul if (ret) { 552cc18c5fdSVinod Koul dev_err(bus->dev, "failed to add machine device\n"); 553cc18c5fdSVinod Koul platform_device_put(pdev); 554cc18c5fdSVinod Koul return -EIO; 555cc18c5fdSVinod Koul } 556f65cf7d6SYong Zhi 557f65cf7d6SYong Zhi 558cc18c5fdSVinod Koul skl->i2s_dev = pdev; 559cc18c5fdSVinod Koul 560cc18c5fdSVinod Koul return 0; 561cc18c5fdSVinod Koul } 562cc18c5fdSVinod Koul 563bcc2a2dcSCezary Rojewski static void skl_machine_device_unregister(struct skl_dev *skl) 564cc18c5fdSVinod Koul { 565cc18c5fdSVinod Koul if (skl->i2s_dev) 566cc18c5fdSVinod Koul platform_device_unregister(skl->i2s_dev); 567cc18c5fdSVinod Koul } 568cc18c5fdSVinod Koul 569bcc2a2dcSCezary Rojewski static int skl_dmic_device_register(struct skl_dev *skl) 570d8c2dab8SJeeja KP { 57176f56faeSRakesh Ughreja struct hdac_bus *bus = skl_to_bus(skl); 572d8c2dab8SJeeja KP struct platform_device *pdev; 573d8c2dab8SJeeja KP int ret; 574d8c2dab8SJeeja KP 575d8c2dab8SJeeja KP /* SKL has one dmic port, so allocate dmic device for this */ 576d8c2dab8SJeeja KP pdev = platform_device_alloc("dmic-codec", -1); 577d8c2dab8SJeeja KP if (!pdev) { 578d8c2dab8SJeeja KP dev_err(bus->dev, "failed to allocate dmic device\n"); 579d8c2dab8SJeeja KP return -ENOMEM; 580d8c2dab8SJeeja KP } 581d8c2dab8SJeeja KP 582d8c2dab8SJeeja KP ret = platform_device_add(pdev); 583d8c2dab8SJeeja KP if (ret) { 584d8c2dab8SJeeja KP dev_err(bus->dev, "failed to add dmic device: %d\n", ret); 585d8c2dab8SJeeja KP platform_device_put(pdev); 586d8c2dab8SJeeja KP return ret; 587d8c2dab8SJeeja KP } 588d8c2dab8SJeeja KP skl->dmic_dev = pdev; 589d8c2dab8SJeeja KP 590d8c2dab8SJeeja KP return 0; 591d8c2dab8SJeeja KP } 592d8c2dab8SJeeja KP 593bcc2a2dcSCezary Rojewski static void skl_dmic_device_unregister(struct skl_dev *skl) 594d8c2dab8SJeeja KP { 595d8c2dab8SJeeja KP if (skl->dmic_dev) 596d8c2dab8SJeeja KP platform_device_unregister(skl->dmic_dev); 597d8c2dab8SJeeja KP } 598d8c2dab8SJeeja KP 599bc2bd45bSSriram Periyasamy static struct skl_clk_parent_src skl_clk_src[] = { 600bc2bd45bSSriram Periyasamy { .clk_id = SKL_XTAL, .name = "xtal" }, 601bc2bd45bSSriram Periyasamy { .clk_id = SKL_CARDINAL, .name = "cardinal", .rate = 24576000 }, 602bc2bd45bSSriram Periyasamy { .clk_id = SKL_PLL, .name = "pll", .rate = 96000000 }, 603bc2bd45bSSriram Periyasamy }; 604bc2bd45bSSriram Periyasamy 605bc2bd45bSSriram Periyasamy struct skl_clk_parent_src *skl_get_parent_clk(u8 clk_id) 606bc2bd45bSSriram Periyasamy { 607bc2bd45bSSriram Periyasamy unsigned int i; 608bc2bd45bSSriram Periyasamy 609bc2bd45bSSriram Periyasamy for (i = 0; i < ARRAY_SIZE(skl_clk_src); i++) { 610bc2bd45bSSriram Periyasamy if (skl_clk_src[i].clk_id == clk_id) 611bc2bd45bSSriram Periyasamy return &skl_clk_src[i]; 612bc2bd45bSSriram Periyasamy } 613bc2bd45bSSriram Periyasamy 614bc2bd45bSSriram Periyasamy return NULL; 615bc2bd45bSSriram Periyasamy } 616bc2bd45bSSriram Periyasamy 6178e79ec98SGuneshwor Singh static void init_skl_xtal_rate(int pci_id) 618bc2bd45bSSriram Periyasamy { 619bc2bd45bSSriram Periyasamy switch (pci_id) { 620bc2bd45bSSriram Periyasamy case 0x9d70: 621bc2bd45bSSriram Periyasamy case 0x9d71: 622bc2bd45bSSriram Periyasamy skl_clk_src[0].rate = 24000000; 623bc2bd45bSSriram Periyasamy return; 624bc2bd45bSSriram Periyasamy 625bc2bd45bSSriram Periyasamy default: 626bc2bd45bSSriram Periyasamy skl_clk_src[0].rate = 19200000; 627bc2bd45bSSriram Periyasamy return; 628bc2bd45bSSriram Periyasamy } 629bc2bd45bSSriram Periyasamy } 630bc2bd45bSSriram Periyasamy 631bcc2a2dcSCezary Rojewski static int skl_clock_device_register(struct skl_dev *skl) 632bc2bd45bSSriram Periyasamy { 633bc2bd45bSSriram Periyasamy struct platform_device_info pdevinfo = {NULL}; 634bc2bd45bSSriram Periyasamy struct skl_clk_pdata *clk_pdata; 635bc2bd45bSSriram Periyasamy 6369e6c382fSCezary Rojewski if (!skl->nhlt) 6379e6c382fSCezary Rojewski return 0; 6389e6c382fSCezary Rojewski 639bc2bd45bSSriram Periyasamy clk_pdata = devm_kzalloc(&skl->pci->dev, sizeof(*clk_pdata), 640bc2bd45bSSriram Periyasamy GFP_KERNEL); 641bc2bd45bSSriram Periyasamy if (!clk_pdata) 642bc2bd45bSSriram Periyasamy return -ENOMEM; 643bc2bd45bSSriram Periyasamy 644bc2bd45bSSriram Periyasamy init_skl_xtal_rate(skl->pci->device); 645bc2bd45bSSriram Periyasamy 646bc2bd45bSSriram Periyasamy clk_pdata->parent_clks = skl_clk_src; 647bc2bd45bSSriram Periyasamy clk_pdata->ssp_clks = skl_ssp_clks; 648bc2bd45bSSriram Periyasamy clk_pdata->num_clks = ARRAY_SIZE(skl_ssp_clks); 649bc2bd45bSSriram Periyasamy 650bc2bd45bSSriram Periyasamy /* Query NHLT to fill the rates and parent */ 651bc2bd45bSSriram Periyasamy skl_get_clks(skl, clk_pdata->ssp_clks); 652bc2bd45bSSriram Periyasamy clk_pdata->pvt_data = skl; 653bc2bd45bSSriram Periyasamy 654bc2bd45bSSriram Periyasamy /* Register Platform device */ 655bc2bd45bSSriram Periyasamy pdevinfo.parent = &skl->pci->dev; 656bc2bd45bSSriram Periyasamy pdevinfo.id = -1; 657bc2bd45bSSriram Periyasamy pdevinfo.name = "skl-ssp-clk"; 658bc2bd45bSSriram Periyasamy pdevinfo.data = clk_pdata; 659bc2bd45bSSriram Periyasamy pdevinfo.size_data = sizeof(*clk_pdata); 660bc2bd45bSSriram Periyasamy skl->clk_dev = platform_device_register_full(&pdevinfo); 661bc2bd45bSSriram Periyasamy return PTR_ERR_OR_ZERO(skl->clk_dev); 662bc2bd45bSSriram Periyasamy } 663bc2bd45bSSriram Periyasamy 664bcc2a2dcSCezary Rojewski static void skl_clock_device_unregister(struct skl_dev *skl) 665bc2bd45bSSriram Periyasamy { 666bc2bd45bSSriram Periyasamy if (skl->clk_dev) 667bc2bd45bSSriram Periyasamy platform_device_unregister(skl->clk_dev); 668bc2bd45bSSriram Periyasamy } 669bc2bd45bSSriram Periyasamy 6708c4e7c2eSPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) 6718c4e7c2eSPierre-Louis Bossart 6726bae5ea9SRakesh Ughreja #define IDISP_INTEL_VENDOR_ID 0x80860000 6736bae5ea9SRakesh Ughreja 6746bae5ea9SRakesh Ughreja /* 6756bae5ea9SRakesh Ughreja * load the legacy codec driver 6766bae5ea9SRakesh Ughreja */ 6776bae5ea9SRakesh Ughreja static void load_codec_module(struct hda_codec *codec) 6786bae5ea9SRakesh Ughreja { 6796bae5ea9SRakesh Ughreja #ifdef MODULE 6806bae5ea9SRakesh Ughreja char modalias[MODULE_NAME_LEN]; 6816bae5ea9SRakesh Ughreja const char *mod = NULL; 6826bae5ea9SRakesh Ughreja 6836bae5ea9SRakesh Ughreja snd_hdac_codec_modalias(&codec->core, modalias, sizeof(modalias)); 6846bae5ea9SRakesh Ughreja mod = modalias; 6856bae5ea9SRakesh Ughreja dev_dbg(&codec->core.dev, "loading %s codec module\n", mod); 6866bae5ea9SRakesh Ughreja request_module(mod); 6876bae5ea9SRakesh Ughreja #endif 6886bae5ea9SRakesh Ughreja } 6896bae5ea9SRakesh Ughreja 6908c4e7c2eSPierre-Louis Bossart #endif /* CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC */ 6918c4e7c2eSPierre-Louis Bossart 692e4746d94SCezary Rojewski static void skl_codec_device_exit(struct device *dev) 693e4746d94SCezary Rojewski { 694e4746d94SCezary Rojewski snd_hdac_device_exit(dev_to_hdac_dev(dev)); 695e4746d94SCezary Rojewski } 696e4746d94SCezary Rojewski 6973fd63658SCezary Rojewski static struct hda_codec *skl_codec_device_init(struct hdac_bus *bus, int addr) 698e4746d94SCezary Rojewski { 699e4746d94SCezary Rojewski struct hda_codec *codec; 700e4746d94SCezary Rojewski int ret; 701e4746d94SCezary Rojewski 702e4746d94SCezary Rojewski codec = snd_hda_codec_device_init(to_hda_bus(bus), addr, "ehdaudio%dD%d", bus->idx, addr); 703e4746d94SCezary Rojewski if (IS_ERR(codec)) { 704e4746d94SCezary Rojewski dev_err(bus->dev, "device init failed for hdac device\n"); 705e4746d94SCezary Rojewski return codec; 706e4746d94SCezary Rojewski } 707e4746d94SCezary Rojewski 708e4746d94SCezary Rojewski codec->core.type = HDA_DEV_ASOC; 709e4746d94SCezary Rojewski codec->core.dev.release = skl_codec_device_exit; 710e4746d94SCezary Rojewski 711e4746d94SCezary Rojewski ret = snd_hdac_device_register(&codec->core); 712e4746d94SCezary Rojewski if (ret) { 713e4746d94SCezary Rojewski dev_err(bus->dev, "failed to register hdac device\n"); 714e4746d94SCezary Rojewski snd_hdac_device_exit(&codec->core); 715e4746d94SCezary Rojewski return ERR_PTR(ret); 716e4746d94SCezary Rojewski } 717e4746d94SCezary Rojewski 718e4746d94SCezary Rojewski return codec; 719e4746d94SCezary Rojewski } 720e4746d94SCezary Rojewski 721d8c2dab8SJeeja KP /* 722d8c2dab8SJeeja KP * Probe the given codec address 723d8c2dab8SJeeja KP */ 72476f56faeSRakesh Ughreja static int probe_codec(struct hdac_bus *bus, int addr) 725d8c2dab8SJeeja KP { 726d8c2dab8SJeeja KP unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) | 727d8c2dab8SJeeja KP (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; 728e6a33532SDan Carpenter unsigned int res = -1; 7298c4e7c2eSPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) 730a74bfc9eSGaosheng Cui struct skl_dev *skl = bus_to_skl(bus); 7316bae5ea9SRakesh Ughreja struct hdac_hda_priv *hda_codec; 7328c4e7c2eSPierre-Louis Bossart #endif 7333fd63658SCezary Rojewski struct hda_codec *codec; 734d8c2dab8SJeeja KP 735d8c2dab8SJeeja KP mutex_lock(&bus->cmd_mutex); 736d8c2dab8SJeeja KP snd_hdac_bus_send_cmd(bus, cmd); 737d8c2dab8SJeeja KP snd_hdac_bus_get_response(bus, addr, &res); 738d8c2dab8SJeeja KP mutex_unlock(&bus->cmd_mutex); 739d8c2dab8SJeeja KP if (res == -1) 740d8c2dab8SJeeja KP return -EIO; 74100deadb5SRakesh Ughreja dev_dbg(bus->dev, "codec #%d probed OK: %x\n", addr, res); 742d8c2dab8SJeeja KP 7438c4e7c2eSPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) 7446bae5ea9SRakesh Ughreja hda_codec = devm_kzalloc(&skl->pci->dev, sizeof(*hda_codec), 7456bae5ea9SRakesh Ughreja GFP_KERNEL); 7466bae5ea9SRakesh Ughreja if (!hda_codec) 7476298542fSRakesh Ughreja return -ENOMEM; 7486298542fSRakesh Ughreja 7493fd63658SCezary Rojewski codec = skl_codec_device_init(bus, addr); 7503fd63658SCezary Rojewski if (IS_ERR(codec)) 7513fd63658SCezary Rojewski return PTR_ERR(codec); 7526bae5ea9SRakesh Ughreja 7533fd63658SCezary Rojewski hda_codec->codec = codec; 7543fd63658SCezary Rojewski dev_set_drvdata(&codec->core.dev, hda_codec); 7556bae5ea9SRakesh Ughreja 7566bae5ea9SRakesh Ughreja /* use legacy bus only for HDA codecs, idisp uses ext bus */ 7576bae5ea9SRakesh Ughreja if ((res & 0xFFFF0000) != IDISP_INTEL_VENDOR_ID) { 7583fd63658SCezary Rojewski codec->core.type = HDA_DEV_LEGACY; 7593fd63658SCezary Rojewski load_codec_module(hda_codec->codec); 7606bae5ea9SRakesh Ughreja } 7616bae5ea9SRakesh Ughreja return 0; 7628c4e7c2eSPierre-Louis Bossart #else 7633fd63658SCezary Rojewski codec = skl_codec_device_init(bus, addr); 7643fd63658SCezary Rojewski return PTR_ERR_OR_ZERO(codec); 7658c4e7c2eSPierre-Louis Bossart #endif /* CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC */ 766d8c2dab8SJeeja KP } 767d8c2dab8SJeeja KP 768d8c2dab8SJeeja KP /* Codec initialization */ 76976f56faeSRakesh Ughreja static void skl_codec_create(struct hdac_bus *bus) 770d8c2dab8SJeeja KP { 771d8c2dab8SJeeja KP int c, max_slots; 772d8c2dab8SJeeja KP 773d8c2dab8SJeeja KP max_slots = HDA_MAX_CODECS; 774d8c2dab8SJeeja KP 775d8c2dab8SJeeja KP /* First try to probe all given codec slots */ 776d8c2dab8SJeeja KP for (c = 0; c < max_slots; c++) { 777d8c2dab8SJeeja KP if ((bus->codec_mask & (1 << c))) { 77876f56faeSRakesh Ughreja if (probe_codec(bus, c) < 0) { 779d8c2dab8SJeeja KP /* 780d8c2dab8SJeeja KP * Some BIOSen give you wrong codec addresses 781d8c2dab8SJeeja KP * that don't exist 782d8c2dab8SJeeja KP */ 783d8c2dab8SJeeja KP dev_warn(bus->dev, 784d8c2dab8SJeeja KP "Codec #%d probe error; disabling it...\n", c); 785d8c2dab8SJeeja KP bus->codec_mask &= ~(1 << c); 786d8c2dab8SJeeja KP /* 787d8c2dab8SJeeja KP * More badly, accessing to a non-existing 788d8c2dab8SJeeja KP * codec often screws up the controller bus, 789d8c2dab8SJeeja KP * and disturbs the further communications. 790d8c2dab8SJeeja KP * Thus if an error occurs during probing, 791d8c2dab8SJeeja KP * better to reset the controller bus to get 792d8c2dab8SJeeja KP * back to the sanity state. 793d8c2dab8SJeeja KP */ 794d8c2dab8SJeeja KP snd_hdac_bus_stop_chip(bus); 7950c8ba9d2SJayachandran B skl_init_chip(bus, true); 796d8c2dab8SJeeja KP } 797d8c2dab8SJeeja KP } 798d8c2dab8SJeeja KP } 799d8c2dab8SJeeja KP } 800d8c2dab8SJeeja KP 801ab1b732dSVinod Koul static int skl_i915_init(struct hdac_bus *bus) 802ab1b732dSVinod Koul { 803ab1b732dSVinod Koul int err; 804ab1b732dSVinod Koul 805ab1b732dSVinod Koul /* 806ab1b732dSVinod Koul * The HDMI codec is in GPU so we need to ensure that it is powered 807ab1b732dSVinod Koul * up and ready for probe 808ab1b732dSVinod Koul */ 809ab1b732dSVinod Koul err = snd_hdac_i915_init(bus); 810ab1b732dSVinod Koul if (err < 0) 811ab1b732dSVinod Koul return err; 812ab1b732dSVinod Koul 8134f799e73STakashi Iwai snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true); 814ab1b732dSVinod Koul 8154f799e73STakashi Iwai return 0; 816ab1b732dSVinod Koul } 817ab1b732dSVinod Koul 818ab1b732dSVinod Koul static void skl_probe_work(struct work_struct *work) 819ab1b732dSVinod Koul { 820bcc2a2dcSCezary Rojewski struct skl_dev *skl = container_of(work, struct skl_dev, probe_work); 82176f56faeSRakesh Ughreja struct hdac_bus *bus = skl_to_bus(skl); 822ca841843SGuennadi Liakhovetski struct hdac_ext_link *hlink; 823ab1b732dSVinod Koul int err; 824ab1b732dSVinod Koul 825ab1b732dSVinod Koul if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { 826ab1b732dSVinod Koul err = skl_i915_init(bus); 827ab1b732dSVinod Koul if (err < 0) 828ab1b732dSVinod Koul return; 829ab1b732dSVinod Koul } 830ab1b732dSVinod Koul 8312ef81057SCezary Rojewski skl_init_pci(skl); 8322ef81057SCezary Rojewski skl_dum_set(bus); 8332ef81057SCezary Rojewski 834ab1b732dSVinod Koul err = skl_init_chip(bus, true); 835ab1b732dSVinod Koul if (err < 0) { 836ab1b732dSVinod Koul dev_err(bus->dev, "Init chip failed with err: %d\n", err); 837ab1b732dSVinod Koul goto out_err; 838ab1b732dSVinod Koul } 839ab1b732dSVinod Koul 840ab1b732dSVinod Koul /* codec detection */ 841ab1b732dSVinod Koul if (!bus->codec_mask) 842ab1b732dSVinod Koul dev_info(bus->dev, "no hda codecs found!\n"); 843ab1b732dSVinod Koul 844ab1b732dSVinod Koul /* create codec instances */ 84576f56faeSRakesh Ughreja skl_codec_create(bus); 846ab1b732dSVinod Koul 847752c93aaSPankaj Bharadiya /* register platform dai and controls */ 848752c93aaSPankaj Bharadiya err = skl_platform_register(bus->dev); 849752c93aaSPankaj Bharadiya if (err < 0) { 850752c93aaSPankaj Bharadiya dev_err(bus->dev, "platform register failed: %d\n", err); 851687ae9e2STakashi Iwai goto out_err; 852752c93aaSPankaj Bharadiya } 853752c93aaSPankaj Bharadiya 854752c93aaSPankaj Bharadiya err = skl_machine_device_register(skl); 855752c93aaSPankaj Bharadiya if (err < 0) { 856752c93aaSPankaj Bharadiya dev_err(bus->dev, "machine register failed: %d\n", err); 857752c93aaSPankaj Bharadiya goto out_err; 858752c93aaSPankaj Bharadiya } 859752c93aaSPankaj Bharadiya 8604c10473dSPierre-Louis Bossart /* 8614c10473dSPierre-Louis Bossart * we are done probing so decrement link counts 8624c10473dSPierre-Louis Bossart */ 8634c10473dSPierre-Louis Bossart list_for_each_entry(hlink, &bus->hlink_list, list) 8644c10473dSPierre-Louis Bossart snd_hdac_ext_bus_link_put(bus, hlink); 8654c10473dSPierre-Louis Bossart 8664f799e73STakashi Iwai if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) 8674f799e73STakashi Iwai snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false); 868ab1b732dSVinod Koul 869ab1b732dSVinod Koul /* configure PM */ 870ab1b732dSVinod Koul pm_runtime_put_noidle(bus->dev); 871ab1b732dSVinod Koul pm_runtime_allow(bus->dev); 872ab1b732dSVinod Koul skl->init_done = 1; 873ab1b732dSVinod Koul 874ab1b732dSVinod Koul return; 875ab1b732dSVinod Koul 876ab1b732dSVinod Koul out_err: 877ab1b732dSVinod Koul if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) 8784f799e73STakashi Iwai snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false); 879ab1b732dSVinod Koul } 880ab1b732dSVinod Koul 881d8c2dab8SJeeja KP /* 882d8c2dab8SJeeja KP * constructor 883d8c2dab8SJeeja KP */ 884d8c2dab8SJeeja KP static int skl_create(struct pci_dev *pci, 885bcc2a2dcSCezary Rojewski struct skl_dev **rskl) 886d8c2dab8SJeeja KP { 8876bae5ea9SRakesh Ughreja struct hdac_ext_bus_ops *ext_ops = NULL; 888bcc2a2dcSCezary Rojewski struct skl_dev *skl; 88976f56faeSRakesh Ughreja struct hdac_bus *bus; 89000deadb5SRakesh Ughreja struct hda_bus *hbus; 891d8c2dab8SJeeja KP int err; 892d8c2dab8SJeeja KP 893d8c2dab8SJeeja KP *rskl = NULL; 894d8c2dab8SJeeja KP 895d8c2dab8SJeeja KP err = pci_enable_device(pci); 896d8c2dab8SJeeja KP if (err < 0) 897d8c2dab8SJeeja KP return err; 898d8c2dab8SJeeja KP 899d8c2dab8SJeeja KP skl = devm_kzalloc(&pci->dev, sizeof(*skl), GFP_KERNEL); 900d8c2dab8SJeeja KP if (!skl) { 901d8c2dab8SJeeja KP pci_disable_device(pci); 902d8c2dab8SJeeja KP return -ENOMEM; 903d8c2dab8SJeeja KP } 90476f56faeSRakesh Ughreja 90500deadb5SRakesh Ughreja hbus = skl_to_hbus(skl); 90676f56faeSRakesh Ughreja bus = skl_to_bus(skl); 9076bae5ea9SRakesh Ughreja 908776cb3b8SAmadeusz Sławiński INIT_LIST_HEAD(&skl->ppl_list); 909776cb3b8SAmadeusz Sławiński INIT_LIST_HEAD(&skl->bind_list); 910776cb3b8SAmadeusz Sławiński 9118c4e7c2eSPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) 9126bae5ea9SRakesh Ughreja ext_ops = snd_soc_hdac_hda_get_ops(); 9136bae5ea9SRakesh Ughreja #endif 914ae91a189STakashi Iwai snd_hdac_ext_bus_init(bus, &pci->dev, NULL, ext_ops); 91576f56faeSRakesh Ughreja bus->use_posbuf = 1; 916d8c2dab8SJeeja KP skl->pci = pci; 917ab1b732dSVinod Koul INIT_WORK(&skl->probe_work, skl_probe_work); 91876f56faeSRakesh Ughreja bus->bdl_pos_adj = 0; 919d8c2dab8SJeeja KP 92000deadb5SRakesh Ughreja mutex_init(&hbus->prepare_mutex); 92100deadb5SRakesh Ughreja hbus->pci = pci; 92200deadb5SRakesh Ughreja hbus->mixer_assigned = -1; 92300deadb5SRakesh Ughreja hbus->modelname = "sklbus"; 92400deadb5SRakesh Ughreja 925d8c2dab8SJeeja KP *rskl = skl; 926d8c2dab8SJeeja KP 927d8c2dab8SJeeja KP return 0; 928d8c2dab8SJeeja KP } 929d8c2dab8SJeeja KP 93076f56faeSRakesh Ughreja static int skl_first_init(struct hdac_bus *bus) 931d8c2dab8SJeeja KP { 932bcc2a2dcSCezary Rojewski struct skl_dev *skl = bus_to_skl(bus); 933d8c2dab8SJeeja KP struct pci_dev *pci = skl->pci; 934d8c2dab8SJeeja KP int err; 935d8c2dab8SJeeja KP unsigned short gcap; 936d8c2dab8SJeeja KP int cp_streams, pb_streams, start_idx; 937d8c2dab8SJeeja KP 938d8c2dab8SJeeja KP err = pci_request_regions(pci, "Skylake HD audio"); 939d8c2dab8SJeeja KP if (err < 0) 940d8c2dab8SJeeja KP return err; 941d8c2dab8SJeeja KP 942d8c2dab8SJeeja KP bus->addr = pci_resource_start(pci, 0); 943d8c2dab8SJeeja KP bus->remap_addr = pci_ioremap_bar(pci, 0); 944d8c2dab8SJeeja KP if (bus->remap_addr == NULL) { 945d8c2dab8SJeeja KP dev_err(bus->dev, "ioremap error\n"); 946d8c2dab8SJeeja KP return -ENXIO; 947d8c2dab8SJeeja KP } 948d8c2dab8SJeeja KP 949ec8ae570SVinod Koul snd_hdac_bus_parse_capabilities(bus); 95005057001SJeeja KP 951fa11ab56SPierre-Louis Bossart /* check if PPCAP exists */ 952fa11ab56SPierre-Louis Bossart if (!bus->ppcap) { 953135ab457SPierre-Louis Bossart dev_err(bus->dev, "bus ppcap not set, HDAudio or DSP not present?\n"); 954fa11ab56SPierre-Louis Bossart return -ENODEV; 955fa11ab56SPierre-Louis Bossart } 956fa11ab56SPierre-Louis Bossart 957542cedecSYu Zhao if (skl_acquire_irq(bus, 0) < 0) 958542cedecSYu Zhao return -EBUSY; 959542cedecSYu Zhao 960d8c2dab8SJeeja KP pci_set_master(pci); 961542cedecSYu Zhao synchronize_irq(bus->irq); 962d8c2dab8SJeeja KP 963d8c2dab8SJeeja KP gcap = snd_hdac_chip_readw(bus, GCAP); 964d8c2dab8SJeeja KP dev_dbg(bus->dev, "chipset global capabilities = 0x%x\n", gcap); 965d8c2dab8SJeeja KP 966fa11ab56SPierre-Louis Bossart /* read number of streams from GCAP register */ 967fa11ab56SPierre-Louis Bossart cp_streams = (gcap >> 8) & 0x0f; 968fa11ab56SPierre-Louis Bossart pb_streams = (gcap >> 12) & 0x0f; 969fa11ab56SPierre-Louis Bossart 970fa11ab56SPierre-Louis Bossart if (!pb_streams && !cp_streams) { 971fa11ab56SPierre-Louis Bossart dev_err(bus->dev, "no streams found in GCAP definitions?\n"); 972fa11ab56SPierre-Louis Bossart return -EIO; 973fa11ab56SPierre-Louis Bossart } 974fa11ab56SPierre-Louis Bossart 975fa11ab56SPierre-Louis Bossart bus->num_streams = cp_streams + pb_streams; 976fa11ab56SPierre-Louis Bossart 977d8c2dab8SJeeja KP /* allow 64bit DMA address if supported by H/W */ 978d3afb002STakashi Iwai if (dma_set_mask_and_coherent(bus->dev, DMA_BIT_MASK(64))) 979d3afb002STakashi Iwai dma_set_mask_and_coherent(bus->dev, DMA_BIT_MASK(32)); 980c22a8086STakashi Iwai dma_set_max_seg_size(bus->dev, UINT_MAX); 981d8c2dab8SJeeja KP 982d8c2dab8SJeeja KP /* initialize streams */ 983d8c2dab8SJeeja KP snd_hdac_ext_stream_init_all 98476f56faeSRakesh Ughreja (bus, 0, cp_streams, SNDRV_PCM_STREAM_CAPTURE); 985d8c2dab8SJeeja KP start_idx = cp_streams; 986d8c2dab8SJeeja KP snd_hdac_ext_stream_init_all 98776f56faeSRakesh Ughreja (bus, start_idx, pb_streams, SNDRV_PCM_STREAM_PLAYBACK); 988d8c2dab8SJeeja KP 989d8c2dab8SJeeja KP err = snd_hdac_bus_alloc_stream_pages(bus); 990d8c2dab8SJeeja KP if (err < 0) 991d8c2dab8SJeeja KP return err; 992d8c2dab8SJeeja KP 9932ef81057SCezary Rojewski return 0; 994d8c2dab8SJeeja KP } 995d8c2dab8SJeeja KP 996d8c2dab8SJeeja KP static int skl_probe(struct pci_dev *pci, 997d8c2dab8SJeeja KP const struct pci_device_id *pci_id) 998d8c2dab8SJeeja KP { 999bcc2a2dcSCezary Rojewski struct skl_dev *skl; 1000d8c2dab8SJeeja KP struct hdac_bus *bus = NULL; 1001d8c2dab8SJeeja KP int err; 1002d8c2dab8SJeeja KP 1003d82b51c8SPierre-Louis Bossart switch (skl_pci_binding) { 1004d82b51c8SPierre-Louis Bossart case SND_SKL_PCI_BIND_AUTO: 100582d9d54aSJaroslav Kysela err = snd_intel_dsp_driver_probe(pci); 100682d9d54aSJaroslav Kysela if (err != SND_INTEL_DSP_DRIVER_ANY && 100782d9d54aSJaroslav Kysela err != SND_INTEL_DSP_DRIVER_SST) 1008d82b51c8SPierre-Louis Bossart return -ENODEV; 1009d82b51c8SPierre-Louis Bossart break; 1010d82b51c8SPierre-Louis Bossart case SND_SKL_PCI_BIND_LEGACY: 1011135ab457SPierre-Louis Bossart dev_info(&pci->dev, "Module parameter forced binding with HDAudio legacy, aborting probe\n"); 1012d82b51c8SPierre-Louis Bossart return -ENODEV; 1013d82b51c8SPierre-Louis Bossart case SND_SKL_PCI_BIND_ASOC: 1014d82b51c8SPierre-Louis Bossart dev_info(&pci->dev, "Module parameter forced binding with SKL driver, bypassed detection logic\n"); 1015d82b51c8SPierre-Louis Bossart break; 1016d82b51c8SPierre-Louis Bossart default: 1017d82b51c8SPierre-Louis Bossart dev_err(&pci->dev, "invalid value for skl_pci_binding module parameter, ignored\n"); 1018d82b51c8SPierre-Louis Bossart break; 1019d82b51c8SPierre-Louis Bossart } 1020d82b51c8SPierre-Louis Bossart 1021d8c2dab8SJeeja KP /* we use ext core ops, so provide NULL for ops here */ 102219abfefdSTakashi Iwai err = skl_create(pci, &skl); 1023d8c2dab8SJeeja KP if (err < 0) 1024d8c2dab8SJeeja KP return err; 1025d8c2dab8SJeeja KP 102676f56faeSRakesh Ughreja bus = skl_to_bus(skl); 1027d8c2dab8SJeeja KP 102876f56faeSRakesh Ughreja err = skl_first_init(bus); 1029f231c34cSPierre-Louis Bossart if (err < 0) { 1030f231c34cSPierre-Louis Bossart dev_err(bus->dev, "skl_first_init failed with err: %d\n", err); 1031d8c2dab8SJeeja KP goto out_free; 1032f231c34cSPierre-Louis Bossart } 1033d8c2dab8SJeeja KP 10344b235c43SVinod Koul skl->pci_id = pci->device; 10354b235c43SVinod Koul 10362e9dc2b6SVinod Koul device_disable_async_suspend(bus->dev); 10372e9dc2b6SVinod Koul 10381169cbf6SPierre-Louis Bossart skl->nhlt = intel_nhlt_init(bus->dev); 103987b2bdf0SJeeja KP 1040979cf59aSWei Yongjun if (skl->nhlt == NULL) { 1041f231c34cSPierre-Louis Bossart #if !IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) 1042f231c34cSPierre-Louis Bossart dev_err(bus->dev, "no nhlt info found\n"); 1043979cf59aSWei Yongjun err = -ENODEV; 1044ab1b732dSVinod Koul goto out_free; 1045f231c34cSPierre-Louis Bossart #else 1046135ab457SPierre-Louis Bossart dev_warn(bus->dev, "no nhlt info found, continuing to try to enable HDAudio codec\n"); 1047f231c34cSPierre-Louis Bossart #endif 1048f231c34cSPierre-Louis Bossart } else { 104987b2bdf0SJeeja KP 10500cf5a171SSubhransu S. Prusty err = skl_nhlt_create_sysfs(skl); 1051f231c34cSPierre-Louis Bossart if (err < 0) { 1052f231c34cSPierre-Louis Bossart dev_err(bus->dev, "skl_nhlt_create_sysfs failed with err: %d\n", err); 10530cf5a171SSubhransu S. Prusty goto out_nhlt_free; 1054f231c34cSPierre-Louis Bossart } 10550cf5a171SSubhransu S. Prusty 10564b235c43SVinod Koul skl_nhlt_update_topology_bin(skl); 10574b235c43SVinod Koul 1058bc2bd45bSSriram Periyasamy /* create device for dsp clk */ 1059bc2bd45bSSriram Periyasamy err = skl_clock_device_register(skl); 1060f231c34cSPierre-Louis Bossart if (err < 0) { 1061f231c34cSPierre-Louis Bossart dev_err(bus->dev, "skl_clock_device_register failed with err: %d\n", err); 1062bc2bd45bSSriram Periyasamy goto out_clk_free; 1063f231c34cSPierre-Louis Bossart } 1064f231c34cSPierre-Louis Bossart } 1065f231c34cSPierre-Louis Bossart 1066f231c34cSPierre-Louis Bossart pci_set_drvdata(skl->pci, bus); 1067f231c34cSPierre-Louis Bossart 1068bc2bd45bSSriram Periyasamy 1069752c93aaSPankaj Bharadiya err = skl_find_machine(skl, (void *)pci_id->driver_data); 1070f231c34cSPierre-Louis Bossart if (err < 0) { 1071f231c34cSPierre-Louis Bossart dev_err(bus->dev, "skl_find_machine failed with err: %d\n", err); 1072c286b3f9SJeeja KP goto out_nhlt_free; 1073f231c34cSPierre-Louis Bossart } 1074cc18c5fdSVinod Koul 10752a29b200SJeeja KP err = skl_init_dsp(skl); 10762a29b200SJeeja KP if (err < 0) { 10772a29b200SJeeja KP dev_dbg(bus->dev, "error failed to register dsp\n"); 1078752c93aaSPankaj Bharadiya goto out_nhlt_free; 107905057001SJeeja KP } 1080bcc2a2dcSCezary Rojewski skl->enable_miscbdcge = skl_enable_miscbdcge; 1081bcc2a2dcSCezary Rojewski skl->clock_power_gating = skl_clock_power_gating; 10827f981bdcSPierre-Louis Bossart 1083ec8ae570SVinod Koul if (bus->mlcap) 108476f56faeSRakesh Ughreja snd_hdac_ext_bus_get_ml_capabilities(bus); 108505057001SJeeja KP 1086d8c2dab8SJeeja KP /* create device for soc dmic */ 1087d8c2dab8SJeeja KP err = skl_dmic_device_register(skl); 1088f231c34cSPierre-Louis Bossart if (err < 0) { 1089f231c34cSPierre-Louis Bossart dev_err(bus->dev, "skl_dmic_device_register failed with err: %d\n", err); 10902a29b200SJeeja KP goto out_dsp_free; 1091f231c34cSPierre-Louis Bossart } 1092d8c2dab8SJeeja KP 1093ab1b732dSVinod Koul schedule_work(&skl->probe_work); 1094d8c2dab8SJeeja KP 1095d8c2dab8SJeeja KP return 0; 1096d8c2dab8SJeeja KP 10972a29b200SJeeja KP out_dsp_free: 10982a29b200SJeeja KP skl_free_dsp(skl); 1099bc2bd45bSSriram Periyasamy out_clk_free: 1100bc2bd45bSSriram Periyasamy skl_clock_device_unregister(skl); 1101c286b3f9SJeeja KP out_nhlt_free: 11029e6c382fSCezary Rojewski if (skl->nhlt) 11031169cbf6SPierre-Louis Bossart intel_nhlt_free(skl->nhlt); 1104d8c2dab8SJeeja KP out_free: 110576f56faeSRakesh Ughreja skl_free(bus); 1106d8c2dab8SJeeja KP 1107d8c2dab8SJeeja KP return err; 1108d8c2dab8SJeeja KP } 1109d8c2dab8SJeeja KP 1110c5a76a24SJeeja KP static void skl_shutdown(struct pci_dev *pci) 1111c5a76a24SJeeja KP { 111276f56faeSRakesh Ughreja struct hdac_bus *bus = pci_get_drvdata(pci); 1113c5a76a24SJeeja KP struct hdac_stream *s; 1114c5a76a24SJeeja KP struct hdac_ext_stream *stream; 1115bcc2a2dcSCezary Rojewski struct skl_dev *skl; 1116c5a76a24SJeeja KP 111776f56faeSRakesh Ughreja if (!bus) 1118c5a76a24SJeeja KP return; 1119c5a76a24SJeeja KP 112076f56faeSRakesh Ughreja skl = bus_to_skl(bus); 1121c5a76a24SJeeja KP 1122ab1b732dSVinod Koul if (!skl->init_done) 1123c5a76a24SJeeja KP return; 1124c5a76a24SJeeja KP 112512054f0cSPierre-Louis Bossart snd_hdac_stop_streams_and_chip(bus); 1126c5a76a24SJeeja KP list_for_each_entry(s, &bus->stream_list, list) { 1127c5a76a24SJeeja KP stream = stream_to_hdac_ext_stream(s); 112876f56faeSRakesh Ughreja snd_hdac_ext_stream_decouple(bus, stream, false); 1129c5a76a24SJeeja KP } 1130c5a76a24SJeeja KP 1131c5a76a24SJeeja KP snd_hdac_bus_stop_chip(bus); 1132c5a76a24SJeeja KP } 1133c5a76a24SJeeja KP 1134d8c2dab8SJeeja KP static void skl_remove(struct pci_dev *pci) 1135d8c2dab8SJeeja KP { 113676f56faeSRakesh Ughreja struct hdac_bus *bus = pci_get_drvdata(pci); 1137bcc2a2dcSCezary Rojewski struct skl_dev *skl = bus_to_skl(bus); 1138d8c2dab8SJeeja KP 1139776cb3b8SAmadeusz Sławiński cancel_work_sync(&skl->probe_work); 1140d8018361SVinod Koul 1141d8c2dab8SJeeja KP pm_runtime_get_noresume(&pci->dev); 11427373f481SVinod Koul 11437373f481SVinod Koul /* codec removal, invoke bus_device_remove */ 114476f56faeSRakesh Ughreja snd_hdac_ext_bus_device_remove(bus); 11457373f481SVinod Koul 1146d8c2dab8SJeeja KP skl_platform_unregister(&pci->dev); 11472a29b200SJeeja KP skl_free_dsp(skl); 1148cc18c5fdSVinod Koul skl_machine_device_unregister(skl); 1149d8c2dab8SJeeja KP skl_dmic_device_unregister(skl); 1150bc2bd45bSSriram Periyasamy skl_clock_device_unregister(skl); 11510cf5a171SSubhransu S. Prusty skl_nhlt_remove_sysfs(skl); 11529e6c382fSCezary Rojewski if (skl->nhlt) 11531169cbf6SPierre-Louis Bossart intel_nhlt_free(skl->nhlt); 115476f56faeSRakesh Ughreja skl_free(bus); 1155d8c2dab8SJeeja KP } 1156d8c2dab8SJeeja KP 1157d8c2dab8SJeeja KP /* PCI IDs */ 1158d8c2dab8SJeeja KP static const struct pci_device_id skl_ids[] = { 115935bc99aaSPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKL) 1160d8c2dab8SJeeja KP /* Sunrise Point-LP */ 1161cc18c5fdSVinod Koul { PCI_DEVICE(0x8086, 0x9d70), 1162cbaa7f0bSPierre-Louis Bossart .driver_data = (unsigned long)&snd_soc_acpi_intel_skl_machines}, 116335bc99aaSPierre-Louis Bossart #endif 116435bc99aaSPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_APL) 1165b379b1faSSenthilnathan Veppur /* BXT-P */ 1166b379b1faSSenthilnathan Veppur { PCI_DEVICE(0x8086, 0x5a98), 1167cbaa7f0bSPierre-Louis Bossart .driver_data = (unsigned long)&snd_soc_acpi_intel_bxt_machines}, 116835bc99aaSPierre-Louis Bossart #endif 116935bc99aaSPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_KBL) 1170451dfb5fSVinod Koul /* KBL */ 1171451dfb5fSVinod Koul { PCI_DEVICE(0x8086, 0x9D71), 1172cbaa7f0bSPierre-Louis Bossart .driver_data = (unsigned long)&snd_soc_acpi_intel_kbl_machines}, 117335bc99aaSPierre-Louis Bossart #endif 117435bc99aaSPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_GLK) 117525504863SVinod Koul /* GLK */ 117625504863SVinod Koul { PCI_DEVICE(0x8086, 0x3198), 1177cbaa7f0bSPierre-Louis Bossart .driver_data = (unsigned long)&snd_soc_acpi_intel_glk_machines}, 117835bc99aaSPierre-Louis Bossart #endif 117935bc99aaSPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_CNL) 118086d7ce3dSGuneshwor Singh /* CNL */ 118186d7ce3dSGuneshwor Singh { PCI_DEVICE(0x8086, 0x9dc8), 1182cbaa7f0bSPierre-Louis Bossart .driver_data = (unsigned long)&snd_soc_acpi_intel_cnl_machines}, 118335bc99aaSPierre-Louis Bossart #endif 118435bc99aaSPierre-Louis Bossart #if IS_ENABLED(CONFIG_SND_SOC_INTEL_CFL) 1185e6b98db9STakashi Iwai /* CFL */ 1186e6b98db9STakashi Iwai { PCI_DEVICE(0x8086, 0xa348), 1187e6b98db9STakashi Iwai .driver_data = (unsigned long)&snd_soc_acpi_intel_cnl_machines}, 118835bc99aaSPierre-Louis Bossart #endif 11895f740b24SEvan Green #if IS_ENABLED(CONFIG_SND_SOC_INTEL_CML_LP) 11905f740b24SEvan Green /* CML-LP */ 11915f740b24SEvan Green { PCI_DEVICE(0x8086, 0x02c8), 11925f740b24SEvan Green .driver_data = (unsigned long)&snd_soc_acpi_intel_cnl_machines}, 11935f740b24SEvan Green #endif 11945f740b24SEvan Green #if IS_ENABLED(CONFIG_SND_SOC_INTEL_CML_H) 11955f740b24SEvan Green /* CML-H */ 11965f740b24SEvan Green { PCI_DEVICE(0x8086, 0x06c8), 11975f740b24SEvan Green .driver_data = (unsigned long)&snd_soc_acpi_intel_cnl_machines}, 11985f740b24SEvan Green #endif 1199d8c2dab8SJeeja KP { 0, } 1200d8c2dab8SJeeja KP }; 1201d8c2dab8SJeeja KP MODULE_DEVICE_TABLE(pci, skl_ids); 1202d8c2dab8SJeeja KP 1203d8c2dab8SJeeja KP /* pci_driver definition */ 1204d8c2dab8SJeeja KP static struct pci_driver skl_driver = { 1205d8c2dab8SJeeja KP .name = KBUILD_MODNAME, 1206d8c2dab8SJeeja KP .id_table = skl_ids, 1207d8c2dab8SJeeja KP .probe = skl_probe, 1208d8c2dab8SJeeja KP .remove = skl_remove, 1209c5a76a24SJeeja KP .shutdown = skl_shutdown, 1210d8c2dab8SJeeja KP .driver = { 1211d8c2dab8SJeeja KP .pm = &skl_pm, 1212d8c2dab8SJeeja KP }, 1213d8c2dab8SJeeja KP }; 1214d8c2dab8SJeeja KP module_pci_driver(skl_driver); 1215d8c2dab8SJeeja KP 1216d8c2dab8SJeeja KP MODULE_LICENSE("GPL v2"); 1217d8c2dab8SJeeja KP MODULE_DESCRIPTION("Intel Skylake ASoC HDA driver"); 1218