root/trunk/libffado/src/oxford/oxford_device.cpp

Revision 1543, 9.9 kB (checked in by ppalmers, 15 years ago)

- Clean up class names
- Change probe code for all devices (except MOTU) to use the config file based approach

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB.
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 2 of the License, or
12  * (at your option) version 3 of the License.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 /*
25  * Oxford Semiconductor OXFW970 and OXFW971 support
26  */
27
28 #include "devicemanager.h"
29 #include "oxford_device.h"
30
31 #include "libavc/general/avc_plug.h"
32
33 #include "libieee1394/configrom.h"
34 #include "libieee1394/ieee1394service.h"
35
36 #include "libstreaming/amdtp-oxford/AmdtpOxfordReceiveStreamProcessor.h"
37 #include "libstreaming/amdtp/AmdtpTransmitStreamProcessor.h"
38 #include "libstreaming/amdtp/AmdtpPort.h"
39 #include "libstreaming/amdtp/AmdtpPortInfo.h"
40
41 #include <sstream>
42
43 using namespace std;
44
45 namespace Oxford {
46
47 Device::Device(DeviceManager& d, std::auto_ptr<ConfigRom>( configRom ))
48     : GenericAVC::Device( d, configRom)
49 {
50     debugOutput( DEBUG_LEVEL_VERBOSE, "Created Oxford::Device (NodeID %d)\n",
51                  getConfigRom().getNodeId() );
52
53     m_fixed_clocksource.type = FFADODevice::eCT_Internal;
54     m_fixed_clocksource.valid = true;
55     m_fixed_clocksource.locked = true;
56     m_fixed_clocksource.id = 0;
57     m_fixed_clocksource.slipping = false;
58     m_fixed_clocksource.description = "Internal";
59
60 }
61
62 Device::~Device()
63 {
64 }
65
66 void
67 Device::showDevice()
68 {
69     debugOutput(DEBUG_LEVEL_VERBOSE, "This is a Oxford::Device\n");
70     GenericAVC::Device::showDevice();
71 }
72
73 bool
74 Device::probe( Util::Configuration& c, ConfigRom& configRom, bool generic )
75 {
76     if(generic) {
77         // heuristic yet that can tell us whether it's oxford based
78         return false;
79     } else {
80         unsigned int vendorId = configRom.getNodeVendorId();
81         unsigned int modelId = configRom.getModelId();
82         Util::Configuration::VendorModelEntry vme = c.findDeviceVME( vendorId, modelId );
83         return c.isValid(vme) && vme.driver == Util::Configuration::eD_Oxford;
84     }
85 }
86
87 bool
88 Device::discover()
89 {
90     Util::MutexLockHelper lock(m_DeviceMutex);
91
92     unsigned int vendorId = getConfigRom().getNodeVendorId();
93     unsigned int modelId = getConfigRom().getModelId();
94
95     Util::Configuration &c = getDeviceManager().getConfiguration();
96     Util::Configuration::VendorModelEntry vme = c.findDeviceVME( vendorId, modelId );
97
98     if (c.isValid(vme) && vme.driver == Util::Configuration::eD_Oxford) {
99         debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s\n",
100                      vme.vendor_name.c_str(),
101                      vme.model_name.c_str());
102     } else {
103         debugWarning("Using Oxford AV/C support for unsupported device '%s %s'\n",
104                      getConfigRom().getVendorName().c_str(), getConfigRom().getModelName().c_str());
105     }
106
107     // do the actual discovery
108     if ( !Unit::discover() ) {
109         debugError( "Could not discover unit\n" );
110         return false;
111     }
112
113     // the FCA202 has only an audio subunit
114     if((getAudioSubunit( 0 ) == NULL)) {
115         debugError( "Unit doesn't have an Audio subunit.\n");
116         return false;
117     }
118
119     return true;
120 }
121
122 FFADODevice *
123 Device::createDevice(DeviceManager& d, std::auto_ptr<ConfigRom>( configRom ))
124 {
125     unsigned int vendorId = configRom->getNodeVendorId();
126
127     switch(vendorId) {
128         default: return new Device(d, configRom );
129     }
130 }
131
132 std::vector<int>
133 Device::getSupportedSamplingFrequencies()
134 {
135     std::vector<int> frequencies;
136     frequencies.push_back(44100);
137     frequencies.push_back(48000);
138     frequencies.push_back(96000);
139     return frequencies;
140 }
141
142 FFADODevice::ClockSourceVector
143 Device::getSupportedClockSources() {
144     FFADODevice::ClockSourceVector r;
145     r.push_back(m_fixed_clocksource);
146     return r;
147 }
148
149 bool
150 Device::setActiveClockSource(ClockSource s) {
151     // can't change, hence only succeed when identical
152     return s.id == m_fixed_clocksource.id;
153 }
154
155 FFADODevice::ClockSource
156 Device::getActiveClockSource() {
157     return m_fixed_clocksource;
158 }
159
160 bool
161 Device::prepare()
162 {
163     bool snoopMode=false;
164     Util::MutexLockHelper lock(m_DeviceMutex);
165     if(!getOption("snoopMode", snoopMode)) {
166         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
167     }
168
169     ///////////
170     // get plugs
171
172     AVC::Plug* inputPlug = getPlugById( m_pcrPlugs, AVC::Plug::eAPD_Input, 0 );
173     if ( !inputPlug ) {
174         debugError( "setSampleRate: Could not retrieve iso input plug 0\n" );
175         return false;
176     }
177     AVC::Plug* outputPlug = getPlugById( m_pcrPlugs, AVC::Plug::eAPD_Output, 0 );
178     if ( !outputPlug ) {
179         debugError( "setSampleRate: Could not retrieve iso output plug 0\n" );
180         return false;
181     }
182
183     // get the device specific and/or global SP configuration
184     Util::Configuration &config = getDeviceManager().getConfiguration();
185     // base value is the config.h value
186     float recv_sp_dll_bw = STREAMPROCESSOR_DLL_BW_HZ;
187     float xmit_sp_dll_bw = STREAMPROCESSOR_DLL_BW_HZ;
188
189     int xmit_max_cycles_early_transmit = AMDTP_MAX_CYCLES_TO_TRANSMIT_EARLY;
190     int xmit_transfer_delay = AMDTP_TRANSMIT_TRANSFER_DELAY;
191     int xmit_min_cycles_before_presentation = AMDTP_MIN_CYCLES_BEFORE_PRESENTATION;
192
193     // we can override that globally
194     config.getValueForSetting("streaming.common.recv_sp_dll_bw", recv_sp_dll_bw);
195     config.getValueForSetting("streaming.common.xmit_sp_dll_bw", xmit_sp_dll_bw);
196     config.getValueForSetting("streaming.amdtp.xmit_max_cycles_early_transmit", xmit_max_cycles_early_transmit);
197     config.getValueForSetting("streaming.amdtp.xmit_transfer_delay", xmit_transfer_delay);
198     config.getValueForSetting("streaming.amdtp.xmit_min_cycles_before_presentation", xmit_min_cycles_before_presentation);
199
200     // or override in the device section
201     uint32_t vendorid = getConfigRom().getNodeVendorId();
202     uint32_t modelid = getConfigRom().getModelId();
203     config.getValueForDeviceSetting(vendorid, modelid, "recv_sp_dll_bw", recv_sp_dll_bw);
204     config.getValueForDeviceSetting(vendorid, modelid, "xmit_sp_dll_bw", xmit_sp_dll_bw);
205     config.getValueForDeviceSetting(vendorid, modelid, "xmit_max_cycles_early_transmit", xmit_max_cycles_early_transmit);
206     config.getValueForDeviceSetting(vendorid, modelid, "xmit_transfer_delay", xmit_transfer_delay);
207     config.getValueForDeviceSetting(vendorid, modelid, "xmit_min_cycles_before_presentation", xmit_min_cycles_before_presentation);
208
209     // initialize the SP's
210     debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing receive processor...\n");
211     // create & add streamprocessors
212     Streaming::StreamProcessor *p;
213
214     if ( outputPlug->getNrOfChannels() == 0 ) {
215         debugError("Receive plug has no channels\n");
216         return false;
217     }
218     p = new Streaming::AmdtpOxfordReceiveStreamProcessor(*this,
219                              outputPlug->getNrOfChannels());
220
221     if(!p->init()) {
222         debugFatal("Could not initialize receive processor!\n");
223         delete p;
224         return false;
225     }
226
227     if (!addPlugToProcessor(*outputPlug, p,
228         Streaming::Port::E_Capture)) {
229         debugFatal("Could not add plug to processor!\n");
230         delete p;
231         return false;
232     }
233
234     if(!p->setDllBandwidth(recv_sp_dll_bw)) {
235         debugFatal("Could not set DLL bandwidth\n");
236         delete p;
237         return false;
238     }
239
240     m_receiveProcessors.push_back(p);
241
242     // do the transmit processor
243     debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing transmit processor%s...\n",
244             (snoopMode?" in snoop mode":""));
245     if (snoopMode) {
246         // we are snooping, so this is receive too.
247         p=new Streaming::AmdtpOxfordReceiveStreamProcessor(*this,
248                                   inputPlug->getNrOfChannels());
249     } else {
250         Streaming::AmdtpTransmitStreamProcessor * t;
251         t=new Streaming::AmdtpTransmitStreamProcessor(*this,
252                                 inputPlug->getNrOfChannels());
253
254         // NOTE: the oxford devices don't allow payload, otherwise they generate distorted sound
255         // if this generates a compile error it means you try to compile something that won't work
256         t->sendPayloadForNoDataPackets(false);
257
258         // transmit control parameters
259         t->setMaxCyclesToTransmitEarly(xmit_max_cycles_early_transmit);
260         t->setTransferDelay(xmit_transfer_delay);
261         t->setMinCyclesBeforePresentation(xmit_min_cycles_before_presentation);
262
263         p=t;
264     }
265
266     if(!p->init()) {
267         debugFatal("Could not initialize transmit processor %s!\n",
268             (snoopMode?" in snoop mode":""));
269         delete p;
270         return false;
271     }
272
273     if (snoopMode) {
274         if (!addPlugToProcessor(*inputPlug, p,
275             Streaming::Port::E_Capture)) {
276             debugFatal("Could not add plug to processor!\n");
277             return false;
278         }
279         if(!p->setDllBandwidth(recv_sp_dll_bw)) {
280             debugFatal("Could not set DLL bandwidth\n");
281             delete p;
282             return false;
283         }
284     } else {
285         if (!addPlugToProcessor(*inputPlug, p,
286             Streaming::Port::E_Playback)) {
287             debugFatal("Could not add plug to processor!\n");
288             return false;
289         }
290         if(!p->setDllBandwidth(xmit_sp_dll_bw)) {
291             debugFatal("Could not set DLL bandwidth\n");
292             delete p;
293             return false;
294         }
295     }
296
297     // we put this SP into the transmit SP vector,
298     // no matter if we are in snoop mode or not
299     // this allows us to find out what direction
300     // a certain stream should have.
301     m_transmitProcessors.push_back(p);
302
303     return true;
304 }
305
306
307 } // Oxford
Note: See TracBrowser for help on using the browser.