diff options
author | Christian Pointner <equinox@helsinki.at> | 2024-05-10 18:56:00 (GMT) |
---|---|---|
committer | Christian Pointner <equinox@helsinki.at> | 2024-05-10 18:56:00 (GMT) |
commit | af6bfbbd2496b1f5aa02b94caff4e6f988fa32c9 (patch) | |
tree | 45bebb68a0bf3bfc2fff1646f6fa0f4b976fba57 /snd-alpx-dkms/snd-alpx/alpx_cards.c | |
parent | 7035064ca063fdf15669ceb790ecef1e5ed054b0 (diff) |
rename package to snd-alpx-dkms
Diffstat (limited to 'snd-alpx-dkms/snd-alpx/alpx_cards.c')
-rw-r--r-- | snd-alpx-dkms/snd-alpx/alpx_cards.c | 545 |
1 files changed, 545 insertions, 0 deletions
diff --git a/snd-alpx-dkms/snd-alpx/alpx_cards.c b/snd-alpx-dkms/snd-alpx/alpx_cards.c new file mode 100644 index 0000000..7f9ec3a --- /dev/null +++ b/snd-alpx-dkms/snd-alpx/alpx_cards.c @@ -0,0 +1,545 @@ +// 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/pci.h> + +#include "alpx_cards.h" +#include "alpx_reg.h" +#include "alpx_mtd.h" +#include "alpx_axcmem.h" +#include "alpx_variants_dante.h" + +#include <linux/delay.h> + +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; +} |