Skip to content

Commit

Permalink
ASoC: SOF: amd: Add support for Rembrandt plaform.
Browse files Browse the repository at this point in the history
Add pci driver and platform driver to enable SOF support on ACP6x
architecture based Rembrandt platform.

Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
Signed-off-by: V sujith kumar Reddy <Vsujithkumar.Reddy@amd.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20220913144319.1055302-3-Vsujithkumar.Reddy@amd.com
Signed-off-by: Mark Brown <broonie@kernel.org>
  • Loading branch information
V sujith kumar Reddy authored and Mark Brown committed Sep 20, 2022
1 parent 4da6b03 commit 41cb85b
Show file tree
Hide file tree
Showing 7 changed files with 351 additions and 1 deletion.
10 changes: 10 additions & 0 deletions sound/soc/sof/amd/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,14 @@ config SND_SOC_SOF_AMD_RENOIR
select SND_SOC_SOF_AMD_COMMON
help
Select this option for SOF support on AMD Renoir platform

config SND_SOC_SOF_AMD_REMBRANDT
tristate "SOF support for REMBRANDT"
depends on SND_SOC_SOF_PCI
select SND_SOC_SOF_AMD_COMMON
help
Select this option for SOF support on AMD Rembrandt platform
Say Y if you want to enable SOF on Rembrandt.
If unsure select "N".

endif
2 changes: 2 additions & 0 deletions sound/soc/sof/amd/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

snd-sof-amd-acp-objs := acp.o acp-loader.o acp-ipc.o acp-pcm.o acp-stream.o acp-trace.o acp-common.o
snd-sof-amd-renoir-objs := pci-rn.o renoir.o
snd-sof-amd-rembrandt-objs := pci-rmb.o rembrandt.o

obj-$(CONFIG_SND_SOC_SOF_AMD_COMMON) += snd-sof-amd-acp.o
obj-$(CONFIG_SND_SOC_SOF_AMD_RENOIR) +=snd-sof-amd-renoir.o
obj-$(CONFIG_SND_SOC_SOF_AMD_REMBRANDT) +=snd-sof-amd-rembrandt.o
8 changes: 7 additions & 1 deletion sound/soc/sof/amd/acp-dsp-offset.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,22 +49,28 @@
#define ACP_CONTROL 0x1004

#define ACP3X_I2S_PIN_CONFIG 0x1400
#define ACP6X_I2S_PIN_CONFIG 0x1440

/* Registers offsets from ACP_PGFSM block */
#define ACP3X_PGFSM_BASE 0x141C
#define ACP6X_PGFSM_BASE 0x1024
#define PGFSM_CONTROL_OFFSET 0x0
#define PGFSM_STATUS_OFFSET 0x4
#define ACP3X_CLKMUX_SEL 0x1424
#define ACP6X_CLKMUX_SEL 0x102C

/* Registers from ACP_INTR block */
#define ACP3X_EXT_INTR_STAT 0x1808
#define ACP6X_EXT_INTR_STAT 0x1A0C

#define ACP3X_DSP_SW_INTR_BASE 0x1814
#define ACP6X_DSP_SW_INTR_BASE 0x1808
#define DSP_SW_INTR_CNTL_OFFSET 0x0
#define DSP_SW_INTR_STAT_OFFSET 0x4
#define DSP_SW_INTR_TRIG_OFFSET 0x8
#define ACP_ERROR_STATUS 0x18C4
#define ACP3X_AXI2DAGB_SEM_0 0x1880
#define ACP6X_AXI2DAGB_SEM_0 0x1874

/* Registers from ACP_SHA block */
#define ACP_SHA_DSP_FW_QUALIFIER 0x1C70
Expand All @@ -78,5 +84,5 @@
#define ACP_SHA_PSP_ACK 0x1C74

#define ACP_SCRATCH_REG_0 0x10000

#define ACP6X_DSP_FUSION_RUNSTALL 0x0644
#endif
7 changes: 7 additions & 0 deletions sound/soc/sof/amd/acp-loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,12 +198,19 @@ EXPORT_SYMBOL_NS(acp_dsp_pre_fw_run, SND_SOC_SOF_AMD_COMMON);

int acp_sof_dsp_run(struct snd_sof_dev *sdev)
{
const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
int val;

snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_DSP0_RUNSTALL, ACP_DSP_RUN);
val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_DSP0_RUNSTALL);
dev_dbg(sdev->dev, "ACP_DSP0_RUNSTALL : 0x%0x\n", val);

