summaryrefslogtreecommitdiff
path: root/snd-alpx/alpx_xdma.c
diff options
context:
space:
mode:
authorChristian Pointner <equinox@helsinki.at>2024-05-10 18:26:46 (GMT)
committerChristian Pointner <equinox@helsinki.at>2024-05-10 18:26:46 (GMT)
commit627f7d488817e308d6f3a92fd9a877723ac7ae1d (patch)
tree554a3c53c90b20da5bd0da0c8da67a9b169bd10f /snd-alpx/alpx_xdma.c
import snd-alpx V3.4.3
Diffstat (limited to 'snd-alpx/alpx_xdma.c')
-rw-r--r--snd-alpx/alpx_xdma.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/snd-alpx/alpx_xdma.c b/snd-alpx/alpx_xdma.c
new file mode 100644
index 0000000..c6b4bf2
--- /dev/null
+++ b/snd-alpx/alpx_xdma.c
@@ -0,0 +1,103 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+* Support for Digigram AlpX PCI-e boards
+*
+* Copyright (c) 2024 Digigram Digital (info@digigram.com)
+*/
+
+#include <linux/version.h>
+
+#include "alpx_xdma.h"
+
+
+#if KERNEL_VERSION(6, 7, 0) > LINUX_VERSION_CODE
+#include "core/generic/6.3/amd_xdma.h"
+#include "include/6.3/amd_xdma.h"
+#else
+#include <linux/platform_data/amd_xdma.h>
+#include <linux/dma/amd_xdma.h>
+#endif
+
+
+static struct xdma_chan_info alpx_xdma_chan_info[2] = {
+ [0].dir = DMA_MEM_TO_DEV,
+ [1].dir = DMA_DEV_TO_MEM,
+};
+
+struct alpx_xdma_platform_data {
+ struct resource resources[2];
+ struct dma_slave_map map[2];
+ struct xdma_platdata platdata;
+};
+
+struct platform_device *alpx_xdma_register(struct pci_dev *pci_dev)
+{
+ struct alpx_xdma_platform_data *data;
+ struct platform_device *xdma_pdev;
+ int nvectors, vector, ret;
+
+ data = devm_kzalloc(&pci_dev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return NULL;
+
+ xdma_pdev = platform_device_alloc("xdma", PLATFORM_DEVID_AUTO);
+ if (!xdma_pdev)
+ return NULL;
+
+ data->resources[0].start = pci_resource_start(pci_dev, 2);
+ data->resources[0].end = pci_resource_end(pci_dev, 2);
+ data->resources[0].flags = IORESOURCE_MEM;
+
+ nvectors = pci_alloc_irq_vectors(pci_dev, 2, 2,
+ PCI_IRQ_MSIX | PCI_IRQ_MSI | PCI_IRQ_LEGACY);
+ if (nvectors < 0)
+ goto put_pdev;
+
+ vector = pci_irq_vector(pci_dev, 0);
+ data->resources[1].start = vector;
+ data->resources[1].end = vector + nvectors - 1;
+ data->resources[1].flags = IORESOURCE_IRQ;
+
+ ret = platform_device_add_resources(xdma_pdev, data->resources,
+ ARRAY_SIZE(data->resources));
+ if (ret)
+ goto free_irq_vectors;
+
+ data->map[0].devname = pci_name(pci_dev);
+ data->map[0].slave = "h2c-0";
+ data->map[0].param = &alpx_xdma_chan_info[0];
+
+ data->map[1].devname = pci_name(pci_dev);
+ data->map[1].slave = "c2h-0";
+ data->map[1].param = &alpx_xdma_chan_info[1];
+
+ data->platdata.max_dma_channels = 4;
+ data->platdata.device_map = data->map;
+ data->platdata.device_map_cnt = ARRAY_SIZE(data->map);
+
+ ret = platform_device_add_data(xdma_pdev, &data->platdata, sizeof(data->platdata));
+ if (ret)
+ goto free_irq_vectors;
+
+ xdma_pdev->dev.parent = &pci_dev->dev;
+
+ ret = platform_device_add(xdma_pdev);
+ if (ret)
+ goto free_irq_vectors;
+
+ return xdma_pdev;
+
+free_irq_vectors:
+ pci_free_irq_vectors(pci_dev);
+put_pdev:
+ platform_device_put(xdma_pdev);
+
+ return NULL;
+}
+
+void alpx_xdma_unregister(struct pci_dev *pci_dev,
+ struct platform_device *xdma_pdev)
+{
+ platform_device_unregister(xdma_pdev);
+ pci_free_irq_vectors(pci_dev);
+}