root/trunk/libffado/src/rme/rme_avdevice.cpp

Revision 1547, 12.2 kB (checked in by jwoithe, 15 years ago)

RME:
- quickly fix device detection by comparing config file modelid against the unit's unit version since RME use unit version to differentiate models
- documentation update
- refinements to device defines
- begin to fill in device initialisation details

Line 
1 /*
2  * Copyright (C) 2005-2009 by Jonathan Woithe
3  * Copyright (C) 2005-2008 by Pieter Palmers
4  *
5  * This file is part of FFADO
6  * FFADO = Free Firewire (pro-)audio drivers for linux
7  *
8  * FFADO is based upon FreeBoB.
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 2 of the License, or
13  * (at your option) version 3 of the License.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 #warning RME support is currently useless (detection only)
26
27 #include "rme/rme_avdevice.h"
28 #include "rme/fireface_def.h"
29
30 #include "libieee1394/configrom.h"
31 #include "libieee1394/ieee1394service.h"
32
33 #include "debugmodule/debugmodule.h"
34
35 #include "devicemanager.h"
36
37 #include <string>
38 #include <stdint.h>
39 #include <assert.h>
40 #include "libutil/ByteSwap.h"
41
42 #include <iostream>
43 #include <sstream>
44
45 #include <libraw1394/csr.h>
46
47 // Known values for the unit version of RME devices
48 #define RME_UNITVERSION_FF800  0x0001
49 #define RME_UNITVERSION_FF400  0x0002
50
51 namespace Rme {
52
53 // The RME devices expect async packet data in little endian format (as
54 // opposed to bus order, which is big endian).  Therefore define our own
55 // 32-bit byteswap function to do this.
56 #if __BYTE_ORDER == __BIG_ENDIAN
57 static inline uint32_t
58 ByteSwapToDevice32(uint32_t d)
59 {
60     return byteswap_32(d);
61 }
62 ByteSwapFromDevice32(uint32_t d)
63 {
64     return byteswap_32(d);
65 }
66 #else
67 static inline uint32_t
68 ByteSwapToDevice32(uint32_t d)
69 {
70     return d;
71 }
72 static inline uint32_t
73 ByteSwapFromDevice32(uint32_t d)
74 {
75     return d;
76 }
77 #endif
78
79 // Template for an RME Device object method which intelligently returns a
80 // register or value applicable to the connected model and warns if something
81 // isn't quite right.
82 #define MODEL_SELECTOR(_name,_ff400_arg,_ff800_arg) \
83 unsigned long long int \
84 Device::_name() { \
85     switch (m_rme_model) { \
86         case RME_MODEL_FIREFACE400: return _ff400_arg; \
87         case RME_MODEL_FIREFACE800: return _ff800_arg; \
88     default: \
89       debugOutput( DEBUG_LEVEL_WARNING, "Bad RME model %d\n", m_rme_model ); \
90   } \
91   return 0xffffffffffffffffLL; \
92 }
93
94 Device::Device( DeviceManager& d,
95                       std::auto_ptr<ConfigRom>( configRom ))
96     : FFADODevice( d, configRom )
97     , m_rme_model( RME_MODEL_NONE )
98     , m_ddsFreq( -1 )
99 {
100     debugOutput( DEBUG_LEVEL_VERBOSE, "Created Rme::Device (NodeID %d)\n",
101                  getConfigRom().getNodeId() );
102 }
103
104 Device::~Device()
105 {
106
107 }
108
109 MODEL_SELECTOR(cmd_buffer_addr, RME_FF400_CMD_BUFFER, RME_FF800_CMD_BUFFER)
110 MODEL_SELECTOR(stream_init_reg, RME_FF400_STREAM_INIT_REG, RME_FF800_STREAM_INIT_REG)
111 MODEL_SELECTOR(stream_start_reg, RME_FF400_STREAM_START_REG, RME_FF800_STREAM_START_REG)
112 MODEL_SELECTOR(stream_end_reg, RME_FF400_STREAM_END_REG, RME_FF800_STREAM_END_REG)
113 MODEL_SELECTOR(flash_settings_addr, RME_FF400_FLASH_SETTINGS_ADDR, RME_FF800_FLASH_SETTINGS_ADDR)
114 MODEL_SELECTOR(flash_mixer_vol_addr, RME_FF400_FLASH_MIXER_VOLUME_ADDR, RME_FF800_FLASH_MIXER_VOLUME_ADDR)
115 MODEL_SELECTOR(flash_mixer_pan_addr, RME_FF400_FLASH_MIXER_PAN_ADDR, RME_FF800_FLASH_MIXER_PAN_ADDR)
116 MODEL_SELECTOR(flash_mixer_hw_addr, RME_FF400_FLASH_MIXER_HW_ADDR, RME_FF800_FLASH_MIXER_HW_ADDR)
117
118 bool
119 Device::probe( Util::Configuration& c, ConfigRom& configRom, bool generic )
120 {
121     if (generic) {
122         return false;
123     } else {
124         // check if device is in supported devices list.  Note that the RME
125         // devices use the unit version to identify the individual devices.
126         // To avoid having to extend the configuration file syntax to
127         // include this at this point, we'll use the configuration file
128         // model ID to test against the device unit version.  This can be
129         // tidied up if the configuration file is extended at some point to
130         // include the unit version.
131         unsigned int vendorId = configRom.getNodeVendorId();
132         unsigned int unitVersion = configRom.getUnitVersion();
133
134         Util::Configuration::VendorModelEntry vme = c.findDeviceVME( vendorId, unitVersion );
135         return c.isValid(vme) && vme.driver == Util::Configuration::eD_RME;
136     }
137 }
138
139 FFADODevice *
140 Device::createDevice(DeviceManager& d, std::auto_ptr<ConfigRom>( configRom ))
141 {
142     return new Device(d, configRom );
143 }
144
145 bool
146 Device::discover()
147 {
148     unsigned int vendorId = getConfigRom().getNodeVendorId();
149     // See note in Device::probe() about why we use the unit version here.
150     unsigned int unitVersion = getConfigRom().getUnitVersion();
151
152     Util::Configuration &c = getDeviceManager().getConfiguration();
153     Util::Configuration::VendorModelEntry vme = c.findDeviceVME( vendorId, unitVersion );
154
155     if (c.isValid(vme) && vme.driver == Util::Configuration::eD_RME) {
156         debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s\n",
157                      vme.vendor_name.c_str(),
158                      vme.model_name.c_str());
159     } else {
160         debugWarning("Device '%s %s' unsupported by RME driver (no generic RME support)\n",
161                      getConfigRom().getVendorName().c_str(), getConfigRom().getModelName().c_str());
162     }
163
164     if (unitVersion == RME_UNITVERSION_FF800) {
165         m_rme_model = RME_MODEL_FIREFACE800;
166     } else
167     if (unitVersion == RME_MODEL_FIREFACE400) {
168         m_rme_model = RME_MODEL_FIREFACE400;
169     } else {
170         debugError("Unsupported model\n");
171         return false;
172     }
173
174     init_hardware();
175     read_device_settings();
176
177     return true;
178 }
179
180 int
181 Device::getSamplingFrequency( ) {
182 /*
183  * Retrieve the current sample rate from the RME device.  At this stage it
184  * seems that the "current rate" can't be retrieved from the device.  Other
185  * drivers don't read the DDS control register and there isn't anywhere else
186  * where the frequency is sent back to the PC.  Unless we test the DDS
187  * control register for readabilty and find it can be read we'll assume it
188  * can't and instead cache the DDS frequency.
189  *
190  * If the device frequency has not been set this function will return -1
191  * (the default value of m_ddsFreq).
192  */
193     return m_ddsFreq;
194 }
195
196 int
197 Device::getConfigurationId()
198 {
199     return 0;
200 }
201
202 bool
203 Device::setSamplingFrequency( int samplingFrequency )
204 {
205 /*
206  * Set the RME device's samplerate.  The RME can do sampling frequencies of
207  * 32k, 44.1k and 48k along with the corresponding 2x and 4x rates.
208  * However, it can also do +/- 4% from any of these "base" frequencies using
209  * its DDS.  This makes it a little long-winded to work out whether a given
210  * frequency is supported or not.
211  *
212  * This function is concerned with setting the device up for streaming, so the
213  * register we want to write to is in fact the streaming sample rate portion of
214  * the streaming initialisation function (as opposed to the DDS frequency register
215  * which is distinct on the FF800.  How the FF800's DDS register will ultimately
216  * be controlled is yet to be determined.
217  */
218
219     /* Work out whether the requested rate is supported */
220     /* FIXME: the +/- 4% range is only doable if the DDS is engaged */
221     if (!((samplingFrequency >= 32000*0.96 && samplingFrequency <= 32000*1.04) ||
222         (samplingFrequency >= 44100*0.96 && samplingFrequency <= 44100*1.04) ||
223         (samplingFrequency >= 48000*0.96 && samplingFrequency <= 48000*1.04) ||
224         (samplingFrequency >= 64000*0.96 && samplingFrequency <= 64000*1.04) ||
225         (samplingFrequency >= 88200*0.96 && samplingFrequency <= 88200*1.04) ||
226         (samplingFrequency >= 96000*0.96 && samplingFrequency <= 96000*1.04) ||
227         (samplingFrequency >= 128000*0.96 && samplingFrequency <= 128000*1.04) ||
228         (samplingFrequency >= 176000*0.96 && samplingFrequency <= 176000*1.04) ||
229         (samplingFrequency >= 192000*0.96 && samplingFrequency <= 192000*1.04))) {
230         return false;
231     }
232    
233     /* Send the desired frequency to the RME */
234     if (writeRegister(stream_init_reg(), samplingFrequency) != 0)
235       return false;
236
237     m_ddsFreq = samplingFrequency;
238     return true;
239 }
240
241 #define RME_CHECK_AND_ADD_SR(v, x) \
242     { \
243     if (((x >= 32000*0.96 && x <= 32000*1.04) || \
244         (x >= 44100*0.96 && x <= 44100*1.04) || \
245         (x >= 48000*0.96 && x <= 48000*1.04) || \
246         (x >= 64000*0.96 && x <= 64000*1.04) || \
247         (x >= 88200*0.96 && x <= 88200*1.04) || \
248         (x >= 96000*0.96 && x <= 96000*1.04) || \
249         (x >= 128000*0.96 && x <= 128000*1.04) || \
250         (x >= 176000*0.96 && x <= 176000*1.04) || \
251         (x >= 192000*0.96 && x <= 192000*1.04))) { \
252         v.push_back(x); \
253     };};
254
255 std::vector<int>
256 Device::getSupportedSamplingFrequencies()
257 {
258     std::vector<int> frequencies;
259     /* FIXME: the +/- 4% frequency range is only doable if the DDS is
260      * engaged.
261      */
262     RME_CHECK_AND_ADD_SR(frequencies, 32000);
263     RME_CHECK_AND_ADD_SR(frequencies, 44100);
264     RME_CHECK_AND_ADD_SR(frequencies, 48000);
265     RME_CHECK_AND_ADD_SR(frequencies, 64000);
266     RME_CHECK_AND_ADD_SR(frequencies, 88200);
267     RME_CHECK_AND_ADD_SR(frequencies, 96000);
268     RME_CHECK_AND_ADD_SR(frequencies, 128000);
269     RME_CHECK_AND_ADD_SR(frequencies, 176400);
270     RME_CHECK_AND_ADD_SR(frequencies, 192000);
271     return frequencies;
272 }
273
274 FFADODevice::ClockSourceVector
275 Device::getSupportedClockSources() {
276     FFADODevice::ClockSourceVector r;
277     return r;
278 }
279
280 bool
281 Device::setActiveClockSource(ClockSource s) {
282     return false;
283 }
284
285 FFADODevice::ClockSource
286 Device::getActiveClockSource() {
287     ClockSource s;
288     return s;
289 }
290
291 bool
292 Device::lock() {
293
294     return true;
295 }
296
297
298 bool
299 Device::unlock() {
300
301     return true;
302 }
303
304 void
305 Device::showDevice()
306 {
307     unsigned int vendorId = getConfigRom().getNodeVendorId();
308     unsigned int modelId = getConfigRom().getModelId();
309
310     Util::Configuration &c = getDeviceManager().getConfiguration();
311     Util::Configuration::VendorModelEntry vme = c.findDeviceVME( vendorId, modelId );
312
313     debugOutput(DEBUG_LEVEL_VERBOSE,
314         "%s %s at node %d\n", vme.vendor_name.c_str(), vme.model_name.c_str(), getNodeId());
315 }
316
317 bool
318 Device::prepare() {
319
320         debugOutput(DEBUG_LEVEL_NORMAL, "Preparing Device...\n" );
321
322         return true;
323 }
324
325 int
326 Device::getStreamCount() {
327         return 0; // one receive, one transmit
328 }
329
330 Streaming::StreamProcessor *
331 Device::getStreamProcessorByIndex(int i) {
332     return NULL;
333 }
334
335 bool
336 Device::startStreamByIndex(int i) {
337     return false;
338 }
339
340 bool
341 Device::stopStreamByIndex(int i) {
342     return false;
343
344 }
345
346 unsigned int
347 Device::readRegister(fb_nodeaddr_t reg) {
348
349     quadlet_t quadlet;
350    
351     quadlet = 0;
352     if (get1394Service().read(0xffc0 | getNodeId(), reg, 1, &quadlet) <= 0) {
353         debugError("Error doing RME read from register 0x%06x\n",reg);
354     }
355     return ByteSwapFromDevice32(quadlet);
356 }
357
358 signed int
359 Device::readBlock(fb_nodeaddr_t reg, quadlet_t *buf, unsigned int n_quads) {
360
361     unsigned int i;
362
363     if (get1394Service().read(0xffc0 | getNodeId(), reg, n_quads, buf) <= 0) {
364         debugError("Error doing RME block read of %d quadlets from register 0x%06x\n",
365             n_quads, reg);
366         return -1;
367     }
368     for (i=0; i<n_quads; i++) {
369        buf[i] = ByteSwapFromDevice32(buf[i]);
370     }
371
372     return 0;
373 }
374
375 signed int
376 Device::writeRegister(fb_nodeaddr_t reg, quadlet_t data) {
377
378     unsigned int err = 0;
379     data = ByteSwapToDevice32(data);
380     if (get1394Service().write(0xffc0 | getNodeId(), reg, 1, &data) <= 0) {
381         err = 1;
382         debugError("Error doing RME write to register 0x%06x\n",reg);
383     }
384     return (err==0)?0:-1;
385 }
386
387 signed int
388 Device::writeBlock(fb_nodeaddr_t reg, quadlet_t *data, unsigned int n_quads) {
389 //
390 // Write a block of data to the device starting at address "reg".  Note that
391 // the conditional byteswap is done "in place" on data, so the contents of
392 // data may be modified by calling this function.
393 //
394     unsigned int err = 0;
395     unsigned int i;
396
397     for (i=0; i<n_quads; i++) {
398       data[i] = ByteSwapToDevice32(data[i]);
399     }
400     if (get1394Service().write(0xffc0 | getNodeId(), reg, n_quads, data) <= 0) {
401         err = 1;
402         debugError("Error doing RME block write of %d quadlets to register 0x%06x\n",
403           n_quads, reg);
404     }
405     return (err==0)?0:-1;
406 }
407                  
408 }
Note: See TracBrowser for help on using the browser.