diff options
author | Christian Pointner <equinox@helsinki.at> | 2024-05-10 18:52:23 (GMT) |
---|---|---|
committer | Christian Pointner <equinox@helsinki.at> | 2024-05-10 18:52:23 (GMT) |
commit | a641800acf13b5fb1463d4280c3ee7fc267143fb (patch) | |
tree | 248b647a682f71d9eb90d14d24081368ea905a42 /snd-alpx/alpx_core.c | |
parent | cc4badffe0e02d159c21eb90ea080a6a2f90cb4b (diff) |
import whole driver package
Diffstat (limited to 'snd-alpx/alpx_core.c')
-rw-r--r-- | snd-alpx/alpx_core.c | 901 |
1 files changed, 0 insertions, 901 deletions
diff --git a/snd-alpx/alpx_core.c b/snd-alpx/alpx_core.c deleted file mode 100644 index 0fb4d82..0000000 --- a/snd-alpx/alpx_core.c +++ /dev/null @@ -1,901 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* -* Support for Digigram AlpX PCI-e boards -* -* Copyright (c) 2024 Digigram Digital (info@digigram.com) -*/ - -#include "alpx.h" -#include "alpx_reg.h" -#include "alpx_mtd.h" -#include "alpx_led.h" -#include "alpx_controls.h" -#include "alpx_streams.h" -#include "alpx_version.h" -#include "alpx_variants_stereo.h" -#include "alpx_variants_stereo_apps_preFW283.h" -#include "alpx_variants_mc.h" -#include "alpx_variants_882_apps_preFW240.h" -#include "alpx_variants_dead.h" -#include "alpx_variants_madi.h" -#include "alpx_variants_dante.h" -#include "alpx_cards.h" -#include "alpx_xdma.h" -#include "snd_alpx_xdma.h" - - -#include <linux/version.h> -#include <linux/kmod.h> - -#if !defined (CONFIG_WITHOUT_GPIO) -#define ALPX_WITH_GPIO -#include <linux/gpio.h> -#include <linux/gpio/driver.h> -#include "alpx_gpio.h" -#define ALPX_GPIO_OPTION_STRING "" -#else -#warning !! GPIOs are DISABLED !! -#define ALPX_GPIO_OPTION_STRING "(without GPIO)" -#endif - - -#include <linux/mtd/partitions.h> -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/platform_device.h> -#include <linux/delay.h> -#include <linux/version.h> -#include <sound/control.h> -#include <sound/core.h> -#include <sound/initval.h> -#include <sound/pcm.h> -#include <linux/string.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 - -#ifdef WITH_REG_DEBUG -#include <linux/device.h> -#endif - -/* Constants */ - -/* Structures */ - -/* Parameters */ - -#define ALPX_DEFAULT_CARD_NAME "Digigram AlpX" - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for " ALPX_DEFAULT_CARD_NAME " soundcard."); - -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for " ALPX_DEFAULT_CARD_NAME " soundcard."); - -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable " ALPX_DEFAULT_CARD_NAME " soundcard."); - -unsigned int log_transfers = 0; -module_param(log_transfers, uint, 0644); -MODULE_PARM_DESC(log_transfers, "0: no transfer logged(default), 1 : transfers logged"); - -static bool with_board_in_prod_mode = false; -module_param(with_board_in_prod_mode, bool, 0644); -MODULE_PARM_DESC(with_board_in_prod_mode, "0: board in USER mode(default) ; 1: board in PRODUCTION mode "); - -static bool with_board_in_dead_mode = false; -module_param(with_board_in_dead_mode, bool, 0644); -MODULE_PARM_DESC(with_board_in_dead_mode, "0: board in NORMAL mode(default) ; 1: board in DEAD mode "); - -static unsigned int dante_configured_fs = ALPDANTE_DEFAULT_FS; -module_param(dante_configured_fs, uint, 0644); -MODULE_PARM_DESC(dante_configured_fs, "Configured FS for Alp DANTE card (value in Hz, default: 48000)"); - -static bool dante_loopback_enabled = false; -module_param(dante_loopback_enabled, bool, 0644); -MODULE_PARM_DESC(dante_loopback_enabled, "Enable the Loopback for Alp DANTE card (default: FALSE)"); - -static bool alp222_pre_FW283_apps_support = false; -module_param(alp222_pre_FW283_apps_support, bool, 0644); -MODULE_PARM_DESC(alp222_pre_FW283_apps_support, "For ALp222e cards ONLY, Enable the compatibility mode for applications written for PRE V283 Firmwares (default: FALSE)"); - -static bool alp882_pre_FW240_apps_support = false; -module_param(alp882_pre_FW240_apps_support, bool, 0644); -MODULE_PARM_DESC(alp882_pre_FW240_apps_support, "For ALp882e cards ONLY, Enable the compatibility mode for applications written for PRE V240 Firmwares (default: FALSE)"); - - -/* Below, this is significant only if WITH_REG_DEBUG is defined */ -#ifdef WITH_REG_DEBUG -#warning BUILD with Registers Debug enabled - -static ssize_t reg_offset_show(struct device* dev, struct device_attribute* attr, char* buf ) -{ - - //HOWTO struct dev TO struct alpx_device : - struct snd_card* const card = dev_get_drvdata(dev); - struct alpx_device* const alpx_dev = card->private_data; - - dev_dbg( dev,"%s(): CALLED for card: 0x%p : REG OFFSET: 0x%08x\n", __func__, - alpx_dev, - alpx_dev->dbg_reg_offset); - - - return scnprintf(buf, PAGE_SIZE, "0x%08x\n", alpx_dev->dbg_reg_offset); -} - -static ssize_t reg_offset_store(struct device* dev, struct device_attribute* attr, const char* buf , size_t count) -{ - //HOWTO struct dev TO struct alpx_device : - struct snd_card* const card = dev_get_drvdata(dev); - struct alpx_device* const alpx_dev = card->private_data; - - unsigned int reg_offset = 0; - if (kstrtou32(buf, 0, ®_offset) < 0) - return -EINVAL; - - //Check offset range - if ((reg_offset < ALP222_MIN_REG_OFFSET) && - (reg_offset > ALP222_MAX_REG_OFFSET)) - return -EINVAL; - - alpx_dev->dbg_reg_offset = reg_offset; - dev_dbg( dev,"%s(): CALLED for alpx: %p, reg_offset: 0x%08x\n", __func__, alpx_dev, alpx_dev->dbg_reg_offset); - - return count; -} - -//static struct device_attribute dev_reg_addr = __ATTR_RW(reg_addr); -static struct device_attribute dev_reg_offset = __ATTR_RW(reg_offset); - -/******************************/ -static ssize_t reg_value_show(struct device* dev, struct device_attribute* attr, char* buf ) -{ - - //HOWTO struct dev TO struct alpx_device : - struct snd_card* const card = dev_get_drvdata(dev); - struct alpx_device* const alpx_dev = card->private_data; - /* Read the register once to cope with 'clear on read' registers */ - const uint32_t reg_value = readl(alpx_dev->base+ alpx_dev->dbg_reg_offset); - - dev_dbg( dev,"%s(): CALLED for %p, (dev:%p): [0x%08x] => 0x%08x\n", __func__, - alpx_dev, dev, - alpx_dev->dbg_reg_offset, - reg_value); - - return scnprintf(buf, PAGE_SIZE, "0x%08x\n", reg_value); -} - -static ssize_t reg_value_store(struct device* dev, struct device_attribute* attr, const char* buf , size_t count) -{ - //HOWTO struct dev TO struct alpx_device : - struct snd_card* const card = dev_get_drvdata(dev); - struct alpx_device* const alpx_dev = card->private_data; - - uint32_t reg_value = 0; - if (kstrtou32(buf, 0, ®_value) < 0) - return -EINVAL; - - - writel(reg_value, alpx_dev->base + alpx_dev->dbg_reg_offset); - - dev_dbg( dev,"%s(): CALLED for alpx: %p, [0x%08x] <= 0x%08x, Check:0x%08x\n", __func__, - alpx_dev, - alpx_dev->dbg_reg_offset, - reg_value, - readl(alpx_dev->base+ alpx_dev->dbg_reg_offset)); - - return count; -} - -static struct device_attribute dev_reg_value = __ATTR_RW(reg_value); - -#endif - -/******************************/ -static ssize_t serial_number_show(struct device* dev, struct device_attribute* attr, char* buf ) -{ - - struct snd_card* const card = dev_get_drvdata(dev); - struct alpx_device* alpx_dev = card->private_data; - - dev_dbg(alpx_dev->dev, " %s() : AFTER shift %llu / 0x%llx\n", __func__, alpx_dev->identity.serial_number, alpx_dev->identity.serial_number); - - return scnprintf(buf, PAGE_SIZE, "%llu\n", alpx_dev->identity.serial_number); -} - -static struct device_attribute dev_serial_number = __ATTR_RO(serial_number); -/***************************************/ - -static ssize_t ver_fpga_show(struct device* dev, struct device_attribute* attr, char* buf ) -{ - - struct snd_card* const card = dev_get_drvdata(dev); - struct alpx_device* alpx_dev = card->private_data; - - return scnprintf(buf, PAGE_SIZE, "%u\n", alpx_dev->identity.ver_fpga); -} - -static struct device_attribute dev_ver_fpga = __ATTR_RO(ver_fpga); - -/***************************************/ -static ssize_t ver_mcu_show(struct device* dev, struct device_attribute* attr, char* buf ) -{ - - struct snd_card* const card = dev_get_drvdata(dev); - struct alpx_device* alpx_dev = card->private_data; - - return scnprintf(buf, PAGE_SIZE, "%u.%lu\n", - ALPX_COMMON_VERSION_VERSION(alpx_dev->identity.ver_mcu), - ALPX_COMMON_VERSION_REVISION(alpx_dev->identity.ver_mcu) ); -} - -static struct device_attribute dev_ver_mcu = __ATTR_RO(ver_mcu); -/***************************************/ -static ssize_t dante_card_name_show(struct device* dev, struct device_attribute* attr, char* buf ) -{ - - struct snd_card* const card = dev_get_drvdata(dev); - struct alpx_device* alpx_dev = card->private_data; - - int result = alpdante_get_dante_name(alpx_dev, buf, ALPDANTE_NETWORK_NAME_LENGTH); - return (!result) ? strlcat(buf, "\n", PAGE_SIZE) : 0; -} - -static struct device_attribute dev_dante_card_name = __ATTR_RO(dante_card_name); -/***************************************/ - -/* PCI */ - -static void alpx_card_private_free(struct snd_card *card) -{ - struct alpx_device *alpx_dev = card->private_data; - -#if defined (ALPX_WITH_GPIO) - if (alpx_dev->variant->features & ALPX_VARIANT_FEATURE_GPIOS) - alpx_gpio_unregister(alpx_dev); -#endif - - if (alpx_dev->controls) - kfree(alpx_dev->controls); - - /* dirty crash avoid when dma fails and frees card before pipes are init. */ -} - -static inline unsigned int is_alp222_with_mic_option(struct alpx_device* alpx_dev) -{ - const u32 reg_mic = readl(alpx_dev->base + ALP222_CONTROL_BASE + ALP222_MIC_CONTROL_REG); - dev_dbg(alpx_dev->dev, "Daughter_Control[0x%08x:%x] = 0x%08x\n", - ALP222_CONTROL_BASE, - ALP222_MIC_CONTROL_REG, - reg_mic); - return reg_mic & (1<<ALP222_MIC_HERE_POS); -} - -static int alpx_core_set_pci_bus(struct alpx_device* alpx_dev) -{ - int ret = pci_enable_device(alpx_dev->pci_dev); - if (ret) { - dev_err(alpx_dev->dev, "failed to enable PCI device\n"); - return ret; - } - - /* Enable PCI relaxed ordering. */ - pcie_capability_set_word(alpx_dev->pci_dev, PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_RELAX_EN); - - /* Enable extended tagging. */ - pcie_capability_set_word(alpx_dev->pci_dev, PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_EXT_TAG); - - /* Set maximum memory read request. */ - pcie_set_readrq(alpx_dev->pci_dev, 512); - - pci_set_master(alpx_dev->pci_dev); - - return ret; -} - - -/****************************************************************/ -/* -* This function will HANDLE the XMA module dependency either from kernel or -* from the package according to the kernel's version. -* Return an error the kernel's module is in bad version (kernel <6.7) as no CYLLIC DMA -* was yet supported. -* MUST be CALLED after alpx_xdma_register() to get the xdma_dev -*/ -static int alpx_core_handle_xdma_dep (struct device *dev, struct platform_device* xdma_dev) -{ - - dev_info(dev, "Handling XDMA support for Linux : %d.\n", LINUX_VERSION_CODE); - -#if KERNEL_VERSION(6, 3, 0) > LINUX_VERSION_CODE - dev_info(dev, "OLD Kernel, USE snd-alpx-xdma.\n"); - //NO XDMA in the kernel Force the dependency to package's xdma module already done before call by - // SND_ALPX_XDMA_DEP(); - -#elif KERNEL_VERSION(6, 7, 0) <= LINUX_VERSION_CODE - #if IS_ENABLED(CONFIG_XILINX_XDMA) - dev_info(dev, "Kernel XDMA Ok, USE xdma.\n"); - //NO XDMA in the kernel Force the dependency to package's xdma module. - xdma_get_user_irq(xdma_dev, 256); //Dumb irq to for an error : no way - #else - dev_info(dev, "Kernel XDMA NOT enabled, USE snd-alpx-xdma.\n"); - //Dependency already handled by SND_ALPX_XDMA_DEP() call defined accordingly !! - #endif -#elif (KERNEL_VERSION(6, 3, 0) <= LINUX_VERSION_CODE) && \ - (KERNEL_VERSION(6, 7, 0) > LINUX_VERSION_CODE) - //FORCE snd-alpx-xdma use as kernel's one w/o cyclic support - #if IS_ENABLED(CONFIG_XILINX_XDMA) - #if IS_MODULE(CONFIG_XILINX_XDMA) - #warning "Xilinx XDMA module must be unloaded before use : NOT COMPLIANT !!" - #else - #error "Xilinx XDMA moule in Kernel is not COMPLIANT, Kernel must be Reconfigured/Rebuild without it !!!!" - #endif - #endif -#endif - return 0; -} -/****************************************************************************/ -static int alpx_probe(struct pci_dev *pci_dev, - const struct pci_device_id *pci_device_id) -{ - static int card_idx = 0; - struct device *dev = &pci_dev->dev; - struct alpx_device *alpx_dev; - struct snd_card *card; - struct snd_pcm *pcm; - int ret; - int is_update_required = 0; - - /* Module identity */ - - dev_info(dev,"version %s %s build date: %s, time: %s. %s, %s\n", - ALPX_MODULE_VERSION, - ALPX_GPIO_OPTION_STRING, - __DATE__ , - __TIME__, - SND_ALPX_XDMA_DEP(), - log_transfers ? "Transfers Logged":""); - - /* Ensure dependency on AlpX XDMA support if needed*/ - SND_ALPX_XDMA_DEP(); - - /* Card */ - - if (card_idx >= SNDRV_CARDS) - return -ENODEV; - - if (!enable[card_idx]) { - card_idx++; - return -ENOENT; - } - - dev_dbg(dev,"%s() : PCI Id : Vendor: 0x04%x, Device: 0x%04x, subvendor: 0x%04x, subdevice: 0x%04x\n", __func__, - pci_device_id->vendor, - pci_device_id->device, - pci_device_id->subvendor, - pci_device_id->subdevice); - - dev_dbg(dev,"%s() : PCI dev: Vendor: 0x04%x, Device: 0x%04x, subvendor: 0x%04x, subdevice: 0x%04x\n", __func__, - pci_dev->vendor, - pci_dev->device, - pci_dev->subsystem_vendor, - pci_dev->subsystem_device); - - - ret = snd_card_new(dev, index[card_idx], id[card_idx], THIS_MODULE, - sizeof(*alpx_dev), &card); - if (ret) { - dev_err(dev," snd_card_new() => %d\n", ret); - return ret; - } - - card->private_free = alpx_card_private_free; - - /* PCI */ - - pci_set_drvdata(pci_dev, card); - - alpx_dev = card->private_data; - alpx_dev->dev = dev; - alpx_dev->pci_dev = pci_dev; - - ret = alpx_core_set_pci_bus(alpx_dev); - if (ret){ - dev_err(dev," alpx_core_set_pci_bus(alpx_dev) => %d\n", ret); - goto error_card; - } - - //Map USER BAR now to get access to all card's resources - alpx_dev->base = pci_ioremap_bar(pci_dev, 0); - - /* PCI */ - - ret = pci_enable_device(pci_dev); - if (ret) { - dev_err(dev, "failed to enable PCI device\n"); - goto error_card; - } - - /* Enable PCI relaxed ordering. */ - pcie_capability_set_word(pci_dev, PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_RELAX_EN); - - /* Enable extended tagging. */ - pcie_capability_set_word(pci_dev, PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_EXT_TAG); - - /* Set maximum memory read request. */ - pcie_set_readrq(pci_dev, 512); - - pci_set_master(pci_dev); - - /* XDMA */ - - alpx_dev->xdma_pdev = alpx_xdma_register(pci_dev); - if (!alpx_dev->xdma_pdev) { - dev_err(dev," alpx_xdma_register(alpx_dev) => %d\n", ret); - goto disable_pci_dev; - } - - /* XDMA dependency handling*/ - ret = alpx_core_handle_xdma_dep(dev, alpx_dev->xdma_pdev); - if (ret) { - dev_err(dev, "Error %d when handling xdma dependency !\n", ret); - goto disable_pci_dev; - } - - /* Variant */ - - //Use PCI Id to select the actual variant : WARNING, MIC option is checked with user's registers !! - switch (pci_dev->subsystem_device){ - case ALPX_PCI_ID_SUBSYSTEM_ALP222: - /* HANDLE Alp222_MIC with LINE PCI Id : firmwares ante V272*/ - if (alp222_pre_FW283_apps_support) { - dev_warn(alpx_dev->dev, "!!! Alp2220 Pre FW283 Application compatibility mode ACTIVATED !!!"); - } - if (!is_alp222_with_mic_option(alpx_dev)) { - alpx_dev->variant = (!alp222_pre_FW283_apps_support) ? &alp222_variant : &alp222_app_preFW283_variant; - } - else { - alpx_dev->variant = (!alp222_pre_FW283_apps_support) ? &alp222_mic_variant : &alp222_app_preFW283_mic_variant; - alp222_mic_controls_default_config(alpx_dev); - } - break; - case ALPX_PCI_ID_SUBSYSTEM_ALP222_MIC: - if (alp222_pre_FW283_apps_support) { - dev_warn(alpx_dev->dev, "!!! Alp222 Pre FW283 Application compatibility mode ACTIVATED !!!"); - } - alpx_dev->variant = (!alp222_pre_FW283_apps_support) ? &alp222_mic_variant : &alp222_app_preFW283_mic_variant; - alp222_mic_controls_default_config(alpx_dev); - break; - case ALPX_PCI_ID_SUBSYSTEM_MADI: - alpx_dev->variant = &alpx_madi_variant; - break; - case ALPX_PCI_ID_SUBSYSTEM_ALP882: - if (alp882_pre_FW240_apps_support) - dev_warn(alpx_dev->dev, "!!! Alp882 LINE with Pre FW240 Application compatibility mode ACTIVATED !!!"); - alpx_dev->variant = (!alp882_pre_FW240_apps_support) ? &alp882_line_variant : &alp882_app_preFW240_line_variant; - break; - case ALPX_PCI_ID_SUBSYSTEM_ALP882_MIC: - if (alp882_pre_FW240_apps_support) - dev_warn(alpx_dev->dev, "!!! Alp882 MIC with Pre FW240 Application compatibility mode ACTIVATED !!!"); - alpx_dev->variant = (!alp882_pre_FW240_apps_support) ? &alp882_mic_variant : &alp882_app_preFW240_mic_variant; - break; - case ALPX_PCI_ID_SUBSYSTEM_ALP442: - alpx_dev->variant = &alp442_line_variant; - break; - case ALPX_PCI_ID_SUBSYSTEM_ALP442_MIC: - alpx_dev->variant = &alp442_mic_variant; - break; - case ALPX_PCI_ID_SUBSYSTEM_MADI_ALP_DEAD: - alpx_dev->variant = &alpx_dead_variant; - break; - case ALPX_PCI_ID_SUBSYSTEM_ALPDANTE: - alpx_dev->variant = &alpx_dante_variant; - break; - default: - dev_warn(alpx_dev->dev,"ALPX Driver: Model Id 0x%04x is not supported => DEAD by default Here !\n", - pci_dev->subsystem_device); - alpx_dev->variant = &alpx_dead_variant; - } - - /* FORCED DEAD mode, not for DANTE card */ - if (with_board_in_dead_mode) - { - /* Check DEAD mode for supported variants*/ - if (alpx_dev->variant->model != ALPX_VARIANT_MODEL_ALPDANTE) { - alpx_dev->variant = &alpx_dead_variant; - dev_warn(alpx_dev->dev, " !!! Board forced in DEAD mode !!\n"); - } - else { - dev_err(alpx_dev->dev, " NO DEAD mode supported for this board : %s\n", alpx_dev->variant->shortname); - ret = -EINVAL; - goto unregister_xdma; - } - } - - /* MTD */ - if (alpx_dev->variant->flash_partitions.qty != 0) { -// /* mtd Handle the PRODUCTION access or DEAD card, BUT not for DANTE cards*/ - with_board_in_prod_mode &= (alpx_dev->variant->model != ALPX_VARIANT_MODEL_ALPDANTE); - - if ( with_board_in_prod_mode || - (alpx_dev->variant->model == ALPX_VARIANT_DEAD)) { - dev_warn( alpx_dev->dev," Flash in PRODUCTION mode or DEAD card: full access !\n"); - ret = alpx_mtd_probe(alpx_dev, alpx_dev->variant->flash_partitions.partitions ,alpx_dev->variant->flash_partitions.qty); - } - else { - dev_dbg( alpx_dev->dev," Flash in USER mode: firmware update access only.\n"); - ret = alpx_mtd_probe(alpx_dev, - &alpx_dev->variant->flash_partitions.partitions[ALPX_FLASH_PARTITION_FW_ID] , - alpx_dev->variant->flash_partitions.qty_for_fw_update); - } - - if (ret) - goto unregister_xdma; - } - - if (alpx_dev->variant->model == ALPX_VARIANT_DEAD) { - dev_warn(alpx_dev->dev," !!!! DEAD card found : Flash in PROD mode and nothing else !!\n"); - return 0; - } - - /* finalize identity */ - switch (alpx_dev->variant->model) { - case ALPX_VARIANT_MODEL_ALP882: - case ALPX_VARIANT_MODEL_ALP882_MIC: - case ALPX_VARIANT_MODEL_ALP442: - case ALPX_VARIANT_MODEL_ALP442_MIC: - alpmultichan_finalize_identity(alpx_dev); - /* Check FW compatibility */ - if (alpx_dev->identity.ver_fpga < ALPMC_SUPPORTED_BASE_FW_VERSION) { - dev_warn(alpx_dev->dev, "UNSUPPORTED MultiChannels firmware version %d (supported started at %d), UPDATE required !!\n", - alpx_dev->identity.ver_fpga, - ALPMC_SUPPORTED_BASE_FW_VERSION); - is_update_required = 1; - } - - break; - case ALPX_VARIANT_MODEL_ALP222: - case ALPX_VARIANT_MODEL_ALP222_MIC: - alpstereo_finalize_identity(alpx_dev); - /* Check FW compatibility */ - if (alpx_dev->identity.ver_fpga < ALP222_SUPPORTED_BASE_FW_VERSION) { - dev_warn(alpx_dev->dev, "UNSUPPORTED Stereo firmware version %d (supported started at %d), UPDATE required !!\n", - alpx_dev->identity.ver_fpga, - ALP222_SUPPORTED_BASE_FW_VERSION); -// is_update_required = 1; - } - break; - case ALPX_VARIANT_MODEL_ALPDANTE: - alpdante_finalize_identity(alpx_dev); - /* Check FW compatibility */ - if (alpx_dev->identity.ver_fpga < ALPDANTE_SUPPORTED_BASE_FW_VERSION) { - dev_warn(alpx_dev->dev, "UNSUPPORTED AlpDANTE firmware version %d (supported started at %d), UPDATE required !!\n", - alpx_dev->identity.ver_fpga, - ALPDANTE_SUPPORTED_BASE_FW_VERSION); - is_update_required = 1; - } - break; - default: - dev_warn(alpx_dev->dev, " identity not finalized for this model : %d\n", alpx_dev->variant->model); - } - - - /* Remount MTD with SERIAL number added only in USER mod, to clearly identify the cards */ - if (!with_board_in_prod_mode ) { - - //Build a special partition table to add the serial number (A COPY) !! - struct mtd_partition fw_partitions_table[ALPX_FLASH_PARTITION_QTY]; - char part_names[ALPX_FLASH_PARTITION_QTY][128]; - unsigned int part_idx = 0; - - for (part_idx = 0 ; part_idx < alpx_dev->variant->flash_partitions.qty_for_fw_update ; ++part_idx) { - - fw_partitions_table[part_idx] = alpx_dev->variant->flash_partitions.partitions[ALPX_FLASH_PARTITION_FW_ID + part_idx]; - scnprintf(part_names[part_idx], PAGE_SIZE, "%s-%llu", - fw_partitions_table[part_idx].name, - alpx_dev->identity.serial_number); - - fw_partitions_table[part_idx].name = part_names[part_idx]; - } - - dev_dbg( alpx_dev->dev," Flash in USER mode: firmware partitionS with S/N appened.\n"); - /* Replace the current partitions */ - alpx_mtd_remove(alpx_dev); - ret = alpx_mtd_probe(alpx_dev, - fw_partitions_table, - alpx_dev->variant->flash_partitions.qty_for_fw_update); - } - - if (ret){ - dev_err(alpx_dev->dev," Error %d when re-creating Firmware partition\n", ret); - goto unregister_xdma; - } - - //Stop here if update required. - if (is_update_required == 1) - return 0; - - /* Information */ - - strcpy(card->driver, "Driver AlpX"); - - //Check if replaced by parameters, default : use the variant names - dev_dbg( alpx_dev->dev,"%s() : id[%d] = %s\n", __func__, - card_idx, - id[card_idx] == NULL ? "NULL" : id[card_idx]); - - if (id[card_idx]) - sprintf(card->shortname, id[card_idx]); - else - sprintf(card->shortname, alpx_dev->variant->shortname); - - strcpy(card->longname, alpx_dev->variant->longname); - strcpy(card->mixername, alpx_dev->variant->mixername); - - /* Pipes */ - - spin_lock_init(&alpx_dev->config.lock); - - alpx_pipe_init(&alpx_dev->playback, true); - alpx_pipe_init(&alpx_dev->capture, false); - - /* PCM */ - - ret = snd_pcm_new(card, card->shortname, 0, 1, 1, &pcm); - if (ret) { - dev_err(dev," snd_pcm_new(card) => %d\n", ret); - goto unregister_xdma; - } - - pcm->private_data = alpx_dev; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &alpx_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &alpx_capture_ops); - - pcm->info_flags = 0; - - strcpy(pcm->name, card->longname); - - /* Controls */ - - ret = alpx_controls_register(card); - if (ret) { - dev_err(dev," alpx_controls_register(card) => %d\n", ret); - goto unregister_xdma; - } - - /* Buffer */ - -#if KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE - snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, dev, - alpx_dev->variant->playback_hw->buffer_bytes_max, - alpx_dev->variant->playback_hw->buffer_bytes_max); -#else - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, dev, - alpx_dev->variant->playback_hw->buffer_bytes_max, - alpx_dev->variant->playback_hw->buffer_bytes_max); -#endif -#if defined (ALPX_WITH_GPIO) - /* GPIO */ - - if (alpx_dev->variant->features & ALPX_VARIANT_FEATURE_GPIOS) - ret = alpx_gpio_register(alpx_dev, card->shortname); - - if (ret) { - dev_err(dev," alpx_gpio_register(alpx_dev) => %d\n", ret); - goto unregister_xdma; - } -#endif - /* Proc */ - ret = alpx_proc_probe(alpx_dev); - if (ret) { - dev_err(dev," alpx_proc_probe(alpx_dev) => %d\n", ret); - goto unregister_xdma; - } - - /* Card */ - - ret = snd_card_register(card); - if (ret){ - dev_err(dev," snd_card_register(card) => %d\n", ret); - goto error_proc; - } - - /* Sys FS files */ - /* Reg debug */ -#ifdef WITH_REG_DEBUG - dev_info(dev,"REG_DEBUG activated\n"); - alpx_dev->dbg_reg_offset = ALP222_MIN_REG_OFFSET; - - ret = device_create_file(dev, &dev_reg_offset); - if (ret) - { - dev_err(dev," device_create_file(addr) => %d\n", ret); - } - else - { - dev_err(dev," device_create_file(addr) : Ok\n"); - } - - ret = device_create_file(dev, &dev_reg_value); - if (ret) - { - dev_err(dev," device_create_file(value) => %d\n", ret); - } -#endif - - /* Serial number file */ - ret = device_create_file(dev, &dev_serial_number); - if (ret) - { - dev_err(dev," Serial Number device_create_file() => %d\n", ret); - } - - /* FPGA version file */ - ret = device_create_file(dev, &dev_ver_fpga); - if (ret) - { - dev_err(dev," FPGA Version device_create_file() => %d\n", ret); - } - - /* MCU version file */ - ret = device_create_file(dev, &dev_ver_mcu); - if (ret) - { - dev_err(dev," MCU Version device_create_file() => %d\n", ret); - } - - /* DANTE card's name */ - if (alpx_dev->variant->model == ALPX_VARIANT_MODEL_ALPDANTE) { - ret = device_create_file(dev, &dev_dante_card_name); - if (ret) - { - dev_err(dev," DANTE card's name device_create_file() => %d\n", ret); - } - } - - /* Production area replication from USER to GOLDEN if needed*/ - if (((alpx_dev->variant->model == ALPX_VARIANT_MODEL_ALP222) || - (alpx_dev->variant->model == ALPX_VARIANT_MODEL_ALP222_MIC)) && - alpx_mtd_is_available(alpx_dev) && - !alpx_mtd_is_golden_prod_area_valid(alpx_dev)) { - dev_info(alpx_dev->dev," Production area in GOLDEN must be INITIALIZED\n"); - ret = alpx_mtd_replicate_prod_area(alpx_dev); - if (!ret) { - dev_info(alpx_dev->dev," Production area in GOLDEN is INITIALIZED\n"); - } - else { - dev_warn(alpx_dev->dev," Production area in GOLDEN NOT CORRECTLY INITIALIZED !!\n"); - } - } - - switch (alpx_dev->variant->model){ - case ALPX_VARIANT_MODEL_ALP222: - case ALPX_VARIANT_MODEL_ALP222_MIC: - alpstereo_print_identity(alpx_dev, card, "Created"); - break; - case ALPX_VARIANT_MODEL_ALP882: - case ALPX_VARIANT_MODEL_ALP882_MIC: - case ALPX_VARIANT_MODEL_ALP442: - case ALPX_VARIANT_MODEL_ALP442_MIC: - alpmultichan_print_identity(alpx_dev, card, "Created"); - break; - case ALPX_VARIANT_MODEL_MADI: - case ALPX_VARIANT_MODEL_MADI_LOOPBACK: - alpmadi_print_identity(alpx_dev, card, "Created"); - break; - case ALPX_VARIANT_MODEL_ALPDANTE: - alpdante_print_identity(alpx_dev, card, "Created"); - alpdante_card_setup(alpx_dev, card, dante_configured_fs, dante_loopback_enabled); - break; - default: - dev_warn(alpx_dev->dev," !!! UNKNOW variant identity: %d !!!!\n", alpx_dev->variant->model); - }; - - card_idx++; - - return 0; - -error_proc: - dev_err(alpx_dev->dev," %s(): Error : 0x%x when creating proc entry\n", __func__, ret); - alpx_proc_remove(alpx_dev); -unregister_xdma: - alpx_xdma_unregister(pci_dev, alpx_dev->xdma_pdev); -disable_pci_dev: - pci_disable_device(pci_dev); -error_card: - dev_err(alpx_dev->dev," %s(): Error : 0x%x when creating the card\n", __func__, ret); - snd_card_free(card); - - return ret; -} - -static void alpx_remove(struct pci_dev *pci_dev) -{ - struct snd_card *card = pci_get_drvdata(pci_dev); - struct alpx_device *alpx_dev = card->private_data; - - switch (alpx_dev->variant->model){ - case ALPX_VARIANT_MODEL_ALP222: - case ALPX_VARIANT_MODEL_ALP222_MIC: - alpstereo_print_identity(alpx_dev, card, "Deleted"); - break; - case ALPX_VARIANT_MODEL_ALP882: - case ALPX_VARIANT_MODEL_ALP882_MIC: - case ALPX_VARIANT_MODEL_ALP442: - case ALPX_VARIANT_MODEL_ALP442_MIC: - if (card != NULL) { - alpmultichan_print_identity(alpx_dev, card, "Deleted"); - } - break; - case ALPX_VARIANT_MODEL_MADI: - case ALPX_VARIANT_MODEL_MADI_LOOPBACK: - alpmadi_print_identity(alpx_dev, card, "Deleted"); - break; - case ALPX_VARIANT_MODEL_ALPDANTE: - alpdante_print_identity(alpx_dev, card, "Deleted"); - break; - default: - dev_warn(alpx_dev->dev," !!! UNKNOW variant identity: %d !!!!\n", alpx_dev->variant->model); - } - - /* Reg debug */ -#ifdef WITH_REG_DEBUG - device_remove_file(alpx_dev->dev, &dev_reg_offset); - device_remove_file(alpx_dev->dev, &dev_reg_value); -#endif - device_remove_file(alpx_dev->dev, &dev_serial_number); - device_remove_file(alpx_dev->dev, &dev_ver_fpga); - device_remove_file(alpx_dev->dev, &dev_ver_mcu); - - if (alpx_dev->variant->model == ALPX_VARIANT_MODEL_ALPDANTE) { - device_remove_file(alpx_dev->dev, &dev_dante_card_name); - } - - alpx_mtd_remove(alpx_dev); - alpx_proc_remove(alpx_dev); - - if (alpx_dev->xdma_pdev != NULL) { - alpx_xdma_unregister(pci_dev, alpx_dev->xdma_pdev); - } - - if (card != NULL) { - snd_card_free(card); - } - - pci_disable_device(alpx_dev->pci_dev); -} - -static const struct pci_device_id alpx_pci_ids[] = { - { PCI_DEVICE(PCI_VENDOR_ID_DIGIGRAM, ALPX_PCI_ID_DEVICE) }, - { 0 } -}; - -MODULE_DEVICE_TABLE(pci, alpx_pci_ids); - -static struct pci_driver alpx_driver = { - .name = KBUILD_MODNAME, - .id_table = alpx_pci_ids, - .probe = alpx_probe, - .remove = alpx_remove, -}; - -module_pci_driver(alpx_driver); - -MODULE_DESCRIPTION("AlpX audio cards driver"); -MODULE_AUTHOR("Digigram Digital"); -MODULE_VERSION(ALPX_MODULE_VERSION); -MODULE_LICENSE("GPL"); |