2015-07-09 15:20:09 +05:30
/*
* skl . c - Implementation of ASoC Intel SKL HD Audio driver
*
* Copyright ( C ) 2014 - 2015 Intel Corp
* Author : Jeeja KP < jeeja . kp @ intel . com >
*
* Derived mostly from Intel HDA driver with following copyrights :
* Copyright ( c ) 2004 Takashi Iwai < tiwai @ suse . de >
* PeiSen Hou < pshou @ realtek . com . tw >
* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; version 2 of the License .
*
* This program is distributed in the hope that it will be useful , but
* WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* General Public License for more details .
*
* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
*/
# include <linux/module.h>
# include <linux/pci.h>
# include <linux/pm_runtime.h>
# include <linux/platform_device.h>
2016-01-05 17:16:04 +05:30
# include <linux/firmware.h>
2016-11-03 17:07:16 +05:30
# include <linux/delay.h>
2015-07-09 15:20:09 +05:30
# include <sound/pcm.h>
2017-10-12 18:49:38 -05:00
# include <sound/soc-acpi.h>
2018-06-18 13:29:37 -05:00
# include <sound/soc-acpi-intel-match.h>
2016-02-17 21:34:06 +05:30
# include <sound/hda_register.h>
# include <sound/hdaudio.h>
# include <sound/hda_i915.h>
2015-07-09 15:20:09 +05:30
# include "skl.h"
2015-12-18 15:12:03 +05:30
# include "skl-sst-dsp.h"
# include "skl-sst-ipc.h"
2015-07-09 15:20:09 +05:30
/*
* initialize the PCI registers
*/
static void skl_update_pci_byte ( struct pci_dev * pci , unsigned int reg ,
unsigned char mask , unsigned char val )
{
unsigned char data ;
pci_read_config_byte ( pci , reg , & data ) ;
data & = ~ mask ;
data | = ( val & mask ) ;
pci_write_config_byte ( pci , reg , data ) ;
}
static void skl_init_pci ( struct skl * skl )
{
2018-06-01 22:53:50 -05:00
struct hdac_bus * bus = skl_to_bus ( skl ) ;
2015-07-09 15:20:09 +05:30
/*
* Clear bits 0 - 2 of PCI register TCSEL ( at offset 0x44 )
* TCSEL = = Traffic Class Select Register , which sets PCI express QOS
* Ensuring these bits are 0 clears playback static on some HD Audio
* codecs .
* The PCI register TCSEL is defined in the Intel manuals .
*/
2018-06-01 22:53:50 -05:00
dev_dbg ( bus - > dev , " Clearing TCSEL \n " ) ;
2015-07-09 15:20:09 +05:30
skl_update_pci_byte ( skl - > pci , AZX_PCIREG_TCSEL , 0x07 , 0 ) ;
}
2015-12-18 15:12:03 +05:30
static void update_pci_dword ( struct pci_dev * pci ,
unsigned int reg , u32 mask , u32 val )
{
u32 data = 0 ;
pci_read_config_dword ( pci , reg , & data ) ;
data & = ~ mask ;
data | = ( val & mask ) ;
pci_write_config_dword ( pci , reg , data ) ;
}
/*
* skl_enable_miscbdcge - enable / dsiable CGCTL . MISCBDCGE bits
*
* @ dev : device pointer
* @ enable : enable / disable flag
*/
static void skl_enable_miscbdcge ( struct device * dev , bool enable )
{
struct pci_dev * pci = to_pci_dev ( dev ) ;
u32 val ;
val = enable ? AZX_CGCTL_MISCBDCGE_MASK : 0 ;
update_pci_dword ( pci , AZX_PCIREG_CGCTL , AZX_CGCTL_MISCBDCGE_MASK , val ) ;
}
2018-03-13 09:02:25 +05:30
/**
* skl_clock_power_gating : Enable / Disable clock and power gating
*
* @ dev : Device pointer
* @ enable : Enable / Disable flag
*/
static void skl_clock_power_gating ( struct device * dev , bool enable )
{
struct pci_dev * pci = to_pci_dev ( dev ) ;
2018-06-01 22:53:50 -05:00
struct hdac_bus * bus = pci_get_drvdata ( pci ) ;
2018-03-13 09:02:25 +05:30
u32 val ;
/* Update PDCGE bit of CGCTL register */
val = enable ? AZX_CGCTL_ADSPDCGE : 0 ;
update_pci_dword ( pci , AZX_PCIREG_CGCTL , AZX_CGCTL_ADSPDCGE , val ) ;
/* Update L1SEN bit of EM2 register */
val = enable ? AZX_REG_VS_EM2_L1SEN : 0 ;
snd_hdac_chip_updatel ( bus , VS_EM2 , AZX_REG_VS_EM2_L1SEN , val ) ;
/* Update ADSPPGD bit of PGCTL register */
val = enable ? 0 : AZX_PGCTL_ADSPPGD ;
update_pci_dword ( pci , AZX_PCIREG_PGCTL , AZX_PGCTL_ADSPPGD , val ) ;
}
2015-12-18 15:12:03 +05:30
/*
* While performing reset , controller may not come back properly causing
* issues , so recommendation is to set CGCTL . MISCBDCGE to 0 then do reset
* ( init chip ) and then again set CGCTL . MISCBDCGE to 1
*/
static int skl_init_chip ( struct hdac_bus * bus , bool full_reset )
{
2018-04-01 15:13:23 +05:30
struct hdac_ext_link * hlink ;
2015-12-18 15:12:03 +05:30
int ret ;
skl_enable_miscbdcge ( bus - > dev , false ) ;
ret = snd_hdac_bus_init_chip ( bus , full_reset ) ;
2018-04-01 15:13:23 +05:30
/* Reset stream-to-link mapping */
2018-06-01 22:53:50 -05:00
list_for_each_entry ( hlink , & bus - > hlink_list , list )
2018-04-01 15:13:23 +05:30
bus - > io_ops - > reg_writel ( 0 , hlink - > ml_addr + AZX_REG_ML_LOSIDV ) ;
2015-12-18 15:12:03 +05:30
skl_enable_miscbdcge ( bus - > dev , true ) ;
return ret ;
}
2016-11-03 17:07:16 +05:30
void skl_update_d0i3c ( struct device * dev , bool enable )
{
struct pci_dev * pci = to_pci_dev ( dev ) ;
2018-06-01 22:53:50 -05:00
struct hdac_bus * bus = pci_get_drvdata ( pci ) ;
2016-11-03 17:07:16 +05:30
u8 reg ;
int timeout = 50 ;
reg = snd_hdac_chip_readb ( bus , VS_D0I3C ) ;
/* Do not write to D0I3C until command in progress bit is cleared */
while ( ( reg & AZX_REG_VS_D0I3C_CIP ) & & - - timeout ) {
udelay ( 10 ) ;
reg = snd_hdac_chip_readb ( bus , VS_D0I3C ) ;
}
/* Highly unlikely. But if it happens, flag error explicitly */
if ( ! timeout ) {
dev_err ( bus - > dev , " Before D0I3C update: D0I3C CIP timeout \n " ) ;
return ;
}
if ( enable )
reg = reg | AZX_REG_VS_D0I3C_I3 ;
else
reg = reg & ( ~ AZX_REG_VS_D0I3C_I3 ) ;
snd_hdac_chip_writeb ( bus , VS_D0I3C , reg ) ;
timeout = 50 ;
/* Wait for cmd in progress to be cleared before exiting the function */
reg = snd_hdac_chip_readb ( bus , VS_D0I3C ) ;
while ( ( reg & AZX_REG_VS_D0I3C_CIP ) & & - - timeout ) {
udelay ( 10 ) ;
reg = snd_hdac_chip_readb ( bus , VS_D0I3C ) ;
}
/* Highly unlikely. But if it happens, flag error explicitly */
if ( ! timeout ) {
dev_err ( bus - > dev , " After D0I3C update: D0I3C CIP timeout \n " ) ;
return ;
}
dev_dbg ( bus - > dev , " D0I3C register = 0x%x \n " ,
snd_hdac_chip_readb ( bus , VS_D0I3C ) ) ;
}
2015-07-09 15:20:09 +05:30
/* called from IRQ */
static void skl_stream_update ( struct hdac_bus * bus , struct hdac_stream * hstr )
{
snd_pcm_period_elapsed ( hstr - > substream ) ;
}
static irqreturn_t skl_interrupt ( int irq , void * dev_id )
{
2018-06-01 22:53:50 -05:00
struct hdac_bus * bus = dev_id ;
2015-07-09 15:20:09 +05:30
u32 status ;
if ( ! pm_runtime_active ( bus - > dev ) )
return IRQ_NONE ;
spin_lock ( & bus - > reg_lock ) ;
status = snd_hdac_chip_readl ( bus , INTSTS ) ;
if ( status = = 0 | | status = = 0xffffffff ) {
spin_unlock ( & bus - > reg_lock ) ;
return IRQ_NONE ;
}
/* clear rirb int */
status = snd_hdac_chip_readb ( bus , RIRBSTS ) ;
if ( status & RIRB_INT_MASK ) {
if ( status & RIRB_INT_RESPONSE )
snd_hdac_bus_update_rirb ( bus ) ;
snd_hdac_chip_writeb ( bus , RIRBSTS , RIRB_INT_MASK ) ;
}
spin_unlock ( & bus - > reg_lock ) ;
return snd_hdac_chip_readl ( bus , INTSTS ) ? IRQ_WAKE_THREAD : IRQ_HANDLED ;
}
static irqreturn_t skl_threaded_handler ( int irq , void * dev_id )
{
2018-06-01 22:53:50 -05:00
struct hdac_bus * bus = dev_id ;
2015-07-09 15:20:09 +05:30
u32 status ;
status = snd_hdac_chip_readl ( bus , INTSTS ) ;
snd_hdac_bus_handle_stream_irq ( bus , status , skl_stream_update ) ;
return IRQ_HANDLED ;
}
2018-06-01 22:53:50 -05:00
static int skl_acquire_irq ( struct hdac_bus * bus , int do_disconnect )
2015-07-09 15:20:09 +05:30
{
2018-06-01 22:53:50 -05:00
struct skl * skl = bus_to_skl ( bus ) ;
2015-07-09 15:20:09 +05:30
int ret ;
ret = request_threaded_irq ( skl - > pci - > irq , skl_interrupt ,
skl_threaded_handler ,
IRQF_SHARED ,
2018-06-01 22:53:50 -05:00
KBUILD_MODNAME , bus ) ;
2015-07-09 15:20:09 +05:30
if ( ret ) {
dev_err ( bus - > dev ,
" unable to grab IRQ %d, disabling device \n " ,
skl - > pci - > irq ) ;
return ret ;
}
bus - > irq = skl - > pci - > irq ;
pci_intx ( skl - > pci , 1 ) ;
return 0 ;
}
2016-11-03 17:07:21 +05:30
static int skl_suspend_late ( struct device * dev )
{
struct pci_dev * pci = to_pci_dev ( dev ) ;
2018-06-01 22:53:50 -05:00
struct hdac_bus * bus = pci_get_drvdata ( pci ) ;
struct skl * skl = bus_to_skl ( bus ) ;
2016-11-03 17:07:21 +05:30
return skl_suspend_late_dsp ( skl ) ;
}
2015-10-27 09:23:00 +09:00
# ifdef CONFIG_PM
2018-06-01 22:53:50 -05:00
static int _skl_suspend ( struct hdac_bus * bus )
2015-10-27 09:23:00 +09:00
{
2018-06-01 22:53:50 -05:00
struct skl * skl = bus_to_skl ( bus ) ;
2016-06-03 18:29:37 +05:30
struct pci_dev * pci = to_pci_dev ( bus - > dev ) ;
2015-10-27 09:23:00 +09:00
int ret ;
2018-06-01 22:53:50 -05:00
snd_hdac_ext_bus_link_power_down_all ( bus ) ;
2015-10-27 09:23:00 +09:00
ret = skl_suspend_dsp ( skl ) ;
if ( ret < 0 )
return ret ;
snd_hdac_bus_stop_chip ( bus ) ;
2016-06-03 18:29:37 +05:30
update_pci_dword ( pci , AZX_PCIREG_PGCTL ,
AZX_PGCTL_LSRMD_MASK , AZX_PGCTL_LSRMD_MASK ) ;
2015-12-18 15:12:03 +05:30
skl_enable_miscbdcge ( bus - > dev , false ) ;
2015-10-27 09:23:00 +09:00
snd_hdac_bus_enter_link_reset ( bus ) ;
2015-12-18 15:12:03 +05:30
skl_enable_miscbdcge ( bus - > dev , true ) ;
2016-06-03 18:29:39 +05:30
skl_cleanup_resources ( skl ) ;
2015-10-27 09:23:00 +09:00
return 0 ;
}
2018-06-01 22:53:50 -05:00
static int _skl_resume ( struct hdac_bus * bus )
2015-10-27 09:23:00 +09:00
{
2018-06-01 22:53:50 -05:00
struct skl * skl = bus_to_skl ( bus ) ;
2015-10-27 09:23:00 +09:00
skl_init_pci ( skl ) ;
2015-12-18 15:12:03 +05:30
skl_init_chip ( bus , true ) ;
2015-10-27 09:23:00 +09:00
return skl_resume_dsp ( skl ) ;
}
# endif
2015-07-09 15:20:09 +05:30
# ifdef CONFIG_PM_SLEEP
/*
* power management
*/
static int skl_suspend ( struct device * dev )
{
struct pci_dev * pci = to_pci_dev ( dev ) ;
2018-06-01 22:53:50 -05:00
struct hdac_bus * bus = pci_get_drvdata ( pci ) ;
struct skl * skl = bus_to_skl ( bus ) ;
2016-04-01 13:36:27 +05:30
int ret = 0 ;
2015-07-09 15:20:09 +05:30
2015-12-03 23:30:00 +05:30
/*
* Do not suspend if streams which are marked ignore suspend are
* running , we need to save the state for these and continue
*/
if ( skl - > supend_active ) {
2016-05-12 08:58:54 +05:30
/* turn off the links and stop the CORB/RIRB DMA if it is On */
2018-06-01 22:53:50 -05:00
snd_hdac_ext_bus_link_power_down_all ( bus ) ;
2016-05-12 08:58:54 +05:30
2018-06-01 22:53:50 -05:00
if ( bus - > cmd_dma_state )
snd_hdac_bus_stop_cmd_io ( bus ) ;
2016-05-12 08:58:54 +05:30
2015-12-18 15:12:06 +05:30
enable_irq_wake ( bus - > irq ) ;
2015-12-03 23:30:00 +05:30
pci_save_state ( pci ) ;
} else {
2018-06-01 22:53:50 -05:00
ret = _skl_suspend ( bus ) ;
2016-04-01 13:36:27 +05:30
if ( ret < 0 )
return ret ;
2016-06-13 17:59:01 +05:30
skl - > skl_sst - > fw_loaded = false ;
2015-12-03 23:30:00 +05:30
}
2016-04-01 13:36:27 +05:30
if ( IS_ENABLED ( CONFIG_SND_SOC_HDAC_HDMI ) ) {
ret = snd_hdac_display_power ( bus , false ) ;
if ( ret < 0 )
dev_err ( bus - > dev ,
" Cannot turn OFF display power on i915 \n " ) ;
}
return ret ;
2015-07-09 15:20:09 +05:30
}
static int skl_resume ( struct device * dev )
{
struct pci_dev * pci = to_pci_dev ( dev ) ;
2018-06-01 22:53:50 -05:00
struct hdac_bus * bus = pci_get_drvdata ( pci ) ;
struct skl * skl = bus_to_skl ( bus ) ;
2016-05-12 08:58:54 +05:30
struct hdac_ext_link * hlink = NULL ;
2015-12-03 23:30:00 +05:30
int ret ;
2016-02-17 21:34:06 +05:30
/* Turned OFF in HDMI codec driver after codec reconfiguration */
if ( IS_ENABLED ( CONFIG_SND_SOC_HDAC_HDMI ) ) {
ret = snd_hdac_display_power ( bus , true ) ;
if ( ret < 0 ) {
dev_err ( bus - > dev ,
" Cannot turn on display power on i915 \n " ) ;
return ret ;
}
}
2015-12-03 23:30:00 +05:30
/*
* resume only when we are not in suspend active , otherwise need to
* restore the device
*/
if ( skl - > supend_active ) {
pci_restore_state ( pci ) ;
2018-06-01 22:53:50 -05:00
snd_hdac_ext_bus_link_power_up_all ( bus ) ;
2015-12-18 15:12:06 +05:30
disable_irq_wake ( bus - > irq ) ;
2016-05-12 08:58:54 +05:30
/*
* turn On the links which are On before active suspend
* and start the CORB / RIRB DMA if On before
* active suspend .
*/
2018-06-01 22:53:50 -05:00
list_for_each_entry ( hlink , & bus - > hlink_list , list ) {
2016-05-12 08:58:54 +05:30
if ( hlink - > ref_count )
snd_hdac_ext_bus_link_power_up ( hlink ) ;
}
2017-11-06 14:30:36 +01:00
ret = 0 ;
2018-06-01 22:53:50 -05:00
if ( bus - > cmd_dma_state )
snd_hdac_bus_init_cmd_io ( bus ) ;
2015-12-03 23:30:00 +05:30
} else {
2018-06-01 22:53:50 -05:00
ret = _skl_resume ( bus ) ;
2016-05-12 08:58:54 +05:30
/* turn off the links which are off before suspend */
2018-06-01 22:53:50 -05:00
list_for_each_entry ( hlink , & bus - > hlink_list , list ) {
2016-05-12 08:58:54 +05:30
if ( ! hlink - > ref_count )
snd_hdac_ext_bus_link_power_down ( hlink ) ;
}
2018-06-01 22:53:50 -05:00
if ( ! bus - > cmd_dma_state )
snd_hdac_bus_stop_cmd_io ( bus ) ;
2015-12-03 23:30:00 +05:30
}
2015-07-09 15:20:09 +05:30
2015-12-03 23:30:00 +05:30
return ret ;
2015-07-09 15:20:09 +05:30
}
# endif /* CONFIG_PM_SLEEP */
# ifdef CONFIG_PM
static int skl_runtime_suspend ( struct device * dev )
{
struct pci_dev * pci = to_pci_dev ( dev ) ;
2018-06-01 22:53:50 -05:00
struct hdac_bus * bus = pci_get_drvdata ( pci ) ;
2015-07-09 15:20:09 +05:30
dev_dbg ( bus - > dev , " in %s \n " , __func__ ) ;
2018-06-01 22:53:50 -05:00
return _skl_suspend ( bus ) ;
2015-07-09 15:20:09 +05:30
}
static int skl_runtime_resume ( struct device * dev )
{
struct pci_dev * pci = to_pci_dev ( dev ) ;
2018-06-01 22:53:50 -05:00
struct hdac_bus * bus = pci_get_drvdata ( pci ) ;
2015-07-09 15:20:09 +05:30
dev_dbg ( bus - > dev , " in %s \n " , __func__ ) ;
2018-06-01 22:53:50 -05:00
return _skl_resume ( bus ) ;
2015-07-09 15:20:09 +05:30
}
# endif /* CONFIG_PM */
static const struct dev_pm_ops skl_pm = {
SET_SYSTEM_SLEEP_PM_OPS ( skl_suspend , skl_resume )
SET_RUNTIME_PM_OPS ( skl_runtime_suspend , skl_runtime_resume , NULL )
2016-11-03 17:07:21 +05:30
. suspend_late = skl_suspend_late ,
2015-07-09 15:20:09 +05:30
} ;
/*
* destructor
*/
2018-06-01 22:53:50 -05:00
static int skl_free ( struct hdac_bus * bus )
2015-07-09 15:20:09 +05:30
{
2018-06-01 22:53:50 -05:00
struct skl * skl = bus_to_skl ( bus ) ;
2015-07-09 15:20:09 +05:30
2017-05-04 14:09:10 +05:30
skl - > init_done = 0 ; /* to be sure */
2015-07-09 15:20:09 +05:30
2018-06-01 22:53:50 -05:00
snd_hdac_ext_stop_streams ( bus ) ;
2015-07-09 15:20:09 +05:30
if ( bus - > irq > = 0 )
2018-06-01 22:53:50 -05:00
free_irq ( bus - > irq , ( void * ) bus ) ;
2015-07-09 15:20:09 +05:30
snd_hdac_bus_free_stream_pages ( bus ) ;
2018-06-01 22:53:50 -05:00
snd_hdac_stream_free_all ( bus ) ;
snd_hdac_link_free_all ( bus ) ;
2016-03-15 16:39:26 +05:30
if ( bus - > remap_addr )
iounmap ( bus - > remap_addr ) ;
2015-07-09 15:20:09 +05:30
pci_release_regions ( skl - > pci ) ;
pci_disable_device ( skl - > pci ) ;
2018-06-01 22:53:50 -05:00
snd_hdac_ext_bus_exit ( bus ) ;
2015-07-09 15:20:09 +05:30
2017-05-04 14:09:10 +05:30
cancel_work_sync ( & skl - > probe_work ) ;
2016-03-15 16:39:27 +05:30
if ( IS_ENABLED ( CONFIG_SND_SOC_HDAC_HDMI ) )
2018-06-01 22:53:50 -05:00
snd_hdac_i915_exit ( bus ) ;
2017-05-04 14:09:10 +05:30
2015-07-09 15:20:09 +05:30
return 0 ;
}
2017-11-22 17:39:46 +05:30
/*
* For each ssp there are 3 clocks ( mclk / sclk / sclkfs ) .
* e . g . for ssp0 , clocks will be named as
* " ssp0_mclk " , " ssp0_sclk " , " ssp0_sclkfs "
* So for skl + , there are 6 ssps , so 18 clocks will be created .
*/
static struct skl_ssp_clk skl_ssp_clks [ ] = {
{ . name = " ssp0_mclk " } , { . name = " ssp1_mclk " } , { . name = " ssp2_mclk " } ,
{ . name = " ssp3_mclk " } , { . name = " ssp4_mclk " } , { . name = " ssp5_mclk " } ,
{ . name = " ssp0_sclk " } , { . name = " ssp1_sclk " } , { . name = " ssp2_sclk " } ,
{ . name = " ssp3_sclk " } , { . name = " ssp4_sclk " } , { . name = " ssp5_sclk " } ,
{ . name = " ssp0_sclkfs " } , { . name = " ssp1_sclkfs " } ,
{ . name = " ssp2_sclkfs " } ,
{ . name = " ssp3_sclkfs " } , { . name = " ssp4_sclkfs " } ,
{ . name = " ssp5_sclkfs " } ,
} ;
2018-08-22 15:25:00 -05:00
static struct snd_soc_acpi_mach * skl_find_hda_machine ( struct skl * skl ,
struct snd_soc_acpi_mach * machines )
{
struct hdac_bus * bus = skl_to_bus ( skl ) ;
struct snd_soc_acpi_mach * mach ;
/* check if we have any codecs detected on bus */
if ( bus - > codec_mask = = 0 )
return NULL ;
/* point to common table */
mach = snd_soc_acpi_intel_hda_machines ;
/* all entries in the machine table use the same firmware */
mach - > fw_filename = machines - > fw_filename ;
return mach ;
}
2017-12-18 10:46:50 +05:30
static int skl_find_machine ( struct skl * skl , void * driver_data )
2015-11-05 21:34:13 +05:30
{
2018-06-01 22:53:50 -05:00
struct hdac_bus * bus = skl_to_bus ( skl ) ;
2017-10-12 18:49:38 -05:00
struct snd_soc_acpi_mach * mach = driver_data ;
2017-12-18 10:46:50 +05:30
struct skl_machine_pdata * pdata ;
2015-11-05 21:34:13 +05:30
2017-10-12 18:49:38 -05:00
mach = snd_soc_acpi_find_machine ( mach ) ;
2018-08-22 15:25:00 -05:00
if ( ! mach ) {
dev_dbg ( bus - > dev , " No matching I2S machine driver found \n " ) ;
mach = skl_find_hda_machine ( skl , driver_data ) ;
if ( ! mach ) {
dev_err ( bus - > dev , " No matching machine driver found \n " ) ;
return - ENODEV ;
}
2015-11-05 21:34:13 +05:30
}
2017-12-18 10:46:50 +05:30
skl - > mach = mach ;
2015-11-05 21:34:15 +05:30
skl - > fw_name = mach - > fw_filename ;
2018-06-18 13:29:36 -05:00
pdata = mach - > pdata ;
2017-12-18 10:46:50 +05:30
2018-06-18 13:29:36 -05:00
if ( pdata ) {
2017-12-18 10:46:50 +05:30
skl - > use_tplg_pcm = pdata - > use_tplg_pcm ;
2018-06-18 13:29:36 -05:00
pdata - > dmic_num = skl_get_dmic_geo ( skl ) ;
}
2017-12-18 10:46:50 +05:30
return 0 ;
}
static int skl_machine_device_register ( struct skl * skl )
{
struct snd_soc_acpi_mach * mach = skl - > mach ;
2018-08-22 15:25:00 -05:00
struct hdac_bus * bus = skl_to_bus ( skl ) ;
struct skl_machine_pdata * pdata ;
2017-12-18 10:46:50 +05:30
struct platform_device * pdev ;
int ret ;
2015-11-05 21:34:13 +05:30
pdev = platform_device_alloc ( mach - > drv_name , - 1 ) ;
if ( pdev = = NULL ) {
dev_err ( bus - > dev , " platform device alloc failed \n " ) ;
return - EIO ;
}
ret = platform_device_add ( pdev ) ;
if ( ret ) {
dev_err ( bus - > dev , " failed to add machine device \n " ) ;
platform_device_put ( pdev ) ;
return - EIO ;
}
2016-05-26 21:30:15 -07:00
2018-08-22 15:25:00 -05:00
if ( mach - > pdata ) {
pdata = ( struct skl_machine_pdata * ) mach - > pdata ;
pdata - > platform = dev_name ( bus - > dev ) ;
pdata - > codec_mask = bus - > codec_mask ;
2016-05-26 21:30:15 -07:00
dev_set_drvdata ( & pdev - > dev , mach - > pdata ) ;
2018-08-22 15:25:00 -05:00
}
2016-05-26 21:30:15 -07:00
2015-11-05 21:34:13 +05:30
skl - > i2s_dev = pdev ;
return 0 ;
}
static void skl_machine_device_unregister ( struct skl * skl )
{
if ( skl - > i2s_dev )
platform_device_unregister ( skl - > i2s_dev ) ;
}
2015-07-09 15:20:09 +05:30
static int skl_dmic_device_register ( struct skl * skl )
{
2018-06-01 22:53:50 -05:00
struct hdac_bus * bus = skl_to_bus ( skl ) ;
2015-07-09 15:20:09 +05:30
struct platform_device * pdev ;
int ret ;
/* SKL has one dmic port, so allocate dmic device for this */
pdev = platform_device_alloc ( " dmic-codec " , - 1 ) ;
if ( ! pdev ) {
dev_err ( bus - > dev , " failed to allocate dmic device \n " ) ;
return - ENOMEM ;
}
ret = platform_device_add ( pdev ) ;
if ( ret ) {
dev_err ( bus - > dev , " failed to add dmic device: %d \n " , ret ) ;
platform_device_put ( pdev ) ;
return ret ;
}
skl - > dmic_dev = pdev ;
return 0 ;
}
static void skl_dmic_device_unregister ( struct skl * skl )
{
if ( skl - > dmic_dev )
platform_device_unregister ( skl - > dmic_dev ) ;
}
2017-11-22 17:39:46 +05:30
static struct skl_clk_parent_src skl_clk_src [ ] = {
{ . clk_id = SKL_XTAL , . name = " xtal " } ,
{ . clk_id = SKL_CARDINAL , . name = " cardinal " , . rate = 24576000 } ,
{ . clk_id = SKL_PLL , . name = " pll " , . rate = 96000000 } ,
} ;
struct skl_clk_parent_src * skl_get_parent_clk ( u8 clk_id )
{
unsigned int i ;
for ( i = 0 ; i < ARRAY_SIZE ( skl_clk_src ) ; i + + ) {
if ( skl_clk_src [ i ] . clk_id = = clk_id )
return & skl_clk_src [ i ] ;
}
return NULL ;
}
2017-12-04 10:30:11 +05:30
static void init_skl_xtal_rate ( int pci_id )
2017-11-22 17:39:46 +05:30
{
switch ( pci_id ) {
case 0x9d70 :
case 0x9d71 :
skl_clk_src [ 0 ] . rate = 24000000 ;
return ;
default :
skl_clk_src [ 0 ] . rate = 19200000 ;
return ;
}
}
static int skl_clock_device_register ( struct skl * skl )
{
struct platform_device_info pdevinfo = { NULL } ;
struct skl_clk_pdata * clk_pdata ;
clk_pdata = devm_kzalloc ( & skl - > pci - > dev , sizeof ( * clk_pdata ) ,
GFP_KERNEL ) ;
if ( ! clk_pdata )
return - ENOMEM ;
init_skl_xtal_rate ( skl - > pci - > device ) ;
clk_pdata - > parent_clks = skl_clk_src ;
clk_pdata - > ssp_clks = skl_ssp_clks ;
clk_pdata - > num_clks = ARRAY_SIZE ( skl_ssp_clks ) ;
/* Query NHLT to fill the rates and parent */
skl_get_clks ( skl , clk_pdata - > ssp_clks ) ;
clk_pdata - > pvt_data = skl ;
/* Register Platform device */
pdevinfo . parent = & skl - > pci - > dev ;
pdevinfo . id = - 1 ;
pdevinfo . name = " skl-ssp-clk " ;
pdevinfo . data = clk_pdata ;
pdevinfo . size_data = sizeof ( * clk_pdata ) ;
skl - > clk_dev = platform_device_register_full ( & pdevinfo ) ;
return PTR_ERR_OR_ZERO ( skl - > clk_dev ) ;
}
static void skl_clock_device_unregister ( struct skl * skl )
{
if ( skl - > clk_dev )
platform_device_unregister ( skl - > clk_dev ) ;
}
2015-07-09 15:20:09 +05:30
/*
* Probe the given codec address
*/
2018-06-01 22:53:50 -05:00
static int probe_codec ( struct hdac_bus * bus , int addr )
2015-07-09 15:20:09 +05:30
{
unsigned int cmd = ( addr < < 28 ) | ( AC_NODE_ROOT < < 20 ) |
( AC_VERB_PARAMETERS < < 8 ) | AC_PAR_VENDOR_ID ;
2017-04-20 13:17:02 +03:00
unsigned int res = - 1 ;
2018-06-01 22:53:57 -05:00
struct skl * skl = bus_to_skl ( bus ) ;
struct hdac_device * hdev ;
2015-07-09 15:20:09 +05:30
mutex_lock ( & bus - > cmd_mutex ) ;
snd_hdac_bus_send_cmd ( bus , cmd ) ;
snd_hdac_bus_get_response ( bus , addr , & res ) ;
mutex_unlock ( & bus - > cmd_mutex ) ;
if ( res = = - 1 )
return - EIO ;
dev_dbg ( bus - > dev , " codec #%d probed OK \n " , addr ) ;
2018-06-01 22:53:57 -05:00
hdev = devm_kzalloc ( & skl - > pci - > dev , sizeof ( * hdev ) , GFP_KERNEL ) ;
if ( ! hdev )
return - ENOMEM ;
return snd_hdac_ext_bus_device_init ( bus , addr , hdev ) ;
2015-07-09 15:20:09 +05:30
}
/* Codec initialization */
2018-06-01 22:53:50 -05:00
static void skl_codec_create ( struct hdac_bus * bus )
2015-07-09 15:20:09 +05:30
{
int c , max_slots ;
max_slots = HDA_MAX_CODECS ;
/* First try to probe all given codec slots */
for ( c = 0 ; c < max_slots ; c + + ) {
if ( ( bus - > codec_mask & ( 1 < < c ) ) ) {
2018-06-01 22:53:50 -05:00
if ( probe_codec ( bus , c ) < 0 ) {
2015-07-09 15:20:09 +05:30
/*
* Some BIOSen give you wrong codec addresses
* that don ' t exist
*/
dev_warn ( bus - > dev ,
" Codec #%d probe error; disabling it... \n " , c ) ;
bus - > codec_mask & = ~ ( 1 < < c ) ;
/*
* More badly , accessing to a non - existing
* codec often screws up the controller bus ,
* and disturbs the further communications .
* Thus if an error occurs during probing ,
* better to reset the controller bus to get
* back to the sanity state .
*/
snd_hdac_bus_stop_chip ( bus ) ;
2015-12-18 15:12:03 +05:30
skl_init_chip ( bus , true ) ;
2015-07-09 15:20:09 +05:30
}
}
}
}
static const struct hdac_bus_ops bus_core_ops = {
. command = snd_hdac_bus_send_cmd ,
. get_response = snd_hdac_bus_get_response ,
} ;
2017-05-04 14:09:10 +05:30
static int skl_i915_init ( struct hdac_bus * bus )
{
int err ;
/*
* The HDMI codec is in GPU so we need to ensure that it is powered
* up and ready for probe
*/
err = snd_hdac_i915_init ( bus ) ;
if ( err < 0 )
return err ;
err = snd_hdac_display_power ( bus , true ) ;
if ( err < 0 )
dev_err ( bus - > dev , " Cannot turn on display power on i915 \n " ) ;
return err ;
}
static void skl_probe_work ( struct work_struct * work )
{
struct skl * skl = container_of ( work , struct skl , probe_work ) ;
2018-06-01 22:53:50 -05:00
struct hdac_bus * bus = skl_to_bus ( skl ) ;
2017-05-04 14:09:10 +05:30
struct hdac_ext_link * hlink = NULL ;
int err ;
if ( IS_ENABLED ( CONFIG_SND_SOC_HDAC_HDMI ) ) {
err = skl_i915_init ( bus ) ;
if ( err < 0 )
return ;
}
err = skl_init_chip ( bus , true ) ;
if ( err < 0 ) {
dev_err ( bus - > dev , " Init chip failed with err: %d \n " , err ) ;
goto out_err ;
}
/* codec detection */
if ( ! bus - > codec_mask )
dev_info ( bus - > dev , " no hda codecs found! \n " ) ;
/* create codec instances */
2018-06-01 22:53:50 -05:00
skl_codec_create ( bus ) ;
2017-05-04 14:09:10 +05:30
2017-12-18 10:46:50 +05:30
/* register platform dai and controls */
err = skl_platform_register ( bus - > dev ) ;
if ( err < 0 ) {
dev_err ( bus - > dev , " platform register failed: %d \n " , err ) ;
return ;
}
if ( bus - > ppcap ) {
err = skl_machine_device_register ( skl ) ;
if ( err < 0 ) {
dev_err ( bus - > dev , " machine register failed: %d \n " , err ) ;
goto out_err ;
}
}
2017-05-04 14:09:10 +05:30
if ( IS_ENABLED ( CONFIG_SND_SOC_HDAC_HDMI ) ) {
err = snd_hdac_display_power ( bus , false ) ;
if ( err < 0 ) {
dev_err ( bus - > dev , " Cannot turn off display power on i915 \n " ) ;
2017-12-18 10:46:50 +05:30
skl_machine_device_unregister ( skl ) ;
2017-05-04 14:09:10 +05:30
return ;
}
}
/*
* we are done probing so decrement link counts
*/
2018-06-01 22:53:50 -05:00
list_for_each_entry ( hlink , & bus - > hlink_list , list )
snd_hdac_ext_bus_link_put ( bus , hlink ) ;
2017-05-04 14:09:10 +05:30
/* configure PM */
pm_runtime_put_noidle ( bus - > dev ) ;
pm_runtime_allow ( bus - > dev ) ;
skl - > init_done = 1 ;
return ;
out_err :
if ( IS_ENABLED ( CONFIG_SND_SOC_HDAC_HDMI ) )
err = snd_hdac_display_power ( bus , false ) ;
}
2015-07-09 15:20:09 +05:30
/*
* constructor
*/
static int skl_create ( struct pci_dev * pci ,
const struct hdac_io_ops * io_ops ,
struct skl * * rskl )
{
struct skl * skl ;
2018-06-01 22:53:50 -05:00
struct hdac_bus * bus ;
2015-07-09 15:20:09 +05:30
int err ;
* rskl = NULL ;
err = pci_enable_device ( pci ) ;
if ( err < 0 )
return err ;
skl = devm_kzalloc ( & pci - > dev , sizeof ( * skl ) , GFP_KERNEL ) ;
if ( ! skl ) {
pci_disable_device ( pci ) ;
return - ENOMEM ;
}
2018-06-01 22:53:50 -05:00
bus = skl_to_bus ( skl ) ;
2018-06-01 22:53:58 -05:00
snd_hdac_ext_bus_init ( bus , & pci - > dev , & bus_core_ops , io_ops , NULL ) ;
2018-06-01 22:53:50 -05:00
bus - > use_posbuf = 1 ;
2015-07-09 15:20:09 +05:30
skl - > pci = pci ;
2017-05-04 14:09:10 +05:30
INIT_WORK ( & skl - > probe_work , skl_probe_work ) ;
2018-06-01 22:53:50 -05:00
bus - > bdl_pos_adj = 0 ;
2015-07-09 15:20:09 +05:30
* rskl = skl ;
return 0 ;
}
2018-06-01 22:53:50 -05:00
static int skl_first_init ( struct hdac_bus * bus )
2015-07-09 15:20:09 +05:30
{
2018-06-01 22:53:50 -05:00
struct skl * skl = bus_to_skl ( bus ) ;
2015-07-09 15:20:09 +05:30
struct pci_dev * pci = skl - > pci ;
int err ;
unsigned short gcap ;
int cp_streams , pb_streams , start_idx ;
err = pci_request_regions ( pci , " Skylake HD audio " ) ;
if ( err < 0 )
return err ;
bus - > addr = pci_resource_start ( pci , 0 ) ;
bus - > remap_addr = pci_ioremap_bar ( pci , 0 ) ;
if ( bus - > remap_addr = = NULL ) {
dev_err ( bus - > dev , " ioremap error \n " ) ;
return - ENXIO ;
}
2017-07-28 16:12:13 +05:30
skl_init_chip ( bus , true ) ;
2016-08-04 15:46:01 +05:30
snd_hdac_bus_parse_capabilities ( bus ) ;
2015-07-09 15:20:11 +05:30
2015-07-09 15:20:09 +05:30
pci_set_master ( pci ) ;
gcap = snd_hdac_chip_readw ( bus , GCAP ) ;
dev_dbg ( bus - > dev , " chipset global capabilities = 0x%x \n " , gcap ) ;
/* allow 64bit DMA address if supported by H/W */
if ( ! dma_set_mask ( bus - > dev , DMA_BIT_MASK ( 64 ) ) ) {
dma_set_coherent_mask ( bus - > dev , DMA_BIT_MASK ( 64 ) ) ;
} else {
dma_set_mask ( bus - > dev , DMA_BIT_MASK ( 32 ) ) ;
dma_set_coherent_mask ( bus - > dev , DMA_BIT_MASK ( 32 ) ) ;
}
/* read number of streams from GCAP register */
cp_streams = ( gcap > > 8 ) & 0x0f ;
pb_streams = ( gcap > > 12 ) & 0x0f ;
if ( ! pb_streams & & ! cp_streams )
return - EIO ;
2018-06-01 22:53:50 -05:00
bus - > num_streams = cp_streams + pb_streams ;
2015-07-09 15:20:09 +05:30
/* initialize streams */
snd_hdac_ext_stream_init_all
2018-06-01 22:53:50 -05:00
( bus , 0 , cp_streams , SNDRV_PCM_STREAM_CAPTURE ) ;
2015-07-09 15:20:09 +05:30
start_idx = cp_streams ;
snd_hdac_ext_stream_init_all
2018-06-01 22:53:50 -05:00
( bus , start_idx , pb_streams , SNDRV_PCM_STREAM_PLAYBACK ) ;
2015-07-09 15:20:09 +05:30
err = snd_hdac_bus_alloc_stream_pages ( bus ) ;
if ( err < 0 )
return err ;
2018-08-13 18:15:14 -05:00
err = skl_acquire_irq ( bus , 0 ) ;
if ( err < 0 )
return err ;
synchronize_irq ( bus - > irq ) ;
2015-07-09 15:20:09 +05:30
/* initialize chip */
skl_init_pci ( skl ) ;
2017-05-04 14:09:10 +05:30
return skl_init_chip ( bus , true ) ;
2015-07-09 15:20:09 +05:30
}
static int skl_probe ( struct pci_dev * pci ,
const struct pci_device_id * pci_id )
{
struct skl * skl ;
struct hdac_bus * bus = NULL ;
int err ;
/* we use ext core ops, so provide NULL for ops here */
err = skl_create ( pci , NULL , & skl ) ;
if ( err < 0 )
return err ;
2018-06-01 22:53:50 -05:00
bus = skl_to_bus ( skl ) ;
2015-07-09 15:20:09 +05:30
2018-06-01 22:53:50 -05:00
err = skl_first_init ( bus ) ;
2015-07-09 15:20:09 +05:30
if ( err < 0 )
goto out_free ;
2016-02-19 11:42:34 +05:30
skl - > pci_id = pci - > device ;
2016-06-22 19:44:19 +05:30
device_disable_async_suspend ( bus - > dev ) ;
2015-10-07 11:31:59 +01:00
skl - > nhlt = skl_nhlt_init ( bus - > dev ) ;
2016-08-12 11:45:18 +00:00
if ( skl - > nhlt = = NULL ) {
err = - ENODEV ;
2017-05-04 14:09:10 +05:30
goto out_free ;
2016-08-12 11:45:18 +00:00
}
2015-10-07 11:31:59 +01:00
2017-01-11 16:31:02 +05:30
err = skl_nhlt_create_sysfs ( skl ) ;
if ( err < 0 )
goto out_nhlt_free ;
2016-02-19 11:42:34 +05:30
skl_nhlt_update_topology_bin ( skl ) ;
2018-06-01 22:53:50 -05:00
pci_set_drvdata ( skl - > pci , bus ) ;
2015-07-09 15:20:09 +05:30
2015-07-09 15:20:11 +05:30
/* check if dsp is there */
2016-08-04 15:46:01 +05:30
if ( bus - > ppcap ) {
2017-11-22 17:39:46 +05:30
/* create device for dsp clk */
err = skl_clock_device_register ( skl ) ;
if ( err < 0 )
goto out_clk_free ;
2017-12-18 10:46:50 +05:30
err = skl_find_machine ( skl , ( void * ) pci_id - > driver_data ) ;
2015-11-05 21:34:13 +05:30
if ( err < 0 )
2016-05-05 11:19:19 +05:30
goto out_nhlt_free ;
2015-11-05 21:34:13 +05:30
2015-10-07 11:31:58 +01:00
err = skl_init_dsp ( skl ) ;
if ( err < 0 ) {
dev_dbg ( bus - > dev , " error failed to register dsp \n " ) ;
2017-12-18 10:46:50 +05:30
goto out_nhlt_free ;
2015-10-07 11:31:58 +01:00
}
2015-12-18 15:12:03 +05:30
skl - > skl_sst - > enable_miscbdcge = skl_enable_miscbdcge ;
2018-03-13 09:02:25 +05:30
skl - > skl_sst - > clock_power_gating = skl_clock_power_gating ;
2015-07-09 15:20:11 +05:30
}
2016-08-04 15:46:01 +05:30
if ( bus - > mlcap )
2018-06-01 22:53:50 -05:00
snd_hdac_ext_bus_get_ml_capabilities ( bus ) ;
2015-07-09 15:20:11 +05:30
2017-05-04 14:09:10 +05:30
snd_hdac_bus_stop_chip ( bus ) ;
2015-07-09 15:20:09 +05:30
/* create device for soc dmic */
err = skl_dmic_device_register ( skl ) ;
if ( err < 0 )
2015-10-07 11:31:58 +01:00
goto out_dsp_free ;
2015-07-09 15:20:09 +05:30
2017-05-04 14:09:10 +05:30
schedule_work ( & skl - > probe_work ) ;
2015-07-09 15:20:09 +05:30
return 0 ;
2015-10-07 11:31:58 +01:00
out_dsp_free :
skl_free_dsp ( skl ) ;
2017-11-22 17:39:46 +05:30
out_clk_free :
skl_clock_device_unregister ( skl ) ;
2016-05-05 11:19:19 +05:30
out_nhlt_free :
skl_nhlt_free ( skl - > nhlt ) ;
2015-07-09 15:20:09 +05:30
out_free :
2018-06-01 22:53:50 -05:00
skl_free ( bus ) ;
2015-07-09 15:20:09 +05:30
return err ;
}
2016-02-05 12:19:09 +05:30
static void skl_shutdown ( struct pci_dev * pci )
{
2018-06-01 22:53:50 -05:00
struct hdac_bus * bus = pci_get_drvdata ( pci ) ;
2016-02-05 12:19:09 +05:30
struct hdac_stream * s ;
struct hdac_ext_stream * stream ;
struct skl * skl ;
2018-06-01 22:53:50 -05:00
if ( ! bus )
2016-02-05 12:19:09 +05:30
return ;
2018-06-01 22:53:50 -05:00
skl = bus_to_skl ( bus ) ;
2016-02-05 12:19:09 +05:30
2017-05-04 14:09:10 +05:30
if ( ! skl - > init_done )
2016-02-05 12:19:09 +05:30
return ;
2018-06-01 22:53:50 -05:00
snd_hdac_ext_stop_streams ( bus ) ;
2016-02-05 12:19:09 +05:30
list_for_each_entry ( s , & bus - > stream_list , list ) {
stream = stream_to_hdac_ext_stream ( s ) ;
2018-06-01 22:53:50 -05:00
snd_hdac_ext_stream_decouple ( bus , stream , false ) ;
2016-02-05 12:19:09 +05:30
}
snd_hdac_bus_stop_chip ( bus ) ;
}
2015-07-09 15:20:09 +05:30
static void skl_remove ( struct pci_dev * pci )
{
2018-06-01 22:53:50 -05:00
struct hdac_bus * bus = pci_get_drvdata ( pci ) ;
struct skl * skl = bus_to_skl ( bus ) ;
2015-07-09 15:20:09 +05:30
2016-07-22 18:58:14 +02:00
release_firmware ( skl - > tplg ) ;
2016-01-05 17:16:04 +05:30
2016-10-20 12:26:16 +02:00
pm_runtime_get_noresume ( & pci - > dev ) ;
2016-03-15 16:39:24 +05:30
/* codec removal, invoke bus_device_remove */
2018-06-01 22:53:50 -05:00
snd_hdac_ext_bus_device_remove ( bus ) ;
2016-03-15 16:39:24 +05:30
2017-06-30 09:06:05 +05:30
skl - > debugfs = NULL ;
2015-07-09 15:20:09 +05:30
skl_platform_unregister ( & pci - > dev ) ;
2015-10-07 11:31:58 +01:00
skl_free_dsp ( skl ) ;
2015-11-05 21:34:13 +05:30
skl_machine_device_unregister ( skl ) ;
2015-07-09 15:20:09 +05:30
skl_dmic_device_unregister ( skl ) ;
2017-11-22 17:39:46 +05:30
skl_clock_device_unregister ( skl ) ;
2017-01-11 16:31:02 +05:30
skl_nhlt_remove_sysfs ( skl ) ;
2016-05-05 11:19:19 +05:30
skl_nhlt_free ( skl - > nhlt ) ;
2018-06-01 22:53:50 -05:00
skl_free ( bus ) ;
2015-07-09 15:20:09 +05:30
dev_set_drvdata ( & pci - > dev , NULL ) ;
}
/* PCI IDs */
static const struct pci_device_id skl_ids [ ] = {
/* Sunrise Point-LP */
2015-11-05 21:34:13 +05:30
{ PCI_DEVICE ( 0x8086 , 0x9d70 ) ,
2018-06-18 13:29:37 -05:00
. driver_data = ( unsigned long ) & snd_soc_acpi_intel_skl_machines } ,
2016-03-11 10:12:54 +05:30
/* BXT-P */
{ PCI_DEVICE ( 0x8086 , 0x5a98 ) ,
2018-06-18 13:29:37 -05:00
. driver_data = ( unsigned long ) & snd_soc_acpi_intel_bxt_machines } ,
2016-07-11 22:02:08 +05:30
/* KBL */
{ PCI_DEVICE ( 0x8086 , 0x9D71 ) ,
2018-06-18 13:29:37 -05:00
. driver_data = ( unsigned long ) & snd_soc_acpi_intel_kbl_machines } ,
2017-02-09 16:44:03 +05:30
/* GLK */
{ PCI_DEVICE ( 0x8086 , 0x3198 ) ,
2018-06-18 13:29:37 -05:00
. driver_data = ( unsigned long ) & snd_soc_acpi_intel_glk_machines } ,
2017-08-02 21:51:20 +05:30
/* CNL */
{ PCI_DEVICE ( 0x8086 , 0x9dc8 ) ,
2018-06-18 13:29:37 -05:00
. driver_data = ( unsigned long ) & snd_soc_acpi_intel_cnl_machines } ,
2015-07-09 15:20:09 +05:30
{ 0 , }
} ;
MODULE_DEVICE_TABLE ( pci , skl_ids ) ;
/* pci_driver definition */
static struct pci_driver skl_driver = {
. name = KBUILD_MODNAME ,
. id_table = skl_ids ,
. probe = skl_probe ,
. remove = skl_remove ,
2016-02-05 12:19:09 +05:30
. shutdown = skl_shutdown ,
2015-07-09 15:20:09 +05:30
. driver = {
. pm = & skl_pm ,
} ,
} ;
module_pci_driver ( skl_driver ) ;
MODULE_LICENSE ( " GPL v2 " ) ;
MODULE_DESCRIPTION ( " Intel Skylake ASoC HDA driver " ) ;