lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <1542000903-19020-5-git-send-email-Vijendar.Mukunda@amd.com>
Date:   Mon, 12 Nov 2018 11:04:55 +0530
From:   Vijendar Mukunda <Vijendar.Mukunda@....com>
To:     unlisted-recipients:; (no To-header on input)
CC:     <vijendar.mukunda@....com>, <Alexander.Deucher@....com>,
        <Vishnuvardhanrao.Ravulapati@....com>,
        Vijendar Mukunda <Vijendar.Mukunda@....com>,
        Maruthi Bayyavarapu <maruthi.bayyavarapu@....com>,
        Liam Girdwood <lgirdwood@...il.com>,
        "Mark Brown" <broonie@...nel.org>,
        Jaroslav Kysela <perex@...ex.cz>,
        Takashi Iwai <tiwai@...e.com>,
        Sanju R Mehta <sanju.mehta@....com>,
        open list <linux-kernel@...r.kernel.org>,
        "moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM..." 
        <alsa-devel@...a-project.org>
Subject: [PATCH 04/11] ASoC: amd: add ACP3x PCM platform driver

PCM platform driver binds to the platform device created by ACP3x PCI
device. PCM driver registers ALSA DMA and CPU DAI components with ASoC
framework.

Signed-off-by: Maruthi Bayyavarapu <maruthi.bayyavarapu@....com>
Tested-by: Ravulapati Vishnu vardhan Rao <Vishnuvardhanrao.Ravulapati@....com>
Signed-off-by: Vijendar Mukunda <vijendar.mukunda@....com>
---
 sound/soc/amd/raven/acp3x-pcm-dma.c | 263 ++++++++++++++++++++++++++++++++++++
 sound/soc/amd/raven/acp3x.h         |   7 +
 2 files changed, 270 insertions(+)
 create mode 100644 sound/soc/amd/raven/acp3x-pcm-dma.c

diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c
new file mode 100644
index 0000000..3e806f7
--- /dev/null
+++ b/sound/soc/amd/raven/acp3x-pcm-dma.c
@@ -0,0 +1,263 @@
+/*
+ * AMD ALSA SoC PCM Driver
+ *
+ * Copyright 2016 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+
+#include "acp3x.h"
+
+#define DRV_NAME "acp3x-i2s-audio"
+
+struct i2s_dev_data {
+	void __iomem *acp3x_base;
+	struct snd_pcm_substream *play_stream;
+	struct snd_pcm_substream *capture_stream;
+};
+
+static int acp3x_power_on(void __iomem *acp3x_base, bool on)
+{
+	u16 val, mask;
+	u32 timeout;
+
+	if (on == true) {
+		val = 1;
+		mask = ACP3x_POWER_ON;
+	} else {
+		val = 0;
+		mask = ACP3x_POWER_OFF;
+	}
+
+	rv_writel(val, acp3x_base + mmACP_PGFSM_CONTROL);
+	timeout = 0;
+	while (true) {
+		val = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
+		if ((val & ACP3x_POWER_OFF_IN_PROGRESS) == mask)
+			break;
+		if (timeout > 100) {
+			pr_err("ACP3x power state change failure\n");
+			return -ENODEV;
+		}
+		timeout++;
+		cpu_relax();
+	}
+	return 0;
+}
+
+static int acp3x_reset(void __iomem *acp3x_base)
+{
+	u32 val, timeout;
+
+	rv_writel(1, acp3x_base + mmACP_SOFT_RESET);
+	timeout = 0;
+	while (true) {
+		val = rv_readl(acp3x_base + mmACP_SOFT_RESET);
+		if ((val & ACP3x_SOFT_RESET__SoftResetAudDone_MASK) ||
+		     timeout > 100) {
+			if (val & ACP3x_SOFT_RESET__SoftResetAudDone_MASK)
+				break;
+			return -ENODEV;
+		}
+		timeout++;
+		cpu_relax();
+	}
+
+	rv_writel(0, acp3x_base + mmACP_SOFT_RESET);
+	timeout = 0;
+	while (true) {
+		val = rv_readl(acp3x_base + mmACP_SOFT_RESET);
+		if (!val || timeout > 100) {
+			if (!val)
+				break;
+			return -ENODEV;
+		}
+		timeout++;
+		cpu_relax();
+	}
+	return 0;
+}
+
+static int acp3x_init(void __iomem *acp3x_base)
+{
+	int ret;
+
+	/* power on */
+	ret = acp3x_power_on(acp3x_base, true);
+	if (ret) {
+		pr_err("ACP3x power on failed\n");
+		return ret;
+	}
+	/* Reset */
+	ret = acp3x_reset(acp3x_base);
+	if (ret) {
+		pr_err("ACP3x reset failed\n");
+		return ret;
+	}
+	return 0;
+}
+
+static int acp3x_deinit(void __iomem *acp3x_base)
+{
+	int ret;
+
+	/* Reset */
+	ret = acp3x_reset(acp3x_base);
+	if (ret) {
+		pr_err("ACP3x reset failed\n");
+		return ret;
+	}
+	/* power off */
+	ret = acp3x_power_on(acp3x_base, false);
+	if (ret) {
+		pr_err("ACP3x power off failed\n");
+		return ret;
+	}
+	return 0;
+}
+
+static struct snd_pcm_ops acp3x_dma_ops = {
+	.open = NULL,
+	.close = NULL,
+	.ioctl = NULL,
+	.hw_params = NULL,
+	.hw_free = NULL,
+	.pointer = NULL,
+	.mmap = NULL,
+};
+
+struct snd_soc_dai_ops acp3x_dai_i2s_ops = {
+	.hw_params = NULL,
+	.trigger   = NULL,
+	.set_fmt = NULL,
+};
+
+static struct snd_soc_dai_driver acp3x_i2s_dai_driver = {
+	.playback = {
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+					SNDRV_PCM_FMTBIT_U8 |
+					SNDRV_PCM_FMTBIT_S24_LE |
+					SNDRV_PCM_FMTBIT_S32_LE,
+		.channels_min = 2,
+		.channels_max = 8,
+
+		.rate_min = 8000,
+		.rate_max = 96000,
+	},
+	.capture = {
+		.rates = SNDRV_PCM_RATE_8000_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+					SNDRV_PCM_FMTBIT_U8 |
+					SNDRV_PCM_FMTBIT_S24_LE |
+					SNDRV_PCM_FMTBIT_S32_LE,
+		.channels_min = 2,
+		.channels_max = 2,
+		.rate_min = 8000,
+		.rate_max = 48000,
+	},
+	.ops = &acp3x_dai_i2s_ops,
+};
+
+static const struct snd_soc_component_driver acp3x_i2s_component = {
+	.name           = DRV_NAME,
+	.ops		= &acp3x_dma_ops,
+	.pcm_new	= acp3x_dma_new,
+};
+
+static int acp3x_audio_probe(struct platform_device *pdev)
+{
+	int status;
+	struct resource *res;
+	struct i2s_dev_data *adata;
+	unsigned int irqflags;
+
+	if (!pdev->dev.platform_data) {
+		dev_err(&pdev->dev, "platform_data not retrieved\n");
+		return -ENODEV;
+	}
+	irqflags = *((unsigned int *)(pdev->dev.platform_data));
+
+	adata = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dev_data),
+			     GFP_KERNEL);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
+			return -ENODEV;
+	}
+
+	adata->acp3x_base = devm_ioremap(&pdev->dev, res->start,
+					 resource_size(res));
+
+	adata->play_stream = NULL;
+	adata->capture_stream = NULL;
+
+	dev_set_drvdata(&pdev->dev, adata);
+	/* Initialize ACP */
+	status = acp3x_init(adata->acp3x_base);
+	if (status)
+		return -ENODEV;
+	status = devm_snd_soc_register_component(&pdev->dev,
+						 &acp3x_i2s_component,
+						 &acp3x_i2s_dai_driver, 1);
+	if (status) {
+		dev_err(&pdev->dev, "Fail to register acp i2s dai\n");
+		goto dev_err;
+	}
+
+	return 0;
+dev_err:
+	status = acp3x_deinit(adata->acp3x_base);
+	if (status)
+		dev_err(&pdev->dev, "ACP de-init failed\n");
+	else
+		dev_info(&pdev->dev, "ACP de-initialized\n");
+	/*ignore device status and return driver probe error*/
+	return -ENODEV;
+}
+
+static int acp3x_audio_remove(struct platform_device *pdev)
+{
+	int ret;
+	struct i2s_dev_data *adata = dev_get_drvdata(&pdev->dev);
+
+	ret = acp3x_deinit(adata->acp3x_base);
+	if (ret)
+		dev_err(&pdev->dev, "ACP de-init failed\n");
+	else
+		dev_info(&pdev->dev, "ACP de-initialized\n");
+
+	return 0;
+}
+
+static struct platform_driver acp3x_dma_driver = {
+	.probe = acp3x_audio_probe,
+	.remove = acp3x_audio_remove,
+	.driver = {
+		.name = "acp3x_rv_i2s",
+	},
+};
+
+module_platform_driver(acp3x_dma_driver);
+
+MODULE_AUTHOR("Maruthi.Bayyavarapu@....com");
+MODULE_AUTHOR("Vijendar.Mukunda@....com");
+MODULE_DESCRIPTION("AMD ACP 3.x PCM Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/amd/raven/acp3x.h b/sound/soc/amd/raven/acp3x.h
index 83b1ed8..f3d3e51 100644
--- a/sound/soc/amd/raven/acp3x.h
+++ b/sound/soc/amd/raven/acp3x.h
@@ -5,6 +5,13 @@
 #define	ACP3x_REG_START	0x1240000
 #define	ACP3x_REG_END	0x1250200
 #define I2S_MODE	0x04
+#define	BT_TX_THRESHOLD 26
+#define	BT_RX_THRESHOLD 25
+#define ACP3x_POWER_ON 0x00
+#define ACP3x_POWER_ON_IN_PROGRESS 0x01
+#define ACP3x_POWER_OFF 0x02
+#define ACP3x_POWER_OFF_IN_PROGRESS 0x03
+#define ACP3x_SOFT_RESET__SoftResetAudDone_MASK	0x00010001
 
 static inline u32 rv_readl(void __iomem *base_addr)
 {
-- 
2.7.4

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