aboutsummaryrefslogtreecommitdiffstats
path: root/meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/1104-ASoC-AMD-add-ACP3x-PCM-driver-DMA-ops.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/1104-ASoC-AMD-add-ACP3x-PCM-driver-DMA-ops.patch')
-rw-r--r--meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/1104-ASoC-AMD-add-ACP3x-PCM-driver-DMA-ops.patch337
1 files changed, 0 insertions, 337 deletions
diff --git a/meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/1104-ASoC-AMD-add-ACP3x-PCM-driver-DMA-ops.patch b/meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/1104-ASoC-AMD-add-ACP3x-PCM-driver-DMA-ops.patch
deleted file mode 100644
index cd5bbdd4..00000000
--- a/meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/1104-ASoC-AMD-add-ACP3x-PCM-driver-DMA-ops.patch
+++ /dev/null
@@ -1,337 +0,0 @@
-From 2f325ed3e8ad6a5500438221823698361da72b5f Mon Sep 17 00:00:00 2001
-From: Maruthi Srinivas Bayyavarapu <Maruthi.Bayyavarapu@amd.com>
-Date: Wed, 29 Mar 2017 18:59:54 +0530
-Subject: [PATCH 1104/4131] ASoC: AMD: add ACP3x PCM driver DMA ops
-
-ACP3x has a DMA controller to access system memory. This controller
-transfers data from/to system memory to/from ACP internal fifo.
-The patch adds PCM driver DMA operations.
-
-Signed-off-by: Maruthi Bayyavarapu <maruthi.bayyavarapu@amd.com>
-Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
----
- sound/soc/amd/raven/acp3x-pcm-dma.c | 269 ++++++++++++++++++++++++++++++++++--
- sound/soc/amd/raven/acp3x.h | 14 ++
- 2 files changed, 275 insertions(+), 8 deletions(-)
-
-diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c
-index 0ce04f0..346ebcb 100644
---- a/sound/soc/amd/raven/acp3x-pcm-dma.c
-+++ b/sound/soc/amd/raven/acp3x-pcm-dma.c
-@@ -31,6 +31,56 @@ struct i2s_dev_data {
- struct snd_pcm_substream *capture_stream;
- };
-
-+struct i2s_stream_instance {
-+ u16 num_pages;
-+ u16 channels;
-+ u32 xfer_resolution;
-+ u32 fmt;
-+ u32 val;
-+ struct page *pg;
-+ void __iomem *acp3x_base;
-+};
-+
-+static const struct snd_pcm_hardware acp3x_pcm_hardware_playback = {
-+ .info = SNDRV_PCM_INFO_INTERLEAVED |
-+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
-+ SNDRV_PCM_INFO_BATCH |
-+ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
-+ .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,
-+ .rates = SNDRV_PCM_RATE_8000_96000,
-+ .rate_min = 8000,
-+ .rate_max = 96000,
-+ .buffer_bytes_max = PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE,
-+ .period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE,
-+ .period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE,
-+ .periods_min = PLAYBACK_MIN_NUM_PERIODS,
-+ .periods_max = PLAYBACK_MAX_NUM_PERIODS,
-+};
-+
-+static const struct snd_pcm_hardware acp3x_pcm_hardware_capture = {
-+ .info = SNDRV_PCM_INFO_INTERLEAVED |
-+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
-+ SNDRV_PCM_INFO_BATCH |
-+ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
-+ .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,
-+ .rates = SNDRV_PCM_RATE_8000_48000,
-+ .rate_min = 8000,
-+ .rate_max = 48000,
-+ .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE,
-+ .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE,
-+ .period_bytes_max = CAPTURE_MAX_PERIOD_SIZE,
-+ .periods_min = CAPTURE_MIN_NUM_PERIODS,
-+ .periods_max = CAPTURE_MAX_NUM_PERIODS,
-+};
-+
- static int acp3x_power_on(void __iomem *acp3x_base, bool on)
- {
- u16 val, mask;
-@@ -168,19 +218,222 @@ static irqreturn_t i2s_irq_handler(int irq, void *dev_id)
- return IRQ_NONE;
- }
-
-+static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
-+{
-+ u16 page_idx;
-+ u64 addr;
-+ u32 low, high, val, acp_fifo_addr;
-+ struct page *pg = rtd->pg;
-+
-+ /* 8 scratch registers used to map one 64 bit address.
-+ * For 2 pages (4096 * 2 bytes), it will be 16 registers.
-+ */
-+ if (direction == SNDRV_PCM_STREAM_PLAYBACK)
-+ val = 0;
-+ else
-+ val = 16;
-+
-+ /* Group Enable */
-+ rv_writel(ACP_SRAM_PTE_OFFSET | BIT(31), rtd->acp3x_base +
-+ mmACPAXI2AXI_ATU_BASE_ADDR_GRP_1);
-+ rv_writel(PAGE_SIZE_4K_ENABLE, rtd->acp3x_base +
-+ mmACPAXI2AXI_ATU_PAGE_SIZE_GRP_1);
-+
-+ for (page_idx = 0; page_idx < rtd->num_pages; page_idx++) {
-+ /* Load the low address of page int ACP SRAM through SRBM */
-+ addr = page_to_phys(pg);
-+ low = lower_32_bits(addr);
-+ high = upper_32_bits(addr);
-+
-+ rv_writel(low, rtd->acp3x_base + mmACP_SCRATCH_REG_0 + val);
-+ high |= BIT(31);
-+ rv_writel(high, rtd->acp3x_base + mmACP_SCRATCH_REG_0 + val
-+ + 4);
-+ /* Move to next physically contiguos page */
-+ val += 8;
-+ pg++;
-+ }
-+
-+ if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
-+ /* Config ringbuffer */
-+ rv_writel(MEM_WINDOW_START, rtd->acp3x_base +
-+ mmACP_BT_TX_RINGBUFADDR);
-+ rv_writel(MAX_BUFFER, rtd->acp3x_base +
-+ mmACP_BT_TX_RINGBUFSIZE);
-+ rv_writel(0x40, rtd->acp3x_base + mmACP_BT_TX_DMA_SIZE);
-+
-+ /* Config audio fifo */
-+ acp_fifo_addr = ACP_SRAM_PTE_OFFSET + (rtd->num_pages * 8)
-+ + 1024;
-+ rv_writel(acp_fifo_addr, rtd->acp3x_base +
-+ mmACP_BT_TX_FIFOADDR);
-+ rv_writel(256, rtd->acp3x_base + mmACP_BT_TX_FIFOSIZE);
-+ rv_writel(PLAYBACK_MIN_PERIOD_SIZE, rtd->acp3x_base +
-+ mmACP_BT_TX_INTR_WATERMARK_SIZE);
-+ } else {
-+ /* Config ringbuffer */
-+ rv_writel(MEM_WINDOW_START + MAX_BUFFER, rtd->acp3x_base +
-+ mmACP_BT_RX_RINGBUFADDR);
-+ rv_writel(MAX_BUFFER, rtd->acp3x_base +
-+ mmACP_BT_RX_RINGBUFSIZE);
-+ rv_writel(0x40, rtd->acp3x_base + mmACP_BT_RX_DMA_SIZE);
-+
-+ /* Config audio fifo */
-+ acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
-+ (rtd->num_pages * 8) + 1024 + 256;
-+ rv_writel(acp_fifo_addr, rtd->acp3x_base +
-+ mmACP_BT_RX_FIFOADDR);
-+ rv_writel(256, rtd->acp3x_base + mmACP_BT_RX_FIFOSIZE);
-+ rv_writel(CAPTURE_MIN_PERIOD_SIZE, rtd->acp3x_base +
-+ mmACP_BT_RX_INTR_WATERMARK_SIZE);
-+ }
-+
-+ /* Enable watermark/period interrupt to host */
-+ rv_writel(BIT(BT_TX_THRESHOLD) | BIT(BT_RX_THRESHOLD),
-+ rtd->acp3x_base + mmACP_EXTERNAL_INTR_CNTL);
-+}
-+
-+static int acp3x_dma_open(struct snd_pcm_substream *substream)
-+{
-+ int ret = 0;
-+
-+ struct snd_pcm_runtime *runtime = substream->runtime;
-+ struct snd_soc_pcm_runtime *prtd = substream->private_data;
-+ struct i2s_dev_data *adata = dev_get_drvdata(prtd->platform->dev);
-+
-+ struct i2s_stream_instance *i2s_data = kzalloc(sizeof(
-+ struct i2s_stream_instance), GFP_KERNEL);
-+ if (i2s_data == NULL)
-+ return -EINVAL;
-+
-+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-+ runtime->hw = acp3x_pcm_hardware_playback;
-+ else
-+ runtime->hw = acp3x_pcm_hardware_capture;
-+
-+ ret = snd_pcm_hw_constraint_integer(runtime,
-+ SNDRV_PCM_HW_PARAM_PERIODS);
-+ if (ret < 0) {
-+ dev_err(prtd->platform->dev, "set integer constraint failed\n");
-+ return ret;
-+ }
-+
-+ if (!adata->play_stream && !adata->capture_stream)
-+ rv_writel(1, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
-+
-+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-+ adata->play_stream = substream;
-+ else
-+ adata->capture_stream = substream;
-+
-+ i2s_data->acp3x_base = adata->acp3x_base;
-+ runtime->private_data = i2s_data;
-+ return 0;
-+}
-+
-+static int acp3x_dma_hw_params(struct snd_pcm_substream *substream,
-+ struct snd_pcm_hw_params *params)
-+{
-+ int status;
-+ uint64_t size;
-+ struct snd_dma_buffer *dma_buffer;
-+ struct page *pg;
-+ struct i2s_stream_instance *rtd = substream->runtime->private_data;
-+
-+ if (rtd == NULL)
-+ return -EINVAL;
-+
-+ dma_buffer = &substream->dma_buffer;
-+ size = params_buffer_bytes(params);
-+ status = snd_pcm_lib_malloc_pages(substream, size);
-+ if (status < 0)
-+ return status;
-+
-+ memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
-+ pg = virt_to_page(substream->dma_buffer.area);
-+ if (pg != NULL) {
-+ rtd->pg = pg;
-+ rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
-+ config_acp3x_dma(rtd, substream->stream);
-+ status = 0;
-+ } else {
-+ status = -ENOMEM;
-+ }
-+ return status;
-+}
-+
-+static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_pcm_substream *substream)
-+{
-+ u32 pos = 0;
-+ struct i2s_stream_instance *rtd = substream->runtime->private_data;
-+
-+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-+ pos = rv_readl(rtd->acp3x_base +
-+ mmACP_BT_TX_LINKPOSITIONCNTR);
-+ else
-+ pos = rv_readl(rtd->acp3x_base +
-+ mmACP_BT_RX_LINKPOSITIONCNTR);
-+
-+ if (pos >= MAX_BUFFER)
-+ pos = 0;
-+
-+ return bytes_to_frames(substream->runtime, pos);
-+}
-+
-+static int acp3x_dma_new(struct snd_soc_pcm_runtime *rtd)
-+{
-+ return snd_pcm_lib_preallocate_pages_for_all(rtd->pcm,
-+ SNDRV_DMA_TYPE_DEV,
-+ NULL, MIN_BUFFER,
-+ MAX_BUFFER);
-+}
-+
-+static int acp3x_dma_hw_free(struct snd_pcm_substream *substream)
-+{
-+ return snd_pcm_lib_free_pages(substream);
-+}
-+
-+static int acp3x_dma_mmap(struct snd_pcm_substream *substream,
-+ struct vm_area_struct *vma)
-+{
-+ return snd_pcm_lib_default_mmap(substream, vma);
-+}
-+
-+static int acp3x_dma_close(struct snd_pcm_substream *substream)
-+{
-+ struct snd_soc_pcm_runtime *prtd = substream->private_data;
-+ struct i2s_dev_data *adata = dev_get_drvdata(prtd->platform->dev);
-+ struct i2s_stream_instance *rtd = substream->runtime->private_data;
-+
-+ kfree(rtd);
-+
-+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-+ adata->play_stream = NULL;
-+ else
-+ adata->capture_stream = NULL;
-+
-+ /* Disable ACP irq, when the current stream is being closed and
-+ * another stream is also not active.
-+ */
-+ if (!adata->play_stream && !adata->capture_stream)
-+ rv_writel(0, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
-+
-+ 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,
-+ .open = acp3x_dma_open,
-+ .close = acp3x_dma_close,
-+ .ioctl = snd_pcm_lib_ioctl,
-+ .hw_params = acp3x_dma_hw_params,
-+ .hw_free = acp3x_dma_hw_free,
-+ .pointer = acp3x_dma_pointer,
-+ .mmap = acp3x_dma_mmap,
- };
-
- static struct snd_soc_platform_driver acp3x_asoc_platform = {
- .ops = &acp3x_dma_ops,
-- .pcm_new = NULL,
-+ .pcm_new = acp3x_dma_new,
- };
-
- struct snd_soc_dai_ops acp3x_dai_i2s_ops = {
-diff --git a/sound/soc/amd/raven/acp3x.h b/sound/soc/amd/raven/acp3x.h
-index b6d4659..d35d252 100644
---- a/sound/soc/amd/raven/acp3x.h
-+++ b/sound/soc/amd/raven/acp3x.h
-@@ -6,7 +6,21 @@
- #define ACP3x_REG_END 0x1250200
- #define BT_TX_THRESHOLD 26
- #define BT_RX_THRESHOLD 25
-+#define ACP_SRAM_PTE_OFFSET 0x02050000
-+#define PAGE_SIZE_4K_ENABLE 0x2
-+#define MEM_WINDOW_START 0x4000000
-
-+#define PLAYBACK_MIN_NUM_PERIODS 2
-+#define PLAYBACK_MAX_NUM_PERIODS 2
-+#define PLAYBACK_MAX_PERIOD_SIZE 4096
-+#define PLAYBACK_MIN_PERIOD_SIZE 4096
-+#define CAPTURE_MIN_NUM_PERIODS 2
-+#define CAPTURE_MAX_NUM_PERIODS 2
-+#define CAPTURE_MAX_PERIOD_SIZE 4096
-+#define CAPTURE_MIN_PERIOD_SIZE 4096
-+
-+#define MAX_BUFFER (PLAYBACK_MAX_PERIOD_SIZE * PLAYBACK_MAX_NUM_PERIODS)
-+#define MIN_BUFFER MAX_BUFFER
-
- static inline u32 rv_readl(void __iomem *base_addr)
- {
---
-2.7.4
-