Unverified Commit 4da6b033 authored by Ajit Kumar Pandey's avatar Ajit Kumar Pandey Committed by Mark Brown
Browse files

ASoC: SOF: amd: Make ACP core code generic for newer SOC transition



Newer AMD SOC differs slightly in terms of few registers offset and
configuration. Add offsets into chip_info struct to make core ACP
code more generic and resusable on newer SOC.

Signed-off-by: default avatarAjit Kumar Pandey <AjitKumar.Pandey@amd.com>
Signed-off-by: default avatarV sujith kumar Reddy <Vsujithkumar.Reddy@amd.com>
Reviewed-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20220913144319.1055302-2-Vsujithkumar.Reddy@amd.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 9f27530a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@
#
# Copyright(c) 2021 Advanced Micro Devices, Inc. All rights reserved.

snd-sof-amd-acp-objs := acp.o acp-loader.o acp-ipc.o acp-pcm.o acp-stream.o acp-trace.o
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

obj-$(CONFIG_SND_SOC_SOF_AMD_COMMON) += snd-sof-amd-acp.o
+110 −0
Original line number Diff line number Diff line
// 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.
//
// Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
//	    V sujith kumar Reddy <Vsujithkumar.Reddy@amd.com>

/* ACP-specific Common code */

#include "../sof-priv.h"
#include "../sof-audio.h"
#include "../ops.h"
#include "../sof-audio.h"
#include "acp.h"
#include "acp-dsp-offset.h"

int acp_dai_probe(struct snd_soc_dai *dai)
{
	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component);
	const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
	unsigned int val;

	val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->i2s_pin_config_offset);
	if (val != desc->i2s_mode) {
		dev_err(sdev->dev, "I2S Mode is not supported (I2S_PIN_CONFIG: %#x)\n", val);
		return -EINVAL;
	}

	return 0;
}
EXPORT_SYMBOL_NS(acp_dai_probe, SND_SOC_SOF_AMD_COMMON);

struct snd_soc_acpi_mach *amd_sof_machine_select(struct snd_sof_dev *sdev)
{
	struct snd_sof_pdata *sof_pdata = sdev->pdata;
	const struct sof_dev_desc *desc = sof_pdata->desc;
	struct snd_soc_acpi_mach *mach;

	mach = snd_soc_acpi_find_machine(desc->machines);
	if (!mach) {
		dev_warn(sdev->dev, "No matching ASoC machine driver found\n");
		return NULL;
	}

	sof_pdata->tplg_filename = mach->sof_tplg_filename;
	sof_pdata->fw_filename = mach->fw_filename;

	return mach;
}

/* AMD Common DSP ops */
struct snd_sof_dsp_ops sof_acp_common_ops = {
	/* probe and remove */
	.probe			= amd_sof_acp_probe,
	.remove			= amd_sof_acp_remove,

	/* Register IO */
	.write			= sof_io_write,
	.read			= sof_io_read,

	/* Block IO */
	.block_read		= acp_dsp_block_read,
	.block_write		= acp_dsp_block_write,

	/*Firmware loading */
	.load_firmware		= snd_sof_load_firmware_memcpy,
	.pre_fw_run		= acp_dsp_pre_fw_run,
	.get_bar_index		= acp_get_bar_index,

	/* DSP core boot */
	.run			= acp_sof_dsp_run,

	/*IPC */
	.send_msg		= acp_sof_ipc_send_msg,
	.ipc_msg_data		= acp_sof_ipc_msg_data,
	.get_mailbox_offset	= acp_sof_ipc_get_mailbox_offset,
	.irq_thread		= acp_sof_ipc_irq_thread,

	/* stream callbacks */
	.pcm_open		= acp_pcm_open,
	.pcm_close		= acp_pcm_close,
	.pcm_hw_params		= acp_pcm_hw_params,

	.hw_info		= SNDRV_PCM_INFO_MMAP |
				  SNDRV_PCM_INFO_MMAP_VALID |
				  SNDRV_PCM_INFO_INTERLEAVED |
				  SNDRV_PCM_INFO_PAUSE |
				  SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,

	/* Machine driver callbacks */
	.machine_select		= amd_sof_machine_select,
	.machine_register	= sof_machine_register,
	.machine_unregister	= sof_machine_unregister,

	/* Trace Logger */
	.trace_init		= acp_sof_trace_init,
	.trace_release		= acp_sof_trace_release,

	/* PM */
	.suspend                = amd_sof_acp_suspend,
	.resume                 = amd_sof_acp_resume,
};
EXPORT_SYMBOL_NS(sof_acp_common_ops, SND_SOC_SOF_AMD_COMMON);

MODULE_IMPORT_NS(SND_SOC_SOF_AMD_COMMON);
MODULE_DESCRIPTION("ACP SOF COMMON Driver");
MODULE_LICENSE("Dual BSD/GPL");
+13 −12
Original line number Diff line number Diff line
@@ -48,22 +48,23 @@
#define ACP_SOFT_RESET				0x1000
#define ACP_CONTROL				0x1004

#define ACP_I2S_PIN_CONFIG			0x1400
#define ACP3X_I2S_PIN_CONFIG			0x1400

/* Registers from ACP_PGFSM block */
#define ACP_PGFSM_CONTROL			0x141C
#define ACP_PGFSM_STATUS			0x1420
#define ACP_CLKMUX_SEL				0x1424
/* Registers offsets from ACP_PGFSM block */
#define ACP3X_PGFSM_BASE			0x141C
#define PGFSM_CONTROL_OFFSET			0x0
#define PGFSM_STATUS_OFFSET			0x4
#define ACP3X_CLKMUX_SEL			0x1424

