1d8c2dab8SJeeja KP /* 2d8c2dab8SJeeja KP * skl.c - Implementation of ASoC Intel SKL HD Audio driver 3d8c2dab8SJeeja KP * 4d8c2dab8SJeeja KP * Copyright (C) 2014-2015 Intel Corp 5d8c2dab8SJeeja KP * Author: Jeeja KP <jeeja.kp@intel.com> 6d8c2dab8SJeeja KP * 7d8c2dab8SJeeja KP * Derived mostly from Intel HDA driver with following copyrights: 8d8c2dab8SJeeja KP * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de> 9d8c2dab8SJeeja KP * PeiSen Hou <pshou@realtek.com.tw> 10d8c2dab8SJeeja KP * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11d8c2dab8SJeeja KP * 12d8c2dab8SJeeja KP * This program is free software; you can redistribute it and/or modify 13d8c2dab8SJeeja KP * it under the terms of the GNU General Public License as published by 14d8c2dab8SJeeja KP * the Free Software Foundation; version 2 of the License. 15d8c2dab8SJeeja KP * 16d8c2dab8SJeeja KP * This program is distributed in the hope that it will be useful, but 17d8c2dab8SJeeja KP * WITHOUT ANY WARRANTY; without even the implied warranty of 18d8c2dab8SJeeja KP * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19d8c2dab8SJeeja KP * General Public License for more details. 20d8c2dab8SJeeja KP * 21d8c2dab8SJeeja KP * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 22d8c2dab8SJeeja KP */ 23d8c2dab8SJeeja KP 24d8c2dab8SJeeja KP #include <linux/module.h> 25d8c2dab8SJeeja KP #include <linux/pci.h> 26d8c2dab8SJeeja KP #include <linux/pm_runtime.h> 27d8c2dab8SJeeja KP #include <linux/platform_device.h> 28d8018361SVinod Koul #include <linux/firmware.h> 29d8c2dab8SJeeja KP #include <sound/pcm.h> 30cc18c5fdSVinod Koul #include "../common/sst-acpi.h" 316980c057SVinod Koul #include <sound/hda_register.h> 326980c057SVinod Koul #include <sound/hdaudio.h> 336980c057SVinod Koul #include <sound/hda_i915.h> 34d8c2dab8SJeeja KP #include "skl.h" 350c8ba9d2SJayachandran B #include "skl-sst-dsp.h" 360c8ba9d2SJayachandran B #include "skl-sst-ipc.h" 37d8c2dab8SJeeja KP 38f65cf7d6SYong Zhi static struct skl_machine_pdata skl_dmic_data; 39f65cf7d6SYong Zhi 40d8c2dab8SJeeja KP /* 41d8c2dab8SJeeja KP * initialize the PCI registers 42d8c2dab8SJeeja KP */ 43d8c2dab8SJeeja KP static void skl_update_pci_byte(struct pci_dev *pci, unsigned int reg, 44d8c2dab8SJeeja KP unsigned char mask, unsigned char val) 45d8c2dab8SJeeja KP { 46d8c2dab8SJeeja KP unsigned char data; 47d8c2dab8SJeeja KP 48d8c2dab8SJeeja KP pci_read_config_byte(pci, reg, &data); 49d8c2dab8SJeeja KP data &= ~mask; 50d8c2dab8SJeeja KP data |= (val & mask); 51d8c2dab8SJeeja KP pci_write_config_byte(pci, reg, data); 52d8c2dab8SJeeja KP } 53d8c2dab8SJeeja KP 54d8c2dab8SJeeja KP static void skl_init_pci(struct skl *skl) 55d8c2dab8SJeeja KP { 56d8c2dab8SJeeja KP struct hdac_ext_bus *ebus = &skl->ebus; 57d8c2dab8SJeeja KP 58d8c2dab8SJeeja KP /* 59d8c2dab8SJeeja KP * Clear bits 0-2 of PCI register TCSEL (at offset 0x44) 60d8c2dab8SJeeja KP * TCSEL == Traffic Class Select Register, which sets PCI express QOS 61d8c2dab8SJeeja KP * Ensuring these bits are 0 clears playback static on some HD Audio 62d8c2dab8SJeeja KP * codecs. 63d8c2dab8SJeeja KP * The PCI register TCSEL is defined in the Intel manuals. 64d8c2dab8SJeeja KP */ 65d8c2dab8SJeeja KP dev_dbg(ebus_to_hbus(ebus)->dev, "Clearing TCSEL\n"); 66d8c2dab8SJeeja KP skl_update_pci_byte(skl->pci, AZX_PCIREG_TCSEL, 0x07, 0); 67d8c2dab8SJeeja KP } 68d8c2dab8SJeeja KP 690c8ba9d2SJayachandran B static void update_pci_dword(struct pci_dev *pci, 700c8ba9d2SJayachandran B unsigned int reg, u32 mask, u32 val) 710c8ba9d2SJayachandran B { 720c8ba9d2SJayachandran B u32 data = 0; 730c8ba9d2SJayachandran B 740c8ba9d2SJayachandran B pci_read_config_dword(pci, reg, &data); 750c8ba9d2SJayachandran B data &= ~mask; 760c8ba9d2SJayachandran B data |= (val & mask); 770c8ba9d2SJayachandran B pci_write_config_dword(pci, reg, data); 780c8ba9d2SJayachandran B } 790c8ba9d2SJayachandran B 800c8ba9d2SJayachandran B /* 810c8ba9d2SJayachandran B * skl_enable_miscbdcge - enable/dsiable CGCTL.MISCBDCGE bits 820c8ba9d2SJayachandran B * 830c8ba9d2SJayachandran B * @dev: device pointer 840c8ba9d2SJayachandran B * @enable: enable/disable flag 850c8ba9d2SJayachandran B */ 860c8ba9d2SJayachandran B static void skl_enable_miscbdcge(struct device *dev, bool enable) 870c8ba9d2SJayachandran B { 880c8ba9d2SJayachandran B struct pci_dev *pci = to_pci_dev(dev); 890c8ba9d2SJayachandran B u32 val; 900c8ba9d2SJayachandran B 910c8ba9d2SJayachandran B val = enable ? AZX_CGCTL_MISCBDCGE_MASK : 0; 920c8ba9d2SJayachandran B 930c8ba9d2SJayachandran B update_pci_dword(pci, AZX_PCIREG_CGCTL, AZX_CGCTL_MISCBDCGE_MASK, val); 940c8ba9d2SJayachandran B } 950c8ba9d2SJayachandran B 960c8ba9d2SJayachandran B /* 970c8ba9d2SJayachandran B * While performing reset, controller may not come back properly causing 980c8ba9d2SJayachandran B * issues, so recommendation is to set CGCTL.MISCBDCGE to 0 then do reset 990c8ba9d2SJayachandran B * (init chip) and then again set CGCTL.MISCBDCGE to 1 1000c8ba9d2SJayachandran B */ 1010c8ba9d2SJayachandran B static int skl_init_chip(struct hdac_bus *bus, bool full_reset) 1020c8ba9d2SJayachandran B { 1030c8ba9d2SJayachandran B int ret; 1040c8ba9d2SJayachandran B 1050c8ba9d2SJayachandran B skl_enable_miscbdcge(bus->dev, false); 1060c8ba9d2SJayachandran B ret = snd_hdac_bus_init_chip(bus, full_reset); 1070c8ba9d2SJayachandran B skl_enable_miscbdcge(bus->dev, true); 1080c8ba9d2SJayachandran B 1090c8ba9d2SJayachandran B return ret; 1100c8ba9d2SJayachandran B } 1110c8ba9d2SJayachandran B 112d8c2dab8SJeeja KP /* called from IRQ */ 113d8c2dab8SJeeja KP static void skl_stream_update(struct hdac_bus *bus, struct hdac_stream *hstr) 114d8c2dab8SJeeja KP { 115d8c2dab8SJeeja KP snd_pcm_period_elapsed(hstr->substream); 116d8c2dab8SJeeja KP } 117d8c2dab8SJeeja KP 118d8c2dab8SJeeja KP static irqreturn_t skl_interrupt(int irq, void *dev_id) 119d8c2dab8SJeeja KP { 120d8c2dab8SJeeja KP struct hdac_ext_bus *ebus = dev_id; 121d8c2dab8SJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 122d8c2dab8SJeeja KP u32 status; 123d8c2dab8SJeeja KP 124d8c2dab8SJeeja KP if (!pm_runtime_active(bus->dev)) 125d8c2dab8SJeeja KP return IRQ_NONE; 126d8c2dab8SJeeja KP 127d8c2dab8SJeeja KP spin_lock(&bus->reg_lock); 128d8c2dab8SJeeja KP 129d8c2dab8SJeeja KP status = snd_hdac_chip_readl(bus, INTSTS); 130d8c2dab8SJeeja KP if (status == 0 || status == 0xffffffff) { 131d8c2dab8SJeeja KP spin_unlock(&bus->reg_lock); 132d8c2dab8SJeeja KP return IRQ_NONE; 133d8c2dab8SJeeja KP } 134d8c2dab8SJeeja KP 135d8c2dab8SJeeja KP /* clear rirb int */ 136d8c2dab8SJeeja KP status = snd_hdac_chip_readb(bus, RIRBSTS); 137d8c2dab8SJeeja KP if (status & RIRB_INT_MASK) { 138d8c2dab8SJeeja KP if (status & RIRB_INT_RESPONSE) 139d8c2dab8SJeeja KP snd_hdac_bus_update_rirb(bus); 140d8c2dab8SJeeja KP snd_hdac_chip_writeb(bus, RIRBSTS, RIRB_INT_MASK); 141d8c2dab8SJeeja KP } 142d8c2dab8SJeeja KP 143d8c2dab8SJeeja KP spin_unlock(&bus->reg_lock); 144d8c2dab8SJeeja KP 145d8c2dab8SJeeja KP return snd_hdac_chip_readl(bus, INTSTS) ? IRQ_WAKE_THREAD : IRQ_HANDLED; 146d8c2dab8SJeeja KP } 147d8c2dab8SJeeja KP 148d8c2dab8SJeeja KP static irqreturn_t skl_threaded_handler(int irq, void *dev_id) 149d8c2dab8SJeeja KP { 150d8c2dab8SJeeja KP struct hdac_ext_bus *ebus = dev_id; 151d8c2dab8SJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 152d8c2dab8SJeeja KP u32 status; 153d8c2dab8SJeeja KP 154d8c2dab8SJeeja KP status = snd_hdac_chip_readl(bus, INTSTS); 155d8c2dab8SJeeja KP 156d8c2dab8SJeeja KP snd_hdac_bus_handle_stream_irq(bus, status, skl_stream_update); 157d8c2dab8SJeeja KP 158d8c2dab8SJeeja KP return IRQ_HANDLED; 159d8c2dab8SJeeja KP } 160d8c2dab8SJeeja KP 161d8c2dab8SJeeja KP static int skl_acquire_irq(struct hdac_ext_bus *ebus, int do_disconnect) 162d8c2dab8SJeeja KP { 163d8c2dab8SJeeja KP struct skl *skl = ebus_to_skl(ebus); 164d8c2dab8SJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 165d8c2dab8SJeeja KP int ret; 166d8c2dab8SJeeja KP 167d8c2dab8SJeeja KP ret = request_threaded_irq(skl->pci->irq, skl_interrupt, 168d8c2dab8SJeeja KP skl_threaded_handler, 169d8c2dab8SJeeja KP IRQF_SHARED, 170d8c2dab8SJeeja KP KBUILD_MODNAME, ebus); 171d8c2dab8SJeeja KP if (ret) { 172d8c2dab8SJeeja KP dev_err(bus->dev, 173d8c2dab8SJeeja KP "unable to grab IRQ %d, disabling device\n", 174d8c2dab8SJeeja KP skl->pci->irq); 175d8c2dab8SJeeja KP return ret; 176d8c2dab8SJeeja KP } 177d8c2dab8SJeeja KP 178d8c2dab8SJeeja KP bus->irq = skl->pci->irq; 179d8c2dab8SJeeja KP pci_intx(skl->pci, 1); 180d8c2dab8SJeeja KP 181d8c2dab8SJeeja KP return 0; 182d8c2dab8SJeeja KP } 183d8c2dab8SJeeja KP 184d8c2dab8SJeeja KP #ifdef CONFIG_PM 18561722f44SJeeja KP static int _skl_suspend(struct hdac_ext_bus *ebus) 186d8c2dab8SJeeja KP { 1872a29b200SJeeja KP struct skl *skl = ebus_to_skl(ebus); 18861722f44SJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 1892a29b200SJeeja KP int ret; 190d8c2dab8SJeeja KP 19101bb84b5SJeeja KP snd_hdac_ext_bus_link_power_down_all(ebus); 19201bb84b5SJeeja KP 1932a29b200SJeeja KP ret = skl_suspend_dsp(skl); 1942a29b200SJeeja KP if (ret < 0) 1952a29b200SJeeja KP return ret; 196d8c2dab8SJeeja KP 197d8c2dab8SJeeja KP snd_hdac_bus_stop_chip(bus); 1980c8ba9d2SJayachandran B skl_enable_miscbdcge(bus->dev, false); 199d8c2dab8SJeeja KP snd_hdac_bus_enter_link_reset(bus); 2000c8ba9d2SJayachandran B skl_enable_miscbdcge(bus->dev, true); 201d8c2dab8SJeeja KP 202d8c2dab8SJeeja KP return 0; 203d8c2dab8SJeeja KP } 204d8c2dab8SJeeja KP 20561722f44SJeeja KP static int _skl_resume(struct hdac_ext_bus *ebus) 20661722f44SJeeja KP { 20761722f44SJeeja KP struct skl *skl = ebus_to_skl(ebus); 20861722f44SJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 20961722f44SJeeja KP 21061722f44SJeeja KP skl_init_pci(skl); 2110c8ba9d2SJayachandran B skl_init_chip(bus, true); 21261722f44SJeeja KP 21361722f44SJeeja KP return skl_resume_dsp(skl); 21461722f44SJeeja KP } 21561722f44SJeeja KP #endif 21661722f44SJeeja KP 21761722f44SJeeja KP #ifdef CONFIG_PM_SLEEP 21861722f44SJeeja KP /* 21961722f44SJeeja KP * power management 22061722f44SJeeja KP */ 22161722f44SJeeja KP static int skl_suspend(struct device *dev) 22261722f44SJeeja KP { 22361722f44SJeeja KP struct pci_dev *pci = to_pci_dev(dev); 22461722f44SJeeja KP struct hdac_ext_bus *ebus = pci_get_drvdata(pci); 2254557c305SJeeja KP struct skl *skl = ebus_to_skl(ebus); 2261f4956fdSJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 227af037412SSubhransu S. Prusty int ret = 0; 22861722f44SJeeja KP 2294557c305SJeeja KP /* 2304557c305SJeeja KP * Do not suspend if streams which are marked ignore suspend are 2314557c305SJeeja KP * running, we need to save the state for these and continue 2324557c305SJeeja KP */ 2334557c305SJeeja KP if (skl->supend_active) { 234cce6c149SVinod Koul /* turn off the links and stop the CORB/RIRB DMA if it is On */ 235c2e20cd8SVinod Koul snd_hdac_ext_bus_link_power_down_all(ebus); 236cce6c149SVinod Koul 237cce6c149SVinod Koul if (ebus->cmd_dma_state) 238cce6c149SVinod Koul snd_hdac_bus_stop_cmd_io(&ebus->bus); 239cce6c149SVinod Koul 2401f4956fdSJeeja KP enable_irq_wake(bus->irq); 2414557c305SJeeja KP pci_save_state(pci); 2424557c305SJeeja KP pci_disable_device(pci); 2434557c305SJeeja KP } else { 244af037412SSubhransu S. Prusty ret = _skl_suspend(ebus); 245af037412SSubhransu S. Prusty if (ret < 0) 246af037412SSubhransu S. Prusty return ret; 24761722f44SJeeja KP } 248af037412SSubhransu S. Prusty 249af037412SSubhransu S. Prusty if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { 250af037412SSubhransu S. Prusty ret = snd_hdac_display_power(bus, false); 251af037412SSubhransu S. Prusty if (ret < 0) 252af037412SSubhransu S. Prusty dev_err(bus->dev, 253af037412SSubhransu S. Prusty "Cannot turn OFF display power on i915\n"); 254af037412SSubhransu S. Prusty } 255af037412SSubhransu S. Prusty 256af037412SSubhransu S. Prusty return ret; 2574557c305SJeeja KP } 25861722f44SJeeja KP 25961722f44SJeeja KP static int skl_resume(struct device *dev) 26061722f44SJeeja KP { 26161722f44SJeeja KP struct pci_dev *pci = to_pci_dev(dev); 26261722f44SJeeja KP struct hdac_ext_bus *ebus = pci_get_drvdata(pci); 2634557c305SJeeja KP struct skl *skl = ebus_to_skl(ebus); 2641f4956fdSJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 265cce6c149SVinod Koul struct hdac_ext_link *hlink = NULL; 2664557c305SJeeja KP int ret; 26761722f44SJeeja KP 2686980c057SVinod Koul /* Turned OFF in HDMI codec driver after codec reconfiguration */ 2696980c057SVinod Koul if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { 2706980c057SVinod Koul ret = snd_hdac_display_power(bus, true); 2716980c057SVinod Koul if (ret < 0) { 2726980c057SVinod Koul dev_err(bus->dev, 2736980c057SVinod Koul "Cannot turn on display power on i915\n"); 2746980c057SVinod Koul return ret; 2756980c057SVinod Koul } 2766980c057SVinod Koul } 2776980c057SVinod Koul 2784557c305SJeeja KP /* 2794557c305SJeeja KP * resume only when we are not in suspend active, otherwise need to 2804557c305SJeeja KP * restore the device 2814557c305SJeeja KP */ 2824557c305SJeeja KP if (skl->supend_active) { 2834557c305SJeeja KP pci_restore_state(pci); 2844557c305SJeeja KP ret = pci_enable_device(pci); 285c2e20cd8SVinod Koul snd_hdac_ext_bus_link_power_up_all(ebus); 2861f4956fdSJeeja KP disable_irq_wake(bus->irq); 287cce6c149SVinod Koul /* 288cce6c149SVinod Koul * turn On the links which are On before active suspend 289cce6c149SVinod Koul * and start the CORB/RIRB DMA if On before 290cce6c149SVinod Koul * active suspend. 291cce6c149SVinod Koul */ 292cce6c149SVinod Koul list_for_each_entry(hlink, &ebus->hlink_list, list) { 293cce6c149SVinod Koul if (hlink->ref_count) 294cce6c149SVinod Koul snd_hdac_ext_bus_link_power_up(hlink); 295cce6c149SVinod Koul } 296cce6c149SVinod Koul 297cce6c149SVinod Koul if (ebus->cmd_dma_state) 298cce6c149SVinod Koul snd_hdac_bus_init_cmd_io(&ebus->bus); 2994557c305SJeeja KP } else { 3004557c305SJeeja KP ret = _skl_resume(ebus); 301cce6c149SVinod Koul 302cce6c149SVinod Koul /* turn off the links which are off before suspend */ 303cce6c149SVinod Koul list_for_each_entry(hlink, &ebus->hlink_list, list) { 304cce6c149SVinod Koul if (!hlink->ref_count) 305cce6c149SVinod Koul snd_hdac_ext_bus_link_power_down(hlink); 306cce6c149SVinod Koul } 307cce6c149SVinod Koul 308cce6c149SVinod Koul if (!ebus->cmd_dma_state) 309cce6c149SVinod Koul snd_hdac_bus_stop_cmd_io(&ebus->bus); 3104557c305SJeeja KP } 3114557c305SJeeja KP 3124557c305SJeeja KP return ret; 31361722f44SJeeja KP } 31461722f44SJeeja KP #endif /* CONFIG_PM_SLEEP */ 31561722f44SJeeja KP 31661722f44SJeeja KP #ifdef CONFIG_PM 31761722f44SJeeja KP static int skl_runtime_suspend(struct device *dev) 31861722f44SJeeja KP { 31961722f44SJeeja KP struct pci_dev *pci = to_pci_dev(dev); 32061722f44SJeeja KP struct hdac_ext_bus *ebus = pci_get_drvdata(pci); 32161722f44SJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 32261722f44SJeeja KP 32361722f44SJeeja KP dev_dbg(bus->dev, "in %s\n", __func__); 32461722f44SJeeja KP 32561722f44SJeeja KP return _skl_suspend(ebus); 32661722f44SJeeja KP } 32761722f44SJeeja KP 328d8c2dab8SJeeja KP static int skl_runtime_resume(struct device *dev) 329d8c2dab8SJeeja KP { 330d8c2dab8SJeeja KP struct pci_dev *pci = to_pci_dev(dev); 331d8c2dab8SJeeja KP struct hdac_ext_bus *ebus = pci_get_drvdata(pci); 332d8c2dab8SJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 333d8c2dab8SJeeja KP 334d8c2dab8SJeeja KP dev_dbg(bus->dev, "in %s\n", __func__); 335d8c2dab8SJeeja KP 33661722f44SJeeja KP return _skl_resume(ebus); 337d8c2dab8SJeeja KP } 338d8c2dab8SJeeja KP #endif /* CONFIG_PM */ 339d8c2dab8SJeeja KP 340d8c2dab8SJeeja KP static const struct dev_pm_ops skl_pm = { 341d8c2dab8SJeeja KP SET_SYSTEM_SLEEP_PM_OPS(skl_suspend, skl_resume) 342d8c2dab8SJeeja KP SET_RUNTIME_PM_OPS(skl_runtime_suspend, skl_runtime_resume, NULL) 343d8c2dab8SJeeja KP }; 344d8c2dab8SJeeja KP 345d8c2dab8SJeeja KP /* 346d8c2dab8SJeeja KP * destructor 347d8c2dab8SJeeja KP */ 348d8c2dab8SJeeja KP static int skl_free(struct hdac_ext_bus *ebus) 349d8c2dab8SJeeja KP { 350d8c2dab8SJeeja KP struct skl *skl = ebus_to_skl(ebus); 351d8c2dab8SJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 352d8c2dab8SJeeja KP 353d8c2dab8SJeeja KP skl->init_failed = 1; /* to be sure */ 354d8c2dab8SJeeja KP 355d8c2dab8SJeeja KP snd_hdac_ext_stop_streams(ebus); 356d8c2dab8SJeeja KP 357d8c2dab8SJeeja KP if (bus->irq >= 0) 358d8c2dab8SJeeja KP free_irq(bus->irq, (void *)bus); 359d8c2dab8SJeeja KP snd_hdac_bus_free_stream_pages(bus); 360d8c2dab8SJeeja KP snd_hdac_stream_free_all(ebus); 361d8c2dab8SJeeja KP snd_hdac_link_free_all(ebus); 362077411e5SVinod Koul 363077411e5SVinod Koul if (bus->remap_addr) 364077411e5SVinod Koul iounmap(bus->remap_addr); 365077411e5SVinod Koul 366d8c2dab8SJeeja KP pci_release_regions(skl->pci); 367d8c2dab8SJeeja KP pci_disable_device(skl->pci); 368d8c2dab8SJeeja KP 369d8c2dab8SJeeja KP snd_hdac_ext_bus_exit(ebus); 370d8c2dab8SJeeja KP 3715b2fe898SVinod Koul if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) 3725b2fe898SVinod Koul snd_hdac_i915_exit(&ebus->bus); 373d8c2dab8SJeeja KP return 0; 374d8c2dab8SJeeja KP } 375d8c2dab8SJeeja KP 376cc18c5fdSVinod Koul static int skl_machine_device_register(struct skl *skl, void *driver_data) 377cc18c5fdSVinod Koul { 378cc18c5fdSVinod Koul struct hdac_bus *bus = ebus_to_hbus(&skl->ebus); 379cc18c5fdSVinod Koul struct platform_device *pdev; 380cc18c5fdSVinod Koul struct sst_acpi_mach *mach = driver_data; 381cc18c5fdSVinod Koul int ret; 382cc18c5fdSVinod Koul 383cc18c5fdSVinod Koul mach = sst_acpi_find_machine(mach); 384cc18c5fdSVinod Koul if (mach == NULL) { 385cc18c5fdSVinod Koul dev_err(bus->dev, "No matching machine driver found\n"); 386cc18c5fdSVinod Koul return -ENODEV; 387cc18c5fdSVinod Koul } 388aecf6fd8SVinod Koul skl->fw_name = mach->fw_filename; 389cc18c5fdSVinod Koul 390cc18c5fdSVinod Koul pdev = platform_device_alloc(mach->drv_name, -1); 391cc18c5fdSVinod Koul if (pdev == NULL) { 392cc18c5fdSVinod Koul dev_err(bus->dev, "platform device alloc failed\n"); 393cc18c5fdSVinod Koul return -EIO; 394cc18c5fdSVinod Koul } 395cc18c5fdSVinod Koul 396cc18c5fdSVinod Koul ret = platform_device_add(pdev); 397cc18c5fdSVinod Koul if (ret) { 398cc18c5fdSVinod Koul dev_err(bus->dev, "failed to add machine device\n"); 399cc18c5fdSVinod Koul platform_device_put(pdev); 400cc18c5fdSVinod Koul return -EIO; 401cc18c5fdSVinod Koul } 402f65cf7d6SYong Zhi 403f65cf7d6SYong Zhi if (mach->pdata) 404f65cf7d6SYong Zhi dev_set_drvdata(&pdev->dev, mach->pdata); 405f65cf7d6SYong Zhi 406cc18c5fdSVinod Koul skl->i2s_dev = pdev; 407cc18c5fdSVinod Koul 408cc18c5fdSVinod Koul return 0; 409cc18c5fdSVinod Koul } 410cc18c5fdSVinod Koul 411cc18c5fdSVinod Koul static void skl_machine_device_unregister(struct skl *skl) 412cc18c5fdSVinod Koul { 413cc18c5fdSVinod Koul if (skl->i2s_dev) 414cc18c5fdSVinod Koul platform_device_unregister(skl->i2s_dev); 415cc18c5fdSVinod Koul } 416cc18c5fdSVinod Koul 417d8c2dab8SJeeja KP static int skl_dmic_device_register(struct skl *skl) 418d8c2dab8SJeeja KP { 419d8c2dab8SJeeja KP struct hdac_bus *bus = ebus_to_hbus(&skl->ebus); 420d8c2dab8SJeeja KP struct platform_device *pdev; 421d8c2dab8SJeeja KP int ret; 422d8c2dab8SJeeja KP 423d8c2dab8SJeeja KP /* SKL has one dmic port, so allocate dmic device for this */ 424d8c2dab8SJeeja KP pdev = platform_device_alloc("dmic-codec", -1); 425d8c2dab8SJeeja KP if (!pdev) { 426d8c2dab8SJeeja KP dev_err(bus->dev, "failed to allocate dmic device\n"); 427d8c2dab8SJeeja KP return -ENOMEM; 428d8c2dab8SJeeja KP } 429d8c2dab8SJeeja KP 430d8c2dab8SJeeja KP ret = platform_device_add(pdev); 431d8c2dab8SJeeja KP if (ret) { 432d8c2dab8SJeeja KP dev_err(bus->dev, "failed to add dmic device: %d\n", ret); 433d8c2dab8SJeeja KP platform_device_put(pdev); 434d8c2dab8SJeeja KP return ret; 435d8c2dab8SJeeja KP } 436d8c2dab8SJeeja KP skl->dmic_dev = pdev; 437d8c2dab8SJeeja KP 438d8c2dab8SJeeja KP return 0; 439d8c2dab8SJeeja KP } 440d8c2dab8SJeeja KP 441d8c2dab8SJeeja KP static void skl_dmic_device_unregister(struct skl *skl) 442d8c2dab8SJeeja KP { 443d8c2dab8SJeeja KP if (skl->dmic_dev) 444d8c2dab8SJeeja KP platform_device_unregister(skl->dmic_dev); 445d8c2dab8SJeeja KP } 446d8c2dab8SJeeja KP 447d8c2dab8SJeeja KP /* 448d8c2dab8SJeeja KP * Probe the given codec address 449d8c2dab8SJeeja KP */ 450d8c2dab8SJeeja KP static int probe_codec(struct hdac_ext_bus *ebus, int addr) 451d8c2dab8SJeeja KP { 452d8c2dab8SJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 453d8c2dab8SJeeja KP unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) | 454d8c2dab8SJeeja KP (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; 455d8c2dab8SJeeja KP unsigned int res; 456d8c2dab8SJeeja KP 457d8c2dab8SJeeja KP mutex_lock(&bus->cmd_mutex); 458d8c2dab8SJeeja KP snd_hdac_bus_send_cmd(bus, cmd); 459d8c2dab8SJeeja KP snd_hdac_bus_get_response(bus, addr, &res); 460d8c2dab8SJeeja KP mutex_unlock(&bus->cmd_mutex); 461d8c2dab8SJeeja KP if (res == -1) 462d8c2dab8SJeeja KP return -EIO; 463d8c2dab8SJeeja KP dev_dbg(bus->dev, "codec #%d probed OK\n", addr); 464d8c2dab8SJeeja KP 465d8c2dab8SJeeja KP return snd_hdac_ext_bus_device_init(ebus, addr); 466d8c2dab8SJeeja KP } 467d8c2dab8SJeeja KP 468d8c2dab8SJeeja KP /* Codec initialization */ 469d8c2dab8SJeeja KP static int skl_codec_create(struct hdac_ext_bus *ebus) 470d8c2dab8SJeeja KP { 471d8c2dab8SJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 472d8c2dab8SJeeja KP int c, max_slots; 473d8c2dab8SJeeja KP 474d8c2dab8SJeeja KP max_slots = HDA_MAX_CODECS; 475d8c2dab8SJeeja KP 476d8c2dab8SJeeja KP /* First try to probe all given codec slots */ 477d8c2dab8SJeeja KP for (c = 0; c < max_slots; c++) { 478d8c2dab8SJeeja KP if ((bus->codec_mask & (1 << c))) { 479d8c2dab8SJeeja KP if (probe_codec(ebus, c) < 0) { 480d8c2dab8SJeeja KP /* 481d8c2dab8SJeeja KP * Some BIOSen give you wrong codec addresses 482d8c2dab8SJeeja KP * that don't exist 483d8c2dab8SJeeja KP */ 484d8c2dab8SJeeja KP dev_warn(bus->dev, 485d8c2dab8SJeeja KP "Codec #%d probe error; disabling it...\n", c); 486d8c2dab8SJeeja KP bus->codec_mask &= ~(1 << c); 487d8c2dab8SJeeja KP /* 488d8c2dab8SJeeja KP * More badly, accessing to a non-existing 489d8c2dab8SJeeja KP * codec often screws up the controller bus, 490d8c2dab8SJeeja KP * and disturbs the further communications. 491d8c2dab8SJeeja KP * Thus if an error occurs during probing, 492d8c2dab8SJeeja KP * better to reset the controller bus to get 493d8c2dab8SJeeja KP * back to the sanity state. 494d8c2dab8SJeeja KP */ 495d8c2dab8SJeeja KP snd_hdac_bus_stop_chip(bus); 4960c8ba9d2SJayachandran B skl_init_chip(bus, true); 497d8c2dab8SJeeja KP } 498d8c2dab8SJeeja KP } 499d8c2dab8SJeeja KP } 500d8c2dab8SJeeja KP 501d8c2dab8SJeeja KP return 0; 502d8c2dab8SJeeja KP } 503d8c2dab8SJeeja KP 504d8c2dab8SJeeja KP static const struct hdac_bus_ops bus_core_ops = { 505d8c2dab8SJeeja KP .command = snd_hdac_bus_send_cmd, 506d8c2dab8SJeeja KP .get_response = snd_hdac_bus_get_response, 507d8c2dab8SJeeja KP }; 508d8c2dab8SJeeja KP 509d8c2dab8SJeeja KP /* 510d8c2dab8SJeeja KP * constructor 511d8c2dab8SJeeja KP */ 512d8c2dab8SJeeja KP static int skl_create(struct pci_dev *pci, 513d8c2dab8SJeeja KP const struct hdac_io_ops *io_ops, 514d8c2dab8SJeeja KP struct skl **rskl) 515d8c2dab8SJeeja KP { 516d8c2dab8SJeeja KP struct skl *skl; 517d8c2dab8SJeeja KP struct hdac_ext_bus *ebus; 518d8c2dab8SJeeja KP 519d8c2dab8SJeeja KP int err; 520d8c2dab8SJeeja KP 521d8c2dab8SJeeja KP *rskl = NULL; 522d8c2dab8SJeeja KP 523d8c2dab8SJeeja KP err = pci_enable_device(pci); 524d8c2dab8SJeeja KP if (err < 0) 525d8c2dab8SJeeja KP return err; 526d8c2dab8SJeeja KP 527d8c2dab8SJeeja KP skl = devm_kzalloc(&pci->dev, sizeof(*skl), GFP_KERNEL); 528d8c2dab8SJeeja KP if (!skl) { 529d8c2dab8SJeeja KP pci_disable_device(pci); 530d8c2dab8SJeeja KP return -ENOMEM; 531d8c2dab8SJeeja KP } 532d8c2dab8SJeeja KP ebus = &skl->ebus; 533d8c2dab8SJeeja KP snd_hdac_ext_bus_init(ebus, &pci->dev, &bus_core_ops, io_ops); 534d8c2dab8SJeeja KP ebus->bus.use_posbuf = 1; 535d8c2dab8SJeeja KP skl->pci = pci; 536d8c2dab8SJeeja KP 537d8c2dab8SJeeja KP ebus->bus.bdl_pos_adj = 0; 538d8c2dab8SJeeja KP 539d8c2dab8SJeeja KP *rskl = skl; 540d8c2dab8SJeeja KP 541d8c2dab8SJeeja KP return 0; 542d8c2dab8SJeeja KP } 543d8c2dab8SJeeja KP 5446980c057SVinod Koul static int skl_i915_init(struct hdac_bus *bus) 5456980c057SVinod Koul { 5466980c057SVinod Koul int err; 5476980c057SVinod Koul 5486980c057SVinod Koul /* 5496980c057SVinod Koul * The HDMI codec is in GPU so we need to ensure that it is powered 5506980c057SVinod Koul * up and ready for probe 5516980c057SVinod Koul */ 5526980c057SVinod Koul err = snd_hdac_i915_init(bus); 5536980c057SVinod Koul if (err < 0) 5546980c057SVinod Koul return err; 5556980c057SVinod Koul 5566980c057SVinod Koul err = snd_hdac_display_power(bus, true); 5576980c057SVinod Koul if (err < 0) { 5586980c057SVinod Koul dev_err(bus->dev, "Cannot turn on display power on i915\n"); 5596980c057SVinod Koul return err; 5606980c057SVinod Koul } 5616980c057SVinod Koul 5626980c057SVinod Koul return err; 5636980c057SVinod Koul } 5646980c057SVinod Koul 565d8c2dab8SJeeja KP static int skl_first_init(struct hdac_ext_bus *ebus) 566d8c2dab8SJeeja KP { 567d8c2dab8SJeeja KP struct skl *skl = ebus_to_skl(ebus); 568d8c2dab8SJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 569d8c2dab8SJeeja KP struct pci_dev *pci = skl->pci; 570d8c2dab8SJeeja KP int err; 571d8c2dab8SJeeja KP unsigned short gcap; 572d8c2dab8SJeeja KP int cp_streams, pb_streams, start_idx; 573d8c2dab8SJeeja KP 574d8c2dab8SJeeja KP err = pci_request_regions(pci, "Skylake HD audio"); 575d8c2dab8SJeeja KP if (err < 0) 576d8c2dab8SJeeja KP return err; 577d8c2dab8SJeeja KP 578d8c2dab8SJeeja KP bus->addr = pci_resource_start(pci, 0); 579d8c2dab8SJeeja KP bus->remap_addr = pci_ioremap_bar(pci, 0); 580d8c2dab8SJeeja KP if (bus->remap_addr == NULL) { 581d8c2dab8SJeeja KP dev_err(bus->dev, "ioremap error\n"); 582d8c2dab8SJeeja KP return -ENXIO; 583d8c2dab8SJeeja KP } 584d8c2dab8SJeeja KP 58505057001SJeeja KP snd_hdac_ext_bus_parse_capabilities(ebus); 58605057001SJeeja KP 587d8c2dab8SJeeja KP if (skl_acquire_irq(ebus, 0) < 0) 588d8c2dab8SJeeja KP return -EBUSY; 589d8c2dab8SJeeja KP 590d8c2dab8SJeeja KP pci_set_master(pci); 591d8c2dab8SJeeja KP synchronize_irq(bus->irq); 592d8c2dab8SJeeja KP 593d8c2dab8SJeeja KP gcap = snd_hdac_chip_readw(bus, GCAP); 594d8c2dab8SJeeja KP dev_dbg(bus->dev, "chipset global capabilities = 0x%x\n", gcap); 595d8c2dab8SJeeja KP 596d8c2dab8SJeeja KP /* allow 64bit DMA address if supported by H/W */ 597d8c2dab8SJeeja KP if (!dma_set_mask(bus->dev, DMA_BIT_MASK(64))) { 598d8c2dab8SJeeja KP dma_set_coherent_mask(bus->dev, DMA_BIT_MASK(64)); 599d8c2dab8SJeeja KP } else { 600d8c2dab8SJeeja KP dma_set_mask(bus->dev, DMA_BIT_MASK(32)); 601d8c2dab8SJeeja KP dma_set_coherent_mask(bus->dev, DMA_BIT_MASK(32)); 602d8c2dab8SJeeja KP } 603d8c2dab8SJeeja KP 604d8c2dab8SJeeja KP /* read number of streams from GCAP register */ 605d8c2dab8SJeeja KP cp_streams = (gcap >> 8) & 0x0f; 606d8c2dab8SJeeja KP pb_streams = (gcap >> 12) & 0x0f; 607d8c2dab8SJeeja KP 608d8c2dab8SJeeja KP if (!pb_streams && !cp_streams) 609d8c2dab8SJeeja KP return -EIO; 610d8c2dab8SJeeja KP 611d8c2dab8SJeeja KP ebus->num_streams = cp_streams + pb_streams; 612d8c2dab8SJeeja KP 613d8c2dab8SJeeja KP /* initialize streams */ 614d8c2dab8SJeeja KP snd_hdac_ext_stream_init_all 615d8c2dab8SJeeja KP (ebus, 0, cp_streams, SNDRV_PCM_STREAM_CAPTURE); 616d8c2dab8SJeeja KP start_idx = cp_streams; 617d8c2dab8SJeeja KP snd_hdac_ext_stream_init_all 618d8c2dab8SJeeja KP (ebus, start_idx, pb_streams, SNDRV_PCM_STREAM_PLAYBACK); 619d8c2dab8SJeeja KP 620d8c2dab8SJeeja KP err = snd_hdac_bus_alloc_stream_pages(bus); 621d8c2dab8SJeeja KP if (err < 0) 622d8c2dab8SJeeja KP return err; 623d8c2dab8SJeeja KP 624d8c2dab8SJeeja KP /* initialize chip */ 625d8c2dab8SJeeja KP skl_init_pci(skl); 626d8c2dab8SJeeja KP 6276980c057SVinod Koul if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { 6286980c057SVinod Koul err = skl_i915_init(bus); 6296980c057SVinod Koul if (err < 0) 6306980c057SVinod Koul return err; 6316980c057SVinod Koul } 6326980c057SVinod Koul 6330c8ba9d2SJayachandran B skl_init_chip(bus, true); 634d8c2dab8SJeeja KP 635d8c2dab8SJeeja KP /* codec detection */ 636d8c2dab8SJeeja KP if (!bus->codec_mask) { 637029890c6SJeeja KP dev_info(bus->dev, "no hda codecs found!\n"); 638d8c2dab8SJeeja KP } 639d8c2dab8SJeeja KP 640d8c2dab8SJeeja KP return 0; 641d8c2dab8SJeeja KP } 642d8c2dab8SJeeja KP 643d8c2dab8SJeeja KP static int skl_probe(struct pci_dev *pci, 644d8c2dab8SJeeja KP const struct pci_device_id *pci_id) 645d8c2dab8SJeeja KP { 646d8c2dab8SJeeja KP struct skl *skl; 647d8c2dab8SJeeja KP struct hdac_ext_bus *ebus = NULL; 648d8c2dab8SJeeja KP struct hdac_bus *bus = NULL; 649cce6c149SVinod Koul struct hdac_ext_link *hlink = NULL; 650d8c2dab8SJeeja KP int err; 651d8c2dab8SJeeja KP 652d8c2dab8SJeeja KP /* we use ext core ops, so provide NULL for ops here */ 653d8c2dab8SJeeja KP err = skl_create(pci, NULL, &skl); 654d8c2dab8SJeeja KP if (err < 0) 655d8c2dab8SJeeja KP return err; 656d8c2dab8SJeeja KP 657d8c2dab8SJeeja KP ebus = &skl->ebus; 658d8c2dab8SJeeja KP bus = ebus_to_hbus(ebus); 659d8c2dab8SJeeja KP 660d8c2dab8SJeeja KP err = skl_first_init(ebus); 661d8c2dab8SJeeja KP if (err < 0) 662d8c2dab8SJeeja KP goto out_free; 663d8c2dab8SJeeja KP 6644b235c43SVinod Koul skl->pci_id = pci->device; 6654b235c43SVinod Koul 66687b2bdf0SJeeja KP skl->nhlt = skl_nhlt_init(bus->dev); 66787b2bdf0SJeeja KP 66887b2bdf0SJeeja KP if (skl->nhlt == NULL) 66987b2bdf0SJeeja KP goto out_free; 67087b2bdf0SJeeja KP 6714b235c43SVinod Koul skl_nhlt_update_topology_bin(skl); 6724b235c43SVinod Koul 673d8c2dab8SJeeja KP pci_set_drvdata(skl->pci, ebus); 674d8c2dab8SJeeja KP 675f65cf7d6SYong Zhi skl_dmic_data.dmic_num = skl_get_dmic_geo(skl); 676f65cf7d6SYong Zhi 67705057001SJeeja KP /* check if dsp is there */ 67805057001SJeeja KP if (ebus->ppcap) { 679cc18c5fdSVinod Koul err = skl_machine_device_register(skl, 680cc18c5fdSVinod Koul (void *)pci_id->driver_data); 681cc18c5fdSVinod Koul if (err < 0) 682c286b3f9SJeeja KP goto out_nhlt_free; 683cc18c5fdSVinod Koul 6842a29b200SJeeja KP err = skl_init_dsp(skl); 6852a29b200SJeeja KP if (err < 0) { 6862a29b200SJeeja KP dev_dbg(bus->dev, "error failed to register dsp\n"); 687cc18c5fdSVinod Koul goto out_mach_free; 68805057001SJeeja KP } 6890c8ba9d2SJayachandran B skl->skl_sst->enable_miscbdcge = skl_enable_miscbdcge; 6900c8ba9d2SJayachandran B 6912a29b200SJeeja KP } 69205057001SJeeja KP if (ebus->mlcap) 69305057001SJeeja KP snd_hdac_ext_bus_get_ml_capabilities(ebus); 69405057001SJeeja KP 695d8c2dab8SJeeja KP /* create device for soc dmic */ 696d8c2dab8SJeeja KP err = skl_dmic_device_register(skl); 697d8c2dab8SJeeja KP if (err < 0) 6982a29b200SJeeja KP goto out_dsp_free; 699d8c2dab8SJeeja KP 700d8c2dab8SJeeja KP /* register platform dai and controls */ 701d8c2dab8SJeeja KP err = skl_platform_register(bus->dev); 702d8c2dab8SJeeja KP if (err < 0) 703d8c2dab8SJeeja KP goto out_dmic_free; 704d8c2dab8SJeeja KP 705d8c2dab8SJeeja KP /* create codec instances */ 706d8c2dab8SJeeja KP err = skl_codec_create(ebus); 707d8c2dab8SJeeja KP if (err < 0) 708d8c2dab8SJeeja KP goto out_unregister; 709d8c2dab8SJeeja KP 7106980c057SVinod Koul if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) { 7116980c057SVinod Koul err = snd_hdac_display_power(bus, false); 7126980c057SVinod Koul if (err < 0) { 7136980c057SVinod Koul dev_err(bus->dev, "Cannot turn off display power on i915\n"); 7146980c057SVinod Koul return err; 7156980c057SVinod Koul } 7166980c057SVinod Koul } 7176980c057SVinod Koul 718cce6c149SVinod Koul /* 719cce6c149SVinod Koul * we are done probling so decrement link counts 720cce6c149SVinod Koul */ 721cce6c149SVinod Koul list_for_each_entry(hlink, &ebus->hlink_list, list) 722cce6c149SVinod Koul snd_hdac_ext_bus_link_put(ebus, hlink); 723cce6c149SVinod Koul 724d8c2dab8SJeeja KP /*configure PM */ 725d8c2dab8SJeeja KP pm_runtime_put_noidle(bus->dev); 726d8c2dab8SJeeja KP pm_runtime_allow(bus->dev); 727d8c2dab8SJeeja KP 728d8c2dab8SJeeja KP return 0; 729d8c2dab8SJeeja KP 730d8c2dab8SJeeja KP out_unregister: 731d8c2dab8SJeeja KP skl_platform_unregister(bus->dev); 732d8c2dab8SJeeja KP out_dmic_free: 733d8c2dab8SJeeja KP skl_dmic_device_unregister(skl); 7342a29b200SJeeja KP out_dsp_free: 7352a29b200SJeeja KP skl_free_dsp(skl); 736cc18c5fdSVinod Koul out_mach_free: 737cc18c5fdSVinod Koul skl_machine_device_unregister(skl); 738c286b3f9SJeeja KP out_nhlt_free: 739c286b3f9SJeeja KP skl_nhlt_free(skl->nhlt); 740d8c2dab8SJeeja KP out_free: 741d8c2dab8SJeeja KP skl->init_failed = 1; 742d8c2dab8SJeeja KP skl_free(ebus); 743d8c2dab8SJeeja KP 744d8c2dab8SJeeja KP return err; 745d8c2dab8SJeeja KP } 746d8c2dab8SJeeja KP 747c5a76a24SJeeja KP static void skl_shutdown(struct pci_dev *pci) 748c5a76a24SJeeja KP { 749c5a76a24SJeeja KP struct hdac_ext_bus *ebus = pci_get_drvdata(pci); 750c5a76a24SJeeja KP struct hdac_bus *bus = ebus_to_hbus(ebus); 751c5a76a24SJeeja KP struct hdac_stream *s; 752c5a76a24SJeeja KP struct hdac_ext_stream *stream; 753c5a76a24SJeeja KP struct skl *skl; 754c5a76a24SJeeja KP 755c5a76a24SJeeja KP if (ebus == NULL) 756c5a76a24SJeeja KP return; 757c5a76a24SJeeja KP 758c5a76a24SJeeja KP skl = ebus_to_skl(ebus); 759c5a76a24SJeeja KP 760c5a76a24SJeeja KP if (skl->init_failed) 761c5a76a24SJeeja KP return; 762c5a76a24SJeeja KP 763c5a76a24SJeeja KP snd_hdac_ext_stop_streams(ebus); 764c5a76a24SJeeja KP list_for_each_entry(s, &bus->stream_list, list) { 765c5a76a24SJeeja KP stream = stream_to_hdac_ext_stream(s); 766c5a76a24SJeeja KP snd_hdac_ext_stream_decouple(ebus, stream, false); 767c5a76a24SJeeja KP } 768c5a76a24SJeeja KP 769c5a76a24SJeeja KP snd_hdac_bus_stop_chip(bus); 770c5a76a24SJeeja KP } 771c5a76a24SJeeja KP 772d8c2dab8SJeeja KP static void skl_remove(struct pci_dev *pci) 773d8c2dab8SJeeja KP { 774d8c2dab8SJeeja KP struct hdac_ext_bus *ebus = pci_get_drvdata(pci); 775d8c2dab8SJeeja KP struct skl *skl = ebus_to_skl(ebus); 776d8c2dab8SJeeja KP 777d8018361SVinod Koul if (skl->tplg) 778d8018361SVinod Koul release_firmware(skl->tplg); 779d8018361SVinod Koul 780d8c2dab8SJeeja KP if (pci_dev_run_wake(pci)) 781d8c2dab8SJeeja KP pm_runtime_get_noresume(&pci->dev); 7827373f481SVinod Koul 7837373f481SVinod Koul /* codec removal, invoke bus_device_remove */ 7847373f481SVinod Koul snd_hdac_ext_bus_device_remove(ebus); 7857373f481SVinod Koul 786d8c2dab8SJeeja KP skl_platform_unregister(&pci->dev); 7872a29b200SJeeja KP skl_free_dsp(skl); 788cc18c5fdSVinod Koul skl_machine_device_unregister(skl); 789d8c2dab8SJeeja KP skl_dmic_device_unregister(skl); 790c286b3f9SJeeja KP skl_nhlt_free(skl->nhlt); 791d8c2dab8SJeeja KP skl_free(ebus); 792d8c2dab8SJeeja KP dev_set_drvdata(&pci->dev, NULL); 793d8c2dab8SJeeja KP } 794d8c2dab8SJeeja KP 795cc18c5fdSVinod Koul static struct sst_acpi_mach sst_skl_devdata[] = { 796cc18c5fdSVinod Koul { "INT343A", "skl_alc286s_i2s", "intel/dsp_fw_release.bin", NULL, NULL, NULL }, 79702cc2355SFang, Yang A { "INT343B", "skl_nau88l25_ssm4567_i2s", "intel/dsp_fw_release.bin", 798f65cf7d6SYong Zhi NULL, NULL, &skl_dmic_data }, 79969b7f9c4SRohit Ainapure { "MX98357A", "skl_nau88l25_max98357a_i2s", "intel/dsp_fw_release.bin", 800f65cf7d6SYong Zhi NULL, NULL, &skl_dmic_data }, 801cc18c5fdSVinod Koul {} 802cc18c5fdSVinod Koul }; 803cc18c5fdSVinod Koul 804b379b1faSSenthilnathan Veppur static struct sst_acpi_mach sst_bxtp_devdata[] = { 805b379b1faSSenthilnathan Veppur { "INT343A", "bxt_alc298s_i2s", "intel/dsp_fw_bxtn.bin", NULL, NULL, NULL }, 806b379b1faSSenthilnathan Veppur }; 807b379b1faSSenthilnathan Veppur 808d8c2dab8SJeeja KP /* PCI IDs */ 809d8c2dab8SJeeja KP static const struct pci_device_id skl_ids[] = { 810d8c2dab8SJeeja KP /* Sunrise Point-LP */ 811cc18c5fdSVinod Koul { PCI_DEVICE(0x8086, 0x9d70), 812cc18c5fdSVinod Koul .driver_data = (unsigned long)&sst_skl_devdata}, 813b379b1faSSenthilnathan Veppur /* BXT-P */ 814b379b1faSSenthilnathan Veppur { PCI_DEVICE(0x8086, 0x5a98), 815b379b1faSSenthilnathan Veppur .driver_data = (unsigned long)&sst_bxtp_devdata}, 816d8c2dab8SJeeja KP { 0, } 817d8c2dab8SJeeja KP }; 818d8c2dab8SJeeja KP MODULE_DEVICE_TABLE(pci, skl_ids); 819d8c2dab8SJeeja KP 820d8c2dab8SJeeja KP /* pci_driver definition */ 821d8c2dab8SJeeja KP static struct pci_driver skl_driver = { 822d8c2dab8SJeeja KP .name = KBUILD_MODNAME, 823d8c2dab8SJeeja KP .id_table = skl_ids, 824d8c2dab8SJeeja KP .probe = skl_probe, 825d8c2dab8SJeeja KP .remove = skl_remove, 826c5a76a24SJeeja KP .shutdown = skl_shutdown, 827d8c2dab8SJeeja KP .driver = { 828d8c2dab8SJeeja KP .pm = &skl_pm, 829d8c2dab8SJeeja KP }, 830d8c2dab8SJeeja KP }; 831d8c2dab8SJeeja KP module_pci_driver(skl_driver); 832d8c2dab8SJeeja KP 833d8c2dab8SJeeja KP MODULE_LICENSE("GPL v2"); 834d8c2dab8SJeeja KP MODULE_DESCRIPTION("Intel Skylake ASoC HDA driver"); 835