// SPDX-License-Identifier: GPL-2.0-or-later /* * Support for Digigram AlpX PCI-e boards * * Copyright (c) 2024 Digigram Digital (info@digigram.com) */ #include #include "alpx_cards.h" #include "alpx_reg.h" #include "alpx_mtd.h" #include "alpx_axcmem.h" #include "alpx_variants_dante.h" #include void alpstereo_print_identity(struct alpx_device *alpx_dev, struct snd_card *card, const unsigned char* label) { const unsigned int design_revision = readl(ALPX_REG(alpx_dev, ALP, CONTROL, DESIGN_VERSION)); //Add Build information, only for design >= 1.8 if (design_revision >= ALP222_DESIGN_WITH_BUILD_REGISTER_VERSION) { const unsigned int build_version = alpx_dev->identity.ver_fpga; const unsigned int ctrl_revision = readl(ALPX_COMMON_REG(alpx_dev, ALP222, CONTROL, VERSION)); const unsigned int mxr_revision = readl(ALPX_COMMON_REG(alpx_dev, ALP222, MIXER, VERSION)); const unsigned int ampli_in_revision = readl(ALPX_COMMON_REG(alpx_dev, ALP222, AMPLI_IN, VERSION)); const unsigned int ampli_out_revision = readl(ALPX_COMMON_REG(alpx_dev, ALP222, AMPLI_OUT, VERSION)); const unsigned int proc_revision = alpx_dev->identity.ver_mcu; dev_info( alpx_dev->dev,\ "\n************ \n" "%s Alp Stereo %s soundcard[%d]{#%llu} : %s - %s (%s - 0x%04x), \n\t== Revisions ==\n\t* Build: \t\t%u\n\t* Design: \t\t%u.%lu\n\t* Control: \t\t%u.%lu\n\t* Ampli In:\t\t%u.%lu\n\t* Mixer: \t\t%u.%lu\n" "\t* Ampli Out:\t\t%u.%lu\n\t* MCU:\t\t\t%u.%lu\n" "************\n", label, alpx_is_222_mic(alpx_dev) ? "MIC":"", card->number, alpx_dev->identity.serial_number, card->id, card->shortname, card->longname, alpx_dev->identity.sub_system_id, build_version, ALPX_COMMON_VERSION_VERSION(design_revision), ALPX_COMMON_VERSION_REVISION(design_revision), ALPX_COMMON_VERSION_VERSION(ctrl_revision), ALPX_COMMON_VERSION_REVISION(ctrl_revision), ALPX_COMMON_VERSION_VERSION(ampli_in_revision), ALPX_COMMON_VERSION_REVISION(ampli_in_revision), ALPX_COMMON_VERSION_VERSION(mxr_revision), ALPX_COMMON_VERSION_REVISION(mxr_revision), ALPX_COMMON_VERSION_VERSION(ampli_out_revision), ALPX_COMMON_VERSION_REVISION(ampli_out_revision), ALPX_COMMON_VERSION_VERSION(proc_revision), ALPX_COMMON_VERSION_REVISION(proc_revision) ); } else { const unsigned int ctrl_revision = readl(ALPX_COMMON_REG(alpx_dev, ALP222, CONTROL, VERSION)); const unsigned int mxr_revision = readl(ALPX_COMMON_REG(alpx_dev, ALP222, MIXER, VERSION)); const unsigned int ampli_in_revision = readl(ALPX_COMMON_REG(alpx_dev, ALP222, AMPLI_IN, VERSION)); const unsigned int ampli_out_revision = readl(ALPX_COMMON_REG(alpx_dev, ALP222, AMPLI_OUT, VERSION)); const unsigned int proc_revision = readl(ALPX_REG(alpx_dev, ALP, PROC, VERSION)); dev_info(alpx_dev->dev, "Serial# : %llu\n", alpx_dev->identity.serial_number); dev_info( alpx_dev->dev,\ "\n************ \n" "%s Alp222 soundcard[%d] {#%llu} : %s - %s (%s - 0x%04x), \n\t== Revisions ==\n\t* Design: \t\t%u.%lu\n\t* Control: \t\t%u.%lu\n\t* Ampli In:\t\t%u.%lu\n\t* Mixer: \t\t%u.%lu\n" "\t* Ampli Out:\t\t%u.%lu\n\t* MCU:\t\t\t%u.%lu\n" "************\n", label, card->number, alpx_dev->identity.serial_number, card->id, card->shortname, card->longname, alpx_dev->identity.sub_system_id, ALPX_COMMON_VERSION_VERSION(design_revision), ALPX_COMMON_VERSION_REVISION(design_revision), ALPX_COMMON_VERSION_VERSION(ctrl_revision), ALPX_COMMON_VERSION_REVISION(ctrl_revision), ALPX_COMMON_VERSION_VERSION(ampli_in_revision), ALPX_COMMON_VERSION_REVISION(ampli_in_revision), ALPX_COMMON_VERSION_VERSION(mxr_revision), ALPX_COMMON_VERSION_REVISION(mxr_revision), ALPX_COMMON_VERSION_VERSION(ampli_out_revision), ALPX_COMMON_VERSION_REVISION(ampli_out_revision), ALPX_COMMON_VERSION_VERSION(proc_revision), ALPX_COMMON_VERSION_REVISION(proc_revision) ); } } void alpmadi_print_identity(struct alpx_device *alpx_dev, struct snd_card *card, const unsigned char* label) { const unsigned int ctrl_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMADI, CONTROL, VERSION)); const unsigned int mxr_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMADI, MIXER, VERSION)); const unsigned int meas_daw_in_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMADI, MEAS_DAW_IN, VERSION)); const unsigned int meas_daw_out_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMADI, MEAS_DAW_OUT, VERSION)); const unsigned int meas_madi_in_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMADI, MEAS_MADI_IN, VERSION)); const unsigned int meas_madi_out_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMADI, MEAS_MADI_OUT, VERSION)); const unsigned int gain_madi_in_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMADI, GAIN_MADI_IN, VERSION)); const unsigned int gain_madi_out_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMADI, GAIN_MADI_OUT, VERSION)); const unsigned int gain_daw_in_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMADI, GAIN_DAW_IN, VERSION)); const unsigned int gain_daw_out_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMADI, GAIN_DAW_OUT, VERSION)); const unsigned int router_in_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMADI, ROUTER_IN, VERSION)); dev_info( alpx_dev->dev,\ "************ \n" "%s AlpMadi soundcard[%d]{#%llu} : %s - %s (%s - 0x%04x), \n\t== Revisions ==\n\t * Control: \t\t%u.%lu\n\t * Mixer: \t\t%u.%lu\n\t * Gain Daw In:\t%u.%lu\n\t * Gain Daw Out:\t%u.%lu\n\t * Gain MADI In:\t\t%u.%lu\n\t * Gain MADI Out:\t%u.%lu\n\t * Meas DAW In:\t%u.%lu\n\t * Meas Daw Out:\t%u.%lu\n\t * Meas MADI In:\t\t%u.%lu\n\t * Meas MADI Out:\t%u.%lu\n\t * Router:\t\t%u.%lu\n" "************\n", label, card->number, alpx_dev->identity.serial_number, card->id, card->shortname, card->longname, alpx_dev->identity.sub_system_id, ALPX_COMMON_VERSION_VERSION(ctrl_revision), ALPX_COMMON_VERSION_REVISION(ctrl_revision), ALPX_COMMON_VERSION_VERSION(mxr_revision), ALPX_COMMON_VERSION_REVISION(mxr_revision), ALPX_COMMON_VERSION_VERSION(gain_daw_in_revision), ALPX_COMMON_VERSION_REVISION(gain_daw_in_revision), ALPX_COMMON_VERSION_VERSION(gain_daw_out_revision), ALPX_COMMON_VERSION_REVISION(gain_daw_out_revision), ALPX_COMMON_VERSION_VERSION(gain_madi_in_revision), ALPX_COMMON_VERSION_REVISION(gain_madi_in_revision), ALPX_COMMON_VERSION_VERSION(gain_madi_out_revision), ALPX_COMMON_VERSION_REVISION(gain_madi_out_revision), ALPX_COMMON_VERSION_VERSION(meas_daw_in_revision), ALPX_COMMON_VERSION_REVISION(meas_daw_in_revision), ALPX_COMMON_VERSION_VERSION(meas_daw_out_revision), ALPX_COMMON_VERSION_REVISION(meas_daw_out_revision), ALPX_COMMON_VERSION_VERSION(meas_madi_in_revision), ALPX_COMMON_VERSION_REVISION(meas_madi_in_revision), ALPX_COMMON_VERSION_VERSION(meas_madi_out_revision), ALPX_COMMON_VERSION_REVISION(meas_madi_out_revision), ALPX_COMMON_VERSION_VERSION(router_in_revision), ALPX_COMMON_VERSION_REVISION(router_in_revision)); } void alpmultichan_print_identity(struct alpx_device *alpx_dev, struct snd_card *card, const unsigned char* label) { const unsigned int design_revision = readl(ALPX_REG(alpx_dev, ALP, CONTROL, DESIGN_VERSION)); const unsigned int build_version = alpx_dev->identity.ver_fpga; const unsigned int ctrl_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMC, CONTROL, VERSION)); const unsigned int mxr_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMC, MIXER, VERSION)); const unsigned int ampli_in_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMC, AMPLI_IN, VERSION)); const unsigned int ampli_out_revision = readl(ALPX_COMMON_REG(alpx_dev, ALPMC, AMPLI_OUT, VERSION)); const unsigned int proc_revision = alpx_dev->identity.ver_mcu; dev_info( alpx_dev->dev,\ "\n************ \n" "%s Alp multi-channels soundcard[%d]{#%llu} : %s - %s (%s - 0x%04x) , \n\t== Revisions ==\n\t* Build: \t\t%u\n\t* Design: \t\t%u.%lu\n\t* Control: \t\t%u.%lu\n\t* Ampli In:\t\t%u.%lu\n\t* Mixer: \t\t%u.%lu\n" "\t* Ampli Out:\t\t%u.%lu\n\t* MCU:\t\t\t%u.%lu\n" "************\n", label, card->number, alpx_dev->identity.serial_number, card->id, card->shortname, card->longname, alpx_dev->identity.sub_system_id, build_version, ALPX_COMMON_VERSION_VERSION(design_revision), ALPX_COMMON_VERSION_REVISION(design_revision), ALPX_COMMON_VERSION_VERSION(ctrl_revision), ALPX_COMMON_VERSION_REVISION(ctrl_revision), ALPX_COMMON_VERSION_VERSION(ampli_in_revision), ALPX_COMMON_VERSION_REVISION(ampli_in_revision), ALPX_COMMON_VERSION_VERSION(mxr_revision), ALPX_COMMON_VERSION_REVISION(mxr_revision), ALPX_COMMON_VERSION_VERSION(ampli_out_revision), ALPX_COMMON_VERSION_REVISION(ampli_out_revision), ALPX_COMMON_VERSION_VERSION(proc_revision), ALPX_COMMON_VERSION_REVISION(proc_revision)); } static int alpx_card_read_serial_number(struct alpx_device* alpx_dev) { unsigned char raw_serial[9]; int ret = alpx_mtd_read_shared(alpx_dev, ALPX_SERIAL_OFFSET_IN_PRODUCTION, raw_serial, sizeof(raw_serial) - 1); raw_serial[sizeof(raw_serial) - 1] = 0; if (ret){ dev_err(alpx_dev->dev, "Error %d when reading Shared Area\n", ret); /* DEFAULT VALUES */ alpx_dev->identity.serial_number = (~ 0); return -EIO; } dev_dbg(alpx_dev->dev, " %s() : BEFORE shift %llu // 0x%llx\n", __func__, (uint64_t)raw_serial, (uint64_t)raw_serial); //Conversion RAW => Little endian (not use be64_to_cpu() ?? Should be tested later) alpx_dev->identity.serial_number = ((uint64_t)raw_serial[0])<<32 | ((uint64_t)raw_serial[1]) << 24 | ((uint64_t)raw_serial[2]) << 16 | ((uint64_t)raw_serial[3]) << 8 | ((uint64_t)raw_serial[4]); return 0; } int alpxxx_finalize_identity(struct alpx_device* alpx_dev) { alpx_dev->identity.ver_mcu = readl(ALPX_REG(alpx_dev, ALP, PROC, VERSION)); alpx_dev->identity.ver_fpga = readl(ALPX_REG(alpx_dev, ALP, CONTROL, BUILD_VERSION)) & ALP_CONTROL_BUILD_VERSION_MASK; return 0; } int alpstereo_finalize_identity(struct alpx_device* alpx_dev) { int ret = alpxxx_finalize_identity(alpx_dev); if (ret){ dev_err(alpx_dev->dev, "Error %d when finalizing base identity\n", ret); return ret; } ret = alpx_mtd_load_shared_from(alpx_dev, alpx_dev->variant->flash_partitions.partitions[ALPX_FLASH_PARTITION_PRODUCTION_ID].offset); /* DEFAULT VALUES */ alpx_dev->identity.sub_system_id = (~ 0); alpx_dev->identity.sub_system_id = (~ 0); if (ret){ dev_err(alpx_dev->dev, "Error %d when extracting Production Area\n", ret); return -EIO; } alpx_card_read_serial_number(alpx_dev); alpx_dev->identity.sub_system_id = alpx_dev->pci_dev->subsystem_device; return 0; } int alpmultichan_finalize_identity(struct alpx_device* alpx_dev) { int ret = alpxxx_finalize_identity(alpx_dev); if (ret){ dev_err(alpx_dev->dev, "Error %d when finalizing base identity\n", ret); return ret; } ret = alpx_mtd_load_shared_from(alpx_dev, alpx_dev->variant->flash_partitions.partitions[ALPX_FLASH_PARTITION_PRODUCTION_ID].offset); /* DEFAULT VALUES */ alpx_dev->identity.sub_system_id = alpx_dev->pci_dev->subsystem_device; if (ret){ dev_err(alpx_dev->dev, "Error %d when extracting Production Area\n", ret); return -EIO; } alpx_card_read_serial_number(alpx_dev); return 0; } int alpdante_finalize_identity(struct alpx_device* alpx_dev) { void* fir_reg = NULL; void* csppr_reg = NULL; void* ublaze_version_reg = NULL; void* design_bloc_version_reg = NULL; void* low_serial_reg = NULL; void* high_serial_reg = NULL; uint32_t low_serial_raw = 0; uint32_t high_serial_raw = 0; dev_info(alpx_dev->dev, "DANTE card detected, finalizing identity\n"); /* All this is extracted from AXcMEM registers */ fir_reg = alpx_axcmem_getRegAddr(alpx_dev, &ALPDANTE_FIR_LOC); csppr_reg = alpx_axcmem_getRegAddr(alpx_dev, &ALPDANTE_CSPPR_LOC); ublaze_version_reg = alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, &ALPDANTE_CSPPR_LOC, &ALPDANTE_UBLAZE_VERSION_LOC); design_bloc_version_reg = alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, &ALPDANTE_CSPPR_LOC, &ALPDANTE_DESIGN_BLOC_VERSION_LOC); low_serial_reg = alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, &ALPDANTE_CSPPR_LOC, &ALPDANTE_LOW_SERIAL_NUM_LOC); high_serial_reg = alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, &ALPDANTE_CSPPR_LOC, &ALPDANTE_HIGH_SERIAL_NUM_LOC); dev_dbg(alpx_dev->dev, "FIR[0x%lx]=>%d\n", (uint8_t*)fir_reg - (uint8_t*)alpx_dev->base, alpx_axcmem_getRegBEU16Value(fir_reg)); dev_dbg(alpx_dev->dev, "CSPPR[0x%lx]=> %d\n", (uint8_t*)csppr_reg - (uint8_t*)alpx_dev->base, alpx_axcmem_getRegU8Value(csppr_reg)); dev_dbg(alpx_dev->dev, "uBlaze Version[0x%lx]=> %d\n", (uint8_t*)ublaze_version_reg - (uint8_t*)alpx_dev->base, alpx_axcmem_getRegU16Value(ublaze_version_reg)); dev_dbg(alpx_dev->dev, "Design bloc Version[0x%lx]=> %d\n", (uint8_t*)design_bloc_version_reg - (uint8_t*)alpx_dev->base, alpx_axcmem_getRegU16Value(design_bloc_version_reg)); alpx_dev->identity.ver_mcu = alpx_axcmem_getRegU16Value(ublaze_version_reg); alpx_dev->identity.ver_fpga = alpx_axcmem_getRegBEU16Value(fir_reg); low_serial_raw = alpx_axcmem_getRegU32Value(low_serial_reg); high_serial_raw = alpx_axcmem_getRegU32Value(high_serial_reg); dev_dbg(alpx_dev->dev, "Low serial number[0x%lx]=> 0x%x\n", (uint8_t*)low_serial_reg - (uint8_t*)alpx_dev->base, low_serial_raw); dev_dbg(alpx_dev->dev, "High serial number[0x%lx]=> 0x%x\n", (uint8_t*)high_serial_reg - (uint8_t*)alpx_dev->base, high_serial_raw); alpx_dev->identity.serial_number = ((uint64_t)high_serial_raw)<<8 | (((uint64_t)low_serial_raw) >> 24); /* DEFAULT VALUES */ alpx_dev->identity.sub_system_id = alpx_dev->pci_dev->subsystem_device; return 0; } void alpdante_print_identity(struct alpx_device *alpx_dev, struct snd_card *card, const unsigned char* label) { void* design_bloc_version_reg = design_bloc_version_reg = alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, &ALPDANTE_CSPPR_LOC, &ALPDANTE_DESIGN_BLOC_VERSION_LOC); const unsigned int design_bloc_version = alpx_axcmem_getRegU16Value(design_bloc_version_reg); char dante_name[ALPDANTE_NETWORK_NAME_LENGTH]; dante_name[ALPDANTE_NETWORK_NAME_LENGTH - 1] = 0; alpdante_get_dante_name(alpx_dev, dante_name, ALPDANTE_NETWORK_NAME_LENGTH); dev_info( alpx_dev->dev, "\n************ \n" "%s Alp DANTE soundcard[%d]{#%llu / %s }: %s - %s (%s - 0x%04x) , \n\t== Revisions ==\n\t* Build: \t\t%u\n\t* Design: \t\t%u.%lu\n\t* MCU:\t\t\t%u.%lu\n" "************\n", label, card->number, alpx_dev->identity.serial_number, dante_name, card->id, card->shortname, card->longname, alpx_dev->identity.sub_system_id, alpx_dev->identity.ver_fpga, ALPX_DANTE_VERSION_VERSION(design_bloc_version), ALPX_DANTE_VERSION_REVISION(design_bloc_version), ALPX_DANTE_VERSION_VERSION(alpx_dev->identity.ver_mcu), ALPX_DANTE_VERSION_REVISION(alpx_dev->identity.ver_mcu)); } int alpdante_get_dante_name(struct alpx_device* alpx_dev, char* name, unsigned int length) { if (length < ALPDANTE_NETWORK_NAME_LENGTH) { dev_warn(alpx_dev->dev, "name parameter must be at least %d char long !\n", ALPDANTE_NETWORK_NAME_LENGTH); return -EINVAL; } return alpx_acxmem_getByteArrayByRefLoc(alpx_dev, &ALPDANTE_CNAMPR_LOC, &ALPDANTE_NAME_LOC, name, length); } int alpdante_store_config(struct alpx_device* alpx_dev) { void* fsdr_reg = alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, &ALPDANTE_FPPR_LOC, &ALPDANTE_FSDR_LOC); void* fcr_reg = alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, &ALPDANTE_FPPR_LOC, &ALPDANTE_FCR_LOC); void* fcar_reg = alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, &ALPDANTE_FPPR_LOC, &ALPDANTE_FCAR_LOC); void* smalar_reg = alpx_axcmem_getRegAddr(alpx_dev, &ALPDANTE_SMALAR_LOC); unsigned int waitLoopQty = ALPDANTE_FLASH_LOCK_ACCESS_TRY_QTY; u32 cmd_status = 0; int result = 0; dev_info(alpx_dev->dev, "Storing configuration ...\n"); //Wait for availability while ((alpx_axcmem_getRegU8Value(smalar_reg) != ALPDANTE_SMALAR_AVAILABLE) && (--waitLoopQty)) { dev_dbg(alpx_dev->dev," FCR:0x%x : Not yet available, wai a bit...\n", alpx_axcmem_getRegU8Value(smalar_reg)); mdelay(ALPDANTE_FLASH_WAIT_STEP_TIME); } if (waitLoopQty != 0) { alpx_axcmem_setRegU8Value(smalar_reg, ALPDANTE_SMALAR_IN_USE); dev_dbg(alpx_dev->dev," Semaphore taken\n"); } else { dev_err(alpx_dev->dev, "!! Flash memory unavailable !!\n "); return -EBUSY; } //Write sequence alpx_axcmem_setRegU8Value(fsdr_reg, 1); alpx_axcmem_setRegU8Value(fcr_reg, ALPDANTE_FPPR_SAVE_REGISTERS_CMD_ID); //Wait for completion waitLoopQty = ALPDANTE_FPPR_SAVE_REGS_CMD_COMPLETION_WAIT_STEPS_QTY; while ((alpx_axcmem_getRegU8Value(fcr_reg) != ALPDANTE_FPPR_NOPE_CMD_ID) && (--waitLoopQty)) { dev_dbg(alpx_dev->dev,"FCR: 0x%x : Cmd in progress, wait a bit...\n", alpx_axcmem_getRegU8Value(fcr_reg)); mdelay(ALPDANTE_FLASH_WAIT_STEP_TIME); } if (waitLoopQty==0) { dev_err(alpx_dev->dev, "!! Flash Command TIMEOUT!!\n"); result = -EIO; goto EXIT; } cmd_status = ALPDANTE_FPPR_CMD_STATUS(alpx_axcmem_getRegU32Value(fcar_reg)); dev_info(alpx_dev->dev, "Configuration %s (0x%x)\n", cmd_status ? "NOT STORED !" : "STORED", cmd_status); result = (cmd_status == 0) ? 0 : -EIO; EXIT: alpx_axcmem_setRegU8Value(smalar_reg, ALPDANTE_SMALAR_AVAILABLE); dev_dbg(alpx_dev->dev," Semaphore released\n"); return result; } int alpdante_card_setup(struct alpx_device *alpx_dev, struct snd_card *card, unsigned int configured_fs, bool is_loopback_enabled) { unsigned int sr_config_value = 0; void* sr_config_reg = alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, &ALPDANTE_CLKPR_LOC, &ALPDANTE_SRConfig_LOC); unsigned int fppr_prod_test_value = 0; void* fppr_prod_test_reg = alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, &ALPDANTE_ERRTST_LOC, &ALPDANTE_PROD_TEST_LOC); dev_dbg(alpx_dev->dev, "Setting AlpDANTE card {S/N: %llu} ...\n", alpx_dev->identity.serial_number); switch (configured_fs) { case 44100: sr_config_value = ALPDANTE_CLK_MANAGER_CLK_VALUE_44_1K; alpx_dev->variant->capture_hw->rates=SNDRV_PCM_RATE_44100; alpx_dev->variant->capture_hw->channels_min = 64; alpx_dev->variant->capture_hw->channels_max = 64; alpx_dev->variant->capture_hw->rate_min = configured_fs; alpx_dev->variant->capture_hw->rate_max = configured_fs; break; case 48000: sr_config_value = ALPDANTE_CLK_MANAGER_CLK_VALUE_48K; alpx_dev->variant->capture_hw->rates=SNDRV_PCM_RATE_48000; alpx_dev->variant->capture_hw->channels_min = 64; alpx_dev->variant->capture_hw->channels_max = 64; alpx_dev->variant->capture_hw->rate_min = configured_fs; alpx_dev->variant->capture_hw->rate_max = configured_fs; break; case 88200: sr_config_value = ALPDANTE_CLK_MANAGER_CLK_VALUE_88_2K; alpx_dev->variant->capture_hw->rates=SNDRV_PCM_RATE_88200; alpx_dev->variant->capture_hw->channels_min = 32; alpx_dev->variant->capture_hw->channels_max = 32; alpx_dev->variant->capture_hw->rate_min = configured_fs; alpx_dev->variant->capture_hw->rate_max = configured_fs; break; case 96000: sr_config_value = ALPDANTE_CLK_MANAGER_CLK_VALUE_96K; alpx_dev->variant->capture_hw->rates=SNDRV_PCM_RATE_96000; alpx_dev->variant->capture_hw->channels_min = 32; alpx_dev->variant->capture_hw->channels_max = 32; alpx_dev->variant->capture_hw->rate_min = configured_fs; alpx_dev->variant->capture_hw->rate_max = configured_fs; break; case 176400: sr_config_value = ALPDANTE_CLK_MANAGER_CLK_VALUE_176_4K; alpx_dev->variant->capture_hw->rates=SNDRV_PCM_RATE_176400; alpx_dev->variant->capture_hw->channels_min = 16; alpx_dev->variant->capture_hw->channels_max = 16; alpx_dev->variant->capture_hw->rate_min = configured_fs; alpx_dev->variant->capture_hw->rate_max = configured_fs; break; case 192000: sr_config_value = ALPDANTE_CLK_MANAGER_CLK_VALUE_192K; alpx_dev->variant->capture_hw->rates=SNDRV_PCM_RATE_192000; alpx_dev->variant->capture_hw->channels_min = 16; alpx_dev->variant->capture_hw->channels_max = 16; alpx_dev->variant->capture_hw->rate_min = configured_fs; alpx_dev->variant->capture_hw->rate_max = configured_fs; break; default: dev_err(alpx_dev->dev, "AlpDANTE card {S/N: %llu}; %dHz : unsupported FS, keep default %dHz !\n", alpx_dev->identity.serial_number, configured_fs, alpx_dev->variant->capture_hw->rate_min); }; dev_dbg(alpx_dev->dev, "Setting AlpDANTE card {S/N: %llu}: FS:%dHz => reg=0x%x\n", alpx_dev->identity.serial_number, alpx_dev->variant->capture_hw->rate_min, sr_config_value); alpx_axcmem_setRegU8Value(sr_config_reg, sr_config_value); dev_info(alpx_dev->dev, "AlpDANTE card {S/N: %llu}: loopback mode %s.\n", alpx_dev->identity.serial_number, is_loopback_enabled ? "ENABLED" : "DISABLED"); fppr_prod_test_value = alpx_axcmem_getRegU8Value(fppr_prod_test_reg); fppr_prod_test_value = is_loopback_enabled ? (ALPDANTE_PROD_TEST_LOOPBACK | fppr_prod_test_value) : (fppr_prod_test_value & ~ALPDANTE_PROD_TEST_LOOPBACK); alpx_axcmem_setRegU8Value(fppr_prod_test_reg, fppr_prod_test_value); dev_dbg(alpx_dev->dev, "fppr_prod_test_value = 0x%x, reg: 0x%x\n", fppr_prod_test_value, alpx_axcmem_getRegU8Value(fppr_prod_test_reg)); return alpdante_store_config(alpx_dev); } /* Helpers */ unsigned int alpx_get_samples_counter(struct alpx_device *alpx_dev) { if (alpx_dev->variant->model != ALPX_VARIANT_MODEL_ALPDANTE) { return readl(ALPX_REG(alpx_dev, ALP, CLK_MANAGER, SAMPLES_COUNT)); } else { void* sample_count_reg = alpx_axcmem_getPointedRegAddrByRefLoc(alpx_dev, &ALPDANTE_CSPPR_LOC, &ALPDANTE_SAMPLE_COUNT_LOC); return alpx_axcmem_getRegU32Value(sample_count_reg); } return 0; }