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

Revision 1629, 17.5 kB (checked in by jwoithe, 15 years ago)

RME: refine shared device configuration locking. Rename some data objects for clarity. Move frequency settings into the shared configuration object since ultimately these need to be accessible to all FFADO/RME processes. Other minor cleanups.

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 at an early development stage and is not functional
26
27 #include "rme/rme_avdevice.h"
28 #include "rme/fireface_def.h"
29 #include "rme/fireface_settings_ctrls.h"
30
31 #include "libieee1394/configrom.h"
32 #include "libieee1394/ieee1394service.h"
33
34 #include "debugmodule/debugmodule.h"
35
36 #include "devicemanager.h"
37
38 #include <string>
39 #include <stdint.h>
40 #include <assert.h>
41 #include "libutil/ByteSwap.h"
42
43 #include <iostream>
44 #include <sstream>
45
46 #include <libraw1394/csr.h>
47
48 // Known values for the unit version of RME devices
49 #define RME_UNITVERSION_FF800  0x0001
50 #define RME_UNITVERSION_FF400  0x0002
51
52 namespace Rme {
53
54 // The RME devices expect async packet data in little endian format (as
55 // opposed to bus order, which is big endian).  Therefore define our own
56 // 32-bit byteswap function to do this.
57 #if __BYTE_ORDER == __BIG_ENDIAN
58 static inline uint32_t
59 ByteSwapToDevice32(uint32_t d)
60 {
61     return byteswap_32(d);
62 }
63 ByteSwapFromDevice32(uint32_t d)
64 {
65     return byteswap_32(d);
66 }
67 #else
68 static inline uint32_t
69 ByteSwapToDevice32(uint32_t d)
70 {
71     return d;
72 }
73 static inline uint32_t
74 ByteSwapFromDevice32(uint32_t d)
75 {
76     return d;
77 }
78 #endif
79
80 Device::Device( DeviceManager& d,
81                       std::auto_ptr<ConfigRom>( configRom ))
82     : FFADODevice( d, configRom )
83     , m_rme_model( RME_MODEL_NONE )
84     , num_channels( 0 )
85     , samples_per_packet( 0 )
86     , speed800( 0 )
87     , m_MixerContainer( NULL )
88     , m_ControlContainer( NULL )
89 {
90     debugOutput( DEBUG_LEVEL_VERBOSE, "Created Rme::Device (NodeID %d)\n",
91                  getConfigRom().getNodeId() );
92 }
93
94 Device::~Device()
95 {
96     destroyMixer();
97
98     if (dev_config != NULL) {
99         switch (rme_shm_close(dev_config)) {
100             case RSO_CLOSE:
101                 debugOutput( DEBUG_LEVEL_VERBOSE, "Configuration shared data object closed\n");
102                 break;
103             case RSO_CLOSE_DELETE:
104                 debugOutput( DEBUG_LEVEL_VERBOSE, "Configuration shared data object closed and deleted (no other users)\n");
105                 break;
106         }
107     }
108 }
109
110 bool
111 Device::buildMixer() {
112     signed int i;
113     bool result = true;
114
115     destroyMixer();
116     debugOutput(DEBUG_LEVEL_VERBOSE, "Building an RME mixer...\n");
117
118
119     // Non-mixer device controls
120     m_ControlContainer = new Control::Container(this, "Control");
121     if (!m_ControlContainer) {
122         debugError("Could not create control container\n");
123         destroyMixer();
124         return false;
125     }
126
127     result &= m_ControlContainer->addElement(
128         new RmeSettingsCtrl(*this, RME_CTRL_INFO_MODEL, 0,
129             "Model", "Model ID", ""));
130     result &= m_ControlContainer->addElement(
131         new RmeSettingsCtrl(*this, RME_CTRL_INFO_TCO_PRESENT, 0,
132             "TCO_present", "TCO is present", ""));
133
134     result &= m_ControlContainer->addElement(
135         new RmeSettingsCtrl(*this, RME_CTRL_PHANTOM_SW, 0,
136             "Phantom", "Phantom switches", ""));
137     result &= m_ControlContainer->addElement(
138         new RmeSettingsCtrl(*this, RME_CTRL_INPUT_LEVEL, 0,
139             "Input_level", "Input level", ""));
140     result &= m_ControlContainer->addElement(
141         new RmeSettingsCtrl(*this, RME_CTRL_OUTPUT_LEVEL, 0,
142             "Output_level", "Output level", ""));
143     result &= m_ControlContainer->addElement(
144         new RmeSettingsCtrl(*this, RME_CTRL_PHONES_LEVEL, 0,
145             "Phones_level", "Phones level", ""));
146
147     if (m_rme_model == RME_MODEL_FIREFACE400) {
148         // Instrument input options
149         for (i=3; i<=4; i++) {
150             char path[32], desc[64];
151             snprintf(path, sizeof(path), "Chan%d_opt_instr", i);
152             snprintf(desc, sizeof(desc), "Chan%d instrument option", i);
153             result &= m_ControlContainer->addElement(
154                 new RmeSettingsCtrl(*this, RME_CTRL_FF400_INSTR_SW, i,
155                     path, desc, ""));
156             snprintf(path, sizeof(path), "Chan%d_opt_pad", i);
157             snprintf(desc, sizeof(desc), "Chan%d pad option", i);
158             result &= m_ControlContainer->addElement(
159                 new RmeSettingsCtrl(*this, RME_CTRL_FF400_PAD_SW, i,
160                     path, desc, ""));
161         }
162
163         // Input/output gains
164         result &= m_ControlContainer->addElement(
165             new RmeSettingsMatrixCtrl(*this, RME_MATRIXCTRL_GAINS, "Gains"));
166     }
167
168     if (!result) {
169         debugWarning("One or more device control elements could not be created\n");
170         destroyMixer();
171         return false;
172     }
173
174     if (!addElement(m_ControlContainer)) {
175         debugWarning("Could not register mixer to device\n");
176         // clean up
177         destroyMixer();
178         return false;
179     }
180
181     return true;
182 }
183
184 bool
185 Device::destroyMixer() {
186     bool ret = true;
187     debugOutput(DEBUG_LEVEL_VERBOSE, "destroy mixer...\n");
188
189     if (m_MixerContainer == NULL) {
190         debugOutput(DEBUG_LEVEL_VERBOSE, "no mixer to destroy...\n");
191     } else
192     if (!deleteElement(m_MixerContainer)) {
193         debugError("Mixer present but not registered to the avdevice\n");
194         ret = false;
195     } else {
196         // remove and delete (as in free) child control elements
197         m_MixerContainer->clearElements(true);
198         delete m_MixerContainer;
199         m_MixerContainer = NULL;
200     }
201
202     // remove control container
203     if (m_ControlContainer == NULL) {
204         debugOutput(DEBUG_LEVEL_VERBOSE, "no controls to destroy...\n");
205     } else
206     if (!deleteElement(m_ControlContainer)) {
207         debugError("Controls present but not registered to the avdevice\n");
208         ret = false;
209     } else {
210         // remove and delete (as in free) child control elements
211         m_ControlContainer->clearElements(true);
212         delete m_ControlContainer;
213         m_ControlContainer = NULL;
214     }
215
216     return false;
217 }
218
219 bool
220 Device::probe( Util::Configuration& c, ConfigRom& configRom, bool generic )
221 {
222     if (generic) {
223         return false;
224     } else {
225         // check if device is in supported devices list.  Note that the RME
226         // devices use the unit version to identify the individual devices.
227         // To avoid having to extend the configuration file syntax to
228         // include this at this point, we'll use the configuration file
229         // model ID to test against the device unit version.  This can be
230         // tidied up if the configuration file is extended at some point to
231         // include the unit version.
232         unsigned int vendorId = configRom.getNodeVendorId();
233         unsigned int unitVersion = configRom.getUnitVersion();
234
235         Util::Configuration::VendorModelEntry vme = c.findDeviceVME( vendorId, unitVersion );
236         return c.isValid(vme) && vme.driver == Util::Configuration::eD_RME;
237     }
238 }
239
240 FFADODevice *
241 Device::createDevice(DeviceManager& d, std::auto_ptr<ConfigRom>( configRom ))
242 {
243     return new Device(d, configRom );
244 }
245
246 bool
247 Device::discover()
248 {
249     signed int i;
250     unsigned int vendorId = getConfigRom().getNodeVendorId();
251     // See note in Device::probe() about why we use the unit version here.
252     unsigned int unitVersion = getConfigRom().getUnitVersion();
253
254     Util::Configuration &c = getDeviceManager().getConfiguration();
255     Util::Configuration::VendorModelEntry vme = c.findDeviceVME( vendorId, unitVersion );
256
257     if (c.isValid(vme) && vme.driver == Util::Configuration::eD_RME) {
258         debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s\n",
259                      vme.vendor_name.c_str(),
260                      vme.model_name.c_str());
261     } else {
262         debugWarning("Device '%s %s' unsupported by RME driver (no generic RME support)\n",
263                      getConfigRom().getVendorName().c_str(), getConfigRom().getModelName().c_str());
264     }
265
266     if (unitVersion == RME_UNITVERSION_FF800) {
267         m_rme_model = RME_MODEL_FIREFACE800;
268     } else
269     if (unitVersion == RME_MODEL_FIREFACE400) {
270         m_rme_model = RME_MODEL_FIREFACE400;
271     } else {
272         debugError("Unsupported model\n");
273         return false;
274     }
275
276     // Set up the shared data object for configuration data
277     i = rme_shm_open(&dev_config);
278     if (i == RSO_OPEN_CREATED) {
279         debugOutput( DEBUG_LEVEL_VERBOSE, "New configuration shared data object created\n");
280     } else
281     if (i == RSO_OPEN_ATTACHED) {
282         debugOutput( DEBUG_LEVEL_VERBOSE, "Attached to existing configuration shared data object\n");
283     }
284     if (dev_config == NULL) {
285         debugOutput( DEBUG_LEVEL_WARNING, "Could not create/access shared configuration memory object, using process-local storage\n");
286         memset(&local_dev_config_obj, 0, sizeof(local_dev_config_obj));
287         dev_config = &local_dev_config_obj;
288     }
289     settings = &dev_config->settings;
290     tco_settings = &dev_config->tco_settings;
291
292     // If device is FF800, check to see if the TCO is fitted
293     if (m_rme_model == RME_MODEL_FIREFACE800) {
294         dev_config->tco_present = (read_tco(NULL, 0) == 0);
295     }
296     debugOutput(DEBUG_LEVEL_VERBOSE, "TCO present: %s\n",
297       dev_config->tco_present?"yes":"no");
298
299     init_hardware();
300
301     if (!buildMixer()) {
302         debugWarning("Could not build mixer\n");
303     }
304
305     // This is just for testing
306     read_device_flash_settings(NULL);
307
308     return true;
309 }
310
311 int
312 Device::getSamplingFrequency( ) {
313
314     // Retrieve the current sample rate.  For practical purposes this
315     // is the software rate currently in use.
316     return dev_config->software_freq;
317 }
318
319 int
320 Device::getConfigurationId()
321 {
322     return 0;
323 }
324
325 bool
326 Device::setDDSFrequency( int dds_freq )
327 {
328     // Set a fixed DDS frequency.  If the device is the clock master this
329     // will immediately be copied to the hardware DDS register.  Otherwise
330     // it will take effect as required at the time the sampling rate is
331     // changed or streaming is started.
332
333     // If the device is streaming, the new DDS rate must have the same
334     // multiplier as the software sample rate
335     if (hardware_is_streaming()) {
336         if (multiplier_of_freq(dds_freq) != multiplier_of_freq(dev_config->software_freq))
337             return false;
338     }
339
340     dev_config->dds_freq = dds_freq;
341     if (settings->clock_mode == FF_STATE_CLOCKMODE_MASTER) {
342         if (set_hardware_dds_freq(dds_freq) != 0)
343             return false;
344     }
345
346     return true;
347 }
348
349 bool
350 Device::setSamplingFrequency( int samplingFrequency )
351 {
352     // Request a sampling rate on behalf of software.  Software is limited
353     // to sample rates of 32k, 44.1k, 48k and the 2x/4x multiples of these.
354     // The user may lock the device to a much wider range of frequencies via
355     // the explicit DDS controls in the control panel.  If the explicit DDS
356     // control is active the software is limited to the "standard" speeds
357     // corresponding to the multiplier in use by the DDS.
358     //
359     // Similarly, if the device is externally clocked the software is
360     // limited to the external clock frequency.
361     //
362     // Otherwise the software has free choice of the software speeds noted
363     // above.
364
365     bool ret = -1;
366     signed int i, j;
367     signed int mult[3] = {1, 2, 4};
368     signed int base_freq[3] = {32000, 44100, 48000};
369     signed int freq = samplingFrequency;
370     FF_state_t state;
371     signed int fixed_freq = 0;
372
373     get_hardware_state(&state);
374
375     // If device is locked to a frequency via external clock, explicit
376     // setting of the DDS or by virtue of streaming being active, get that
377     // frequency.
378     if (state.clock_mode == FF_STATE_CLOCKMODE_AUTOSYNC) {
379         // FIXME: if synced to TCO, is autosync_freq valid?
380         fixed_freq = state.autosync_freq;
381     } else
382     if (dev_config->dds_freq > 0) {
383         fixed_freq = dev_config->dds_freq;
384     } else
385     if (hardware_is_streaming()) {
386         fixed_freq = dev_config->software_freq;
387     }
388
389     // If the device is running to a fixed frequency, software can only
390     // request frequencies with the same multiplier.  Similarly, the
391     // multiplier is locked in "master" clock mode if the device is
392     // streaming.
393     if (fixed_freq > 0) {
394         signed int fixed_mult = multiplier_of_freq(fixed_freq);
395         if (multiplier_of_freq(freq) != multiplier_of_freq(fixed_freq))
396             return -1;
397         for (j=0; j<3; j++) {
398             if (freq == base_freq[j]*fixed_mult) {
399                 ret = 0;
400                 break;
401             }
402         }
403     } else {
404         for (i=0; i<3; i++) {
405             for (j=0; j<3; j++) {
406                 if (freq == base_freq[j]*mult[i]) {
407                     ret = 0;
408                     break;
409                 }
410             }
411         }
412     }
413     // If requested frequency is unavailable, return -1
414     if (ret == -1)
415         return false;
416
417     // If a DDS frequency has been explicitly requested this is always
418     // used to programm the hardware DDS regardless of the rate requested
419     // by the software.  Otherwise we use the requested sampling rate.
420     if (dev_config->dds_freq > 0)
421         freq = dev_config->dds_freq;
422     if (set_hardware_dds_freq(freq) != 0)
423         return false;
424
425     dev_config->software_freq = samplingFrequency;
426     return true;
427 }
428
429 std::vector<int>
430 Device::getSupportedSamplingFrequencies()
431 {
432     std::vector<int> frequencies;
433     signed int i, j;
434     signed int mult[3] = {1, 2, 4};
435     signed int freq[3] = {32000, 44100, 48000};
436     FF_state_t state;
437
438     get_hardware_state(&state);
439
440     // Generate the list of supported frequencies.  If the device is
441     // externally clocked the frequency is limited to the external clock
442     // frequency.  If the device is running the multiplier is fixed.
443     if (state.clock_mode == FF_STATE_CLOCKMODE_AUTOSYNC) {
444         // FIXME: if synced to TCO, is autosync_freq valid?
445         frequencies.push_back(state.autosync_freq);
446     } else
447     if (state.is_streaming) {
448         unsigned int fixed_mult = multiplier_of_freq(dev_config->software_freq);
449         for (j=0; j<3; j++) {
450             frequencies.push_back(freq[j]*fixed_mult);
451         }
452     } else {
453         for (i=0; i<3; i++) {
454             for (j=0; j<3; j++) {
455                 frequencies.push_back(freq[j]*mult[i]);
456             }
457         }
458     }
459     return frequencies;
460 }
461
462 FFADODevice::ClockSourceVector
463 Device::getSupportedClockSources() {
464     FFADODevice::ClockSourceVector r;
465     return r;
466 }
467
468 bool
469 Device::setActiveClockSource(ClockSource s) {
470     return false;
471 }
472
473 FFADODevice::ClockSource
474 Device::getActiveClockSource() {
475     ClockSource s;
476     return s;
477 }
478
479 bool
480 Device::lock() {
481
482     return true;
483 }
484
485
486 bool
487 Device::unlock() {
488
489     return true;
490 }
491
492 void
493 Device::showDevice()
494 {
495     unsigned int vendorId = getConfigRom().getNodeVendorId();
496     unsigned int modelId = getConfigRom().getModelId();
497
498     Util::Configuration &c = getDeviceManager().getConfiguration();
499     Util::Configuration::VendorModelEntry vme = c.findDeviceVME( vendorId, modelId );
500
501     debugOutput(DEBUG_LEVEL_VERBOSE,
502         "%s %s at node %d\n", vme.vendor_name.c_str(), vme.model_name.c_str(), getNodeId());
503 }
504
505 bool
506 Device::prepare() {
507
508         debugOutput(DEBUG_LEVEL_NORMAL, "Preparing Device...\n" );
509
510         return true;
511 }
512
513 int
514 Device::getStreamCount() {
515         return 0; // one receive, one transmit
516 }
517
518 Streaming::StreamProcessor *
519 Device::getStreamProcessorByIndex(int i) {
520     return NULL;
521 }
522
523 bool
524 Device::startStreamByIndex(int i) {
525     return false;
526 }
527
528 bool
529 Device::stopStreamByIndex(int i) {
530     return false;
531
532 }
533
534 unsigned int
535 Device::readRegister(fb_nodeaddr_t reg) {
536
537     quadlet_t quadlet;
538    
539     quadlet = 0;
540     if (get1394Service().read(0xffc0 | getNodeId(), reg, 1, &quadlet) <= 0) {
541         debugError("Error doing RME read from register 0x%06x\n",reg);
542     }
543     return ByteSwapFromDevice32(quadlet);
544 }
545
546 signed int
547 Device::readBlock(fb_nodeaddr_t reg, quadlet_t *buf, unsigned int n_quads) {
548
549     unsigned int i;
550
551     if (get1394Service().read(0xffc0 | getNodeId(), reg, n_quads, buf) <= 0) {
552         debugError("Error doing RME block read of %d quadlets from register 0x%06x\n",
553             n_quads, reg);
554         return -1;
555     }
556     for (i=0; i<n_quads; i++) {
557        buf[i] = ByteSwapFromDevice32(buf[i]);
558     }
559
560     return 0;
561 }
562
563 signed int
564 Device::writeRegister(fb_nodeaddr_t reg, quadlet_t data) {
565
566     unsigned int err = 0;
567     data = ByteSwapToDevice32(data);
568     if (get1394Service().write(0xffc0 | getNodeId(), reg, 1, &data) <= 0) {
569         err = 1;
570         debugError("Error doing RME write to register 0x%06x\n",reg);
571     }
572     return (err==0)?0:-1;
573 }
574
575 signed int
576 Device::writeBlock(fb_nodeaddr_t reg, quadlet_t *data, unsigned int n_quads) {
577 //
578 // Write a block of data to the device starting at address "reg".  Note that
579 // the conditional byteswap is done "in place" on data, so the contents of
580 // data may be modified by calling this function.
581 //
582     unsigned int err = 0;
583     unsigned int i;
584
585     for (i=0; i<n_quads; i++) {
586       data[i] = ByteSwapToDevice32(data[i]);
587     }
588     if (get1394Service().write(0xffc0 | getNodeId(), reg, n_quads, data) <= 0) {
589         err = 1;
590         debugError("Error doing RME block write of %d quadlets to register 0x%06x\n",
591           n_quads, reg);
592     }
593     return (err==0)?0:-1;
594 }
595                  
596 }
Note: See TracBrowser for help on using the browser.