2020-05-01 09:58:50 -05:00
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2019-04-12 11:09:00 -05:00
//
// This file is provided under a dual BSD/GPLv2 license. When using or
// redistributing this file, you may do so under either license.
//
// Copyright(c) 2018 Intel Corporation. All rights reserved.
//
// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
//
# include <linux/firmware.h>
2020-01-07 10:08:39 -06:00
# include <linux/dmi.h>
2019-04-12 11:09:00 -05:00
# include <linux/module.h>
# include <linux/pci.h>
# include <linux/pm_runtime.h>
# include <sound/soc-acpi.h>
# include <sound/soc-acpi-intel-match.h>
# include <sound/sof.h>
# include "ops.h"
2021-03-01 18:31:21 -06:00
# include "sof-pci-dev.h"
2019-04-12 11:09:00 -05:00
static char * fw_path ;
module_param ( fw_path , charp , 0444 ) ;
MODULE_PARM_DESC ( fw_path , " alternate path for SOF firmware. " ) ;
static char * tplg_path ;
module_param ( tplg_path , charp , 0444 ) ;
MODULE_PARM_DESC ( tplg_path , " alternate path for SOF topology. " ) ;
2019-10-08 11:44:38 -05:00
static int sof_pci_debug ;
module_param_named ( sof_pci_debug , sof_pci_debug , int , 0444 ) ;
MODULE_PARM_DESC ( sof_pci_debug , " SOF PCI debug options (0x0 all off) " ) ;
2020-08-21 14:56:00 -05:00
static const char * sof_override_tplg_name ;
2019-10-08 11:44:38 -05:00
# define SOF_PCI_DISABLE_PM_RUNTIME BIT(0)
2020-08-21 14:56:00 -05:00
static int sof_tplg_cb ( const struct dmi_system_id * id )
{
sof_override_tplg_name = id - > driver_data ;
return 1 ;
}
static const struct dmi_system_id sof_tplg_table [ ] = {
{
. callback = sof_tplg_cb ,
. matches = {
DMI_MATCH ( DMI_PRODUCT_FAMILY , " Google_Volteer " ) ,
2020-09-10 19:27:05 +03:00
DMI_MATCH ( DMI_OEM_STRING , " AUDIO-MAX98373_ALC5682I_I2S_UP4 " ) ,
2020-08-21 14:56:00 -05:00
} ,
. driver_data = " sof-tgl-rt5682-ssp0-max98373-ssp2.tplg " ,
} ,
2021-08-02 10:21:49 -05:00
{
. callback = sof_tplg_cb ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Intel Corporation " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Alder Lake Client Platform " ) ,
DMI_MATCH ( DMI_OEM_STRING , " AUDIO-ADL_MAX98373_ALC5682I_I2S " ) ,
} ,
. driver_data = " sof-adl-rt5682-ssp0-max98373-ssp2.tplg " ,
} ,
2020-08-21 14:56:00 -05:00
{ }
} ;
2020-01-07 10:08:39 -06:00
static const struct dmi_system_id community_key_platforms [ ] = {
{
. ident = " Up Squared " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " AAEON " ) ,
DMI_MATCH ( DMI_BOARD_NAME , " UP-APL01 " ) ,
}
} ,
2021-02-08 17:18:53 -06:00
{
. ident = " Up Extreme " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " AAEON " ) ,
DMI_MATCH ( DMI_BOARD_NAME , " UP-WHL01 " ) ,
}
} ,
2020-01-07 10:08:39 -06:00
{
. ident = " Google Chromebooks " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Google " ) ,
}
} ,
{ } ,
} ;
2021-03-01 18:31:21 -06:00
const struct dev_pm_ops sof_pci_pm = {
2019-10-25 17:41:22 -05:00
. prepare = snd_sof_prepare ,
. complete = snd_sof_complete ,
2019-04-12 11:09:00 -05:00
SET_SYSTEM_SLEEP_PM_OPS ( snd_sof_suspend , snd_sof_resume )
SET_RUNTIME_PM_OPS ( snd_sof_runtime_suspend , snd_sof_runtime_resume ,
2019-07-02 16:24:27 +03:00
snd_sof_runtime_idle )
2019-04-12 11:09:00 -05:00
} ;
2021-03-01 18:31:21 -06:00
EXPORT_SYMBOL_NS ( sof_pci_pm , SND_SOC_SOF_PCI_DEV ) ;
2019-04-12 11:09:00 -05:00
static void sof_pci_probe_complete ( struct device * dev )
{
dev_dbg ( dev , " Completing SOF PCI probe " ) ;
2019-10-08 11:44:38 -05:00
if ( sof_pci_debug & SOF_PCI_DISABLE_PM_RUNTIME )
return ;
2019-04-12 11:09:00 -05:00
/* allow runtime_pm */
pm_runtime_set_autosuspend_delay ( dev , SND_SOF_SUSPEND_DELAY_MS ) ;
pm_runtime_use_autosuspend ( dev ) ;
/*
* runtime pm for pci device is " forbidden " by default .
* so call pm_runtime_allow ( ) to enable it .
*/
pm_runtime_allow ( dev ) ;
2019-07-22 09:13:42 -05:00
/* mark last_busy for pm_runtime to make sure not suspend immediately */
pm_runtime_mark_last_busy ( dev ) ;
2019-04-12 11:09:00 -05:00
/* follow recommendation in pci-driver.c to decrement usage counter */
pm_runtime_put_noidle ( dev ) ;
}
2021-03-01 18:31:21 -06:00
int sof_pci_probe ( struct pci_dev * pci , const struct pci_device_id * pci_id )
2019-04-12 11:09:00 -05:00
{
struct device * dev = & pci - > dev ;
const struct sof_dev_desc * desc =
( const struct sof_dev_desc * ) pci_id - > driver_data ;
struct snd_sof_pdata * sof_pdata ;
int ret ;
dev_dbg ( & pci - > dev , " PCI DSP detected " ) ;
2021-05-21 12:27:58 +03:00
if ( ! desc - > ops ) {
2019-04-12 11:09:00 -05:00
dev_err ( dev , " error: no matching PCI descriptor ops \n " ) ;
return - ENODEV ;
}
sof_pdata = devm_kzalloc ( dev , sizeof ( * sof_pdata ) , GFP_KERNEL ) ;
if ( ! sof_pdata )
return - ENOMEM ;
ret = pcim_enable_device ( pci ) ;
if ( ret < 0 )
return ret ;
ret = pci_request_regions ( pci , " Audio DSP " ) ;
if ( ret < 0 )
return ret ;
sof_pdata - > name = pci_name ( pci ) ;
2021-05-21 12:27:59 +03:00
sof_pdata - > desc = desc ;
2019-04-12 11:09:00 -05:00
sof_pdata - > dev = dev ;
2019-12-04 15:15:53 -06:00
sof_pdata - > fw_filename = desc - > default_fw_filename ;
2019-04-12 11:09:00 -05:00
2020-01-07 10:08:39 -06:00
/*
* for platforms using the SOF community key , change the
* default path automatically to pick the right files from the
* linux - firmware tree . This can be overridden with the
* fw_path kernel parameter , e . g . for developers .
*/
2019-04-12 11:09:00 -05:00
/* alternate fw and tplg filenames ? */
2020-01-07 10:08:39 -06:00
if ( fw_path ) {
2019-04-12 11:09:00 -05:00
sof_pdata - > fw_filename_prefix = fw_path ;
2020-01-07 10:08:39 -06:00
dev_dbg ( dev ,
" Module parameter used, changed fw path to %s \n " ,
sof_pdata - > fw_filename_prefix ) ;
} else if ( dmi_check_system ( community_key_platforms ) ) {
sof_pdata - > fw_filename_prefix =
devm_kasprintf ( dev , GFP_KERNEL , " %s/%s " ,
sof_pdata - > desc - > default_fw_path ,
" community " ) ;
dev_dbg ( dev ,
" Platform uses community key, changed fw path to %s \n " ,
sof_pdata - > fw_filename_prefix ) ;
} else {
2019-04-12 11:09:00 -05:00
sof_pdata - > fw_filename_prefix =
sof_pdata - > desc - > default_fw_path ;
2020-01-07 10:08:39 -06:00
}
2019-04-12 11:09:00 -05:00
if ( tplg_path )
sof_pdata - > tplg_filename_prefix = tplg_path ;
else
sof_pdata - > tplg_filename_prefix =
sof_pdata - > desc - > default_tplg_path ;
2020-08-21 14:56:00 -05:00
dmi_check_system ( sof_tplg_table ) ;
if ( sof_override_tplg_name )
sof_pdata - > tplg_filename = sof_override_tplg_name ;
2021-04-09 15:09:59 -07:00
/* set callback to be called on successful device probe to enable runtime_pm */
2019-04-12 11:09:00 -05:00
sof_pdata - > sof_probe_complete = sof_pci_probe_complete ;
2021-04-09 15:09:59 -07:00
2019-04-12 11:09:00 -05:00
/* call sof helper for DSP hardware probe */
ret = snd_sof_device_probe ( dev , sof_pdata ) ;
2021-04-09 15:09:59 -07:00
if ( ret )
pci_release_regions ( pci ) ;
2019-04-12 11:09:00 -05:00
return ret ;
}
2021-03-01 18:31:21 -06:00
EXPORT_SYMBOL_NS ( sof_pci_probe , SND_SOC_SOF_PCI_DEV ) ;
2019-04-12 11:09:00 -05:00
2021-03-01 18:31:21 -06:00
void sof_pci_remove ( struct pci_dev * pci )
2019-04-12 11:09:00 -05:00
{
/* call sof helper for DSP hardware remove */
snd_sof_device_remove ( & pci - > dev ) ;
/* follow recommendation in pci-driver.c to increment usage counter */
2021-02-10 12:52:37 +02:00
if ( snd_sof_device_probe_completed ( & pci - > dev ) & &
! ( sof_pci_debug & SOF_PCI_DISABLE_PM_RUNTIME ) )
2019-10-08 11:44:38 -05:00
pm_runtime_get_noresume ( & pci - > dev ) ;
2019-04-12 11:09:00 -05:00
/* release pci regions and disable device */
pci_release_regions ( pci ) ;
}
2021-03-01 18:31:21 -06:00
EXPORT_SYMBOL_NS ( sof_pci_remove , SND_SOC_SOF_PCI_DEV ) ;
2019-04-12 11:09:00 -05:00
2021-03-01 18:31:21 -06:00
void sof_pci_shutdown ( struct pci_dev * pci )
2021-01-13 17:26:16 +02:00
{
snd_sof_device_shutdown ( & pci - > dev ) ;
}
2021-03-01 18:31:21 -06:00
EXPORT_SYMBOL_NS ( sof_pci_shutdown , SND_SOC_SOF_PCI_DEV ) ;
2019-04-12 11:09:00 -05:00
MODULE_LICENSE ( " Dual BSD/GPL " ) ;