Index: /trunk/libffado/src/rme/rme_shm.h =================================================================== --- /trunk/libffado/src/rme/rme_shm.h (revision 1629) +++ /trunk/libffado/src/rme/rme_shm.h (revision 1671) @@ -40,4 +40,5 @@ signed int dds_freq; // Optionally explicitly set hardware freq signed int software_freq; // Sampling frequency in use by software + signed int hardware_freq; // Frequency actually programmed into hardware signed int is_streaming; Index: /trunk/libffado/src/rme/fireface_hw.cpp =================================================================== --- /trunk/libffado/src/rme/fireface_hw.cpp (revision 1629) +++ /trunk/libffado/src/rme/fireface_hw.cpp (revision 1671) @@ -619,6 +619,4 @@ return write_tco(tc, 4); - - return 0; } @@ -638,4 +636,7 @@ else ret = writeRegister(RME_FF800_STREAM_SRATE, freq); + + if (ret == 0) + dev_config->hardware_freq = freq; return ret; @@ -674,4 +675,5 @@ Device::hardware_start_streaming(unsigned int listen_channel) { + signed int ret = 0; // Listen_channel is the ISO channel the PC will listen on for data sent // by the Fireface. @@ -679,14 +681,24 @@ quadlet_t data = num_channels; - if (m_rme_model == RME_MODEL_FIREFACE400) { - addr = RME_FF400_STREAM_START_REG; - data |= (listen_channel << 5); - } else { - addr = RME_FF800_STREAM_START_REG; - if (speed800) - data |= RME_FF800_STREAMING_SPEED_800; // Flag 800 Mbps speed - } - - return writeRegister(addr, data); + config_lock(); + if (not(hardware_is_streaming())) { + if (m_rme_model == RME_MODEL_FIREFACE400) { + addr = RME_FF400_STREAM_START_REG; + data |= (listen_channel << 5); + } else { + addr = RME_FF800_STREAM_START_REG; + if (speed800) + data |= RME_FF800_STREAMING_SPEED_800; // Flag 800 Mbps speed + } + + ret = writeRegister(addr, data); + if (ret != 0) { + dev_config->is_streaming = 1; + } + } else + ret = -1; + config_unlock(); + + return ret; } @@ -696,15 +708,25 @@ fb_nodeaddr_t addr; quadlet_t buf[4] = {0, 0, 0, 1}; - unsigned int size; - - if (m_rme_model == RME_MODEL_FIREFACE400) { - addr = RME_FF400_STREAM_END_REG; - size = RME_FF400_STREAM_END_SIZE; - } else { - addr = RME_FF800_STREAM_END_REG; - size = RME_FF800_STREAM_END_SIZE; - } - - return writeBlock(addr, buf, size); + unsigned int size, ret = 0; + + config_lock(); + if (hardware_is_streaming()) { + if (m_rme_model == RME_MODEL_FIREFACE400) { + addr = RME_FF400_STREAM_END_REG; + size = RME_FF400_STREAM_END_SIZE; + } else { + addr = RME_FF800_STREAM_END_REG; + size = RME_FF800_STREAM_END_SIZE; + } + + ret = writeBlock(addr, buf, size); + if (ret != 0) { + dev_config->is_streaming = 0; + } + } else + ret = -1; + config_unlock(); + + return ret; } Index: /trunk/libffado/src/rme/rme_avdevice.cpp =================================================================== --- /trunk/libffado/src/rme/rme_avdevice.cpp (revision 1660) +++ /trunk/libffado/src/rme/rme_avdevice.cpp (revision 1671) @@ -25,4 +25,6 @@ #warning RME support is at an early development stage and is not functional +#include "config.h" + #include "rme/rme_avdevice.h" #include "rme/fireface_def.h" @@ -516,6 +518,14 @@ signed int mult, bandwidth; + signed int freq; + signed int err = 0; debugOutput(DEBUG_LEVEL_NORMAL, "Preparing Device...\n" ); + + freq = getSamplingFrequency(); + if (freq <= 0) { + debugOutput(DEBUG_LEVEL_ERROR, "Can't continue: sampling frequency not set\n"); + return false; + } // The number of frames transmitted in a single packet is solely @@ -553,6 +563,7 @@ // Both the FF400 and FF800 require we allocate a tx iso channel. The - // rx channel is also allocated for the FF400 while the FF800 handles - // the rx channel allocation for that device. + // rx channel is also allocated for the FF400. The FF800 chooses + // the rx channel to be used but does not handle the bus-level + // channel/bandwidth allocation/ if (iso_tx_channel < 0) { iso_tx_channel = get1394Service().allocateIsoChannelGeneric(bandwidth); @@ -570,14 +581,40 @@ } } - - if (iso_tx_channel<0 || iso_rx_channel<0) { + + if (iso_tx_channel>=0 && iso_rx_channel>=0) { + err = hardware_init_streaming(dev_config->hardware_freq, iso_tx_channel) != 0; + if (err) { + debugFatal("Could not intialise device streaming system\n"); + } + } else { + err = 1; + debugFatal("Could not allocate iso channels\n"); + } + + if (err) { if (iso_tx_channel >= 0) get1394Service().freeIsoChannel(iso_tx_channel); if (iso_rx_channel >= 0) get1394Service().freeIsoChannel(iso_rx_channel); - debugFatal("Could not allocate iso channels\n"); - return false; - } - + return false; + } + + // get the device specific and/or global SP configuration + Util::Configuration &config = getDeviceManager().getConfiguration(); + // base value is the config.h value + float recv_sp_dll_bw = STREAMPROCESSOR_DLL_BW_HZ; + float xmit_sp_dll_bw = STREAMPROCESSOR_DLL_BW_HZ; + + // we can override that globally + config.getValueForSetting("streaming.spm.recv_sp_dll_bw", recv_sp_dll_bw); + config.getValueForSetting("streaming.spm.xmit_sp_dll_bw", xmit_sp_dll_bw); + + // or override in the device section + config.getValueForDeviceSetting(getConfigRom().getNodeVendorId(), getConfigRom().getModelId(), "recv_sp_dll_bw", recv_sp_dll_bw); + config.getValueForDeviceSetting(getConfigRom().getNodeVendorId(), getConfigRom().getModelId(), "xmit_sp_dll_bw", xmit_sp_dll_bw); + + // Other things to be done: + // * create a receive stream processor, set DLL bandwidth, add ports + // * create a transmit stream processor, set DLL bandwidth, add ports return true; @@ -596,11 +633,24 @@ bool Device::startStreamByIndex(int i) { - return false; + // The RME does not allow separate enabling of the transmit and receive + // streams. Therefore we start all streaming when index 0 is referenced + // and silently ignore the start requests for other streams + // (unconditionally flagging them as being successful). + if (i == 0) { + if (hardware_start_streaming(iso_rx_channel) != 0) + return false; + } + return true; } bool Device::stopStreamByIndex(int i) { - return false; - + // See comments in startStreamByIndex() as to why we act only when stream + // 0 is requested. + if (i == 0) { + if (hardware_stop_streaming() != 0) + return false; + } + return true; }