/* Some platforms won't support fusion DSP,keep offset zero for no support */
if (desc->fusion_dsp_offset) {
snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->fusion_dsp_offset, ACP_DSP_RUN);
val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->fusion_dsp_offset);
dev_dbg(sdev->dev, "ACP_DSP0_FUSION_RUNSTALL : 0x%0x\n", val);
}
return 0;
}
EXPORT_SYMBOL_NS(acp_sof_dsp_run, SND_SOC_SOF_AMD_COMMON);
5 changes: 5 additions & 0 deletions sound/soc/sof/amd/acp.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

#define ACP_DSP_INTR_EN_MASK 0x00000001
#define ACP3X_SRAM_PTE_OFFSET 0x02050000
#define ACP6X_SRAM_PTE_OFFSET 0x03800000
#define PAGE_SIZE_4K_ENABLE 0x2
#define ACP_PAGE_SIZE 0x1000
#define ACP_DMA_CH_RUN 0x02
Expand All @@ -54,6 +55,7 @@
#define ACP_DSP_TO_HOST_IRQ 0x04

#define HOST_BRIDGE_CZN 0x1630
#define HOST_BRIDGE_RMB 0x14B5
#define ACP_SHA_STAT 0x8000
#define ACP_PSP_TIMEOUT_COUNTER 5
#define ACP_EXT_INTR_ERROR_STAT 0x20000000
Expand Down Expand Up @@ -150,6 +152,7 @@ struct sof_amd_acp_desc {
u32 i2s_pin_config_offset;
u32 hw_semaphore_offset;
u32 acp_clkmux_sel;
u32 fusion_dsp_offset;
};

/* Common device data struct for ACP devices */
Expand Down Expand Up @@ -223,6 +226,8 @@ extern struct snd_sof_dsp_ops sof_acp_common_ops;

extern struct snd_sof_dsp_ops sof_renoir_ops;
int sof_renoir_ops_init(struct snd_sof_dev *sdev);
extern struct snd_sof_dsp_ops sof_rembrandt_ops;
int sof_rembrandt_ops_init(struct snd_sof_dev *sdev);

int acp_dai_probe(struct snd_soc_dai *dai);
struct snd_soc_acpi_mach *amd_sof_machine_select(struct snd_sof_dev *sdev);
Expand Down
186 changes: 186 additions & 0 deletions sound/soc/sof/amd/pci-rmb.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
//
// 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) 2022 Advanced Micro Devices, Inc. All rights reserved.
//
// Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>

/*.
* PCI interface for Rembrandt ACP device
*/

#include <linux/module.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <sound/sof.h>
#include <sound/soc-acpi.h>

#include "../ops.h"
#include "../sof-pci-dev.h"
#include "../../amd/mach-config.h"
#include "acp.h"
#include "acp-dsp-offset.h"

#define ACP6x_REG_START 0x1240000
#define ACP6x_REG_END 0x125C000

static struct platform_device *dmic_dev;
static struct platform_device *pdev;

static const struct resource rembrandt_res[] = {
{
.start = 0,
.end = ACP6x_REG_END - ACP6x_REG_START,
.name = "acp_mem",
.flags = IORESOURCE_MEM,
},
{
.start = 0,
.end = 0,
.name = "acp_dai_irq",
.flags = IORESOURCE_IRQ,
},
};

static const struct sof_amd_acp_desc rembrandt_chip_info = {
.rev = 6,
.host_bridge_id = HOST_BRIDGE_RMB,
.i2s_mode = 0x0a,
.pgfsm_base = ACP6X_PGFSM_BASE,
.ext_intr_stat = ACP6X_EXT_INTR_STAT,
.dsp_intr_base = ACP6X_DSP_SW_INTR_BASE,
.sram_pte_offset = ACP6X_SRAM_PTE_OFFSET,
.i2s_pin_config_offset = ACP6X_I2S_PIN_CONFIG,
.hw_semaphore_offset = ACP6X_AXI2DAGB_SEM_0,
.acp_clkmux_sel = ACP6X_CLKMUX_SEL,
.fusion_dsp_offset = ACP6X_DSP_FUSION_RUNSTALL,
};

