[01/13] ASoC: amd: acp: Add acp6.3 pci legacy driver support

Message ID 20231021145110.478744-1-Syed.SabaKareem@amd.com
State New
Headers
Series [01/13] ASoC: amd: acp: Add acp6.3 pci legacy driver support |

Commit Message

Saba Kareem, Syed Oct. 21, 2023, 2:50 p.m. UTC
  Add pci legacy driver support and create platform driver for
acp6.3 based platforms.

Signed-off-by: Syed Saba Kareem <Syed.SabaKareem@amd.com>
---
 sound/soc/amd/acp/acp-legacy-common.c |   4 +
 sound/soc/amd/acp/acp-pci.c           |   4 +
 sound/soc/amd/acp/acp63.c             | 314 ++++++++++++++++++++++++++
 sound/soc/amd/acp/amd.h               |   4 +
 4 files changed, 326 insertions(+)
 create mode 100644 sound/soc/amd/acp/acp63.c
  

Comments

Krzysztof Kozlowski Oct. 23, 2023, 8:01 a.m. UTC | #1
On 21/10/2023 16:50, Syed Saba Kareem wrote:
> Add pci legacy driver support and create platform driver for
> acp6.3 based platforms.
> 
> Signed-off-by: Syed Saba Kareem <Syed.SabaKareem@amd.com>
> ---
>  sound/soc/amd/acp/acp-legacy-common.c |   4 +
>  sound/soc/amd/acp/acp-pci.c           |   4 +
>  sound/soc/amd/acp/acp63.c             | 314 ++++++++++++++++++++++++++
>  sound/soc/amd/acp/amd.h               |   4 +
>  4 files changed, 326 insertions(+)
>  create mode 100644 sound/soc/amd/acp/acp63.c
> 


> +
> +static const struct dev_pm_ops acp63_dma_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(NULL, acp63_pcm_resume)
> +};
> +
> +static struct platform_driver acp63_driver = {
> +	.probe = acp63_audio_probe,
> +	.remove_new = acp63_audio_remove,
> +	.driver = {
> +		.name = "acp_asoc_acp63",
> +		.pm = &acp63_dma_pm_ops,
> +	},
> +};
> +
> +module_platform_driver(acp63_driver);
> +
> +MODULE_DESCRIPTION("AMD ACP acp63 Driver");
> +MODULE_IMPORT_NS(SND_SOC_ACP_COMMON);
> +MODULE_LICENSE("Dual BSD/GPL");
> +MODULE_ALIAS("platform:" DRV_NAME);

You should not need MODULE_ALIAS() in normal cases. If you need it,
usually it means your device ID table is wrong.


Best regards,
Krzysztof
  
Mark Brown Oct. 25, 2023, 4:50 p.m. UTC | #2
On Sat, Oct 21, 2023 at 08:20:42PM +0530, Syed Saba Kareem wrote:
> Add pci legacy driver support and create platform driver for
> acp6.3 based platforms.

I've queued this series for CI - there were some valid concerns that
Amadeusz and Krzysztof raised but they're relatively minor, please send
incremental patches fixing these issues (assuming CI is fine).
  
syed saba kareem Oct. 26, 2023, 9:44 a.m. UTC | #3
Will send the fixes as incremental patches.

On 10/25/23 22:20, Mark Brown wrote:
> On Sat, Oct 21, 2023 at 08:20:42PM +0530, Syed Saba Kareem wrote:
>> Add pci legacy driver support and create platform driver for
>> acp6.3 based platforms.
> I've queued this series for CI - there were some valid concerns that
> Amadeusz and Krzysztof raised but they're relatively minor, please send
> incremental patches fixing these issues (assuming CI is fine).
  
