root/trunk/libffado/src/dice/dice_eap.cpp

Revision 2803, 68.2 kB (checked in by jwoithe, 3 years ago)

Cosmetic: capitalise "L" in "Linux".

"Linux" is a proper noun so it should start with a capital letter. These
changes are almost all within comments.

This patch was originally proposed by pander on the ffado-devel mailing
list. It has been expanded to cover all similar cases to maintain
consistency throughout the source tree.

Line 
1 /*
2  * Copyright (C) 2005-2009 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 #include "dice_avdevice.h"
25
26 #include "dice_eap.h"
27 #include "dice_defines.h"
28
29 #include "libutil/SystemTimeSource.h"
30 #include "libutil/ByteSwap.h"
31
32 #include <cstdio>
33
34 namespace Dice {
35
36 // ----------- helper functions -------------
37
38 #if 0
39 static const char *
40 srcBlockToString(const char id)
41 {
42     switch(id) {
43         case eRS_AES:   return "AES ";
44         case eRS_ADAT:  return "ADAT";
45         case eRS_Mixer: return "MXR ";
46         case eRS_InS0:  return "INS0";
47         case eRS_InS1:  return "INS1";
48         case eRS_ARM:   return "ARM ";
49         case eRS_ARX0:  return "AVS0";
50         case eRS_ARX1:  return "AVS1";
51         case eRS_Muted: return "MUTE";
52         default :       return "RSVD";
53     }
54 }
55
56 static  const char *
57 dstBlockToString(const char id)
58 {
59     switch(id) {
60         case eRD_AES:    return "AES ";
61         case eRD_ADAT:   return "ADAT";
62         case eRD_Mixer0: return "MXR0";
63         case eRD_Mixer1: return "MXR1";
64         case eRD_InS0:   return "INS0";
65         case eRD_InS1:   return "INS1";
66         case eRD_ARM:    return "ARM ";
67         case eRD_ATX0:   return "AVS0";
68         case eRD_ATX1:   return "AVS1";
69         case eRD_Muted:  return "MUTE";
70         default : return "RSVD";
71     }
72 }
73 #endif
74
75 IMPL_DEBUG_MODULE( EAP, EAP, DEBUG_LEVEL_NORMAL );
76
77 EAP::EAP(Device &d)
78 : Control::Container(&d, "EAP")
79 , m_device(d)
80 , m_mixer( NULL )
81 , m_router( NULL )
82 , m_standalone( NULL )
83 , m_current_cfg_routing_low ( RouterConfig(*this, eRT_CurrentCfg, DICE_EAP_CURRCFG_LOW_ROUTER ) )
84 , m_current_cfg_routing_mid ( RouterConfig(*this, eRT_CurrentCfg, DICE_EAP_CURRCFG_MID_ROUTER ) )
85 , m_current_cfg_routing_high( RouterConfig(*this, eRT_CurrentCfg, DICE_EAP_CURRCFG_HIGH_ROUTER) )
86 , m_current_cfg_stream_low  ( StreamConfig(*this, eRT_CurrentCfg, DICE_EAP_CURRCFG_LOW_STREAM ) )
87 , m_current_cfg_stream_mid  ( StreamConfig(*this, eRT_CurrentCfg, DICE_EAP_CURRCFG_MID_STREAM ) )
88 , m_current_cfg_stream_high ( StreamConfig(*this, eRT_CurrentCfg, DICE_EAP_CURRCFG_HIGH_STREAM) )
89 {
90 }
91
92 EAP::~EAP()
93 {
94     // remove all control elements registered to this device (w/o free)
95     clearElements(false);
96
97     // delete the helper classes
98     if(m_mixer) delete m_mixer;
99     if(m_router) delete m_router;
100     if(m_standalone) delete m_standalone;
101 }
102
103 // offsets and sizes are returned in quadlets, but we use byte values, hence the *= 4
104 #define DICE_EAP_READREG_AND_CHECK(base, addr, var) { \
105     if(!readReg(base, addr, &var)) { \
106         debugError("Could not initialize " #var "\n"); \
107         return false; \
108     } \
109     var *= 4; \
110 }
111
112 bool
113 EAP::init() {
114     if(!supportsEAP(m_device)) {
115         debugWarning("no EAP mixer (device does not support EAP)\n");
116         return false;
117     }
118
119     // offsets and sizes are returned in quadlets, but we use byte values
120     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_CAPABILITY_SPACE_OFF, m_capability_offset);
121     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_CAPABILITY_SPACE_SZ, m_capability_size);
122     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_CMD_SPACE_OFF, m_cmd_offset);
123     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_CMD_SPACE_SZ, m_cmd_size);
124     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_MIXER_SPACE_OFF, m_mixer_offset);
125     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_MIXER_SPACE_SZ, m_mixer_size);
126     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_PEAK_SPACE_OFF, m_peak_offset);
127     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_PEAK_SPACE_SZ, m_peak_size);
128     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_NEW_ROUTING_SPACE_OFF, m_new_routing_offset);
129     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_NEW_ROUTING_SPACE_SZ, m_new_routing_size);
130     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_NEW_STREAM_CFG_SPACE_OFF, m_new_stream_cfg_offset);
131     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_NEW_STREAM_CFG_SPACE_SZ, m_new_stream_cfg_size);
132     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_CURR_CFG_SPACE_OFF, m_curr_cfg_offset);
133     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_CURR_CFG_SPACE_SZ, m_curr_cfg_size);
134     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_STAND_ALONE_CFG_SPACE_OFF, m_standalone_offset);
135     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_STAND_ALONE_CFG_SPACE_SZ, m_standalone_size);
136     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_APP_SPACE_OFF, m_app_offset);
137     DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_APP_SPACE_SZ, m_app_size);
138
139     // initialize the capability info
140     quadlet_t tmp;
141     if(!readReg(eRT_Capability, DICE_EAP_CAPABILITY_ROUTER, &tmp)) {
142         debugError("Could not read router capabilities\n");
143         return false;
144     }
145     m_router_exposed = (tmp >> DICE_EAP_CAP_ROUTER_EXPOSED) & 0x01;
146     m_router_readonly = (tmp >> DICE_EAP_CAP_ROUTER_READONLY) & 0x01;
147     m_router_flashstored = (tmp >> DICE_EAP_CAP_ROUTER_FLASHSTORED) & 0x01;
148     m_router_nb_entries = (tmp >> DICE_EAP_CAP_ROUTER_MAXROUTES) & 0xFFFF;
149
150     if(!readReg(eRT_Capability, DICE_EAP_CAPABILITY_MIXER, &tmp)) {
151         debugError("Could not read mixer capabilities\n");
152         return false;
153     }
154     m_mixer_exposed = (tmp >> DICE_EAP_CAP_MIXER_EXPOSED) & 0x01;
155     m_mixer_readonly = (tmp >> DICE_EAP_CAP_MIXER_READONLY) & 0x01;
156     m_mixer_flashstored = (tmp >> DICE_EAP_CAP_MIXER_FLASHSTORED) & 0x01;
157     m_mixer_tx_id = (tmp >> DICE_EAP_CAP_MIXER_IN_DEV) & 0x000F;
158     m_mixer_rx_id = (tmp >> DICE_EAP_CAP_MIXER_OUT_DEV) & 0x000F;
159     m_mixer_nb_tx = (tmp >> DICE_EAP_CAP_MIXER_INPUTS) & 0x00FF;
160     m_mixer_nb_rx = (tmp >> DICE_EAP_CAP_MIXER_OUTPUTS) & 0x00FF;
161
162     if(!readReg(eRT_Capability, DICE_EAP_CAPABILITY_GENERAL, &tmp)) {
163         debugError("Could not read general capabilities\n");
164         return false;
165     }
166     m_general_support_dynstream = (tmp >> DICE_EAP_CAP_GENERAL_STRM_CFG_EN) & 0x01;
167     m_general_support_flash = (tmp >> DICE_EAP_CAP_GENERAL_FLASH_EN) & 0x01;
168     m_general_peak_enabled = (tmp >> DICE_EAP_CAP_GENERAL_PEAK_EN) & 0x01;
169     m_general_max_tx = (tmp >> DICE_EAP_CAP_GENERAL_MAX_TX_STREAM) & 0x0F;
170     m_general_max_rx = (tmp >> DICE_EAP_CAP_GENERAL_MAX_RX_STREAM) & 0x0F;
171     m_general_stream_cfg_stored = (tmp >> DICE_EAP_CAP_GENERAL_STRM_CFG_FLS) & 0x01;
172     m_general_chip = (tmp >> DICE_EAP_CAP_GENERAL_CHIP) & 0xFFFF;
173
174     // update our view on the current configuration
175     if(!updateConfigurationCache()) {
176         debugError("Could not initialize configuration cache\n");
177         return false;
178     }
179
180     // initialize the helper classes
181     if (m_mixer_exposed) {
182         // initialize the mixer
183         m_mixer = new EAP::Mixer(*this);
184         if(m_mixer == NULL) {
185             debugError("Could not allocate memory for mixer\n");
186             return false;
187         }
188         if(!m_mixer->init()) {
189             debugError("Could not initialize mixer\n");
190             delete m_mixer;
191             m_mixer = NULL;
192             return false;
193         }
194         // add the mixer to the EAP control container
195         if(!addElement(m_mixer)) {
196             debugWarning("Failed to add mixer to control tree\n");
197         }
198        
199         // initialize the peak meter
200         m_router = new EAP::Router(*this);
201         if(m_router == NULL) {
202             debugError("Could not allocate memory for router\n");
203             return false;
204         }
205         m_router->update();
206
207         // add the router to the EAP control container
208         if(!addElement(m_router)) {
209             debugWarning("Failed to add router to control tree\n");
210         }
211
212        m_standalone = new EAP::StandaloneConfig(*this);
213        if(m_standalone == NULL) {
214            debugError("Could not allocate memory for standalone config\n");
215            return false;
216        }
217     }
218
219     return true;
220 }
221
222
223 void
224 EAP::update()
225 {
226     // update EAP from the last init
227     //   update router sources and destinations
228     if (m_router) {
229         m_router->update();
230     }
231 }
232
233 void
234 EAP::setupSources() {
235     // define router sources (possibly depending on the samplerate)
236     switch(m_device.getCurrentConfig()) {
237         case Device::eDC_Low: setupSources_low(); return;
238         case Device::eDC_Mid: setupSources_mid(); return;
239         case Device::eDC_High: setupSources_high(); return;
240         default:
241             debugError("Unsupported configuration mode\n");
242             return;
243     }
244 }
245
246 void
247 EAP::setupSources_low() {
248     // add the routing sources for a DICE chip
249     switch(m_general_chip) {
250         case DICE_EAP_CAP_GENERAL_CHIP_DICEII:
251             // router/EAP currently not supported
252             break;
253         case DICE_EAP_CAP_GENERAL_CHIP_DICEJR:
254             // second audio port (unique to the junior)
255             addSource("InS1", 0, 8, eRS_InS1, 1);
256         case DICE_EAP_CAP_GENERAL_CHIP_DICEMINI:
257             /// these are common to the mini and junior
258             // the AES receiver
259             addSource("AES", 0, 8, eRS_AES, 1);
260             // the ADAT receiver
261             addSource("ADAT", 0, 8, eRS_ADAT, 1);
262             // the Mixer outputs
263             addSource("MixerOut", 0, 16, eRS_Mixer, 1);
264             // the first audio port
265             addSource("InS0", 0, 8, eRS_InS0, 1);
266             // the ARM audio port
267             addSource("ARM", 0, 8, eRS_ARM, 1);
268             // the 1394 stream receivers
269             addSource("1394_0", 0, 16, eRS_ARX0, 1);
270             addSource("1394_1", 0, 16, eRS_ARX1, 1);
271             // mute
272             addSource("Mute", 0, 1, eRS_Muted);
273             break;
274         default:
275             // this is an unsupported chip
276             break;
277     }
278 }
279
280 void
281 EAP::setupSources_mid() {
282     setupSources_low();
283 }
284
285 void
286 EAP::setupSources_high() {
287     setupSources_low();
288 }
289
290 unsigned int
291 EAP::getSMuteId() {
292     return m_router->getSourceIndex("Mute:00");
293 }
294
295 void
296 EAP::setupDestinations() {
297     switch(m_device.getCurrentConfig()) {
298         case Device::eDC_Low: setupDestinations_low(); return;
299         case Device::eDC_Mid: setupDestinations_mid(); return;
300         case Device::eDC_High: setupDestinations_high(); return;
301         default:
302             debugError("Unsupported configuration mode\n");
303             return;
304     }
305 }
306
307 void
308 EAP::setupDestinations_low() {
309     // add the routing destinations for a DICE chip
310     switch(m_general_chip) {
311         case DICE_EAP_CAP_GENERAL_CHIP_DICEII:
312             // router/EAP currently not supported
313             break;
314         case DICE_EAP_CAP_GENERAL_CHIP_DICEJR:
315             // second audio port (unique to the junior)
316             addDestination("InS1", 0, 8, eRD_InS1, 1);
317         case DICE_EAP_CAP_GENERAL_CHIP_DICEMINI:
318             /// these are common to the mini and junior
319             // the AES receiver
320             addDestination("AES", 0, 8, eRD_AES, 1);
321             // the ADAT receiver
322             addDestination("ADAT", 0, 8, eRD_ADAT, 1);
323             // the Mixer outputs
324             addDestination("MixerIn", 0, 16, eRD_Mixer0, 1);
325             addDestination("MixerIn", 0, 2, eRD_Mixer1, 17);
326             // the first audio port
327             addDestination("InS0", 0, 8, eRD_InS0, 1);
328             // the ARM audio port
329             addDestination("ARM", 0, 8, eRD_ARM, 1);
330             // the 1394 stream receivers
331             addDestination("1394_0", 0, 16, eRD_ATX0, 1);
332             addDestination("1394_1", 0, 16, eRD_ATX1, 1);
333             // mute
334             addDestination("Mute", 0, 1, eRD_Muted, 1);
335             break;
336         default:
337             // this is an unsupported chip
338             break;
339     }
340 }
341 void
342 EAP::setupDestinations_mid() {
343     setupDestinations_low();
344 }
345 void
346 EAP::setupDestinations_high() {
347     setupDestinations_low();
348 }
349
350 void
351 EAP::addSource(const std::string name, unsigned int base, unsigned int count,
352                enum eRouteSource srcid, unsigned int offset)
353 {
354     m_router->addSource(name, srcid, base, count, offset);
355 }
356 void
357 EAP::addDestination(const std::string name, unsigned int base, unsigned int count,
358                     enum eRouteDestination destid, unsigned int offset)
359 {
360     m_router->addDestination(name, destid, base, count, offset);
361 }
362
363 bool
364 EAP::updateConfigurationCache()
365 {
366     if(!m_current_cfg_routing_low.read()) {
367         debugError("Could not initialize current routing configuration (low rates)\n");
368         return false;
369     }
370     if(!m_current_cfg_routing_mid.read()) {
371         debugError("Could not initialize current routing configuration (mid rates)\n");
372         return false;
373     }
374     if(!m_current_cfg_routing_high.read()) {
375         debugError("Could not initialize current routing configuration (high rates)\n");
376         return false;
377     }
378     if(!m_current_cfg_stream_low.read()) {
379         debugError("Could not initialize current stream configuration (low rates)\n");
380         return false;
381     }
382     if(!m_current_cfg_stream_mid.read()) {
383         debugError("Could not initialize current stream configuration (mid rates)\n");
384         return false;
385     }
386     if(!m_current_cfg_stream_high.read()) {
387         debugError("Could not initialize current stream configuration (high rates)\n");
388         return false;
389     }
390     if(m_mixer) m_mixer->updateNameCache();
391
392     return true;
393 }
394
395 // Get capture and playback names
396 //   If the device has a router, capture and playback are destinations and sources, respectively,
397 //     as defined above
398 //   If no router is found, transmitters and receivers names are returned
399
400 stringlist
401 EAP::getCptrNameString(unsigned int i) {
402     std::vector<unsigned int> destid;
403     unsigned int destid_0;
404     stringlist cptr_names;
405     std::string dest_name, src_name;
406    
407     if (m_router) {
408         switch (i) {
409           case 0: destid_0 = (eRD_ATX0<<4); break;
410           case 1: destid_0 = (eRD_ATX1<<4); break;
411           // Only 2 transmitter possible (?)
412           default: return cptr_names;
413         }
414         // At most 16 destinations per eRD
415         for (int j=0; j<16; j++) {
416           destid.push_back(destid_0+j);
417         }
418         for (unsigned it=0; it<destid.size(); it++) {
419           // If destination identifier is not part of the router, destination name will be empty
420           dest_name = m_router->getDestinationName(destid.at(it));
421           if (dest_name.size() > 0) {
422             // get a source possibly routed to the destination (only one source per destination)
423             src_name = m_router->getSourceForDestination(dest_name);
424             if (src_name.size() > 0) {
425               dest_name.append(" ("); dest_name.append(src_name); dest_name.append(")");
426             }
427             cptr_names.push_back(dest_name);
428           }
429         }
430
431     } else {
432         StreamConfig *scfg = getActiveStreamConfig();
433         if(scfg) {
434           cptr_names = scfg->getTxNamesString(i);
435         }
436     }
437     return cptr_names;
438 }
439
440 stringlist
441 EAP::getPbckNameString(unsigned int i) {
442     std::vector<unsigned int> srcid;
443     unsigned int srcid_0;
444     stringlist pbck_names, dest_names;
445     std::string src_name;
446    
447     if (m_router) {
448         switch (i) {
449            case 0: srcid_0 = (eRS_ARX0<<4); break;
450            case 1: srcid_0 = (eRS_ARX1<<4); break;
451             // Only 2 receiver possible (?)
452           default: return pbck_names;
453         }
454         // At most 16 destinations per eRD
455         for (int j=0; j<16; j++) {
456           srcid.push_back(srcid_0+j);
457         }
458         for (unsigned it=0; it<srcid.size(); it++) {
459           // If source identifier is not part of the router, source name will be empty
460           src_name = m_router->getSourceName(srcid.at(it));
461           if (src_name.size() > 0) {
462             // Search for destinations routed to this source
463             //   Multiple destinations for a single source are possible
464             dest_names = m_router->getDestinationsForSource(src_name);
465             if (dest_names.size() > 0) {
466               src_name.append(" (");
467               stringlist::iterator it_d = dest_names.begin();
468               stringlist::iterator it_d_end_m1 = dest_names.end(); --it_d_end_m1;
469               while (it_d != it_d_end_m1) {
470                 src_name.append((*it_d).c_str()); src_name.append("; ");
471                 it_d++;
472               }
473               src_name.append((*it_d).c_str()); src_name.append(")");
474             }
475             pbck_names.push_back(src_name);
476           }
477         }
478     } else {
479         StreamConfig *scfg = getActiveStreamConfig();
480         if(scfg) {
481           pbck_names = scfg->getRxNamesString(i);
482         }
483     }
484     return pbck_names;
485 }
486
487 /**
488  * Returns the router configuration for the current rate mode
489  */
490 EAP::RouterConfig *
491 EAP::getActiveRouterConfig()
492 {
493     switch(m_device.getCurrentConfig()) {
494         case Device::eDC_Low: return &m_current_cfg_routing_low;
495         case Device::eDC_Mid: return &m_current_cfg_routing_mid;
496         case Device::eDC_High: return &m_current_cfg_routing_high;
497         default:
498             debugError("Unsupported configuration mode\n");
499             return NULL;
500     }
501 }
502
503 /**
504  * Returns the stream configuration for the current rate mode
505  */
506 EAP::StreamConfig *
507 EAP::getActiveStreamConfig()
508 {
509     switch(m_device.getCurrentConfig()) {
510         case Device::eDC_Low: return &m_current_cfg_stream_low;
511         case Device::eDC_Mid: return &m_current_cfg_stream_mid;
512         case Device::eDC_High: return &m_current_cfg_stream_high;
513         default:
514             debugError("Unsupported configuration mode\n");
515             return NULL;
516     }
517 }
518
519 /**
520  * Uploads a new router configuration to the device
521  * @param  rcfg The new RouterConfig
522  * @param low store as config for the low rates
523  * @param mid store as config for the mid rates
524  * @param high store as config for the high rates
525  * @return true if successful, false otherwise
526  */
527 bool
528 EAP::updateRouterConfig(RouterConfig& rcfg, bool low, bool mid, bool high) {
529     // write the router config to the appropriate memory space on the device
530     if(!rcfg.write(eRT_NewRouting, 0)) {
531         debugError("Could not write new router configuration\n");
532         return false;
533     }
534     // perform the store operation
535     if(!loadRouterConfig(low, mid, high)) {
536         debugError("Could not activate new router configuration\n");
537         updateConfigurationCache(); // for consistency
538         return false;
539     }
540     return updateConfigurationCache();
541 }
542
543 /**
544  * Uploads a new router configuration to replace the configuration
545  * for the current rate.
546  * @param  rcfg The new RouterConfig
547  * @return true if successful, false otherwise
548  */
549 bool
550 EAP::updateCurrentRouterConfig(RouterConfig& rcfg) {
551     switch(m_device.getCurrentConfig()) {
552         case Device::eDC_Low: return updateRouterConfig(rcfg, true, false, false);
553         case Device::eDC_Mid: return updateRouterConfig(rcfg, false, true, false);
554         case Device::eDC_High: return updateRouterConfig(rcfg, false, false, true);
555         default:
556             debugError("Unsupported configuration mode\n");
557             return false;
558     }
559 }
560
561 /**
562  * Set a default configuration for the router.
563  *  This is necessary for somes devices for hardware coherence, in which case the next
564  *  has to be customized
565  * @param  rcfg The new RouterConfig
566  * @return true if successful, false otherwise
567  */
568 void
569 EAP::setupDefaultRouterConfig_low() {
570     unsigned int i;
571     // add the routing destinations for a DICE chip
572     switch(m_general_chip) {
573         case DICE_EAP_CAP_GENERAL_CHIP_DICEII:
574             // router/EAP currently not supported
575             break;
576         case DICE_EAP_CAP_GENERAL_CHIP_DICEJR:
577             // second audio port (unique to the junior)
578             // Ensure it is not muted
579             for (i=0; i<8; i++) {
580               addRoute(eRS_ARX0, i+8, eRD_InS1, i);
581             }
582         case DICE_EAP_CAP_GENERAL_CHIP_DICEMINI:
583             // the 1394 stream receivers
584             for (i=0; i<8; i++) {
585               addRoute(eRS_InS0, i, eRD_ATX0, i);
586             }
587             for (i=0; i<8; i++) {
588               addRoute(eRS_InS1, i, eRD_ATX0, i+8);
589             }
590             for (i=0; i<8; i++) {
591               addRoute(eRS_ADAT, i, eRD_ATX1, i);
592             }
593             for (i=0; i<8; i++) {
594               addRoute(eRS_AES, i, eRD_ATX1, i+8);
595             }
596             // The audio ports
597             // Ensure that audio port are not muted
598             for (i=0; i<8; i++) {
599               addRoute(eRS_ARX0, i, eRD_InS0, i);
600             }
601             // the AES receiver
602             for (i=0; i<8; i++) {
603               addRoute(eRS_Muted, 0, eRD_AES, i);
604             }
605             // the ADAT receiver
606             for (i=0; i<8; i++) {
607               addRoute(eRS_Muted, 0, eRD_ADAT, i);
608             }
609             // the Mixer outputs
610             for (i=0; i<8; i++) {
611               addRoute(eRS_InS0, i, eRD_Mixer0, i);
612             }
613             for (i=0; i<8; i++) {
614               addRoute(eRS_ADAT, i, eRD_Mixer0, i+8);
615             }
616             for (i=0; i<2; i++) {
617               addRoute(eRS_Muted, 0, eRD_Mixer0, i+16);
618             }
619             // the ARM audio port
620             for (i=0; i<8; i++) {
621               addRoute(eRS_Muted, 0, eRD_ARM, i);
622             }
623             // mute
624             addRoute(eRS_Muted, 0, eRD_Muted, 0);
625             break;
626         default:
627             // this is an unsupported chip
628             break;
629     }
630 }
631
632 void
633 EAP::setupDefaultRouterConfig_mid() {
634     setupDefaultRouterConfig_low();
635 }
636
637 void
638 EAP::setupDefaultRouterConfig_high() {
639     setupDefaultRouterConfig_low();
640 }
641
642 void
643 EAP::setupDefaultRouterConfig() {
644     // First clear routes
645     RouterConfig *rcfg = getActiveRouterConfig();
646     rcfg->clearRoutes();
647
648     // Then define the configuration depending on the samplerate
649     switch(m_device.getCurrentConfig()) {
650         case Device::eDC_Low: setupDefaultRouterConfig_low(); break;
651         case Device::eDC_Mid: setupDefaultRouterConfig_mid(); break;
652         case Device::eDC_High: setupDefaultRouterConfig_high(); break;
653         default:
654             debugError("Unsupported configuration mode\n");
655             return;
656     }
657
658     updateCurrentRouterConfig(*rcfg);
659 }
660
661 /**
662  * Add (create) a route from source to destination
663  */
664 bool
665 EAP::addRoute(enum eRouteSource srcid, unsigned int base_src, enum eRouteDestination dstid,
666               unsigned int base_dst)
667 {
668     RouterConfig *rcfg = getActiveRouterConfig();
669     return rcfg->createRoute((srcid<<4) + base_src, (dstid<<4) + base_dst);
670 }
671
672
673 /**
674  * Uploads a new stream configuration to the device
675  * @param scfg The new StreamConfig
676  * @param low store as config for the low rates
677  * @param mid store as config for the mid rates
678  * @param high store as config for the high rates
679  * @return true if successful, false otherwise
680  */
681 bool
682 EAP::updateStreamConfig(StreamConfig& scfg, bool low, bool mid, bool high) {
683     // write the stream config to the appropriate memory space on the device
684     if(!scfg.write(eRT_NewStreamCfg, 0)) {
685         debugError("Could not write new stream configuration\n");
686         return false;
687     }
688     // perform the store operation
689     if(!loadStreamConfig(low, mid, high)) {
690         debugError("Could not activate new stream configuration\n");
691         updateConfigurationCache(); // for consistency
692         return false;
693     }
694     return updateConfigurationCache();
695 }
696
697 /**
698  * Uploads a new router and stream configuration to the device
699  * @param  rcfg The new RouterConfig
700  * @param  scfg The new StreamConfig
701  * @param low store as config for the low rates
702  * @param mid store as config for the mid rates
703  * @param high store as config for the high rates
704  * @return true if successful, false otherwise
705  */
706 bool
707 EAP::updateStreamConfig(RouterConfig& rcfg, StreamConfig& scfg, bool low, bool mid, bool high) {
708     // write the router config to the appropriate memory space on the device
709     if(!rcfg.write(eRT_NewRouting, 0)) {
710         debugError("Could not write new router configuration\n");
711         return false;
712     }
713     // write the stream config to the appropriate memory space on the device
714     if(!scfg.write(eRT_NewStreamCfg, 0)) {
715         debugError("Could not write new stream configuration\n");
716         return false;
717     }
718     // perform the store operation
719     if(!loadRouterAndStreamConfig(low, mid, high)) {
720         debugError("Could not activate new router/stream configuration\n");
721         updateConfigurationCache(); // for consistency
722         return false;
723     }
724     return updateConfigurationCache();
725 }
726
727
728 bool
729 EAP::loadFlashConfig() {
730     bool retval = true;
731     debugWarning("Untested code\n");
732     fb_quadlet_t cmd = DICE_EAP_CMD_OPCODE_LD_FLASH_CFG;
733     cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_EXECUTE;
734     if(!commandHelper(cmd)) {
735         debugWarning("Command failed\n");
736         retval = false;
737     }
738     retval &= updateConfigurationCache();
739     return retval;
740 }
741
742 bool
743 EAP::storeFlashConfig() {
744     //debugWarning("Untested code\n") // Works. -Arnold;
745     fb_quadlet_t cmd = DICE_EAP_CMD_OPCODE_ST_FLASH_CFG;
746     cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_EXECUTE;
747     return commandHelper(cmd);
748 }
749
750 // helpers
751 void
752 EAP::show()
753 {
754     printMessage("== DICE EAP ==\n");
755     printMessage("Parameter Space info:\n");
756     printMessage(" Capability        : offset=%04X size=%06d\n", m_capability_offset, m_capability_size);
757     printMessage(" Command           : offset=%04X size=%06d\n", m_cmd_offset, m_cmd_size);
758     printMessage(" Mixer             : offset=%04X size=%06d\n", m_mixer_offset, m_mixer_size);
759     printMessage(" Peak              : offset=%04X size=%06d\n", m_peak_offset, m_peak_size);
760     printMessage(" New Routing Cfg   : offset=%04X size=%06d\n", m_new_routing_offset, m_new_routing_size);
761     printMessage(" New Stream Cfg    : offset=%04X size=%06d\n", m_new_stream_cfg_offset, m_new_stream_cfg_size);
762     printMessage(" Current Cfg       : offset=%04X size=%06d\n", m_curr_cfg_offset, m_curr_cfg_size);
763     printMessage(" Standalone Cfg    : offset=%04X size=%06d\n", m_standalone_offset, m_standalone_size);
764     printMessage(" Application Space : offset=%04X size=%06d\n", m_app_offset, m_app_size);
765
766     printMessage("Capabilities:\n");
767     printMessage(" Router: %sexposed, %swritable, %sstored, %d routes\n",
768                                      (m_router_exposed?"":"not "),
769                                      (m_router_readonly?"not ":""),
770                                      (m_router_flashstored?"":"not "),
771                                      m_router_nb_entries);
772     printMessage(" Mixer : %sexposed, %swritable, %sstored\n",
773                                      (m_mixer_exposed?"":"not "),
774                                      (m_mixer_readonly?"not ":""),
775                                      (m_mixer_flashstored?"":"not "));
776     printMessage("         tx id: (%d==eRD_Mixer0) ? %s, rx id: (%d==eRS_Mixer) ? %s\n",
777                                      m_mixer_tx_id, (m_mixer_tx_id == eRD_Mixer0)?"true":"false",
778                                      m_mixer_rx_id, (m_mixer_rx_id == eRS_Mixer) ?"true":"false");
779     printMessage("         nb tx channels: %d, nb rx channels: %d\n", m_mixer_nb_tx, m_mixer_nb_rx);
780     printMessage(" General: dynamic stream config %ssupported\n",
781                                      (m_general_support_dynstream?"":"not "));
782     printMessage("          flash load and store %ssupported\n",
783                                      (m_general_support_flash?"":"not "));
784     printMessage("          peak metering %s\n",
785                                      (m_general_peak_enabled?"enabled":"disabled"));
786     printMessage("          stream config %sstored\n",
787                                      (m_general_stream_cfg_stored?"":"not "));
788     printMessage("          max TX streams: %d, max RX streams: %d\n",
789                                      m_general_max_tx, m_general_max_rx);
790
791     if(m_general_chip == DICE_EAP_CAP_GENERAL_CHIP_DICEII) {
792         printMessage("          Chip: DICE-II\n");
793     } else if(m_general_chip == DICE_EAP_CAP_GENERAL_CHIP_DICEMINI) {
794         printMessage("          Chip: DICE Mini (TCD2210)\n");
795     } else if(m_general_chip == DICE_EAP_CAP_GENERAL_CHIP_DICEJR) {
796         printMessage("          Chip: DICE Junior (TCD2220)\n");
797     }
798
799     printMessage("--- Mixer configuration ---\n");
800     if(m_mixer) {
801         m_mixer->show();
802     }
803     printMessage("--- Router/Peak space ---\n");
804     if(m_router) {
805         m_router->show();
806     }
807
808     printMessage("--- Active Router ---\n");
809     RouterConfig *rcfg = getActiveRouterConfig();
810     if(rcfg) {
811         rcfg->show();
812     }
813     printMessage("--- Active Stream ---\n");
814     StreamConfig *scfg = getActiveStreamConfig();
815     if(scfg) {
816         scfg->show();
817     }
818     printMessage("--- Standalone configuration ---\n");
819     if(m_standalone) {
820         m_standalone->show();
821     }
822
823 // fixme
824 //     size_t len = 0x1000;
825 //     quadlet_t tmp[len];
826 //     if(!readRegBlock( eRT_CurrentCfg, DICE_EAP_CURRCFG_LOW_STREAM, tmp, len*4) ) {
827 //         debugError("Failed to read block\n");
828 //     } else {
829 //         hexDumpQuadlets(tmp, len);
830 //     }
831
832 }
833 void
834 EAP::showApplication()
835 {
836     printMessage("--- Application space ---\n");
837     printMessage(" application space size: %06d\n", m_app_size);
838     fb_quadlet_t* tmp = (fb_quadlet_t *)calloc(128, sizeof(fb_quadlet_t));
839     int appsize = m_app_size/sizeof(fb_quadlet_t);
840     unsigned int offset = 0;
841     unsigned int to_read;
842     while ( appsize > 0 ) {
843         to_read = (appsize<128)?appsize:128;
844         if ( ! readRegBlock( eRT_Application, offset, tmp, to_read*sizeof(fb_quadlet_t) ) )
845             appsize = 0;
846         else {
847             hexDumpQuadlets(tmp, to_read);
848             offset += 128*sizeof(fb_quadlet_t);
849             appsize -= to_read;
850         }
851     }
852 }
853
854 void
855 EAP::showFullRouter()
856 {
857     printMessage("--- Full router content ---\n");
858
859     printMessage(" %d entries to read\n", m_router_nb_entries);
860
861     unsigned int offset;
862     switch(m_device.getCurrentConfig()) {
863         case Device::eDC_Low: offset = DICE_EAP_CURRCFG_LOW_ROUTER; break;
864         case Device::eDC_Mid: offset = DICE_EAP_CURRCFG_MID_ROUTER; break;
865         case Device::eDC_High: offset = DICE_EAP_CURRCFG_HIGH_ROUTER; break;
866         default: offset = 0; break;
867     }
868
869     // Current config
870     printMessage("  Current Configuration:\n");
871     // First bloc is the effective number of routes
872     uint32_t nb_routes;
873     if(!readRegBlock(eRT_CurrentCfg, offset, &nb_routes, 4)) {
874         printMessage("Failed to read number of entries\n");
875         return;
876     }
877     printMessage("   %d routes\n", nb_routes);
878
879     // read the route info
880     uint32_t tmp_entries[m_router_nb_entries];
881     if(!readRegBlock(eRT_CurrentCfg, offset+4, tmp_entries, m_router_nb_entries*4)) {
882         printMessage("Failed to read router config block information\n");
883         return;
884     }
885
886     // decode and print
887     for(unsigned int i=0; i < m_router_nb_entries; i++) {
888         printMessage("    %d: 0x%02x <- 0x%02x;\n", i, tmp_entries[i]&0xff, (tmp_entries[i]>>8)&0xff);
889     }
890
891     // New config
892     printMessage("  New Configuration:\n");
893     // First bloc is the effective number of routes
894     if(!readRegBlock(eRT_NewRouting, 0, &nb_routes, 4)) {
895         printMessage("Failed to read number of entries\n");
896         return;
897     }
898     printMessage("   %d routes\n", nb_routes);
899
900     // read the route info
901     if(!readRegBlock(eRT_NewRouting, 4, tmp_entries, m_router_nb_entries*4)) {
902         printMessage("Failed to read router config block information\n");
903         return;
904     }
905
906     // decode and print
907     for(unsigned int i=0; i < m_router_nb_entries; i++) {
908         printMessage("    %d: 0x%02x <- 0x%02x;\n", i, tmp_entries[i]&0xff, (tmp_entries[i]>>8)&0xff);
909     }
910
911     return;
912 }
913
914 void
915 EAP::showFullPeakSpace()
916 {
917     printMessage("--- Full Peak space content ---\n");
918
919     // read the peak/route info
920     uint32_t tmp_entries[m_router_nb_entries];
921     if(!readRegBlock(eRT_Peak, 0, tmp_entries, m_router_nb_entries*4)) {
922         debugError("Failed to read peak block information\n");
923         return;
924     }
925     // decode and print
926     for (unsigned int i=0; i<m_router_nb_entries; ++i) {
927         printMessage("  %d: 0x%02x: %d;\n", i, tmp_entries[i]&0xff, (tmp_entries[i]&0xfff0000)>>16);
928     }
929     return;
930 }
931
932 // EAP load/store operations
933
934 enum EAP::eWaitReturn
935 EAP::operationBusy() {
936     fb_quadlet_t tmp;
937     if(!readReg(eRT_Command, DICE_EAP_COMMAND_OPCODE, &tmp)) {
938         debugError("Could not read opcode register\n");
939         return eWR_Error;
940     }
941     if( (tmp & DICE_EAP_CMD_OPCODE_FLAG_LD_EXECUTE) == DICE_EAP_CMD_OPCODE_FLAG_LD_EXECUTE) {
942         return eWR_Busy;
943     } else {
944         return eWR_Done;
945     }
946 }
947
948 enum EAP::eWaitReturn
949 EAP::waitForOperationEnd(int max_wait_time_ms) {
950     int max_waits = max_wait_time_ms;
951
952     while(max_waits--) {
953         enum eWaitReturn retval = operationBusy();
954         switch(retval) {
955             case eWR_Busy:
956                 break; // not done yet, keep waiting
957             case eWR_Done:
958                 return eWR_Done;
959             case eWR_Error:
960             case eWR_Timeout:
961                 debugError("Error while waiting for operation to end. (%d)\n", retval);
962         }
963         Util::SystemTimeSource::SleepUsecRelative(1000);
964     }
965     return eWR_Timeout;
966 }
967
968 bool
969 EAP::commandHelper(fb_quadlet_t cmd) {
970     // check whether another command is still running
971     if(operationBusy() == eWR_Busy) {
972         debugError("Other operation in progress\n");
973         return false;
974     }
975
976     // execute the command
977     if(!writeReg(eRT_Command, DICE_EAP_COMMAND_OPCODE, cmd)) {
978         debugError("Could not write opcode register\n");
979         return false;
980     }
981
982     // wait for the operation to end
983     enum eWaitReturn retval = waitForOperationEnd();
984     switch(retval) {
985         case eWR_Done:
986             break; // do nothing
987         case eWR_Timeout:
988             debugWarning("Time-out while waiting for operation to end. (%d)\n", retval);
989             return false;
990         case eWR_Error:
991         case eWR_Busy: // can't be returned
992             debugError("Error while waiting for operation to end. (%d)\n", retval);
993             return false;
994     }
995
996     // check the return value
997     if(!readReg(eRT_Command, DICE_EAP_COMMAND_RETVAL, &cmd)) {
998         debugError("Could not read return value register\n");
999         return false;
1000     }
1001     if(cmd != 0) {
1002         debugWarning("Command failed\n");
1003         return false;
1004     } else {
1005         debugOutput(DEBUG_LEVEL_VERBOSE, "Command successful\n");
1006         return true;
1007     }
1008 }
1009
1010 bool
1011 EAP::loadRouterConfig(bool low, bool mid, bool high) {
1012     fb_quadlet_t cmd = DICE_EAP_CMD_OPCODE_LD_ROUTER;
1013     if(low) cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_LOW;
1014     if(mid) cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_MID;
1015     if(high) cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_HIGH;
1016     cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_EXECUTE;
1017     return commandHelper(cmd);
1018 }
1019
1020 bool
1021 EAP::loadStreamConfig(bool low, bool mid, bool high) {
1022     debugWarning("Untested code\n");
1023     fb_quadlet_t cmd = DICE_EAP_CMD_OPCODE_LD_STRM_CFG;
1024     if(low) cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_LOW;
1025     if(mid) cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_MID;
1026     if(high) cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_HIGH;
1027     cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_EXECUTE;
1028     return commandHelper(cmd);
1029 }
1030
1031 bool
1032 EAP::loadRouterAndStreamConfig(bool low, bool mid, bool high) {
1033     debugWarning("Untested code\n");
1034     fb_quadlet_t cmd = DICE_EAP_CMD_OPCODE_LD_RTR_STRM_CFG;
1035     if(low) cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_LOW;
1036     if(mid) cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_MID;
1037     if(high) cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_HIGH;
1038     cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_EXECUTE;
1039     return commandHelper(cmd);
1040 }
1041
1042 /*
1043   I/O operations
1044   */
1045 bool
1046 EAP::readReg(enum eRegBase base, unsigned offset, fb_quadlet_t *result) {
1047     fb_nodeaddr_t addr = offsetGen(base, offset, 4);
1048     return m_device.readReg(addr, result);
1049 }
1050
1051 bool
1052 EAP::writeReg(enum eRegBase base, unsigned offset, fb_quadlet_t data) {
1053     fb_nodeaddr_t addr = offsetGen(base, offset, 4);
1054     return m_device.writeReg(addr, data);
1055 }
1056
1057 bool
1058 EAP::readRegBlock(enum eRegBase base, unsigned offset, fb_quadlet_t *data, size_t length) {
1059     fb_nodeaddr_t addr = offsetGen(base, offset, length);
1060     return m_device.readRegBlock(addr, data, length);
1061 }
1062
1063 bool
1064 EAP::writeRegBlock(enum eRegBase base, unsigned offset, fb_quadlet_t *data, size_t length) {
1065     fb_nodeaddr_t addr = offsetGen(base, offset, length);
1066     return m_device.writeRegBlock(addr, data, length);
1067 }
1068
1069 fb_nodeaddr_t
1070 EAP::offsetGen(enum eRegBase base, unsigned offset, size_t length) {
1071     fb_nodeaddr_t addr;
1072     fb_nodeaddr_t maxlen;
1073     switch(base) {
1074         case eRT_Base:
1075             addr = 0;
1076             maxlen = DICE_EAP_MAX_SIZE;
1077             break;
1078         case eRT_Capability:
1079             addr = m_capability_offset;
1080             maxlen = m_capability_size;
1081             break;
1082         case eRT_Command:
1083             addr = m_cmd_offset;
1084             maxlen = m_cmd_size;
1085             break;
1086         case eRT_Mixer:
1087             addr = m_mixer_offset;
1088             maxlen = m_mixer_size;
1089             break;
1090         case eRT_Peak:
1091             addr = m_peak_offset;
1092             maxlen = m_peak_size;
1093             break;
1094         case eRT_NewRouting:
1095             addr = m_new_routing_offset;
1096             maxlen = m_new_routing_size;
1097             break;
1098         case eRT_NewStreamCfg:
1099             addr = m_new_stream_cfg_offset;
1100             maxlen = m_new_stream_cfg_size;
1101             break;
1102         case eRT_CurrentCfg:
1103             addr = m_curr_cfg_offset;
1104             maxlen = m_curr_cfg_size;
1105             break;
1106         case eRT_Standalone:
1107             addr = m_standalone_offset;
1108             maxlen = m_standalone_size;
1109             break;
1110         case eRT_Application:
1111             addr = m_app_offset;
1112             maxlen = m_app_size;
1113             break;
1114         default:
1115             debugError("Unsupported base address\n");
1116             return 0;
1117     };
1118
1119     // out-of-range check
1120     if(length > maxlen) {
1121         debugError("requested length too large: %zd > %" PRIu64 "\n", length, maxlen);
1122         return DICE_INVALID_OFFSET;
1123     }
1124     return DICE_EAP_BASE + addr + offset;
1125 }
1126
1127 /**
1128  * Check whether a device supports eap
1129  * @param d the device to check
1130  * @return true if the device supports EAP
1131  */
1132 bool
1133 EAP::supportsEAP(Device &d)
1134 {
1135     DebugModule &m_debugModule = d.m_debugModule;
1136     quadlet_t tmp;
1137     if(!d.readReg(DICE_EAP_BASE, &tmp)) {
1138         debugOutput(DEBUG_LEVEL_VERBOSE, "Could not read from DICE EAP base address\n");
1139         return false;
1140     }
1141     if(!d.readReg(DICE_EAP_BASE + DICE_EAP_ZERO_MARKER_1, &tmp)) {
1142         debugOutput(DEBUG_LEVEL_VERBOSE, "Could not read from DICE EAP zero marker\n");
1143         return false;
1144     }
1145     if(tmp != 0) {
1146         debugOutput(DEBUG_LEVEL_VERBOSE, "DICE EAP zero marker not zero\n");
1147         return false;
1148     }
1149     return true;
1150 }
1151
1152 // -------------------------------- Mixer ----------------------------------
1153 //   Dice matrix-mixer is a one-dimensional array with inputs index varying
1154 //    first
1155 //
1156 //   "ffado convention" is that inputs are rows and outputs are columns
1157 //
1158 EAP::Mixer::Mixer(EAP &p)
1159 : Control::MatrixMixer(&p.m_device, "MatrixMixer")
1160 , m_eap(p)
1161 , m_coeff(NULL)
1162 , m_debugModule(p.m_debugModule)
1163 {
1164 }
1165
1166 EAP::Mixer::~Mixer()
1167 {
1168     if (m_coeff) {
1169         free(m_coeff);
1170         m_coeff = NULL;
1171     }
1172 }
1173
1174 bool
1175 EAP::Mixer::init()
1176 {
1177     if(!m_eap.m_mixer_exposed) {
1178         debugError("Device does not expose mixer\n");
1179         return false;
1180     }
1181
1182     // remove previous coefficient array
1183     if(m_coeff) {
1184         free(m_coeff);
1185         m_coeff = NULL;
1186     }
1187    
1188     // allocate coefficient array
1189     int nb_inputs = m_eap.m_mixer_nb_tx;
1190     int nb_outputs = m_eap.m_mixer_nb_rx;
1191
1192     m_coeff = (fb_quadlet_t *)calloc(nb_outputs * nb_inputs, sizeof(fb_quadlet_t));
1193
1194     // load initial values
1195     if(!loadCoefficients()) {
1196         debugWarning("Could not initialize coefficients\n");
1197         return false;
1198     }
1199     updateNameCache();
1200     return true;
1201 }
1202
1203 bool
1204 EAP::Mixer::loadCoefficients()
1205 {
1206     if(m_coeff == NULL) {
1207         debugError("Coefficient cache not initialized\n");
1208         return false;
1209     }
1210     int nb_inputs = m_eap.m_mixer_nb_tx;
1211     int nb_outputs = m_eap.m_mixer_nb_rx;
1212     if(!m_eap.readRegBlock(eRT_Mixer, 4, m_coeff, nb_inputs * nb_outputs * 4)) {
1213         debugError("Failed to read coefficients\n");
1214         return false;
1215     }
1216     return true;
1217 }
1218
1219 bool
1220 EAP::Mixer::storeCoefficients()
1221 {
1222     if(m_coeff == NULL) {
1223         debugError("Coefficient cache not initialized\n");
1224         return false;
1225     }
1226     if(m_eap.m_mixer_readonly) {
1227         debugWarning("Mixer is read-only\n");
1228         return false;
1229     }
1230     int nb_inputs = m_eap.m_mixer_nb_tx;
1231     int nb_outputs = m_eap.m_mixer_nb_rx;
1232     if(!m_eap.writeRegBlock(eRT_Mixer, 4, m_coeff, nb_inputs * nb_outputs * 4)) {
1233         debugError("Failed to read coefficients\n");
1234         return false;
1235     }
1236     return true;
1237 }
1238
1239 void
1240 EAP::Mixer::updateNameCache()
1241 {
1242 //    debugWarning("What is this function about?\n");
1243     debugOutput(DEBUG_LEVEL_VERBOSE, "What is this function about?\n");
1244 #if 0
1245     // figure out the number of i/o's
1246     int nb_inputs = m_eap.m_mixer_nb_tx;
1247     int nb_outputs = m_eap.m_mixer_nb_rx;
1248
1249     // clear the previous map
1250     m_input_route_map.clear();
1251     m_output_route_map.clear();
1252
1253     // find the active router configuration
1254     RouterConfig * rcfg = m_eap.getActiveRouterConfig();
1255     if(rcfg == NULL) {
1256         debugError("Could not get active routing info\n");
1257         return;
1258     }
1259
1260     // find the inputs
1261     for(int i=0; i < nb_inputs; i++) {
1262         int ch = i;
1263         // the destination id of the mixer input
1264         int dest_int = m_eap.m_mixer_tx_id;
1265
1266         // from the DICE mixer spec:
1267         // we can have 16 channels per "block"
1268         // if there are more, consecutive block id's are assumed
1269         while(ch > 15) {
1270             ch -= 16;
1271             dest_int += 1;
1272         }
1273         // the destination block and channel corresponding with this
1274         // mixer input is now known
1275         enum eRouteDestination dest = rcfg->intToRouteDestination(dest_int);
1276
1277         // get the source for this mixer channel
1278         m_input_route_map[i] = rcfg->getRouteForDestination(dest, ch);
1279
1280         debugOutput(DEBUG_LEVEL_VERBOSE, "Mixer input channel %2d source: %s (%d)\n", i,
1281                                           srcBlockToString(m_input_route_map[i].src),
1282                                           m_input_route_map[i].srcChannel);
1283     }
1284
1285     // find where the outputs are connected to
1286     for(int i=0; i < nb_outputs; i++) {
1287         int ch = i;
1288         // the source id of the mixer input
1289         int src_int = m_eap.m_mixer_rx_id;
1290
1291         // from the DICE mixer spec:
1292         // we can have 16 channels per "block"
1293         // if there are more, consecutive block id's are assumed
1294         while(ch > 15) {
1295             ch -= 16;
1296             src_int += 1;
1297         }
1298
1299         // the source block and channel corresponding with this
1300         // mixer output is now known
1301         enum eRouteSource src = rcfg->intToRouteSource(src_int);
1302
1303         // get the routing destinations for this mixer channel
1304         m_output_route_map[i] = rcfg->getRoutesForSource(src, ch);
1305
1306         #ifdef DEBUG
1307         std::string destinations;
1308         for ( RouterConfig::RouteVectorIterator it = m_output_route_map[i].begin();
1309             it != m_output_route_map[i].end();
1310             ++it )
1311         {
1312             RouterConfig::Route r = *it;
1313             // check whether the destination is valid
1314             if((r.dst != eRD_Invalid) && (r.dstChannel >= 0)) {
1315                 char tmp[128];
1316                 snprintf(tmp, 128, "%s:%d,", dstBlockToString(r.dst), r.dstChannel);
1317                 destinations += tmp;
1318             }
1319         }
1320         debugOutput(DEBUG_LEVEL_VERBOSE, "Mixer output channel %2d destinations: %s\n", i, destinations.c_str());
1321         #endif
1322     }
1323 #endif
1324 }
1325
1326 void
1327 EAP::Mixer::show()
1328 {
1329     int nb_inputs = m_eap.m_mixer_nb_tx;
1330     int nb_outputs = m_eap.m_mixer_nb_rx;
1331
1332     updateNameCache();
1333
1334     const size_t bufflen = 4096;
1335     char tmp[bufflen];
1336     int cnt;
1337
1338     //
1339     // Caution the user that, displaying as further, because inputs index varies first
1340     //  inputs will appears as columns at the opposite of the "ffado convention"
1341     printMessage("   -- inputs index -->>\n");
1342     cnt = 0;
1343     for(int j=0; j < nb_inputs; j++) {
1344         cnt += snprintf(tmp+cnt, bufflen-cnt, "   %02d   ", j);
1345     }
1346     printMessage("%s\n", tmp);
1347
1348     cnt = 0;
1349     for(int j=0; j < nb_inputs; j++) {
1350         cnt += snprintf(tmp+cnt, bufflen-cnt, "%s ", getRowName(j).data());
1351     }
1352     printMessage("%s\n", tmp);
1353
1354     // display coefficients
1355     for(int i=0; i < nb_outputs; i++) {
1356         cnt = 0;
1357         for(int j=0; j < nb_inputs; j++) {
1358             cnt += snprintf(tmp+cnt, bufflen-cnt, "%07d ", *(m_coeff + nb_inputs * i + j));
1359         }
1360  
1361         // Display destinations name
1362         cnt += snprintf(tmp+cnt, bufflen-cnt, "=[%02d]=> %s", i, getColName(i).data());
1363         printMessage("%s\n", tmp);
1364     }
1365
1366 }
1367
1368 int
1369 EAP::Mixer::canWrite( const int row, const int col)
1370 {
1371     if(m_eap.m_mixer_readonly) {
1372         return false;
1373     }
1374     return (row >= 0 && row < m_eap.m_mixer_nb_tx && col >= 0 && col < m_eap.m_mixer_nb_rx);
1375 }
1376
1377 double
1378 EAP::Mixer::setValue( const int row, const int col, const double val)
1379 {
1380     if(m_eap.m_mixer_readonly) {
1381         debugWarning("Mixer is read-only\n");
1382         return false;
1383     }
1384     int nb_outputs = m_eap.m_mixer_nb_tx;
1385     int addr = ((nb_outputs * col) + row) * 4;
1386     quadlet_t tmp = (quadlet_t) val;
1387     if(!m_eap.writeRegBlock(eRT_Mixer, 4+addr, &tmp, 4)) {
1388         debugError("Failed to write coefficient\n");
1389         return 0;
1390     }
1391     return (double)(tmp);
1392 }
1393
1394 double
1395 EAP::Mixer::getValue( const int row, const int col)
1396 {
1397     int nb_outputs = m_eap.m_mixer_nb_tx;
1398     int addr = ((nb_outputs * col) + row) * 4;
1399     quadlet_t tmp;
1400     if(!m_eap.readRegBlock(eRT_Mixer, 4+addr, &tmp, 4)) {
1401         debugError("Failed to read coefficient\n");
1402         return 0;
1403     }
1404     return (double)(tmp);
1405 }
1406
1407 int
1408 EAP::Mixer::getRowCount()
1409 {
1410     return m_eap.m_mixer_nb_tx;
1411 }
1412
1413 int
1414 EAP::Mixer::getColCount()
1415 {
1416     return m_eap.m_mixer_nb_rx;
1417 }
1418
1419 // full map updates are unsupported
1420 bool
1421 EAP::Mixer::getCoefficientMap(int &) {
1422     return false;
1423 }
1424
1425 bool
1426 EAP::Mixer::storeCoefficientMap(int &) {
1427     if(m_eap.m_mixer_readonly) {
1428         debugWarning("Mixer is read-only\n");
1429         return false;
1430     }
1431     return false;
1432 }
1433
1434 // Names
1435 std::string
1436 EAP::Mixer::getRowName(const int row) {
1437     std::string mixer_src, row_name;
1438     if (row < 0 || row > m_eap.m_mixer_nb_tx) return "Invalid";
1439     unsigned int dstid = (eRD_Mixer0<<4) + row; // Mixer has consecutive ID's
1440     debugOutput(DEBUG_LEVEL_VERBOSE, "EAP::Mixer::getRowName( %d ): ID's %d\n", row, dstid);
1441     if (m_eap.m_router){
1442       std::string mixer_dst = m_eap.m_router->getDestinationName(dstid);
1443       mixer_src = m_eap.m_router->getSourceForDestination(mixer_dst);
1444       debugOutput(DEBUG_LEVEL_VERBOSE, "EAP::Mixer::found %s as source for %s\n", mixer_src.data(),
1445                   mixer_dst.data());
1446       row_name = mixer_dst + "\n(" + mixer_src + ")";
1447     }
1448     else {
1449       char tmp[32];
1450       snprintf(tmp, 32, "MixIn:%d", row);
1451       row_name = tmp;
1452     }
1453
1454     return row_name;
1455 }
1456
1457 std::string
1458 EAP::Mixer::getColName(const int col) {
1459     std::string mixer_dst;
1460     stringlist dest_names;
1461    
1462     // invalid col index
1463     if (col < 0 || col > m_eap.m_mixer_nb_rx) {
1464       mixer_dst.append("Invalid");
1465       return mixer_dst;
1466     }
1467    
1468     unsigned int srcid = (eRS_Mixer<<4) + col; // Mixer has consecutive ID's
1469     debugOutput(DEBUG_LEVEL_VERBOSE, "EAP::Mixer::getColName( %d ): ID's %d\n", col, srcid);
1470     if (m_eap.m_router){
1471       std::string mixer_src = m_eap.m_router->getSourceName(srcid);
1472       dest_names = m_eap.m_router->getDestinationsForSource(mixer_src);
1473       mixer_dst = mixer_src + "\n(";
1474       if (dest_names.size() > 0) {
1475         stringlist::iterator it_d = dest_names.begin();
1476         stringlist::iterator it_d_end_m1 = dest_names.end(); --it_d_end_m1;
1477         while (it_d != it_d_end_m1) {
1478           mixer_dst.append((*it_d).c_str()); mixer_dst.append(";\n");
1479           it_d++;
1480         }
1481         mixer_dst.append((*it_d).c_str());
1482       }
1483       mixer_dst.append(")");
1484     } else {
1485       char tmp[32];
1486       snprintf(tmp, 32, "MixOut:%d", col);
1487       mixer_dst.append(tmp);
1488     }
1489
1490     return mixer_dst;
1491 }
1492
1493 //
1494 // ----------- Router -------------
1495 //
1496
1497 EAP::Router::Router(EAP &p)
1498 : Control::CrossbarRouter(&p.m_device, "Router")
1499 , m_eap(p)
1500 , m_peak( *(new PeakSpace(p)) )
1501 , m_debugModule(p.m_debugModule)
1502 {
1503 }
1504
1505 EAP::Router::~Router()
1506 {
1507     delete &m_peak;
1508 }
1509
1510 void
1511 EAP::Router::update()
1512 {
1513     // Clear and
1514     //   define new sources and destinations for the router
1515     m_sources.clear();
1516     m_eap.setupSources();
1517     m_destinations.clear();
1518     m_eap.setupDestinations();
1519     return;
1520 }
1521
1522 void
1523 EAP::Router::addSource(const std::string& basename, enum eRouteSource srcid,
1524                        unsigned int base, unsigned int cnt, unsigned int offset)
1525 {
1526     std::string name = basename + ":";
1527     char tmp[4];
1528     for (unsigned int i=0; i<cnt; i++) {
1529         snprintf(tmp, 4, "%02d", offset+i);
1530         m_sources[name+tmp] = (srcid<<4) + base+i;
1531     }
1532 }
1533
1534 void
1535 EAP::Router::addDestination(const std::string& basename, enum eRouteDestination dstid,
1536                             unsigned int base, unsigned int cnt, unsigned int offset)
1537 {
1538     std::string name = basename + ":";
1539     char tmp[4];
1540     for (unsigned int i=0; i<cnt; i++) {
1541         snprintf(tmp, 4, "%02d", offset+i);
1542         m_destinations[name+tmp] = (dstid<<4) + base+i;
1543     }
1544 }
1545
1546 std::string
1547 EAP::Router::getSourceName(const int srcid)
1548 {
1549     for (std::map<std::string, int>::iterator it=m_sources.begin(); it!=m_sources.end(); ++it) {
1550         if (it->second == srcid) {
1551             return it->first;
1552         }
1553     }
1554     return "";
1555 }
1556
1557 std::string
1558 EAP::Router::getDestinationName(const int dstid)
1559 {
1560     for (std::map<std::string, int>::iterator it=m_destinations.begin(); it!=m_destinations.end(); ++it) {
1561         if (it->second == dstid) {
1562             return it->first;
1563         }
1564     }
1565     return "";
1566 }
1567
1568 int
1569 EAP::Router::getSourceIndex(std::string name)
1570 {
1571     if (m_sources.count(name) < 1)
1572         return -1;
1573     return m_sources[name];
1574 }
1575
1576 int
1577 EAP::Router::getDestinationIndex(std::string name)
1578 {
1579     if (m_destinations.count(name) < 1)
1580         return -1;
1581     return m_destinations[name];
1582 }
1583
1584 stringlist
1585 EAP::Router::getSourceNames()
1586 {
1587     stringlist n;
1588
1589     for (std::map<std::string, int>::iterator it=m_sources.begin(); it!=m_sources.end(); ++it)
1590         n.push_back(it->first);
1591     return n;
1592 }
1593
1594 stringlist
1595 EAP::Router::getDestinationNames()
1596 {
1597     stringlist n;
1598     for (std::map<std::string, int>::iterator it=m_destinations.begin(); it!=m_destinations.end(); ++it)
1599         n.push_back(it->first);
1600     return n;
1601 }
1602
1603 stringlist
1604 EAP::Router::getDestinationsForSource(const std::string& srcname) {
1605     RouterConfig* rcfg = m_eap.getActiveRouterConfig();
1606     if(rcfg == NULL) {
1607         debugError("Could not request active router configuration\n");
1608         return stringlist();
1609     }
1610     stringlist ret;
1611     std::vector<unsigned char> dests = rcfg->getDestinationsForSource(m_sources[srcname]);
1612     std::string name;
1613     for (unsigned int i=0; i<dests.size(); ++i) {
1614         if ((name = getDestinationName(dests[i])) != "") {
1615           ret.push_back(name);
1616         }
1617     }
1618     return ret;
1619 }
1620 std::string
1621 EAP::Router::getSourceForDestination(const std::string& dstname) {
1622     RouterConfig* rcfg = m_eap.getActiveRouterConfig();
1623     if(rcfg == NULL) {
1624         debugError("Could not request active router configuration\n");
1625         return "";
1626     }
1627     int source = rcfg->getSourceForDestination(m_destinations[dstname]);
1628     return getSourceName(source);
1629 }
1630
1631
1632 bool
1633 EAP::Router::canConnect(const int source, const int dest)
1634 {
1635     debugWarning("TODO: Implement canConnect(0x%02x, 0x%02x)\n", source, dest);
1636
1637     // we can connect anything
1638     // FIXME: can we?
1639     return true;
1640 }
1641
1642 bool
1643 EAP::Router::setConnectionState(const int source, const int dest, const bool enable)
1644 {
1645     debugOutput(DEBUG_LEVEL_VERBOSE,"Router::setConnectionState(0x%02x -> 0x%02x ? %i)\n", source, dest, enable);
1646     // get the routing configuration
1647     RouterConfig *rcfg = m_eap.getActiveRouterConfig();
1648     if(rcfg == NULL) {
1649         debugError("Could not request active router configuration\n");
1650         return false;
1651     }
1652
1653     bool ret = false;
1654     if (enable) {
1655         ret = rcfg->setupRoute(source, dest);
1656     } else {
1657         ret = rcfg->muteRoute(dest);
1658         // FixMe:
1659         //   Not all devices are intended to work correctly with a variable number of router entries
1660         //     so muting the destination is preferable
1661         //   Now, this might be useful for some other ones, but is it the right place for this ?
1662         //   ret = rcfg->removeRoute(source, dest);
1663     }
1664     m_eap.updateCurrentRouterConfig(*rcfg);
1665     return ret;
1666 }
1667
1668 bool
1669 EAP::Router::getConnectionState(const int source, const int dest)
1670 {
1671     // get the routing configuration
1672     RouterConfig *rcfg = m_eap.getActiveRouterConfig();
1673     if(rcfg == NULL) {
1674         debugError("Could not request active router configuration\n");
1675         return false;
1676     }
1677     if (rcfg->getSourceForDestination(dest) == source) {
1678         return true;
1679     }
1680     return false;
1681 }
1682
1683 bool
1684 EAP::Router::canConnect(const std::string& src, const std::string& dst)
1685 {
1686     int srcidx = getSourceIndex(src);
1687     int dstidx = getDestinationIndex(dst);
1688     return canConnect(srcidx, dstidx);
1689 }
1690
1691 bool
1692 EAP::Router::setConnectionState(const std::string& src, const std::string& dst, const bool enable)
1693 {
1694     int srcidx = getSourceIndex(src);
1695     int dstidx = getDestinationIndex(dst);
1696     return setConnectionState(srcidx, dstidx, enable);
1697 }
1698
1699 bool
1700 EAP::Router::getConnectionState(const std::string& src, const std::string& dst)
1701 {
1702     int srcidx = getSourceIndex(src);
1703     int dstidx = getDestinationIndex(dst);
1704     return getConnectionState(srcidx, dstidx);
1705 }
1706
1707
1708 bool
1709 EAP::Router::clearAllConnections()
1710 {
1711     // build a new empty routing configuration
1712     RouterConfig newcfg = EAP::RouterConfig(m_eap);
1713
1714     // upload the new router config
1715     if(!m_eap.updateCurrentRouterConfig(newcfg)) {
1716         debugError("Could not update router config\n");
1717         return false;
1718     }
1719     return true;
1720 }
1721
1722 bool
1723 EAP::Router::hasPeakMetering()
1724 {
1725     return m_eap.m_router_exposed;
1726 }
1727
1728 double
1729 EAP::Router::getPeakValue(const std::string& dest)
1730 {
1731     m_peak.read();
1732     unsigned char dst = m_destinations[dest];
1733     return m_peak.getPeak(dst);
1734 }
1735
1736 std::map<std::string, double>
1737 EAP::Router::getPeakValues()
1738 {
1739     m_peak.read();
1740     std::map<std::string, double> ret;
1741     std::map<unsigned char, int> peaks = m_peak.getPeaks();
1742     std::string name;
1743     for (std::map<unsigned char, int>::iterator it=peaks.begin(); it!=peaks.end(); ++it) {
1744         name = getDestinationName(it->first);
1745         if (name.size() != 0) {
1746           ret[name] = it->second;
1747         }
1748     }
1749     return ret;
1750 }
1751
1752 void
1753 EAP::Router::show()
1754 {
1755     // print the peak space as it also contains the routing configuration
1756     printMessage("Router sources:\n");
1757     printMessage(" %llu sources:\n", (unsigned long long)m_sources.size());
1758     for ( std::map<std::string, int>::iterator it=m_sources.begin(); it!=m_sources.end(); ++it ) {
1759         printMessage(" 0x%02x : %s\n", (*it).second, (*it).first.c_str());
1760     }
1761     printMessage("Router destinations:\n");
1762     printMessage(" %llu destinations:\n", (unsigned long long)m_destinations.size());
1763     for ( std::map<std::string, int>::iterator it=m_destinations.begin(); it!=m_destinations.end(); ++it ) {
1764         printMessage(" 0x%02x : %s\n", (*it).second, (*it).first.c_str());
1765     }
1766     printMessage("Router connections:\n");
1767     stringlist sources = getSourceNames();
1768     stringlist destinations = getDestinationNames();
1769     for (stringlist::iterator it1=sources.begin(); it1!=sources.end(); ++it1) {
1770         for (stringlist::iterator it2=destinations.begin(); it2!=destinations.end(); ++it2) {
1771             if (getConnectionState(*it1, *it2)) {
1772                 printMessage(" %s -> %s\n", it1->c_str(), it2->c_str());
1773             }
1774         }
1775     }
1776     printMessage("Active router config:\n");
1777     m_eap.getActiveRouterConfig()->show();
1778     printMessage("Active peak config:\n");
1779     m_peak.read();
1780     m_peak.show();
1781 }
1782
1783 // ----------- routing config -------------
1784 EAP::RouterConfig::RouterConfig(EAP &p)
1785 : m_eap(p)
1786 , m_base(eRT_None), m_offset(0)
1787 , m_debugModule(p.m_debugModule)
1788 {}
1789
1790 EAP::RouterConfig::RouterConfig(EAP &p, enum eRegBase b, unsigned int o)
1791 : m_eap(p)
1792 , m_base(b), m_offset(o)
1793 , m_debugModule(p.m_debugModule)
1794 {}
1795
1796 EAP::RouterConfig::~RouterConfig()
1797 {}
1798
1799 bool
1800 EAP::RouterConfig::read(enum eRegBase base, unsigned offset)
1801 {
1802     // first clear the current route vector
1803     clearRoutes();
1804
1805     uint32_t nb_routes;
1806     if(!m_eap.readRegBlock(base, offset, &nb_routes, 4)) {
1807         debugError("Failed to read number of entries\n");
1808         return false;
1809     }
1810     if(nb_routes == 0) {
1811         debugWarning("No routes found. Base 0x%x, offset 0x%x\n", base, offset);
1812     }
1813
1814     // read the route info
1815     uint32_t tmp_entries[nb_routes];
1816     if(!m_eap.readRegBlock(base, offset+4, tmp_entries, nb_routes*4)) {
1817         debugError("Failed to read router config block information\n");
1818         return false;
1819     }
1820
1821     // decode into the routing map
1822     for(unsigned int i=0; i < nb_routes; i++) {
1823         m_routes2.push_back(std::make_pair(tmp_entries[i]&0xff, (tmp_entries[i]>>8)&0xff));
1824     }
1825     return true;
1826 }
1827
1828 bool
1829 EAP::RouterConfig::write(enum eRegBase base, unsigned offset)
1830 {
1831     uint32_t nb_routes = m_routes2.size();
1832     if(nb_routes == 0) {
1833         debugWarning("Writing 0 routes? This will deactivate routing and make the device very silent...\n");
1834     }
1835     if (nb_routes > 128) {
1836         debugError("More then 128 are not possible, only the first 128 routes will get saved!\n");
1837         nb_routes = 128;
1838     }
1839     uint32_t tmp_entries[nb_routes];
1840
1841     // encode from the routing vector
1842     int i=0;
1843     for (RouteVectorV2::iterator it=m_routes2.begin(); it!=m_routes2.end(); ++it) {
1844         tmp_entries[i] = ((it->second<<8) + it->first)&0xffff;
1845         ++i;
1846     }
1847
1848     unsigned int nb_routes_max = m_eap.getMaxNbRouterEntries();
1849     uint32_t zeros[nb_routes_max+1];
1850
1851     for (unsigned int i=0; i<nb_routes_max+1; ++i) zeros[i] = 0;
1852     if(!m_eap.writeRegBlock(base, offset, zeros, (nb_routes_max+1)*4)) {
1853         debugError("Failed to write zeros to router config block\n");
1854         return false;
1855     }
1856
1857     // write the result to the device
1858     if(!m_eap.writeRegBlock(base, offset+4, tmp_entries, nb_routes*4)) {
1859         debugError("Failed to write router config block information\n");
1860         return false;
1861     }
1862     if(!m_eap.writeRegBlock(base, offset, &nb_routes, 4)) {
1863         debugError("Failed to write number of entries\n");
1864         return false;
1865     }
1866     return true;
1867 }
1868
1869 // Clear the route vector;
1870 bool
1871 EAP::RouterConfig::clearRoutes() {
1872     m_routes2.clear();
1873     return true;
1874 }
1875
1876 // Create a destination with a prescribed source
1877 bool
1878 EAP::RouterConfig::createRoute(unsigned char src, unsigned char dest) {
1879     debugOutput(DEBUG_LEVEL_VERBOSE,"RouterConfig::createRoute( 0x%02x, 0x%02x )\n", src, dest);
1880     m_routes2.push_back(std::make_pair(dest, src));
1881     return true;
1882 }
1883
1884 bool
1885 EAP::RouterConfig::setupRoute(unsigned char src, unsigned char dest) {
1886     debugOutput(DEBUG_LEVEL_VERBOSE,"RouterConfig::setupRoute( 0x%02x, 0x%02x )\n", src, dest);
1887     // modify exisiting routing
1888     for (RouteVectorV2::iterator it=m_routes2.begin(); it!=m_routes2.end(); ++it) {
1889         if (it->first == dest) {
1890           it->second = src;
1891           return true;
1892         }
1893     }
1894     // destination does not yet exist; create it
1895     return createRoute(src, dest);
1896 }
1897
1898
1899 bool
1900 EAP::RouterConfig::removeRoute(unsigned char src, unsigned char dest) {
1901     debugOutput(DEBUG_LEVEL_VERBOSE,"RouterConfig::removeRoute( 0x%02x, 0x%02x )\n", src, dest);
1902     for (RouteVectorV2::iterator it=m_routes2.begin(); it!=m_routes2.end(); ++it) {
1903         if (it->first == dest) {
1904           if (it->second != src) {
1905             return false;
1906           }
1907           m_routes2.erase(it);
1908           return true;
1909         }
1910     }
1911     return false;
1912 }
1913
1914 bool
1915 EAP::RouterConfig::muteRoute(unsigned char dest) {
1916     for (RouteVectorV2::iterator it=m_routes2.begin(); it!=m_routes2.end(); ++it) {
1917         if (it->first == dest) {
1918           it->second = m_eap.getSMuteId();
1919           return true;
1920         }
1921     }
1922     return false;
1923 }
1924
1925 bool
1926 EAP::RouterConfig::removeRoute(unsigned char dest) {
1927     debugOutput(DEBUG_LEVEL_VERBOSE,"RouterConfig::removeRoute( 0x%02x )\n", dest);
1928     for (RouteVectorV2::iterator it=m_routes2.begin(); it!=m_routes2.end(); ++it) {
1929         if (it->first == dest) {
1930           m_routes2.erase(it);
1931           return true;
1932         }
1933     }
1934     return false;
1935 }
1936
1937 unsigned char
1938 EAP::RouterConfig::getSourceForDestination(unsigned char dest) {
1939     for (RouteVectorV2::iterator it=m_routes2.begin(); it!=m_routes2.end(); ++it) {
1940         if (it->first == dest) {
1941           return it->second;
1942         }
1943     }
1944     return -1;
1945 }
1946
1947 std::vector<unsigned char>
1948 EAP::RouterConfig::getDestinationsForSource(unsigned char source) {
1949     std::vector<unsigned char> ret;
1950     for (RouteVectorV2::iterator it=m_routes2.begin(); it!=m_routes2.end(); ++it) {
1951         if (it->second == source) {
1952             ret.push_back(it->first);
1953         }
1954     }
1955     return ret;
1956 }
1957
1958 void
1959 EAP::RouterConfig::show()
1960 {
1961     printMessage("%llu routes\n", (unsigned long long)m_routes2.size());
1962     for ( RouteVectorV2::iterator it=m_routes2.begin(); it!=m_routes2.end(); ++it ) {
1963         printMessage("0x%02x -> 0x%02x\n", it->second, it->first);
1964     }
1965 }
1966
1967 //
1968 // ----------- peak space -------------
1969 //
1970
1971 bool
1972 EAP::PeakSpace::read(enum eRegBase base, unsigned offset)
1973 {
1974     uint32_t nb_routes;
1975     // we have to figure out the number of entries through the currently
1976     // active router config
1977     RouterConfig *rcfg = m_eap.getActiveRouterConfig();
1978     if(rcfg == NULL) {
1979         debugError("Could not get active router config\n");
1980         return false;
1981     }
1982     nb_routes = rcfg->getNbRoutes();
1983
1984     // read the peak/route info
1985     uint32_t tmp_entries[nb_routes];
1986     if(!m_eap.readRegBlock(base, offset, tmp_entries, nb_routes*4)) {
1987         debugError("Failed to read peak block information\n");
1988         return false;
1989     }
1990     // parse the peaks into the map
1991     for (unsigned int i=0; i<nb_routes; ++i) {
1992         unsigned char dest = tmp_entries[i]&0xff;
1993         int peak = (tmp_entries[i]&0xfff0000)>>16;
1994         if (m_peaks.count(dest) == 0 || m_peaks[dest] < peak) {
1995             m_peaks[dest] = peak;
1996         }
1997     }
1998     return true;
1999 }
2000
2001
2002 void
2003 EAP::PeakSpace::show()
2004 {
2005     printMessage("  %zi peaks\n", m_peaks.size());
2006     for (std::map<unsigned char, int>::iterator it=m_peaks.begin(); it!=m_peaks.end(); ++it) {
2007         printMessage("0x%02x : %i\n", it->first, it->second);
2008     }
2009 }
2010
2011 int
2012 EAP::PeakSpace::getPeak(unsigned char dst) {
2013     int ret = m_peaks[dst];
2014     m_peaks.erase(dst);
2015     return ret;
2016 }
2017
2018 std::map<unsigned char, int>
2019 EAP::PeakSpace::getPeaks() {
2020     // Create a new empty map
2021     std::map<unsigned char, int> ret;
2022     // Swap the peak map with the new and empty one
2023     ret.swap(m_peaks);
2024     // Return the now filled map of the peaks :-)
2025     return ret;
2026 }
2027
2028 //
2029 // ----------- stream config block -------------
2030 //
2031
2032 EAP::StreamConfig::StreamConfig(EAP &p, enum eRegBase b, unsigned int o)
2033 : m_eap(p)
2034 , m_base(b), m_offset(o)
2035 , m_nb_tx(0), m_nb_rx(0)
2036 , m_tx_configs(NULL), m_rx_configs(NULL)
2037 , m_debugModule(p.m_debugModule)
2038 {
2039
2040 }
2041
2042 EAP::StreamConfig::~StreamConfig()
2043 {
2044     if(m_tx_configs) delete[]m_tx_configs;
2045     if(m_rx_configs) delete[]m_rx_configs;
2046 }
2047
2048 bool
2049 EAP::StreamConfig::read(enum eRegBase base, unsigned offset)
2050 {
2051     if(!m_eap.readRegBlock(base, offset, &m_nb_tx, 4)) {
2052         debugError("Failed to read number of tx entries\n");
2053         return false;
2054     }
2055     if(!m_eap.readRegBlock(base, offset+4, &m_nb_rx, 4)) {
2056         debugError("Failed to read number of rx entries\n");
2057         return false;
2058     }
2059     debugOutput(DEBUG_LEVEL_VERBOSE, " Entries: TX: %u, RX: %u\n", m_nb_tx, m_nb_rx);
2060
2061     if(m_tx_configs) {
2062         delete[]m_tx_configs;
2063         m_tx_configs = NULL;
2064     }
2065     if(m_rx_configs) {
2066         delete[]m_rx_configs;
2067         m_rx_configs = NULL;
2068     }
2069    
2070     offset += 8;
2071     if(m_nb_tx > 0) {
2072         m_tx_configs = new struct ConfigBlock[m_nb_tx];
2073         for(unsigned int i=0; i<m_nb_tx; i++) {
2074             fb_quadlet_t *ptr = reinterpret_cast<fb_quadlet_t *>(&(m_tx_configs[i]));
2075             if(!m_eap.readRegBlock(base, offset, ptr, sizeof(struct ConfigBlock))) {
2076                 debugError("Failed to read tx entry %d\n", i);
2077                 return false;
2078             }
2079             offset += sizeof(struct ConfigBlock);
2080         }
2081     }
2082
2083     if(m_nb_rx > 0) {
2084         m_rx_configs = new struct ConfigBlock[m_nb_rx];
2085         for(unsigned int i=0; i<m_nb_rx; i++) {
2086             fb_quadlet_t *ptr = reinterpret_cast<fb_quadlet_t *>(&(m_rx_configs[i]));
2087             if(!m_eap.readRegBlock(base, offset, ptr, sizeof(struct ConfigBlock))) {
2088                 debugError("Failed to read rx entry %d\n", i);
2089                 return false;
2090             }
2091             offset += sizeof(struct ConfigBlock);
2092         }
2093     }
2094     return true;
2095 }
2096
2097 bool
2098 EAP::StreamConfig::write(enum eRegBase base, unsigned offset)
2099 {
2100     if(!m_eap.writeRegBlock(base, offset, &m_nb_tx, 4)) {
2101         debugError("Failed to write number of tx entries\n");
2102         return false;
2103     }
2104     if(!m_eap.writeRegBlock(base, offset+4, &m_nb_rx, 4)) {
2105         debugError("Failed to write number of rx entries\n");
2106         return false;
2107     }
2108
2109     offset += 8;
2110     for(unsigned int i=0; i<m_nb_tx; i++) {
2111         fb_quadlet_t *ptr = reinterpret_cast<fb_quadlet_t *>(&(m_tx_configs[i]));
2112         if(!m_eap.writeRegBlock(base, offset, ptr, sizeof(struct ConfigBlock))) {
2113             debugError("Failed to write tx entry %d\n", i);
2114             return false;
2115         }
2116         offset += sizeof(struct ConfigBlock);
2117     }
2118
2119     for(unsigned int i=0; i<m_nb_rx; i++) {
2120         fb_quadlet_t *ptr = reinterpret_cast<fb_quadlet_t *>(&(m_rx_configs[i]));
2121         if(!m_eap.writeRegBlock(base, offset, ptr, sizeof(struct ConfigBlock))) {
2122             debugError("Failed to write rx entry %d\n", i);
2123             return false;
2124         }
2125         offset += sizeof(struct ConfigBlock);
2126     }
2127     return true;
2128 }
2129
2130 stringlist
2131 EAP::StreamConfig::getNamesForBlock(struct ConfigBlock &b)
2132 {
2133     stringlist names;
2134     char namestring[DICE_EAP_CHANNEL_CONFIG_NAMESTR_LEN_BYTES+1];
2135
2136     memcpy(namestring, b.names, DICE_EAP_CHANNEL_CONFIG_NAMESTR_LEN_BYTES);
2137
2138     // Strings from the device are always little-endian,
2139     // so byteswap for big-endian machines
2140     #if __BYTE_ORDER == __BIG_ENDIAN
2141     byteSwapBlock((quadlet_t *)namestring, DICE_EAP_CHANNEL_CONFIG_NAMESTR_LEN_QUADS);
2142     #endif
2143
2144     namestring[DICE_EAP_CHANNEL_CONFIG_NAMESTR_LEN_BYTES]='\0';
2145     return m_eap.m_device.splitNameString(std::string(namestring));
2146 }
2147
2148 stringlist
2149 EAP::StreamConfig::getTxNamesString(unsigned int i)
2150 {
2151     return getNamesForBlock(m_tx_configs[i]);
2152 }
2153
2154 stringlist
2155 EAP::StreamConfig::getRxNamesString(unsigned int i)
2156 {
2157     return getNamesForBlock(m_rx_configs[i]);
2158 }
2159
2160 void
2161 EAP::StreamConfig::showConfigBlock(struct ConfigBlock &b)
2162 {
2163     printMessage(" Channel count : %u audio, %u midi\n", b.nb_audio, b.nb_midi);
2164     printMessage(" AC3 Map       : 0x%08X\n", b.ac3_map);
2165     stringlist channel_names  = getNamesForBlock(b);
2166     printMessage("  Channel names :\n");
2167     for ( stringlist::iterator it = channel_names.begin();
2168         it != channel_names.end();
2169         ++it )
2170     {
2171         printMessage("     %s\n", (*it).c_str());
2172     }
2173 }
2174
2175 void
2176 EAP::StreamConfig::show()
2177 {
2178     for(unsigned int i=0; i<m_nb_tx; i++) {
2179         printMessage("TX Config block %d\n", i);
2180         showConfigBlock(m_tx_configs[i]);
2181     }
2182     for(unsigned int i=0; i<m_nb_rx; i++) {
2183         printMessage("RX Config block %d\n", i);
2184         showConfigBlock(m_rx_configs[i]);
2185     }
2186 }
2187
2188 //
2189 // ----------- standalone config -------------
2190 //
2191
2192 bool
2193 EAP::StandaloneConfig::read(enum eRegBase base, unsigned offset)
2194 {
2195     uint32_t tmp_entries[m_eap.m_standalone_size / sizeof(uint32_t)];
2196
2197     if(!m_eap.readRegBlock(base, offset, tmp_entries, m_eap.m_standalone_size)) {
2198         debugError("Failed to read standalone configuration\n");
2199         return false;
2200     }
2201
2202     m_clk_src = tmp_entries[0];
2203     m_aes_ext = tmp_entries[1];
2204     m_adat_ext = tmp_entries[2];
2205     m_wc_ext = tmp_entries[3];
2206     m_int_ext = tmp_entries[4];
2207
2208     return true;
2209 }
2210
2211 bool
2212 EAP::StandaloneConfig::write(enum eRegBase b, unsigned offset)
2213 {
2214     return false;
2215 }
2216
2217 void
2218 EAP::StandaloneConfig::show()
2219 {
2220     printMessage("Standalone configuration:\n");
2221     read();
2222     printMessage("  Clock source: %08X\n", m_clk_src);
2223     printMessage("  AES EXT:  %08X\n", m_aes_ext);
2224     printMessage("  ADAT EXT: %08X\n", m_adat_ext);
2225     printMessage("  WC EXT:   %08X\n", m_wc_ext);
2226     printMessage("  INT EXT:  %08X\n", m_int_ext);
2227 }
2228
2229 } // namespace Dice
2230
2231
2232 // vim: et
Note: See TracBrowser for help on using the browser.