/* Registers from ACP_INTR block */
#define ACP_EXTERNAL_INTR_ENB			0x1800
#define ACP_EXTERNAL_INTR_CNTL			0x1804
#define ACP_EXTERNAL_INTR_STAT			0x1808
#define ACP_DSP_SW_INTR_CNTL			0x1814
#define ACP_DSP_SW_INTR_STAT                    0x1818
#define ACP_SW_INTR_TRIG                        0x181C
#define ACP3X_EXT_INTR_STAT			0x1808

#define ACP3X_DSP_SW_INTR_BASE			0x1814
#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 ACP_AXI2DAGB_SEM_0			0x1880
#define ACP3X_AXI2DAGB_SEM_0			0x1880

/* Registers from ACP_SHA block */
#define ACP_SHA_DSP_FW_QUALIFIER		0x1C70
+11 −5
Original line number Diff line number Diff line
@@ -30,11 +30,14 @@ EXPORT_SYMBOL_NS(acp_mailbox_read, SND_SOC_SOF_AMD_COMMON);
static void acpbus_trigger_host_to_dsp_swintr(struct acp_dev_data *adata)
{
	struct snd_sof_dev *sdev = adata->dev;
	const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
	u32 swintr_trigger;

	swintr_trigger = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_SW_INTR_TRIG);
	swintr_trigger = snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->dsp_intr_base +
						DSP_SW_INTR_TRIG_OFFSET);
	swintr_trigger |= 0x01;
	snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SW_INTR_TRIG, swintr_trigger);
	snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->dsp_intr_base + DSP_SW_INTR_TRIG_OFFSET,
			  swintr_trigger);
}

static void acp_ipc_host_msg_set(struct snd_sof_dev *sdev)
@@ -61,10 +64,11 @@ static void acp_dsp_ipc_dsp_done(struct snd_sof_dev *sdev)
int acp_sof_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
{
	struct acp_dev_data *adata = sdev->pdata->hw_pdata;
	const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
	unsigned int offset = offsetof(struct scratch_ipc_conf, sof_in_box);
	unsigned int count = ACP_HW_SEM_RETRY_COUNT;

	while (snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_AXI2DAGB_SEM_0)) {
	while (snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->hw_semaphore_offset)) {
		/* Wait until acquired HW Semaphore Lock or timeout*/
		count--;
		if (!count) {
@@ -80,7 +84,7 @@ int acp_sof_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
	acpbus_trigger_host_to_dsp_swintr(adata);

	/* Unlock or Release HW Semaphore */
	snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_AXI2DAGB_SEM_0, 0x0);
	snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->hw_semaphore_offset, 0x0);

	return 0;
}
@@ -186,7 +190,9 @@ EXPORT_SYMBOL_NS(acp_sof_ipc_msg_data, SND_SOC_SOF_AMD_COMMON);

int acp_sof_ipc_get_mailbox_offset(struct snd_sof_dev *sdev)
{
	return ACP_SCRATCH_MEMORY_ADDRESS;
	const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);

	return desc->sram_pte_offset;
}
EXPORT_SYMBOL_NS(acp_sof_ipc_get_mailbox_offset, SND_SOC_SOF_AMD_COMMON);

+7 −6
Original line number Diff line number Diff line
@@ -30,9 +30,10 @@
int acp_dsp_block_read(struct snd_sof_dev *sdev, enum snd_sof_fw_blk_type blk_type,
		       u32 offset, void *dest, size_t size)
{
	const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
	switch (blk_type) {
	case SOF_FW_BLK_TYPE_SRAM:
		offset = offset - ACP_SCRATCH_MEMORY_ADDRESS;
		offset = offset - desc->sram_pte_offset;
		memcpy_from_scratch(sdev, offset, dest, size);
		break;
	default:
@@ -49,6 +50,7 @@ int acp_dsp_block_write(struct snd_sof_dev *sdev, enum snd_sof_fw_blk_type blk_t
{
	struct snd_sof_pdata *plat_data = sdev->pdata;
	struct pci_dev *pci = to_pci_dev(sdev->dev);
	const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
	struct acp_dev_data *adata;
	void *dest;
	u32 dma_size, page_count;
@@ -84,7 +86,7 @@ int acp_dsp_block_write(struct snd_sof_dev *sdev, enum snd_sof_fw_blk_type blk_t
		adata->fw_data_bin_size = size + offset;
		break;
	case SOF_FW_BLK_TYPE_SRAM:
		offset = offset - ACP_SCRATCH_MEMORY_ADDRESS;
		offset = offset - desc->sram_pte_offset;
		memcpy_to_scratch(sdev, offset, src, size);
		return 0;
	default:
@@ -105,14 +107,13 @@ EXPORT_SYMBOL_NS(acp_get_bar_index, SND_SOC_SOF_AMD_COMMON);

static void configure_pte_for_fw_loading(int type, int num_pages, struct acp_dev_data *adata)
{
	struct snd_sof_dev *sdev;
	struct snd_sof_dev *sdev = adata->dev;
	const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
	unsigned int low, high;
	dma_addr_t addr;
	u16 page_idx;
	u32 offset;

	sdev = adata->dev;

	switch (type) {
	case FW_BIN:
		offset = FW_BIN_PTE_OFFSET;
@@ -129,7 +130,7 @@ static void configure_pte_for_fw_loading(int type, int num_pages, struct acp_dev

	/* Group Enable */
	snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACPAXI2AXI_ATU_BASE_ADDR_GRP_1,
			  ACP_SRAM_PTE_OFFSET | BIT(31));
			  desc->sram_pte_offset | BIT(31));
	snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1,
			  PAGE_SIZE_4K_ENABLE);

Loading