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

Revision 2730, 28.4 kB (checked in by jwoithe, 7 months ago)

RME: fix output fader array overflow.

Human readable output fader volumes are stored in the device setting's
output_faders array. The RME hardware flash interface requires derived
values, which are generated and stored in a separate buffer when needed.
This buffer has 32 elements. The last two elements are not fader values,
but a flag to indicate that MIDI is active (element 30) and a submix number
(element 31). It is suspected that these are for the convience of computer
software and are not used by the RME hardware. FFADO does not make use of
either element. As a result, only 30 fader values were copied between the
flash buffer and the output_faders array. However, this creates a buffer
overflow in the output_faders array, since this is defined to have
RME_FF800_MAX_CHANNELS elements, and RME_FF800_MAX_CHANNELS is 28.

The fix is to use the local "nch" variable as the upper bound on the value
conversion loop rather than a fixed value of 30. Unused flash buffer
elements will be unread or unwritten, which is acceptable since the relevant
flash buffer and fader arrays are always zeroed before use.

This issue was flagged by a QA warning in Gentoo and reported to the
ffado-devel mailing list by Hector Martin, along with the suggested fix.

Line 
1 /*
2  * Copyright (C) 2009-2013 by Jonathan Woithe
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 /* This file implements the flash memory methods of the Device object */
25
26 #include <unistd.h>
27 #include <math.h>
28 #include "rme/rme_avdevice.h"
29 #include "rme/fireface_def.h"
30
31 #include "debugmodule/debugmodule.h"
32
33 #define MAX_FLASH_BUSY_RETRIES    25
34
35 namespace Rme {
36
37 signed int
38 Device::wait_while_busy(unsigned int init_delay_ms)
39 {
40     signed int i;
41     quadlet_t status;
42
43     // Wait for the device to become available for a new command.  A delay
44     // of init_delay_ms is executed prior to each test of the device status.
45     for (i=0; i<MAX_FLASH_BUSY_RETRIES; i++) {
46         usleep(init_delay_ms*1000);
47         if (m_rme_model == RME_MODEL_FIREFACE400) {
48             status = readRegister(RME_FF400_FLASH_STAT_REG);
49             if (status == 0)
50                 break;
51         } else
52         if (m_rme_model == RME_MODEL_FIREFACE800) {
53             status = readRegister(RME_FF_STATUS_REG1);
54             if (status & 0x40000000)
55                 break;
56         } else {
57             debugOutput(DEBUG_LEVEL_ERROR, "unimplemented model %d\n", m_rme_model);
58             return -1;
59         }
60     }
61
62     if (i == MAX_FLASH_BUSY_RETRIES)
63         return -1;
64     return 0;
65 }
66
67 signed int
68 Device::get_revision(unsigned int *revision)
69 {
70     signed int err = 0;
71
72     if (m_rme_model == RME_MODEL_FIREFACE800) {
73         *revision = readRegister(RME_FF800_REVISION_REG);
74         return 0;
75     }
76
77     err = writeRegister(RME_FF400_FLASH_CMD_REG, RME_FF400_FLASH_CMD_GET_REVISION);
78     err |= wait_while_busy(2);
79     if (!err)
80       *revision = readRegister(RME_FF400_FLASH_READ_BUFFER);
81
82     return err?-1:0;
83 }
84
85 signed int
86 Device::read_flash(fb_nodeaddr_t addr, quadlet_t *buf, unsigned int n_quads)
87 {
88     // Read "n_quads" quadlets from the Fireface Flash starting at address
89     // addr.  The result is written to "buf" which is assumed big enough to
90     // hold the result.  Return 0 on success, -1 on error.  The caller must ensure
91     // that the flash source address makes sense for the device in use.
92
93     unsigned int xfer_size;
94     unsigned int err = 0;
95     quadlet_t block_desc[2];
96     quadlet_t ff400_addr = (addr & 0xffffffff);
97
98     if (m_rme_model == RME_MODEL_FIREFACE800) {
99         do {
100             xfer_size = (n_quads > RME_FF_FLASH_SECTOR_SIZE_QUADS)?RME_FF_FLASH_SECTOR_SIZE_QUADS:n_quads;
101             err |= readBlock(addr, buf, xfer_size);
102             n_quads -= xfer_size;
103             buf += xfer_size;
104             addr += xfer_size*sizeof(quadlet_t);
105         } while (n_quads>0 && !err);
106     } else {
107         // FF400 case follows
108         do {
109             xfer_size = (n_quads > 32)?32:n_quads;
110             block_desc[0] = ff400_addr;
111             block_desc[1] = xfer_size * sizeof(quadlet_t);
112             // Program the read address and size
113             err |= writeBlock(RME_FF400_FLASH_BLOCK_ADDR_REG, block_desc, 2);
114             // Execute the read and wait for its completion
115             err |= writeRegister(RME_FF400_FLASH_CMD_REG, RME_FF400_FLASH_CMD_READ);
116            if (!err)
117                wait_while_busy(2);
118             // Read from bounce buffer into final destination
119             err |= readBlock(RME_FF400_FLASH_READ_BUFFER, buf, xfer_size);
120
121             n_quads -= xfer_size;
122             ff400_addr += xfer_size*sizeof(quadlet_t);
123             buf += xfer_size;
124         } while (n_quads>0 && !err);
125     }
126
127     return err?-1:0;
128 }
129
130 signed int
131 Device::erase_flash(unsigned int flags)
132 {
133     // Erase the requested flash block.  "flags" should be one of the
134     // RME_FF_FLASH_ERASE_* flags.  Return 0 on success, -1 on error.
135
136     fb_nodeaddr_t addr;
137     quadlet_t data;
138     unsigned int err = 0;
139
140     if (m_rme_model == RME_MODEL_FIREFACE800) {
141         switch (flags) {
142             case RME_FF_FLASH_ERASE_VOLUME:
143                 addr = RME_FF800_FLASH_ERASE_VOLUME_REG; break;
144             case RME_FF_FLASH_ERASE_SETTINGS:
145                 addr = RME_FF800_FLASH_ERASE_SETTINGS_REG; break;
146             case RME_FF_FLASH_ERASE_CONFIG:
147                 addr = RME_FF800_FLASH_ERASE_CONFIG_REG; break;
148             default:
149                 debugOutput(DEBUG_LEVEL_WARNING, "unknown flag %d\n", flags);
150                 return -1;
151         }
152         data = 0;
153     } else
154     if (m_rme_model == RME_MODEL_FIREFACE400) {
155         addr = RME_FF400_FLASH_CMD_REG;
156         switch (flags) {
157             case RME_FF_FLASH_ERASE_VOLUME:
158                 data = RME_FF400_FLASH_CMD_ERASE_VOLUME; break;
159             case RME_FF_FLASH_ERASE_SETTINGS:
160                 data = RME_FF400_FLASH_CMD_ERASE_SETTINGS; break;
161             case RME_FF_FLASH_ERASE_CONFIG:
162                 data = RME_FF400_FLASH_CMD_ERASE_CONFIG; break;
163             default:
164                 debugOutput(DEBUG_LEVEL_WARNING, "unknown flag %d\n", flags);
165                 return -1;
166         }
167     } else {
168         debugOutput(DEBUG_LEVEL_ERROR, "unimplemented model %d\n", m_rme_model);
169         return -1;
170     }
171
172     err |= writeRegister(addr, data);
173     if (!err) {
174         wait_while_busy(500);
175         // After the device is ready, wait a further 20 milliseconds.  The purpose
176         // of this is unclear.  Drivers from other OSes do it, so we should too.
177         usleep(20000);
178     }
179
180     return err?-1:0;
181 }
182
183 signed int
184 Device::write_flash(fb_nodeaddr_t addr, quadlet_t *buf, unsigned int n_quads)
185 {
186     // Write "n_quads" quadlets to the Fireface Flash starting at address
187     // addr.  Return 0 on success, -1 on error.  The caller must ensure the
188     // supplied address is appropriate for the device in use.
189
190     unsigned int xfer_size;
191     unsigned int err = 0;
192     quadlet_t block_desc[2];
193     quadlet_t ff400_addr = (addr & 0xffffffff);
194
195     if (m_rme_model == RME_MODEL_FIREFACE800) {
196         do {
197             xfer_size = (n_quads > RME_FF_FLASH_SECTOR_SIZE_QUADS)?RME_FF_FLASH_SECTOR_SIZE_QUADS:n_quads;
198             err |= writeBlock(addr, buf, xfer_size);
199             if (!err) {
200                 err = wait_while_busy(5) != 0;
201                 if (err)
202                     debugOutput(DEBUG_LEVEL_WARNING, "device still busy after flash write\n");
203             } else
204                 debugOutput(DEBUG_LEVEL_WARNING, "flash writeBlock() failed\n");
205             n_quads -= xfer_size;
206             buf += xfer_size;
207             addr += xfer_size*sizeof(quadlet_t);
208         } while (n_quads>0 && !err);
209         return err?-1:0;
210     }
211
212     // FF400 case follows
213     do {
214         xfer_size = (n_quads > 32)?32:n_quads;
215         // Send data to flash buffer
216         err |= writeBlock(RME_FF400_FLASH_WRITE_BUFFER, buf, xfer_size);
217         // Program the destination address and size
218         block_desc[0] = ff400_addr;
219         block_desc[1] = xfer_size * sizeof(quadlet_t);
220         err |= writeBlock(RME_FF400_FLASH_BLOCK_ADDR_REG, block_desc, 2);
221         // Execute the write and wait for its completion
222         err |= writeRegister(RME_FF400_FLASH_CMD_REG, RME_FF400_FLASH_CMD_WRITE);
223         if (!err)
224             wait_while_busy(2);
225
226         n_quads -= xfer_size;
227         ff400_addr += xfer_size*sizeof(quadlet_t);
228         buf += xfer_size;
229     } while (n_quads>0 && !err);
230
231     return err?-1:0;
232 }
233
234
235 signed int
236 Device::read_device_flash_settings(FF_software_settings_t *dsettings)
237 {
238     // Note: this function does NOT copy the newly read settings into
239     // the hardware registers even if reading into the device's master
240     // settings structure (ie: when dsettings is NULL).  If the settings
241     // read from flash are to be made active the caller must take
242     // care of this (by calling set_hardware_params() for instance).
243
244     if (dsettings == NULL)
245         dsettings = settings;
246
247     // Read the device's configuration flash RAM and use this to set up
248     // the given settings structure.
249
250     FF_device_flash_settings_t hw_settings;
251     signed int i, err = 0;
252     unsigned int rev;
253     long long int addr;
254     quadlet_t status_buf[4];
255
256     i = get_revision(&rev);
257     if (i != 0) {
258         debugOutput(DEBUG_LEVEL_WARNING, "Error reading hardware revision: %d\n", i);
259     } else {
260         debugOutput(DEBUG_LEVEL_VERBOSE, "Hardware revision: 0x%08x\n", rev);
261     }
262
263     // Read settings flash ram block
264     if (m_rme_model == RME_MODEL_FIREFACE800)
265         addr = RME_FF800_FLASH_SETTINGS_ADDR;
266     else
267     if (m_rme_model == RME_MODEL_FIREFACE400)
268         addr = RME_FF400_FLASH_SETTINGS_ADDR;
269     else {
270         debugOutput(DEBUG_LEVEL_ERROR, "unimplemented model %d\n", m_rme_model);
271         return -1;
272     }
273     err = read_flash(addr,
274             (quadlet_t *)&hw_settings, sizeof(hw_settings)/sizeof(uint32_t));
275
276     if (err != 0) {
277         debugOutput(DEBUG_LEVEL_WARNING, "Error reading device flash settings: %d\n", i);
278         return -1;
279     }
280
281     debugOutput(DEBUG_LEVEL_VERBOSE, "Device flash settings:\n");
282     if (hw_settings.clock_mode == FF_DEV_FLASH_INVALID) {
283         debugOutput(DEBUG_LEVEL_VERBOSE, "  Clock mode: not set in device flash\n");
284     } else {
285         debugOutput(DEBUG_LEVEL_VERBOSE, "  Clock mode: %s\n",
286           hw_settings.clock_mode==FF_DEV_FLASH_CLOCK_MODE_MASTER?"Master":"Slave");
287     }
288     if (hw_settings.sample_rate == FF_DEV_FLASH_INVALID) {
289         debugOutput(DEBUG_LEVEL_VERBOSE, "  Sample rate: not set in device flash\n");
290     } else
291     if (hw_settings.sample_rate == FF_DEV_FLASH_SRATE_DDS_INACTIVE) {
292         debugOutput(DEBUG_LEVEL_VERBOSE, "  Sample rate: DDS not active\n");
293     } else {
294         debugOutput(DEBUG_LEVEL_VERBOSE, "  Sample rate: %d Hz (DDS active)\n", hw_settings.sample_rate);
295     }
296
297     // Sanity check the "limit_bandwidth" setting since it has been observed
298     // to take on bogus values for some users.  The reason behind the
299     // unexpected values is currently unknown.  Note that limit_bandwidth is
300     // unsigned, so there's no need to check for values less than 0.
301     if (hw_settings.limit_bandwidth > FF_DEV_FLASH_BWLIMIT_ANALOG_ONLY) {
302         debugOutput(DEBUG_LEVEL_WARNING, "bogus firewire bandwidth limit flag 0x%08x reset to 0 (send all channels)\n",
303           hw_settings.limit_bandwidth);
304         hw_settings.limit_bandwidth = FF_DEV_FLASH_BWLIMIT_SEND_ALL_CHANNELS;
305     }
306
307     if (dsettings != NULL) {
308         memset(dsettings, 0, sizeof(*dsettings));
309         // Copy hardware details to the software settings structure as
310         // appropriate.
311         for (i=0; i<2; i++)
312             dsettings->mic_phantom[i] = hw_settings.mic_phantom[i];
313
314         if (m_rme_model == RME_MODEL_FIREFACE800) {
315             for (i=2; i<4; i++)
316                 dsettings->mic_phantom[i] = hw_settings.mic_phantom[i];
317         } else
318         if (m_rme_model == RME_MODEL_FIREFACE400) {
319             // TODO: confirm this is true
320             for (i=2; i<4; i++)
321                 dsettings->ff400_input_pad[i-2] = hw_settings.mic_phantom[i];
322         } else {
323             debugOutput(DEBUG_LEVEL_ERROR, "unimplemented model %d\n", m_rme_model);
324             return -1;
325         }
326
327         dsettings->spdif_input_mode = hw_settings.spdif_input_mode;
328         dsettings->spdif_output_emphasis = hw_settings.spdif_output_emphasis;
329         dsettings->spdif_output_pro = hw_settings.spdif_output_pro;
330         dsettings->spdif_output_nonaudio = hw_settings.spdif_output_nonaudio;
331         dsettings->spdif_output_mode = hw_settings.spdif_output_mode;
332         dsettings->clock_mode = hw_settings.clock_mode;
333         dsettings->sync_ref = hw_settings.sync_ref;
334         dsettings->tms = hw_settings.tms;
335         dsettings->limit_bandwidth = hw_settings.limit_bandwidth;
336         dsettings->stop_on_dropout = hw_settings.stop_on_dropout;
337         dsettings->input_level = hw_settings.input_level;
338         dsettings->output_level = hw_settings.output_level;
339         if (m_rme_model == RME_MODEL_FIREFACE800) {
340             dsettings->filter = hw_settings.filter;
341             dsettings->fuzz = hw_settings.fuzz;
342         } else
343         if (m_rme_model == RME_MODEL_FIREFACE400) {
344             // TODO: confirm this is true
345             dsettings->ff400_instr_input[0] = hw_settings.fuzz;
346             dsettings->ff400_instr_input[1] = hw_settings.filter;
347         }
348         dsettings->limiter = (hw_settings.p12db_an[0] == 0)?1:0;
349         dsettings->sample_rate = hw_settings.sample_rate;
350         dsettings->word_clock_single_speed = hw_settings.word_clock_single_speed;
351
352         // The FF800 has front/rear selectors for the "instrument" input
353         // (aka channel 1) and the two "mic" channels (aka channels 7 and 8).
354         // The FF400 does not.  The FF400 borrows the mic0 selector field
355         // in the flash configuration structure to use for the "phones"
356         // level which the FF800 doesn't have.
357         if (m_rme_model == RME_MODEL_FIREFACE400)
358             dsettings->phones_level = hw_settings.mic_plug_select[0];
359         else
360         if (m_rme_model == RME_MODEL_FIREFACE800) {
361             // The value for the front/rear selectors coming from the flash
362             // is an indexed value: 0=rear, 1=front, 2=front and rear.  By
363             // adding one to this we can treat input_opt as a bitmask with
364             // bit 0 being "rear" and bit 1 being "front".  This follows the
365             // approach used in drivers for other operating systems and
366             // simplifies certain logic expressions within the driver.
367             dsettings->input_opt[0] = hw_settings.instrument_plug_select + 1;
368             dsettings->input_opt[1] = hw_settings.mic_plug_select[0] + 1;
369             dsettings->input_opt[2] = hw_settings.mic_plug_select[1] + 1;
370         }
371
372         /* If debug is enabled, show what's been read from the flash */
373         debugOutput(DEBUG_LEVEL_VERBOSE, "Settings acquired from flash:\n");
374         if (m_rme_model == RME_MODEL_FIREFACE800) {
375             debugOutput(DEBUG_LEVEL_VERBOSE, "  Phantom: %d %d %d %d\n",
376                 dsettings->mic_phantom[0], dsettings->mic_phantom[1],
377                 dsettings->mic_phantom[2], dsettings->mic_phantom[2]);
378
379         } else
380         if (m_rme_model == RME_MODEL_FIREFACE400) {
381             debugOutput(DEBUG_LEVEL_VERBOSE, "  Phantom: %d %d\n",
382                 dsettings->mic_phantom[0], dsettings->mic_phantom[1]);
383             debugOutput(DEBUG_LEVEL_VERBOSE, "  Input pad: %d %d\n",
384                 dsettings->ff400_input_pad[0], dsettings->ff400_input_pad[1]);
385         }
386         debugOutput(DEBUG_LEVEL_VERBOSE, "  spdif input mode: %d\n", dsettings->spdif_input_mode);
387         debugOutput(DEBUG_LEVEL_VERBOSE, "  spdif output emphasis: %d\n", dsettings->spdif_output_emphasis);
388         debugOutput(DEBUG_LEVEL_VERBOSE, "  spdif output pro: %d\n", dsettings->spdif_output_pro);
389         debugOutput(DEBUG_LEVEL_VERBOSE, "  spdif output nonaudio: %d\n", dsettings->spdif_output_nonaudio);
390         debugOutput(DEBUG_LEVEL_VERBOSE, "  spdif output mode: %d\n", dsettings->spdif_output_mode);
391         debugOutput(DEBUG_LEVEL_VERBOSE, "  clock mode: %d\n", dsettings->clock_mode);
392         debugOutput(DEBUG_LEVEL_VERBOSE, "  sync ref: %d\n", dsettings->sync_ref);
393         debugOutput(DEBUG_LEVEL_VERBOSE, "  tms: %d\n", dsettings->tms);
394         debugOutput(DEBUG_LEVEL_VERBOSE, "  limit firewire bandwidth: %d\n", dsettings->limit_bandwidth);
395         debugOutput(DEBUG_LEVEL_VERBOSE, "  stop on dropout: %d\n", dsettings->stop_on_dropout);
396         debugOutput(DEBUG_LEVEL_VERBOSE, "  input level: %d\n", dsettings->input_level);
397         debugOutput(DEBUG_LEVEL_VERBOSE, "  output level: %d\n", dsettings->output_level);
398         if (m_rme_model == RME_MODEL_FIREFACE800) {
399             debugOutput(DEBUG_LEVEL_VERBOSE, "  filter: %d\n", dsettings->filter);
400             debugOutput(DEBUG_LEVEL_VERBOSE, "  fuzz: %d\n", dsettings->fuzz);
401         } else
402         if (m_rme_model == RME_MODEL_FIREFACE400) {
403             debugOutput(DEBUG_LEVEL_VERBOSE, "  instr input 0: %d\n", dsettings->ff400_instr_input[0]);
404             debugOutput(DEBUG_LEVEL_VERBOSE, "  instr input 1: %d\n", dsettings->ff400_instr_input[1]);
405         }
406         debugOutput(DEBUG_LEVEL_VERBOSE, "  limiter: %d\n", dsettings->limiter);
407         debugOutput(DEBUG_LEVEL_VERBOSE, "  sample rate: %d\n", dsettings->sample_rate);
408         debugOutput(DEBUG_LEVEL_VERBOSE, "  word clock single speed: %d\n", dsettings->word_clock_single_speed);
409         if (m_rme_model == RME_MODEL_FIREFACE400) {
410             debugOutput(DEBUG_LEVEL_VERBOSE, "  phones level: %d\n", dsettings->phones_level);
411         } else
412         if (m_rme_model == RME_MODEL_FIREFACE800) {
413             debugOutput(DEBUG_LEVEL_VERBOSE, "  input opts: %d %d %d\n",
414                 dsettings->input_opt[0], dsettings->input_opt[1],
415                 dsettings->input_opt[2]);
416         }
417     }
418
419     i = readBlock(RME_FF_STATUS_REG0, status_buf, 4);
420     debugOutput(DEBUG_LEVEL_VERBOSE, "Status read: %d: 0x%08x 0x%08x 0x%08x 0x%08x\n", i,
421         status_buf[0], status_buf[1], status_buf[2], status_buf[3]);
422
423     return err!=0?-1:0;
424 }
425
426 signed int
427 Device::write_device_flash_settings(FF_software_settings_t *dsettings)
428 {
429     if (dsettings == NULL)
430         dsettings = settings;
431
432     // Write the given device settings to the device's configuration flash.
433
434     FF_device_flash_settings_t hw_settings;
435     signed int i, err = 0;
436
437     if (dsettings == NULL) {
438         debugOutput(DEBUG_LEVEL_WARNING, "NULL settings parameter\n");
439         return -1;
440     }
441
442     memset(&hw_settings, 0, sizeof(hw_settings));
443
444     // Copy software settings to the hardware structure as appropriate.
445     for (i=0; i<4; i++)
446         hw_settings.mic_phantom[i] = dsettings->mic_phantom[i];
447     hw_settings.spdif_input_mode = dsettings->spdif_input_mode;
448     hw_settings.spdif_output_emphasis = dsettings->spdif_output_emphasis;
449     hw_settings.spdif_output_pro = dsettings->spdif_output_pro;
450     hw_settings.spdif_output_nonaudio = dsettings->spdif_output_nonaudio;
451     hw_settings.spdif_output_mode = dsettings->spdif_output_mode;
452     hw_settings.clock_mode = dsettings->clock_mode;
453     hw_settings.sync_ref = dsettings->sync_ref;
454     hw_settings.tms = dsettings->tms;
455     hw_settings.limit_bandwidth = dsettings->limit_bandwidth;
456     hw_settings.stop_on_dropout = dsettings->stop_on_dropout;
457     hw_settings.input_level = dsettings->input_level;
458     hw_settings.output_level = dsettings->output_level;
459     hw_settings.filter = dsettings->filter;
460     hw_settings.fuzz = dsettings->fuzz;
461     // The limiter can only be disabled if channel 1 uses the "front" input.
462     // Note that p12db_an (as passed to the flash) seems to be a "limiter
463     // disabled" flag.
464     if (m_rme_model==RME_MODEL_FIREFACE800 && dsettings->limiter==0 &&
465             dsettings->input_opt[0]==FF_SWPARAM_FF800_INPUT_OPT_FRONT)
466         hw_settings.p12db_an[0] = 1;
467     else
468         hw_settings.p12db_an[0] = 0;
469     hw_settings.sample_rate = dsettings->sample_rate;
470     hw_settings.word_clock_single_speed = dsettings->word_clock_single_speed;
471
472     // The FF800 has front/rear selectors for the "instrument" input
473     // (aka channel 1) and the two "mic" channels (aka channels 7 and 8).
474     // The FF400 does not.  The FF400 borrows the mic0 selector field
475     // in the flash configuration structure to use for the "phones"
476     // level which the FF800 doesn't have.
477     if (m_rme_model == RME_MODEL_FIREFACE400)
478         hw_settings.mic_plug_select[0] = dsettings->phones_level;
479     else
480     if (m_rme_model == RME_MODEL_FIREFACE800) {
481         // The offset of 1 follows the convention used internally in drivers
482         // for other operating systems.  It permits input_opt to be treated
483         // as a bitmask with bit 0 being "rear" and bit 1 being "front".
484         // In the flash, the corresponding value is the index of the active
485         // option in the list rear, front, front and rear.  See also the
486         // related section of read_device_flash_settings().
487         hw_settings.instrument_plug_select = dsettings->input_opt[0] - 1;
488         hw_settings.mic_plug_select[0] = dsettings->input_opt[1] - 1;
489         hw_settings.mic_plug_select[1] = dsettings->input_opt[2] - 1;
490     }
491
492     // The configuration flash block must be erased before we can write to it
493     err = erase_flash(RME_FF_FLASH_ERASE_SETTINGS) != 0;
494     if (err != 0)
495         debugOutput(DEBUG_LEVEL_WARNING, "Error erasing settings flash block: %d\n", i);
496     else {
497         long long int addr;
498         if (m_rme_model == RME_MODEL_FIREFACE800)
499             addr = RME_FF800_FLASH_SETTINGS_ADDR;
500         else
501         if (m_rme_model == RME_MODEL_FIREFACE400)
502             addr = RME_FF400_FLASH_SETTINGS_ADDR;
503         else {
504             debugOutput(DEBUG_LEVEL_ERROR, "unimplemented model %d\n", m_rme_model);
505             return -1;
506         }
507         err = write_flash(addr,
508                   (quadlet_t *)&hw_settings, sizeof(hw_settings)/sizeof(uint32_t));
509
510         if (err != 0)
511             debugOutput(DEBUG_LEVEL_WARNING, "Error writing device flash settings: %d\n", i);
512     }
513
514     return err!=0?-1:0;
515 }
516
517 static float
518 fader2flashvol(signed int fader)
519 {
520     return (1023.0/3) * log(fader*(exp(3.0)-1.0)/0x10000 + 1);
521 }
522
523 static float
524 flashvol2fader(signed int flash_vol)
525 {
526     // Map the 0 dB flash volume value explicitly to the corresponding
527     // fader value to avoid round-off effects.
528     if (flash_vol == RME_FF_FLASH_0DB_VOL_VALUE)
529       return 0x8000;
530     return 0x10000 * (exp(3.0*flash_vol/1023.0)-1) / (exp(3)-1.0);
531 }
532
533 static void
534 faders2flash(signed int fader0, signed int fader1, unsigned short int *flash_vol, unsigned short int *flash_pan)
535 {
536     signed int v = fader0 + fader1;
537     *flash_pan = 256.0 * fader1 / v;
538     *flash_vol = fader2flashvol(v);
539 }
540
541 static void
542 flash2faders(signed int flash_vol, signed int flash_pan, signed int *fader0, signed int *fader1)
543 {
544     float v = flashvol2fader(flash_vol);
545     *fader0 = v * (1 - flash_pan/256.0);
546     *fader1 = v * (flash_pan/256.0);
547 }
548
549 signed int
550 Device::read_device_mixer_settings(FF_software_settings_t *dsettings)
551 {
552     // Note: this function does NOT send the mixer configuration read from
553     // flash to the mixer control registers.  If the newly read state is
554     // to become active, the caller must arrange for this to happen (perhaps
555     // by calling set_hardware_mixergain(), or relying on "changed" widget
556     // callbacks like the rme.py ffado-mixer module does).
557
558     unsigned short int vbuf[RME_FF_FLASH_MIXER_ARRAY_SIZE/2];
559     unsigned short int pbuf[RME_FF_FLASH_MIXER_ARRAY_SIZE/2];
560     unsigned short int obuf[RME_FF_FLASH_SECTOR_SIZE/2];
561     fb_nodeaddr_t addr = 0;
562     signed int i, in, out;
563     signed int nch = 0;
564     signed int flash_row_size = 0;
565
566     if (dsettings == NULL)
567         dsettings = settings;
568
569     if (m_rme_model == RME_MODEL_FIREFACE400) {
570         addr = RME_FF400_FLASH_MIXER_VOLUME_ADDR;
571         nch = RME_FF400_MAX_CHANNELS;
572         flash_row_size = 18;
573     } else
574     if (m_rme_model == RME_MODEL_FIREFACE800) {
575         addr = RME_FF800_FLASH_MIXER_VOLUME_ADDR;
576         nch = RME_FF800_MAX_CHANNELS;
577         flash_row_size = 32;
578     }
579     if (addr == 0)
580         return -1;
581
582     i = read_flash(addr, (quadlet_t *)(vbuf), RME_FF_FLASH_MIXER_ARRAY_SIZE/4);
583     debugOutput(DEBUG_LEVEL_VERBOSE, "read_flash(%" PRId64 ") returned %d\n", addr, i);
584
585     addr += RME_FF_FLASH_MIXER_ARRAY_SIZE;
586     i = read_flash(addr, (quadlet_t *)(pbuf), RME_FF_FLASH_MIXER_ARRAY_SIZE/4);
587     debugOutput(DEBUG_LEVEL_VERBOSE, "read_flash(%" PRId64 ") returned %d\n", addr, i);
588
589     addr += RME_FF_FLASH_MIXER_ARRAY_SIZE;
590     i = read_flash(addr, (quadlet_t *)obuf, RME_FF_FLASH_SECTOR_SIZE_QUADS);
591     debugOutput(DEBUG_LEVEL_VERBOSE, "read_flash(%" PRId64 ") returned %d\n", addr, i);
592
593     for (out=0; out<nch/2; out++) {
594         for (in=0; in<nch; in++) {
595             flash2faders(vbuf[in+out*2*flash_row_size], pbuf[in+out*2*flash_row_size],
596               &dsettings->input_faders[getMixerGainIndex(in,out*2)],
597               &dsettings->input_faders[getMixerGainIndex(in,out*2+1)]);
598         }
599     }
600     for (out=0; out<nch/2; out++) {
601         for (in=0; in<nch; in++) {
602             flash2faders(vbuf[in+flash_row_size*(out*2+1)], pbuf[in+flash_row_size*(out*2+1)],
603               &dsettings->playback_faders[getMixerGainIndex(in,out*2)],
604               &dsettings->playback_faders[getMixerGainIndex(in,out*2+1)]);
605         }
606     }
607     // Elements 30 and 31 of obuf[] are not output fader values: [30]
608     // indicates MIDI control is active while [31] is a submix number.
609     // It's suspected that neither of these are used by the device directly,
610     // and that these elements are just a convenient place for computer
611     // control applications to store things.  FFADO does not make use
612     // of these.  nch is assumed to be <= RME_FF800_MAX_CHANNELS (28),
613     // the size of the output_faders[] array.
614     for (out=0; out<nch; out++) {
615       dsettings->output_faders[out] = flashvol2fader(obuf[out]);
616     }
617
618     return 0;
619 }
620
621 signed int
622 Device::write_device_mixer_settings(FF_software_settings_t *dsettings)
623 {
624     quadlet_t shadow[RME_FF800_FLASH_MIXER_SHADOW_SIZE/4];
625     unsigned short int vbuf[RME_FF_FLASH_MIXER_ARRAY_SIZE/2];
626     unsigned short int pbuf[RME_FF_FLASH_MIXER_ARRAY_SIZE/2];
627     unsigned short int obuf[RME_FF_FLASH_SECTOR_SIZE/2];
628     fb_nodeaddr_t addr = 0;
629     signed int i, in, out;
630     signed int nch = 0;
631     signed int flash_row_size = 0;
632
633     if (dsettings == NULL)
634         dsettings = settings;
635
636     if (m_rme_model == RME_MODEL_FIREFACE400) {
637         addr = RME_FF400_FLASH_MIXER_VOLUME_ADDR;
638         nch = RME_FF400_MAX_CHANNELS;
639         flash_row_size = 18;
640     } else
641     if (m_rme_model == RME_MODEL_FIREFACE800) {
642         addr = RME_FF800_FLASH_MIXER_SHADOW_ADDR;
643         nch = RME_FF800_MAX_CHANNELS;
644         flash_row_size = 32;
645     }
646     if (addr == 0)
647         return -1;
648
649     // The mixer flash block must be erased before we can write to it
650     i = erase_flash(RME_FF_FLASH_ERASE_VOLUME) != 0;
651     if (i) {
652         debugOutput(DEBUG_LEVEL_VERBOSE, "erase_flash() failed\n");
653         return -1;
654     }
655
656     /* Write the shadow mixer array if the device is a ff800 */
657     if (m_rme_model == RME_MODEL_FIREFACE800) {
658         memset(shadow, 0, sizeof(shadow));
659         for (out=0; out<nch; out++) {
660             for (in=0; in<nch; in++) {
661                 shadow[in+out*0x40] = dsettings->input_faders[getMixerGainIndex(in,out)];
662                 shadow[in+out*0x40+0x20] = dsettings->playback_faders[getMixerGainIndex(in,out)];
663             }
664         }
665         for (out=0; out<nch; out++) {
666             shadow[0x1f80/4+out] = dsettings->output_faders[out];
667         }
668         i = write_flash(addr, shadow, RME_FF800_FLASH_MIXER_SHADOW_SIZE/4);
669         debugOutput(DEBUG_LEVEL_VERBOSE, "write_flash(%" PRId64 ") returned %d\n", addr, i);
670         addr = RME_FF800_FLASH_MIXER_VOLUME_ADDR;
671     }
672
673     memset(vbuf, 0, sizeof(vbuf));
674     memset(pbuf, 0, sizeof(pbuf));
675     for (out=0; out<nch/2; out++) {
676         for (in=0; in<nch; in++) {
677             faders2flash(dsettings->input_faders[getMixerGainIndex(in,out*2)],
678               dsettings->input_faders[getMixerGainIndex(in,out*2+1)],
679               &vbuf[in+out*2*flash_row_size], &pbuf[in+out*2*flash_row_size]);
680         }
681     }
682     for (out=0; out<nch/2; out++) {
683         for (in=0; in<nch; in++) {
684             faders2flash(dsettings->playback_faders[getMixerGainIndex(in,out*2)],
685               dsettings->playback_faders[getMixerGainIndex(in,out*2+1)],
686               &vbuf[in+flash_row_size*(out*2+1)], &pbuf[in+flash_row_size*(out*2+1)]);
687         }
688     }
689
690     // Elements 30 and 31 of obuf[] are not output fader values.  See
691     // comments in read_device_mixer_settings().
692     memset(obuf, 0, sizeof(obuf));
693     for (out=0; out<nch; out++) {
694       obuf[out] = fader2flashvol(dsettings->output_faders[out]);
695     }
696
697     i = write_flash(addr, (quadlet_t *)(vbuf), RME_FF_FLASH_MIXER_ARRAY_SIZE/4);
698     debugOutput(DEBUG_LEVEL_VERBOSE, "write_flash(%" PRId64 ") returned %d\n", addr, i);
699
700     addr += RME_FF_FLASH_MIXER_ARRAY_SIZE;
701     i = write_flash(addr, (quadlet_t *)(pbuf), RME_FF_FLASH_MIXER_ARRAY_SIZE/4);
702     debugOutput(DEBUG_LEVEL_VERBOSE, "write_flash(%" PRId64 ") returned %d\n", addr, i);
703
704     addr += RME_FF_FLASH_MIXER_ARRAY_SIZE;
705     i = write_flash(addr, (quadlet_t *)obuf, RME_FF_FLASH_SECTOR_SIZE_QUADS);
706     debugOutput(DEBUG_LEVEL_VERBOSE, "write_flash(%" PRId64 ") returned %d\n", addr, i);
707
708     return 0;
709 }
710
711 }
Note: See TracBrowser for help on using the browser.