diff options
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.patch | 337 |
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 - |