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

Revision 2096, 19.7 kB (checked in by adi, 11 years ago)

DICE-EAP Mute rather than remove route when disabling a destination

By Philippe Carriere:

Really removing a route is not fully supported by all devices; then
muting is preferable when one just want to set a different connection
state (as part of a modification of one source for another one for a
given destination).

A getMuteId() function is introduced so as to be easily customized for
specific devices, if necessary.

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 #ifndef __DICE_EAP_H
24 #define __DICE_EAP_H
25
26 #include "dice_avdevice.h"
27
28 #define DICE_EAP_BASE                  0x0000000000200000ULL
29 #define DICE_EAP_MAX_SIZE              0x0000000000F00000ULL
30
31 #define DICE_EAP_CAPABILITY_SPACE_OFF      0x0000
32 #define DICE_EAP_CAPABILITY_SPACE_SZ       0x0004
33 #define DICE_EAP_CMD_SPACE_OFF             0x0008
34 #define DICE_EAP_CMD_SPACE_SZ              0x000C
35 #define DICE_EAP_MIXER_SPACE_OFF           0x0010
36 #define DICE_EAP_MIXER_SPACE_SZ            0x0014
37 #define DICE_EAP_PEAK_SPACE_OFF            0x0018
38 #define DICE_EAP_PEAK_SPACE_SZ             0x001C
39 #define DICE_EAP_NEW_ROUTING_SPACE_OFF     0x0020
40 #define DICE_EAP_NEW_ROUTING_SPACE_SZ      0x0024
41 #define DICE_EAP_NEW_STREAM_CFG_SPACE_OFF  0x0028
42 #define DICE_EAP_NEW_STREAM_CFG_SPACE_SZ   0x002C
43 #define DICE_EAP_CURR_CFG_SPACE_OFF        0x0030
44 #define DICE_EAP_CURR_CFG_SPACE_SZ         0x0034
45 #define DICE_EAP_STAND_ALONE_CFG_SPACE_OFF 0x0038
46 #define DICE_EAP_STAND_ALONE_CFG_SPACE_SZ  0x003C
47 #define DICE_EAP_APP_SPACE_OFF             0x0040
48 #define DICE_EAP_APP_SPACE_SZ              0x0044
49 #define DICE_EAP_ZERO_MARKER_1             0x0048
50
51 // CAPABILITY registers
52 #define DICE_EAP_CAPABILITY_ROUTER         0x0000
53 #define DICE_EAP_CAPABILITY_MIXER          0x0004
54 #define DICE_EAP_CAPABILITY_GENERAL        0x0008
55 #define DICE_EAP_CAPABILITY_RESERVED       0x000C
56
57 // CAPABILITY bit definitions
58 #define DICE_EAP_CAP_ROUTER_EXPOSED         0
59 #define DICE_EAP_CAP_ROUTER_READONLY        1
60 #define DICE_EAP_CAP_ROUTER_FLASHSTORED     2
61 #define DICE_EAP_CAP_ROUTER_MAXROUTES      16
62
63 #define DICE_EAP_CAP_MIXER_EXPOSED          0
64 #define DICE_EAP_CAP_MIXER_READONLY         1
65 #define DICE_EAP_CAP_MIXER_FLASHSTORED      2
66 #define DICE_EAP_CAP_MIXER_IN_DEV           4
67 #define DICE_EAP_CAP_MIXER_OUT_DEV          8
68 #define DICE_EAP_CAP_MIXER_INPUTS          16
69 #define DICE_EAP_CAP_MIXER_OUTPUTS         24
70
71 #define DICE_EAP_CAP_GENERAL_STRM_CFG_EN    0
72 #define DICE_EAP_CAP_GENERAL_FLASH_EN       1
73 #define DICE_EAP_CAP_GENERAL_PEAK_EN        2
74 #define DICE_EAP_CAP_GENERAL_MAX_TX_STREAM  4
75 #define DICE_EAP_CAP_GENERAL_MAX_RX_STREAM  8
76 #define DICE_EAP_CAP_GENERAL_STRM_CFG_FLS  12
77 #define DICE_EAP_CAP_GENERAL_CHIP          16
78
79 #define DICE_EAP_CAP_GENERAL_CHIP_DICEII    0
80 #define DICE_EAP_CAP_GENERAL_CHIP_DICEMINI  1
81 #define DICE_EAP_CAP_GENERAL_CHIP_DICEJR    2
82
83 // COMMAND registers
84 #define DICE_EAP_COMMAND_OPCODE         0x0000
85 #define DICE_EAP_COMMAND_RETVAL         0x0004
86
87 // opcodes
88 #define DICE_EAP_CMD_OPCODE_NO_OP            0x0000
89 #define DICE_EAP_CMD_OPCODE_LD_ROUTER        0x0001
90 #define DICE_EAP_CMD_OPCODE_LD_STRM_CFG      0x0002
91 #define DICE_EAP_CMD_OPCODE_LD_RTR_STRM_CFG  0x0003
92 #define DICE_EAP_CMD_OPCODE_LD_FLASH_CFG     0x0004
93 #define DICE_EAP_CMD_OPCODE_ST_FLASH_CFG     0x0005
94
95 #define DICE_EAP_CMD_OPCODE_FLAG_LD_LOW      (1U<<16)
96 #define DICE_EAP_CMD_OPCODE_FLAG_LD_MID      (1U<<17)
97 #define DICE_EAP_CMD_OPCODE_FLAG_LD_HIGH     (1U<<18)
98 #define DICE_EAP_CMD_OPCODE_FLAG_LD_EXECUTE  (1U<<31)
99
100
101 // MIXER registers
102 // TODO
103
104 // PEAK registers
105 // TODO
106
107 // NEW ROUTER registers
108 // TODO
109
110 // NEW STREAM CFG registers
111 // TODO
112
113 // CURRENT CFG registers
114 #define DICE_EAP_CURRCFG_LOW_ROUTER         0x0000
115 #define DICE_EAP_CURRCFG_LOW_STREAM         0x1000
116 #define DICE_EAP_CURRCFG_MID_ROUTER         0x2000
117 #define DICE_EAP_CURRCFG_MID_STREAM         0x3000
118 #define DICE_EAP_CURRCFG_HIGH_ROUTER        0x4000
119 #define DICE_EAP_CURRCFG_HIGH_STREAM        0x5000
120
121 #define DICE_EAP_CHANNEL_CONFIG_NAMESTR_LEN_QUADS  (64)
122 #define DICE_EAP_CHANNEL_CONFIG_NAMESTR_LEN_BYTES  (4*DICE_EAP_CHANNEL_CONFIG_NAMESTR_LEN_QUADS)
123
124 namespace Dice {
125
126 /**
127   @brief Sources for audio hitting the router
128   */
129 enum eRouteSource {
130     eRS_AES = 0,
131     eRS_ADAT = 1,
132     eRS_Mixer = 2,
133     eRS_InS0 = 4,
134     eRS_InS1 = 5,
135     eRS_ARM = 10,
136     eRS_ARX0 = 11,
137     eRS_ARX1 = 12,
138     eRS_Muted = 15,
139     eRS_Invalid = 16,
140 };
141 /**
142   @brief Destinations for audio exiting the router
143   */
144 enum eRouteDestination {
145     eRD_AES = 0,
146     eRD_ADAT = 1,
147     eRD_Mixer0 = 2,
148     eRD_Mixer1 = 3,
149     eRD_InS0 = 4,
150     eRD_InS1 = 5,
151     eRD_ARM = 10,
152     eRD_ATX0 = 11,
153     eRD_ATX1 = 12,
154     eRD_Muted = 15,
155     eRD_Invalid = 16,
156 };
157
158 /**
159   @brief represents the EAP interface available on some devices
160
161   When available, the mixer and router are visible. This class is also the base for custom
162   implementations of EAP extensions.
163   */
164 class EAP : public Control::Container
165 {
166 public:
167     /**
168       @brief Command status
169       */
170     enum eWaitReturn {
171         eWR_Error,
172         eWR_Timeout,
173         eWR_Busy,
174         eWR_Done,
175     };
176     /**
177       @brief Constants for the EAP spaces
178
179       @see offsetGen for the calculation of the real offsets.
180       */
181     enum eRegBase {
182         eRT_Base,
183         eRT_Capability,
184         eRT_Command,
185         eRT_Mixer,
186         eRT_Peak,
187         eRT_NewRouting,
188         eRT_NewStreamCfg,
189         eRT_CurrentCfg,
190         eRT_Standalone,
191         eRT_Application,
192         eRT_None,
193     };
194
195 private:
196
197     /**
198       @brief Description of the routing in the hardware
199       */
200     class RouterConfig {
201     private:
202         friend class Dice::EAP;
203         RouterConfig(EAP &);
204         RouterConfig(EAP &, enum eRegBase, unsigned int offset);
205         ~RouterConfig();
206
207     public:
208
209         bool read() {return read(m_base, m_offset);};
210         bool write() {return write(m_base, m_offset);};
211         bool read(enum eRegBase b, unsigned offset);
212         bool write(enum eRegBase b, unsigned offset);
213         void show();
214
215         /**
216           @brief Set up a route between src and dest
217
218           If a route with that destination exists, it will be replaced. If no route to that
219           destination exists, a new route will be established.
220           */
221         bool setupRoute(unsigned char src, unsigned char dest);
222
223         /**
224           @brief Mute a route for dest
225
226           All EAP devices will support muting.
227           Not all of them support (at least full support) removing a dest (see comment below)
228           */
229         bool muteRoute(unsigned char dest);
230
231         /**
232           @brief Remove a route
233
234           @todo is this really necessary?
235           */
236         bool removeRoute(unsigned char src, unsigned char dest);
237         /**
238           @brief Remove the destinations route
239           */
240         bool removeRoute(unsigned char dest);
241
242         /**
243           @brief Return the source for the given destination
244
245           Returns -1 if the destination is not connected.
246           */
247         unsigned char getSourceForDestination(unsigned char dest);
248         /**
249           @brief Return a list of destinations for a given source
250
251           Returns an empty list if no destination is connected to this source.
252           */
253         std::vector<unsigned char> getDestinationsForSource(unsigned char src);
254
255         unsigned int getNbRoutes() {return m_routes2.size();};
256
257     private:
258         EAP &m_eap;
259         enum eRegBase m_base;
260         unsigned int m_offset;
261
262         /**
263           @brief map for the routes
264
265           The key is the destination as each destination can only have audio from one source.
266           Sources can be routed to several destinations though.
267           */
268 //        typedef std::map<unsigned char,unsigned char> RouteVectorV2;
269         typedef std::vector< std::pair<unsigned char,unsigned char> > RouteVectorV2;
270         RouteVectorV2 m_routes2;
271     private:
272         DECLARE_DEBUG_MODULE_REFERENCE;
273     };
274
275     /**
276       @brief Description of the peak space in hardware
277       */
278     class PeakSpace {
279     private:
280         friend class Dice::EAP;
281         PeakSpace(EAP &p) : m_eap(p), m_base(eRT_Peak), m_offset(0), m_debugModule(p.m_debugModule) {};
282         ~PeakSpace() {};
283
284     public:
285         bool read() {return read(m_base, m_offset);};
286         bool read(enum eRegBase b, unsigned offset);
287         void show();
288
289         std::map<unsigned char, int> getPeaks();
290         int getPeak(unsigned char dest);
291
292     private:
293         EAP &m_eap;
294         enum eRegBase m_base;
295         unsigned int m_offset;
296
297         /**
298           @brief maps peaks to destinations
299           */
300         std::map<unsigned char, int> m_peaks;
301
302         DECLARE_DEBUG_MODULE_REFERENCE;
303     };
304
305     /**
306       @brief Description of the streams in the hardware
307       */
308     class StreamConfig {
309     private:
310         friend class Dice::EAP;
311         StreamConfig(EAP &, enum eRegBase, unsigned int offset);
312         ~StreamConfig();
313
314     public:
315         struct ConfigBlock { // FIXME: somewhere in the DICE avdevice this is present too
316             uint32_t nb_audio;
317             uint32_t nb_midi;
318             uint32_t names[DICE_EAP_CHANNEL_CONFIG_NAMESTR_LEN_QUADS];
319             uint32_t ac3_map;
320         };
321         void showConfigBlock(struct ConfigBlock &);
322         stringlist getNamesForBlock(struct ConfigBlock &b);
323         stringlist getTxNamesString(unsigned int);
324         stringlist getRxNamesString(unsigned int);
325
326         bool read() {return read(m_base, m_offset);};
327         bool write() {return write(m_base, m_offset);};
328         bool read(enum eRegBase b, unsigned offset);
329         bool write(enum eRegBase b, unsigned offset);
330
331         void show();
332
333     private:
334         EAP &m_eap;
335         enum eRegBase m_base;
336         unsigned int m_offset;
337
338         uint32_t m_nb_tx;
339         uint32_t m_nb_rx;
340
341         struct ConfigBlock *m_tx_configs;
342         struct ConfigBlock *m_rx_configs;
343
344         DECLARE_DEBUG_MODULE_REFERENCE;
345     };
346
347 public:
348
349     /**
350       @brief The matrixmixer exposed
351       */
352     class Mixer : public Control::MatrixMixer {
353     public:
354         Mixer(EAP &);
355         ~Mixer();
356
357         bool init();
358         void show();
359
360         void updateNameCache();
361         /**
362          * load the coefficients from the device into the local cache
363          * @return
364          */
365         bool loadCoefficients();
366         /**
367          * Stores the coefficients from the cache to the device
368          * @return
369          */
370         bool storeCoefficients();
371
372         virtual int getRowCount( );
373         virtual int getColCount( );
374
375         virtual int canWrite( const int, const int );
376         virtual double setValue( const int, const int, const double );
377         virtual double getValue( const int, const int );
378
379         //
380         bool hasNames() const { return false; }
381         std::string getRowName( const int );
382         std::string getColName( const int );
383
384         // TODO: implement connections.
385         bool canConnect() const { return false; }
386
387         // full map updates are unsupported
388         virtual bool getCoefficientMap(int &);
389         virtual bool storeCoefficientMap(int &);
390
391     private:
392         EAP &         m_eap;
393         fb_quadlet_t *m_coeff;
394
395         //std::map<int, RouterConfig::Route> m_input_route_map;
396         //std::map<int, RouterConfig::RouteVector> m_output_route_map;
397
398         DECLARE_DEBUG_MODULE_REFERENCE;
399     };
400
401     /**
402       @brief The router exposed
403       */
404     class Router : public Control::CrossbarRouter {
405     public:
406         Router(EAP &);
407         ~Router();
408
409         void update();
410         void show();
411
412         void addDestination(const std::string& name, enum eRouteDestination dstid,
413                             unsigned int base, unsigned int cnt, unsigned int offset=0);
414         void addSource(const std::string& name, enum eRouteSource srcid,
415                        unsigned int base, unsigned int cnt, unsigned int offset=0);
416
417         // per-coefficient access
418         virtual std::string getSourceName(const int);
419         virtual std::string getDestinationName(const int);
420         virtual int getSourceIndex(std::string);
421         virtual int getDestinationIndex(std::string);
422         virtual stringlist getSourceNames();
423         virtual stringlist getDestinationNames();
424
425         std::string getSourceForDestination(const std::string& dstname);
426         stringlist getDestinationsForSource(const std::string& srcname);
427
428         virtual bool canConnect(const int srcidx, const int dstidx);
429         virtual bool setConnectionState(const int srcidx, const int dstidx, const bool enable);
430         virtual bool getConnectionState(const int srcidx, const int dstidx);
431
432         virtual bool canConnect(const std::string& srcname, const std::string& dstname);
433         virtual bool setConnectionState(const std::string& srcname, const std::string& dstname, const bool enable);
434         virtual bool getConnectionState(const std::string& srcname, const std::string& dstname);
435
436         virtual bool clearAllConnections();
437
438         // peak metering support
439         virtual bool hasPeakMetering();
440         virtual double getPeakValue(const std::string& dest);
441         virtual std::map<std::string, double> getPeakValues();
442
443     private:
444         EAP &m_eap;
445         /**
446           @{
447           @brief Name-Index pairs for the sources and destinations
448
449           The index is 'artificial' and is the block/channel combination used in the dice.
450           */
451         std::map<std::string, int> m_sources;
452         std::map<std::string, int> m_destinations;
453         // @}
454
455         PeakSpace &m_peak;
456
457         DECLARE_DEBUG_MODULE_REFERENCE;
458     };
459
460 public:
461     /** constructor */
462     EAP(Device &);
463     /** destructor */
464     virtual ~EAP();
465
466     /**
467       @brief Does this device support the EAP?
468
469       When subclassing EAP, return true only on devices that actually have an EAP.
470
471       @todo Shouldn't this be inside Dice::Device?
472       */
473     static bool supportsEAP(Device &);
474
475     /**
476       @brief Initialize the EAP
477       */
478     bool init();
479
480     /// update EAP
481     void update();
482
483     /// Show information about the EAP
484     void show();
485     /// Dump the first parts of the application space
486     void showApplication();
487     /// Show the full router content
488     void showFullRouter();
489     /// Show the full peak space content
490     void showFullPeakSpace();
491
492     /// Restore from flash
493     bool loadFlashConfig();
494     /// Store to flash
495     bool storeFlashConfig();
496
497     /// Is the current operation still busy?
498     enum eWaitReturn operationBusy();
499     /// Block until the current operation is done
500     enum eWaitReturn waitForOperationEnd(int max_wait_time_ms = 100);
501
502     /// Update all configurations from the device
503     bool updateConfigurationCache();
504
505     /**
506       @{
507       @brief Read and write registers on the device
508       */
509     bool readReg(enum eRegBase, unsigned offset, quadlet_t *);
510     bool writeReg(enum eRegBase, unsigned offset, quadlet_t);
511     bool readRegBlock(enum eRegBase, unsigned, fb_quadlet_t *, size_t);
512     bool writeRegBlock(enum eRegBase, unsigned, fb_quadlet_t *, size_t);
513     bool readRegBlockSwapped(enum eRegBase, unsigned, fb_quadlet_t *, size_t);
514     bool writeRegBlockSwapped(enum eRegBase, unsigned, fb_quadlet_t *, size_t);
515     //@}
516
517     /** @brief Get access to the mixer */
518     Mixer*  getMixer() {return m_mixer;};
519     /** @brief Get access to the router */
520     Router* getRouter() {return m_router;};
521
522     /** @brief Get capture and playback names */
523     stringlist getCptrNameString(unsigned int);
524     stringlist getPbckNameString(unsigned int);
525
526 protected:
527     /**
528       @brief Setup all the available sources
529
530       This adds the needed entries for sources to the router. The default implementation decides on
531       the chip which sources to add, subclasses should only add the sources actually usable for the
532       device.
533
534       To ease custom device support, this function is not in EAP::Router but here.
535       */
536     void setupSources();
537     virtual void setupSources_low();
538     virtual void setupSources_mid();
539     virtual void setupSources_high();
540     virtual unsigned int getSMuteId();
541     /**
542       @brief Setup all the available destinations
543
544       This adds the needed entries for destinations to the router. The default implementation
545       decides on the chip which destinations to add, subclasses should only add the destinations
546       actually usable for the device.
547
548       To ease custom device support, this function is not in EAP::Router but here.
549       */
550     void setupDestinations();
551     virtual void setupDestinations_low();
552     virtual void setupDestinations_mid();
553     virtual void setupDestinations_high();
554
555     /**
556       @brief Actually add the source
557       */
558     void addSource(const std::string name, unsigned int base, unsigned int count,
559                    enum eRouteSource srcid, unsigned int offset=0);
560     /**
561       @brief Actually add the destination
562       */
563     void addDestination(const std::string name, unsigned int base, unsigned int count,
564                         enum eRouteDestination destid, unsigned int offset=0);
565
566     uint16_t getMaxNbRouterEntries() {return m_router_nb_entries;};
567
568 private:
569     /// Return the router configuration for the current rate
570     RouterConfig * getActiveRouterConfig();
571     /// Return the stream configuration for the current rate
572     StreamConfig * getActiveStreamConfig();
573
574     /// Write a new router configuration to the device
575     bool updateRouterConfig(RouterConfig&, bool low, bool mid, bool high);
576     /// Write a new router configuration to the device
577     bool updateCurrentRouterConfig(RouterConfig&);
578     /// Write a new stream configuration to the device
579     bool updateStreamConfig(StreamConfig&, bool low, bool mid, bool high);
580     /// Write a new stream configuration to the device
581     bool updateStreamConfig(RouterConfig&, StreamConfig&, bool low, bool mid, bool high);
582
583     bool loadRouterConfig(bool low, bool mid, bool high);
584     bool loadStreamConfig(bool low, bool mid, bool high);
585     bool loadRouterAndStreamConfig(bool low, bool mid, bool high);
586
587 private:
588     bool     m_router_exposed;
589     bool     m_router_readonly;
590     bool     m_router_flashstored;
591     uint16_t m_router_nb_entries;
592
593     bool     m_mixer_exposed;
594     bool     m_mixer_readonly;
595     bool     m_mixer_flashstored;
596     uint8_t  m_mixer_tx_id;
597     uint8_t  m_mixer_rx_id;
598     uint8_t  m_mixer_nb_tx;
599     uint8_t  m_mixer_nb_rx;
600
601     bool     m_general_support_dynstream;
602     bool     m_general_support_flash;
603     bool     m_general_peak_enabled;
604     uint8_t  m_general_max_tx;
605     uint8_t  m_general_max_rx;
606     bool     m_general_stream_cfg_stored;
607     uint16_t m_general_chip;
608
609     bool commandHelper(fb_quadlet_t cmd);
610
611     /// Calculate the real offset for the different spaces
612     fb_nodeaddr_t offsetGen(enum eRegBase, unsigned, size_t);
613
614 private:
615     Device & m_device;
616     Mixer*   m_mixer;
617     Router*  m_router;
618     RouterConfig m_current_cfg_routing_low;
619     RouterConfig m_current_cfg_routing_mid;
620     RouterConfig m_current_cfg_routing_high;
621     StreamConfig m_current_cfg_stream_low;
622     StreamConfig m_current_cfg_stream_mid;
623     StreamConfig m_current_cfg_stream_high;
624
625     fb_quadlet_t m_capability_offset;
626     fb_quadlet_t m_capability_size;
627     fb_quadlet_t m_cmd_offset;
628     fb_quadlet_t m_cmd_size;
629     fb_quadlet_t m_mixer_offset;
630     fb_quadlet_t m_mixer_size;
631     fb_quadlet_t m_peak_offset;
632     fb_quadlet_t m_peak_size;
633     fb_quadlet_t m_new_routing_offset;
634     fb_quadlet_t m_new_routing_size;
635     fb_quadlet_t m_new_stream_cfg_offset;
636     fb_quadlet_t m_new_stream_cfg_size;
637     fb_quadlet_t m_curr_cfg_offset;
638     fb_quadlet_t m_curr_cfg_size;
639     fb_quadlet_t m_standalone_offset;
640     fb_quadlet_t m_standalone_size;
641     fb_quadlet_t m_app_offset;
642     fb_quadlet_t m_app_size;
643
644 protected:
645     DECLARE_DEBUG_MODULE;
646 };
647
648 };
649
650 #endif // __DICE_EAP_H
Note: See TracBrowser for help on using the browser.