Merge tag 'asoc-v4.21' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-next
ASoC: Updates for v4.21 Not much work on the core this time around but we've seen quite a bit of driver work, including on the generic DT drivers. There's also a large part of the diff from a merge of the DaVinci and OMAP directories, along with some active development there: - Preparatory work from Morimoto-san for merging the audio-graph and audio-graph-scu cards. - A merge of the TI OMAP and DaVinci directories, the OMAP product line has been merged into the DaVinci product line so there is now a lot of IP sharing which meant that the split directories just got in the way. This has pulled in a few architecture changes as well. - A big cleanup of the Maxim MAX9867 driver from Ladislav Michl. - Support for Asahi Kaesi AKM4118, AMD ACP3x, Intel platforms with RT5660, Meson AXG S/PDIF inputs, several Qualcomm IPs and Xilinx I2S controllers.
This commit is contained in:
@@ -247,6 +247,14 @@ static const struct skl_dsp_ops dsp_ops[] = {
|
||||
.init_fw = cnl_sst_init_fw,
|
||||
.cleanup = cnl_sst_dsp_cleanup
|
||||
},
|
||||
{
|
||||
.id = 0xa348,
|
||||
.num_cores = 4,
|
||||
.loader_ops = bxt_get_loader_ops,
|
||||
.init = cnl_sst_dsp_init,
|
||||
.init_fw = cnl_sst_init_fw,
|
||||
.cleanup = cnl_sst_dsp_cleanup
|
||||
},
|
||||
};
|
||||
|
||||
const struct skl_dsp_ops *skl_get_dsp_ops(int pci_id)
|
||||
|
@@ -180,6 +180,9 @@ int skl_get_dmic_geo(struct skl *skl)
|
||||
unsigned int dmic_geo = 0;
|
||||
u8 j;
|
||||
|
||||
if (!nhlt)
|
||||
return 0;
|
||||
|
||||
epnt = (struct nhlt_endpoint *)nhlt->desc;
|
||||
|
||||
for (j = 0; j < nhlt->endpoint_count; j++) {
|
||||
|
@@ -249,6 +249,8 @@ enum skl_ipc_glb_reply {
|
||||
IPC_GLB_REPLY_INVALID_CONFIG_DATA_LEN = 121,
|
||||
IPC_GLB_REPLY_GATEWAY_NOT_INITIALIZED = 140,
|
||||
IPC_GLB_REPLY_GATEWAY_NOT_EXIST = 141,
|
||||
IPC_GLB_REPLY_SCLK_ALREADY_RUNNING = 150,
|
||||
IPC_GLB_REPLY_MCLK_ALREADY_RUNNING = 151,
|
||||
|
||||
IPC_GLB_REPLY_PPL_NOT_INITIALIZED = 160,
|
||||
IPC_GLB_REPLY_PPL_NOT_EXIST = 161,
|
||||
@@ -392,18 +394,47 @@ int skl_ipc_process_notification(struct sst_generic_ipc *ipc,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int skl_ipc_set_reply_error_code(u32 reply)
|
||||
struct skl_ipc_err_map {
|
||||
const char *msg;
|
||||
enum skl_ipc_glb_reply reply;
|
||||
int err;
|
||||
};
|
||||
|
||||
static struct skl_ipc_err_map skl_err_map[] = {
|
||||
{"DSP out of memory", IPC_GLB_REPLY_OUT_OF_MEMORY, -ENOMEM},
|
||||
{"DSP busy", IPC_GLB_REPLY_BUSY, -EBUSY},
|
||||
{"SCLK already running", IPC_GLB_REPLY_SCLK_ALREADY_RUNNING,
|
||||
IPC_GLB_REPLY_SCLK_ALREADY_RUNNING},
|
||||
{"MCLK already running", IPC_GLB_REPLY_MCLK_ALREADY_RUNNING,
|
||||
IPC_GLB_REPLY_MCLK_ALREADY_RUNNING},
|
||||
};
|
||||
|
||||
static int skl_ipc_set_reply_error_code(struct sst_generic_ipc *ipc, u32 reply)
|
||||
{
|
||||
switch (reply) {
|
||||
case IPC_GLB_REPLY_OUT_OF_MEMORY:
|
||||
return -ENOMEM;
|
||||
int i;
|
||||
|
||||
case IPC_GLB_REPLY_BUSY:
|
||||
return -EBUSY;
|
||||
for (i = 0; i < ARRAY_SIZE(skl_err_map); i++) {
|
||||
if (skl_err_map[i].reply == reply)
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
if (i == ARRAY_SIZE(skl_err_map)) {
|
||||
dev_err(ipc->dev, "ipc FW reply: %d FW Error Code: %u\n",
|
||||
reply,
|
||||
ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (skl_err_map[i].err < 0)
|
||||
dev_err(ipc->dev, "ipc FW reply: %s FW Error Code: %u\n",
|
||||
skl_err_map[i].msg,
|
||||
ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp));
|
||||
else
|
||||
dev_info(ipc->dev, "ipc FW reply: %s FW Error Code: %u\n",
|
||||
skl_err_map[i].msg,
|
||||
ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp));
|
||||
|
||||
return skl_err_map[i].err;
|
||||
}
|
||||
|
||||
void skl_ipc_process_reply(struct sst_generic_ipc *ipc,
|
||||
@@ -441,10 +472,7 @@ void skl_ipc_process_reply(struct sst_generic_ipc *ipc,
|
||||
|
||||
}
|
||||
} else {
|
||||
msg->errno = skl_ipc_set_reply_error_code(reply);
|
||||
dev_err(ipc->dev, "ipc FW reply: reply=%d\n", reply);
|
||||
dev_err(ipc->dev, "FW Error Code: %u\n",
|
||||
ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp));
|
||||
msg->errno = skl_ipc_set_reply_error_code(ipc, reply);
|
||||
switch (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) {
|
||||
case IPC_GLB_LOAD_MULTIPLE_MODS:
|
||||
case IPC_GLB_LOAD_LIBRARY:
|
||||
|
@@ -507,7 +507,7 @@ static int skl_find_machine(struct skl *skl, void *driver_data)
|
||||
|
||||
if (pdata) {
|
||||
skl->use_tplg_pcm = pdata->use_tplg_pcm;
|
||||
pdata->dmic_num = skl_get_dmic_geo(skl);
|
||||
mach->mach_params.dmic_num = skl_get_dmic_geo(skl);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -517,7 +517,6 @@ static int skl_machine_device_register(struct skl *skl)
|
||||
{
|
||||
struct snd_soc_acpi_mach *mach = skl->mach;
|
||||
struct hdac_bus *bus = skl_to_bus(skl);
|
||||
struct skl_machine_pdata *pdata;
|
||||
struct platform_device *pdev;
|
||||
int ret;
|
||||
|
||||
@@ -527,6 +526,16 @@ static int skl_machine_device_register(struct skl *skl)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
mach->mach_params.platform = dev_name(bus->dev);
|
||||
mach->mach_params.codec_mask = bus->codec_mask;
|
||||
|
||||
ret = platform_device_add_data(pdev, (const void *)mach, sizeof(*mach));
|
||||
if (ret) {
|
||||
dev_err(bus->dev, "failed to add machine device platform data\n");
|
||||
platform_device_put(pdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = platform_device_add(pdev);
|
||||
if (ret) {
|
||||
dev_err(bus->dev, "failed to add machine device\n");
|
||||
@@ -534,12 +543,6 @@ static int skl_machine_device_register(struct skl *skl)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (mach->pdata) {
|
||||
pdata = (struct skl_machine_pdata *)mach->pdata;
|
||||
pdata->platform = dev_name(bus->dev);
|
||||
pdata->codec_mask = bus->codec_mask;
|
||||
dev_set_drvdata(&pdev->dev, mach->pdata);
|
||||
}
|
||||
|
||||
skl->i2s_dev = pdev;
|
||||
|
||||
@@ -811,12 +814,10 @@ static void skl_probe_work(struct work_struct *work)
|
||||
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;
|
||||
}
|
||||
err = skl_machine_device_register(skl);
|
||||
if (err < 0) {
|
||||
dev_err(bus->dev, "machine register failed: %d\n", err);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -895,6 +896,21 @@ static int skl_first_init(struct hdac_bus *bus)
|
||||
unsigned short gcap;
|
||||
int cp_streams, pb_streams, start_idx;
|
||||
|
||||
/*
|
||||
* detect DSP by checking class/subclass/prog-id information
|
||||
* class=04 subclass 03 prog-if 00: no DSP, legacy driver needs to be used
|
||||
* class=04 subclass 01 prog-if 00: DSP is present (and may be required e.g. for DMIC or SSP support)
|
||||
* class=04 subclass 03 prog-if 80: either of DSP or legacy mode can be used
|
||||
*/
|
||||
if (pci->class == 0x040300) {
|
||||
dev_err(bus->dev, "The DSP is not enabled on this platform, aborting probe\n");
|
||||
return -ENODEV;
|
||||
} else if (pci->class != 0x040100 && pci->class != 0x040380) {
|
||||
dev_err(bus->dev, "Unknown PCI class/subclass/prog-if information (0x%06x) found, aborting probe\n", pci->class);
|
||||
return -ENODEV;
|
||||
}
|
||||
dev_info(bus->dev, "DSP detected with PCI class/subclass/prog-if info 0x%06x\n", pci->class);
|
||||
|
||||
err = pci_request_regions(pci, "Skylake HD audio");
|
||||
if (err < 0)
|
||||
return err;
|
||||
@@ -910,6 +926,12 @@ static int skl_first_init(struct hdac_bus *bus)
|
||||
|
||||
snd_hdac_bus_parse_capabilities(bus);
|
||||
|
||||
/* check if PPCAP exists */
|
||||
if (!bus->ppcap) {
|
||||
dev_err(bus->dev, "bus ppcap not set, HDaudio or DSP not present?\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (skl_acquire_irq(bus, 0) < 0)
|
||||
return -EBUSY;
|
||||
|
||||
@@ -919,6 +941,17 @@ static int skl_first_init(struct hdac_bus *bus)
|
||||
gcap = snd_hdac_chip_readw(bus, GCAP);
|
||||
dev_dbg(bus->dev, "chipset global capabilities = 0x%x\n", gcap);
|
||||
|
||||
/* read number of streams from GCAP register */
|
||||
cp_streams = (gcap >> 8) & 0x0f;
|
||||
pb_streams = (gcap >> 12) & 0x0f;
|
||||
|
||||
if (!pb_streams && !cp_streams) {
|
||||
dev_err(bus->dev, "no streams found in GCAP definitions?\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
bus->num_streams = cp_streams + pb_streams;
|
||||
|
||||
/* 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));
|
||||
@@ -927,15 +960,6 @@ static int skl_first_init(struct hdac_bus *bus)
|
||||
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;
|
||||
|
||||
bus->num_streams = cp_streams + pb_streams;
|
||||
|
||||
/* initialize streams */
|
||||
snd_hdac_ext_stream_init_all
|
||||
(bus, 0, cp_streams, SNDRV_PCM_STREAM_CAPTURE);
|
||||
@@ -968,8 +992,10 @@ static int skl_probe(struct pci_dev *pci,
|
||||
bus = skl_to_bus(skl);
|
||||
|
||||
err = skl_first_init(bus);
|
||||
if (err < 0)
|
||||
if (err < 0) {
|
||||
dev_err(bus->dev, "skl_first_init failed with err: %d\n", err);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
skl->pci_id = pci->device;
|
||||
|
||||
@@ -978,37 +1004,48 @@ static int skl_probe(struct pci_dev *pci,
|
||||
skl->nhlt = skl_nhlt_init(bus->dev);
|
||||
|
||||
if (skl->nhlt == NULL) {
|
||||
#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
|
||||
dev_err(bus->dev, "no nhlt info found\n");
|
||||
err = -ENODEV;
|
||||
goto out_free;
|
||||
#else
|
||||
dev_warn(bus->dev, "no nhlt info found, continuing to try to enable HDaudio codec\n");
|
||||
#endif
|
||||
} else {
|
||||
|
||||
err = skl_nhlt_create_sysfs(skl);
|
||||
if (err < 0) {
|
||||
dev_err(bus->dev, "skl_nhlt_create_sysfs failed with err: %d\n", err);
|
||||
goto out_nhlt_free;
|
||||
}
|
||||
|
||||
skl_nhlt_update_topology_bin(skl);
|
||||
|
||||
/* create device for dsp clk */
|
||||
err = skl_clock_device_register(skl);
|
||||
if (err < 0) {
|
||||
dev_err(bus->dev, "skl_clock_device_register failed with err: %d\n", err);
|
||||
goto out_clk_free;
|
||||
}
|
||||
}
|
||||
|
||||
err = skl_nhlt_create_sysfs(skl);
|
||||
if (err < 0)
|
||||
goto out_nhlt_free;
|
||||
|
||||
skl_nhlt_update_topology_bin(skl);
|
||||
|
||||
pci_set_drvdata(skl->pci, bus);
|
||||
|
||||
/* check if dsp is there */
|
||||
if (bus->ppcap) {
|
||||
/* create device for dsp clk */
|
||||
err = skl_clock_device_register(skl);
|
||||
if (err < 0)
|
||||
goto out_clk_free;
|
||||
|
||||
err = skl_find_machine(skl, (void *)pci_id->driver_data);
|
||||
if (err < 0)
|
||||
goto out_nhlt_free;
|
||||
|
||||
err = skl_init_dsp(skl);
|
||||
if (err < 0) {
|
||||
dev_dbg(bus->dev, "error failed to register dsp\n");
|
||||
goto out_nhlt_free;
|
||||
}
|
||||
skl->skl_sst->enable_miscbdcge = skl_enable_miscbdcge;
|
||||
skl->skl_sst->clock_power_gating = skl_clock_power_gating;
|
||||
err = skl_find_machine(skl, (void *)pci_id->driver_data);
|
||||
if (err < 0) {
|
||||
dev_err(bus->dev, "skl_find_machine failed with err: %d\n", err);
|
||||
goto out_nhlt_free;
|
||||
}
|
||||
|
||||
err = skl_init_dsp(skl);
|
||||
if (err < 0) {
|
||||
dev_dbg(bus->dev, "error failed to register dsp\n");
|
||||
goto out_nhlt_free;
|
||||
}
|
||||
skl->skl_sst->enable_miscbdcge = skl_enable_miscbdcge;
|
||||
skl->skl_sst->clock_power_gating = skl_clock_power_gating;
|
||||
|
||||
if (bus->mlcap)
|
||||
snd_hdac_ext_bus_get_ml_capabilities(bus);
|
||||
|
||||
@@ -1016,8 +1053,10 @@ static int skl_probe(struct pci_dev *pci,
|
||||
|
||||
/* create device for soc dmic */
|
||||
err = skl_dmic_device_register(skl);
|
||||
if (err < 0)
|
||||
if (err < 0) {
|
||||
dev_err(bus->dev, "skl_dmic_device_register failed with err: %d\n", err);
|
||||
goto out_dsp_free;
|
||||
}
|
||||
|
||||
schedule_work(&skl->probe_work);
|
||||
|
||||
@@ -1085,21 +1124,36 @@ static void skl_remove(struct pci_dev *pci)
|
||||
|
||||
/* PCI IDs */
|
||||
static const struct pci_device_id skl_ids[] = {
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKL)
|
||||
/* Sunrise Point-LP */
|
||||
{ PCI_DEVICE(0x8086, 0x9d70),
|
||||
.driver_data = (unsigned long)&snd_soc_acpi_intel_skl_machines},
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_INTEL_APL)
|
||||
/* BXT-P */
|
||||
{ PCI_DEVICE(0x8086, 0x5a98),
|
||||
.driver_data = (unsigned long)&snd_soc_acpi_intel_bxt_machines},
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_INTEL_KBL)
|
||||
/* KBL */
|
||||
{ PCI_DEVICE(0x8086, 0x9D71),
|
||||
.driver_data = (unsigned long)&snd_soc_acpi_intel_kbl_machines},
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_INTEL_GLK)
|
||||
/* GLK */
|
||||
{ PCI_DEVICE(0x8086, 0x3198),
|
||||
.driver_data = (unsigned long)&snd_soc_acpi_intel_glk_machines},
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_INTEL_CNL)
|
||||
/* CNL */
|
||||
{ PCI_DEVICE(0x8086, 0x9dc8),
|
||||
.driver_data = (unsigned long)&snd_soc_acpi_intel_cnl_machines},
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_INTEL_CFL)
|
||||
/* CFL */
|
||||
{ PCI_DEVICE(0x8086, 0xa348),
|
||||
.driver_data = (unsigned long)&snd_soc_acpi_intel_cnl_machines},
|
||||
#endif
|
||||
{ 0, }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, skl_ids);
|
||||
|
@@ -119,10 +119,7 @@ struct skl_dma_params {
|
||||
};
|
||||
|
||||
struct skl_machine_pdata {
|
||||
u32 dmic_num;
|
||||
bool use_tplg_pcm; /* use dais and dai links from topology */
|
||||
const char *platform;
|
||||
u32 codec_mask;
|
||||
};
|
||||
|
||||
struct skl_dsp_ops {
|
||||
|
Reference in New Issue
Block a user