static const struct sof_dev_desc rembrandt_desc = {
.machines = snd_soc_acpi_amd_rmb_sof_machines,
.resindex_lpe_base = 0,
.resindex_pcicfg_base = -1,
.resindex_imr_base = -1,
.irqindex_host_ipc = -1,
.chip_info = &rembrandt_chip_info,
.ipc_supported_mask = BIT(SOF_IPC),
.ipc_default = SOF_IPC,
.default_fw_path = {
[SOF_IPC] = "amd/sof",
},
.default_tplg_path = {
[SOF_IPC] = "amd/sof-tplg",
},
.default_fw_filename = {
[SOF_IPC] = "sof-rmb.ri",
},
.nocodec_tplg_filename = "sof-acp.tplg",
.ops = &sof_rembrandt_ops,
.ops_init = sof_rembrandt_ops_init,
};

static int acp_pci_rmb_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
{
struct platform_device_info pdevinfo;
struct device *dev = &pci->dev;
const struct resource *res_i2s;
struct resource *res;
unsigned int flag, i, addr;
int ret;

flag = snd_amd_acp_find_config(pci);
if (flag != FLAG_AMD_SOF && flag != FLAG_AMD_SOF_ONLY_DMIC)
return -ENODEV;

ret = sof_pci_probe(pci, pci_id);
if (ret != 0)
return ret;

dmic_dev = platform_device_register_data(dev, "dmic-codec", PLATFORM_DEVID_NONE, NULL, 0);
if (IS_ERR(dmic_dev)) {
dev_err(dev, "failed to create DMIC device\n");
sof_pci_remove(pci);
return PTR_ERR(dmic_dev);
}

/* Register platform device only if flag set to FLAG_AMD_SOF_ONLY_DMIC */
if (flag != FLAG_AMD_SOF_ONLY_DMIC)
return 0;

addr = pci_resource_start(pci, 0);
res = devm_kzalloc(&pci->dev, sizeof(struct resource) * ARRAY_SIZE(rembrandt_res),
GFP_KERNEL);
if (!res) {
platform_device_unregister(dmic_dev);
sof_pci_remove(pci);
return -ENOMEM;
}

res_i2s = rembrandt_res;
for (i = 0; i < ARRAY_SIZE(rembrandt_res); i++, res_i2s++) {
res[i].name = res_i2s->name;
res[i].flags = res_i2s->flags;
res[i].start = addr + res_i2s->start;
res[i].end = addr + res_i2s->end;
if (res_i2s->flags == IORESOURCE_IRQ) {
res[i].start = pci->irq;
res[i].end = res[i].start;
}
}

memset(&pdevinfo, 0, sizeof(pdevinfo));

/*
* We have common PCI driver probe for ACP device but we have to support I2S without SOF
* for some distributions. Register platform device that will be used to support non dsp
* ACP's audio ends points on some machines.
*/
pdevinfo.name = "acp_asoc_rembrandt";
pdevinfo.id = 0;
pdevinfo.parent = &pci->dev;
pdevinfo.num_res = ARRAY_SIZE(rembrandt_res);
pdevinfo.res = &res[0];

pdev = platform_device_register_full(&pdevinfo);
if (IS_ERR(pdev)) {
dev_err(&pci->dev, "cannot register %s device\n", pdevinfo.name);
platform_device_unregister(dmic_dev);
sof_pci_remove(pci);
ret = PTR_ERR(pdev);
}

return ret;
};

static void acp_pci_rmb_remove(struct pci_dev *pci)
{
if (dmic_dev)
platform_device_unregister(dmic_dev);
if (pdev)
platform_device_unregister(pdev);

sof_pci_remove(pci);
}

/* PCI IDs */
static const struct pci_device_id rmb_pci_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, ACP_PCI_DEV_ID),
.driver_data = (unsigned long)&rembrandt_desc},
{ 0, }
};
MODULE_DEVICE_TABLE(pci, rmb_pci_ids);

/* pci_driver definition */
static struct pci_driver snd_sof_pci_amd_rmb_driver = {
.name = KBUILD_MODNAME,
.id_table = rmb_pci_ids,
.probe = acp_pci_rmb_probe,
.remove = acp_pci_rmb_remove,
};
module_pci_driver(snd_sof_pci_amd_rmb_driver);

MODULE_LICENSE("Dual BSD/GPL");
MODULE_IMPORT_NS(SND_SOC_SOF_AMD_COMMON);
MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV);
Loading

0 comments on commit 41cb85b

Please sign in to comment.