Krzysztof Kozlowski Oct. 26, 2023, 3 p.m. UTC | #4
On Thu, 26 Oct 2023 at 12:09, syed saba kareem <ssabakar@amd.com> wrote:
> +
> +module_platform_driver(acp63_driver);
> +
> +MODULE_DESCRIPTION("AMD ACP acp63 Driver");
> +MODULE_IMPORT_NS(SND_SOC_ACP_COMMON);
> +MODULE_LICENSE("Dual BSD/GPL");
> +MODULE_ALIAS("platform:" DRV_NAME);
>
> You should not need MODULE_ALIAS() in normal cases. If you need it,
> usually it means your device ID table is wrong.
>
> It is platform driver ,for auto loading MODULE_ALIAS() is required.

Hm, not really. platform_driver does not need MODULE_ALIAS(). At least
99% of them do not need it. Please help us understand what is broken
here that this one platform driver needs alias.

BR,
Krzysztof
  
Mark Brown Oct. 26, 2023, 3:12 p.m. UTC | #5
On Sat, 21 Oct 2023 20:20:42 +0530, Syed Saba Kareem wrote:
> Add pci legacy driver support and create platform driver for
> acp6.3 based platforms.
> 
> 

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next

Thanks!

[01/13] ASoC: amd: acp: Add acp6.3 pci legacy driver support
        commit: 33d120a49b970acbe465041d7b71e0cd6a1d1de0
[02/13] ASoC: amd: acp: refactor acp i2s clock generation code
        commit: 40f74d5f09d7c068bd7a980dc06a688dc8d2b3e3
[03/13] ASoC: amd: acp: add i2s clock generation support for acp6.3 based platforms
        commit: c7bf9156f811bcffb4201a0bf5d1b32d97ec0e5f
[04/13] ASoC: amd: acp: add machine driver support for acp6.3 platform
        commit: 9393bfb4c4dea406dd345820a6b39b9c70a7f934
[05/13] ASoC: amd: acp: add Kconfig options for acp6.3 based platform driver
        commit: d4c2d5391d7efc29fdd59d54355526c9ace16bec
[06/13] ASoC: amd: acp: add code for scanning acp pdm controller
        commit: 3a94c8ad0aae2b14a55059869871ea2d199af489
[07/13] ASoC: amd: acp: add platform and flag data to acp data structure
        commit: 57e857770f6021a73af85e6b201203520cb1a529
[08/13] ASoC: amd: acp: add condition check for i2s clock generation
        commit: 16fb2a25440a85708778f6442914066c98dc2f1e
[09/13] ASoC: amd: acp: add machine driver support for pdm use case
        commit: 39d9ee47167a2210d803f651c8fdcac84f03e766
[10/13] ASoC: amd: acp: change acp-deinit function arguments
        commit: 1b6180c095bc9a6c25e38ae1ec6481f8df20a81f
[11/13] ASoC: amd: acp: change acp power on mask macro value
        commit: caa126f2b0c821811eedf2e2fd435b11844bf0f1
[12/13] ASoC: amd: acp: Add pci legacy driver support for acp7.0 platform
        commit: e84db124cb2158b538820f31f641c28b86fb3ca3
[13/13] ASoC: amd: acp: add machine driver support for acp7.0
        commit: b97f4dac40eecfc2fc9b818b427a8eda44cb7763

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark
  

Patch

diff --git a/sound/soc/amd/acp/acp-legacy-common.c b/sound/soc/amd/acp/acp-legacy-common.c
index 217b4c89b975..e16ef94e6336 100644
--- a/sound/soc/amd/acp/acp-legacy-common.c
+++ b/sound/soc/amd/acp/acp-legacy-common.c
@@ -260,6 +260,10 @@  static int acp_power_on(struct acp_chip_info *chip)
 		acp_pgfsm_stat_reg = ACP6X_PGFSM_STATUS;
 		acp_pgfsm_ctrl_reg = ACP6X_PGFSM_CONTROL;
 		break;
+	case ACP63_DEV:
+		acp_pgfsm_stat_reg = ACP63_PGFSM_STATUS;
+		acp_pgfsm_ctrl_reg = ACP63_PGFSM_CONTROL;
+		break;
 	default:
 		return -EINVAL;
 	}
diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c
index a32c14a109b7..d7fc4a0e9245 100644
--- a/sound/soc/amd/acp/acp-pci.c
+++ b/sound/soc/amd/acp/acp-pci.c
@@ -87,6 +87,10 @@  static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
 		chip->name = "acp_asoc_rembrandt";
 		chip->acp_rev = ACP6X_DEV;
 		break;
+	case 0x63:
+		chip->name = "acp_asoc_acp63";
+		chip->acp_rev = ACP63_DEV;
+		break;
 	default:
 		dev_err(dev, "Unsupported device revision:0x%x\n", pci->revision);
 		ret = -EINVAL;
diff --git a/sound/soc/amd/acp/acp63.c b/sound/soc/amd/acp/acp63.c
new file mode 100644
index 000000000000..f94348ad863d
--- /dev/null
+++ b/sound/soc/amd/acp/acp63.c
@@ -0,0 +1,314 @@ 
+// 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) 2023 Advanced Micro Devices, Inc.
+//
+// Authors: Syed Saba kareem <syed.sabakareem@amd.com>
+/*
+ * Hardware interface for ACP6.3 block
+ */
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+#include <linux/dma-mapping.h>
+#include <linux/pm_runtime.h>
+#include <linux/pci.h>
+#include "amd.h"
+
+#define DRV_NAME "acp_asoc_acp63"
+
+#define CLK_PLL_PWR_REQ_N0		0X0006C2C0
+#define CLK_SPLL_FIELD_2_N0		0X0006C114
+#define CLK_PLL_REQ_N0			0X0006C0DC
+#define CLK_DFSBYPASS_CONTR		0X0006C2C8
+#define CLK_DFS_CNTL_N0			0X0006C1A4
+
+#define PLL_AUTO_STOP_REQ		BIT(4)
+#define PLL_AUTO_START_REQ		BIT(0)
+#define PLL_FRANCE_EN			BIT(4)
+#define EXIT_DPF_BYPASS_0		BIT(16)
+#define EXIT_DPF_BYPASS_1		BIT(17)
+#define CLK0_DIVIDER			0X30
+
+union clk_pll_req_no {
+	struct {
+		u32 fb_mult_int : 9;
+		u32 reserved : 3;
+		u32 pll_spine_div : 4;
+		u32 gb_mult_frac : 16;
+	} bitfields, bits;
+	u32 clk_pll_req_no_reg;
+};
+
+static struct acp_resource rsrc = {
+	.offset = 0,
+	.no_of_ctrls = 2,
+	.irqp_used = 1,
+	.soc_mclk = true,
+	.irq_reg_offset = 0x1a00,
+	.i2s_pin_cfg_offset = 0x1440,
+	.i2s_mode = 0x0a,
+	.scratch_reg_offset = 0x12800,
+	.sram_pte_offset = 0x03802800,
+};
+
+static struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_acp_machines[] = {
+	{
+		.id = "AMDI0052",
+		.drv_name = "acp63-acp",
+	},
+	{},
+};
+
+static struct snd_soc_dai_driver acp63_dai[] = {
+{
+	.name = "acp-i2s-sp",
+	.id = I2S_SP_INSTANCE,
+	.playback = {
+		.stream_name = "I2S SP Playback",
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+		.channels_min = 2,
+		.channels_max = 8,
+		.rate_min = 8000,
+		.rate_max = 96000,
+	},
+	.capture = {
+		.stream_name = "I2S SP Capture",
+		.rates = SNDRV_PCM_RATE_8000_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+		.channels_min = 2,
+		.channels_max = 2,
+		.rate_min = 8000,
+		.rate_max = 48000,
+	},
+	.ops = &asoc_acp_cpu_dai_ops,
+},
+{
+	.name = "acp-i2s-bt",
+	.id = I2S_BT_INSTANCE,
+	.playback = {
+		.stream_name = "I2S BT Playback",
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+		.channels_min = 2,
+		.channels_max = 8,
+		.rate_min = 8000,
+		.rate_max = 96000,
+	},
+	.capture = {
+		.stream_name = "I2S BT Capture",
+		.rates = SNDRV_PCM_RATE_8000_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+		.channels_min = 2,
+		.channels_max = 2,
+		.rate_min = 8000,
+		.rate_max = 48000,
+	},
+	.ops = &asoc_acp_cpu_dai_ops,
+},
+{
+	.name = "acp-i2s-hs",
+	.id = I2S_HS_INSTANCE,
+	.playback = {
+		.stream_name = "I2S HS Playback",
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+		.channels_min = 2,
+		.channels_max = 8,
+		.rate_min = 8000,
+		.rate_max = 96000,
+	},
+	.capture = {
+		.stream_name = "I2S HS Capture",
+		.rates = SNDRV_PCM_RATE_8000_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+		.channels_min = 2,
+		.channels_max = 8,
+		.rate_min = 8000,
+		.rate_max = 48000,
+	},
+	.ops = &asoc_acp_cpu_dai_ops,
+},
+{
+	.name = "acp-pdm-dmic",
+	.id = DMIC_INSTANCE,
+	.capture = {
+		.rates = SNDRV_PCM_RATE_8000_48000,
+		.formats = SNDRV_PCM_FMTBIT_S32_LE,
+		.channels_min = 2,
+		.channels_max = 2,
+		.rate_min = 8000,
+		.rate_max = 48000,
+	},
+	.ops = &acp_dmic_dai_ops,
+},
+};
+
+static int acp63_i2s_master_clock_generate(struct acp_dev_data *adata)
+{
+	u32 data;
+	union clk_pll_req_no clk_pll;
+	struct pci_dev *smn_dev;
+
+	smn_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x14E8, NULL);
+	if (!smn_dev)
+		return -ENODEV;
+
+	/* Clk5 pll register values to get mclk as 196.6MHz*/
+	clk_pll.bits.fb_mult_int = 0x31;
+	clk_pll.bits.pll_spine_div = 0;
+	clk_pll.bits.gb_mult_frac = 0x26E9;
+
+	data = smn_read(smn_dev, CLK_PLL_PWR_REQ_N0);
+	smn_write(smn_dev, CLK_PLL_PWR_REQ_N0, data | PLL_AUTO_STOP_REQ);
+
+	data = smn_read(smn_dev, CLK_SPLL_FIELD_2_N0);
+	if (data & PLL_FRANCE_EN)
+		smn_write(smn_dev, CLK_SPLL_FIELD_2_N0, data | PLL_FRANCE_EN);
+
+	smn_write(smn_dev, CLK_PLL_REQ_N0, clk_pll.clk_pll_req_no_reg);
+
+	data = smn_read(smn_dev, CLK_PLL_PWR_REQ_N0);
+	smn_write(smn_dev, CLK_PLL_PWR_REQ_N0, data | PLL_AUTO_START_REQ);
+
+	data = smn_read(smn_dev, CLK_DFSBYPASS_CONTR);
+	smn_write(smn_dev, CLK_DFSBYPASS_CONTR, data | EXIT_DPF_BYPASS_0);
+	smn_write(smn_dev, CLK_DFSBYPASS_CONTR, data | EXIT_DPF_BYPASS_1);
+
+	smn_write(smn_dev, CLK_DFS_CNTL_N0, CLK0_DIVIDER);
+	return 0;
+}
+
+static int acp63_audio_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct acp_chip_info *chip;
+	struct acp_dev_data *adata;
+	struct resource *res;
+	int ret;
+
+	chip = dev_get_platdata(&pdev->dev);
+	if (!chip || !chip->base) {
+		dev_err(&pdev->dev, "ACP chip data is NULL\n");
+		return -ENODEV;
+	}
+
+	if (chip->acp_rev != ACP63_DEV) {
+		dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev);
+		return -ENODEV;
+	}
+
+	adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL);
+	if (!adata)
+		return -ENOMEM;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "acp_mem");
+	if (!res) {
+		dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
+		return -ENODEV;
+	}
+
+	adata->acp_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!adata->acp_base)
+		return -ENOMEM;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "acp_dai_irq");
+	if (!res) {
+		dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
+		return -ENODEV;
+	}
+
+	adata->i2s_irq = res->start;
+	adata->dev = dev;
+	adata->dai_driver = acp63_dai;
+	adata->num_dai = ARRAY_SIZE(acp63_dai);
+	adata->rsrc = &rsrc;
+	adata->machines = snd_soc_acpi_amd_acp63_acp_machines;
+	acp_machine_select(adata);
+	dev_set_drvdata(dev, adata);
+	ret = acp63_i2s_master_clock_generate(adata);
+	if (ret)
+		return ret;
+
+	acp_enable_interrupts(adata);
+	acp_platform_register(dev);
+	pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS);
+	pm_runtime_use_autosuspend(&pdev->dev);
+	pm_runtime_mark_last_busy(&pdev->dev);
+	pm_runtime_set_active(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+	return 0;
+}
+
+static void acp63_audio_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct acp_dev_data *adata = dev_get_drvdata(dev);
+
+	acp_disable_interrupts(adata);
+	acp_platform_unregister(dev);
+	pm_runtime_disable(&pdev->dev);
+}
+
+static int __maybe_unused acp63_pcm_resume(struct device *dev)
+{
+	struct acp_dev_data *adata = dev_get_drvdata(dev);
+	struct acp_stream *stream;
+	struct snd_pcm_substream *substream;
+	snd_pcm_uframes_t buf_in_frames;
+	u64 buf_size;
+
+	acp63_i2s_master_clock_generate(adata);
+	spin_lock(&adata->acp_lock);
+	list_for_each_entry(stream, &adata->stream_list, list) {
+		if (stream) {
+			substream = stream->substream;
+			if (substream && substream->runtime) {
+				buf_in_frames = (substream->runtime->buffer_size);
+				buf_size = frames_to_bytes(substream->runtime, buf_in_frames);
+				config_pte_for_stream(adata, stream);
+				config_acp_dma(adata, stream, buf_size);
+				if (stream->dai_id)
+					restore_acp_i2s_params(substream, adata, stream);
+				else
+					restore_acp_pdm_params(substream, adata);
+			}
+		}
+	}
+	spin_unlock(&adata->acp_lock);
+	return 0;
+}
+
+static const struct dev_pm_ops acp63_dma_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(NULL, acp63_pcm_resume)
+};
+
+static struct platform_driver acp63_driver = {
+	.probe = acp63_audio_probe,
+	.remove_new = acp63_audio_remove,
+	.driver = {
+		.name = "acp_asoc_acp63",
+		.pm = &acp63_dma_pm_ops,
+	},
+};
+
+module_platform_driver(acp63_driver);
+
+MODULE_DESCRIPTION("AMD ACP acp63 Driver");
+MODULE_IMPORT_NS(SND_SOC_ACP_COMMON);
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h
index d6cfae6ec5f7..487eefa5985f 100644
--- a/sound/soc/amd/acp/amd.h
+++ b/sound/soc/amd/acp/amd.h
@@ -20,6 +20,7 @@ 
 
 #define ACP3X_DEV			3
 #define ACP6X_DEV			6
+#define ACP63_DEV			0x63
 
 #define DMIC_INSTANCE			0x00
 #define I2S_SP_INSTANCE			0x01
@@ -95,6 +96,9 @@ 
 #define ACP6X_PGFSM_CONTROL                     0x1024
 #define ACP6X_PGFSM_STATUS                      0x1028
 
+#define ACP63_PGFSM_CONTROL			ACP6X_PGFSM_CONTROL
+#define ACP63_PGFSM_STATUS			ACP6X_PGFSM_STATUS
+
 #define ACP_SOFT_RST_DONE_MASK	0x00010001
 
 #define ACP_PGFSM_CNTL_POWER_ON_MASK            0x01