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

Revision 1609, 14.7 kB (checked in by jwoithe, 15 years ago)

RME: provide low-level support for the channel 3/4 pad/instrument options of the Fireface-400
RME: update device documentation

Line 
1 /*
2  * Copyright (C) 2009 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 "rme/rme_avdevice.h"
27 #include "rme/fireface_def.h"
28
29 #include "debugmodule/debugmodule.h"
30
31 #define MAX_FLASH_BUSY_RETRIES    25
32
33 namespace Rme {
34
35 signed int
36 Device::wait_while_busy(unsigned int init_delay_ms)
37 {
38     signed int i;
39     quadlet_t status;
40
41     // Wait for the device to become available for a new command.  A delay
42     // of init_delay_ms is executed prior to each test of the device status.
43     for (i=0; i<MAX_FLASH_BUSY_RETRIES; i++) {
44         usleep(init_delay_ms*1000);
45         if (m_rme_model == RME_MODEL_FIREFACE400) {
46             status = readRegister(RME_FF400_FLASH_STAT_REG);
47             if (status == 0)
48                 break;
49         } else {
50             status = readRegister(RME_FF_STATUS_REG1);
51             if (status & 0x40000000)
52                 break;
53         }
54     }
55
56     if (i == MAX_FLASH_BUSY_RETRIES)
57         return -1;
58     return 0;
59 }
60
61 signed int
62 Device::get_revision(unsigned int *revision)
63 {
64     signed int err = 0;
65
66     if (m_rme_model == RME_MODEL_FIREFACE800) {
67         *revision = readRegister(RME_FF800_REVISION_REG);
68         return 0;
69     }
70
71     err = writeRegister(RME_FF400_FLASH_CMD_REG, RME_FF400_FLASH_CMD_GET_REVISION);
72     err |= wait_while_busy(2);
73     if (!err)
74       *revision = readRegister(RME_FF400_FLASH_READ_BUFFER);
75
76     return err?-1:0;
77 }
78
79 signed int
80 Device::read_flash(fb_nodeaddr_t addr, quadlet_t *buf, unsigned int n_quads)
81 {
82     // Read "n_quads" quadlets from the Fireface Flash starting at address
83     // addr.  The result is written to "buf" which is assumed big enough to
84     // hold the result.  Return 0 on success, -1 on error.  The caller must ensure
85     // that the flash source address makes sense for the device in use.
86
87     unsigned int xfer_size;
88     unsigned int err = 0;
89     quadlet_t block_desc[2];
90     quadlet_t ff400_addr = (addr & 0xffffffff);
91
92     if (m_rme_model == RME_MODEL_FIREFACE800) {
93         return readBlock(addr, buf, n_quads);
94     }
95     // FF400 case follows
96     do {
97         xfer_size = (n_quads > 32)?32:n_quads;
98         block_desc[0] = ff400_addr;
99         block_desc[1] = xfer_size * sizeof(quadlet_t);
100         // Program the read address and size
101         err |= writeBlock(RME_FF400_FLASH_BLOCK_ADDR_REG, block_desc, 2);
102         // Execute the read and wait for its completion
103         err |= writeRegister(RME_FF400_FLASH_CMD_REG, RME_FF400_FLASH_CMD_READ);
104         if (!err)
105             wait_while_busy(2);
106         // Read from bounce buffer into final destination
107         err |= readBlock(RME_FF400_FLASH_READ_BUFFER, buf, xfer_size);
108
109         n_quads -= xfer_size;
110         ff400_addr += xfer_size*sizeof(quadlet_t);
111         buf += xfer_size;
112     } while (n_quads>0 && !err);
113
114     return err?-1:0;
115 }
116
117 signed int
118 Device::erase_flash(unsigned int flags)
119 {
120     // Erase the requested flash block.  "flags" should be one of the
121     // RME_FF_FLASH_ERASE_* flags.  Return 0 on success, -1 on error.
122
123     fb_nodeaddr_t addr;
124     quadlet_t data;
125     unsigned int err = 0;
126
127     if (m_rme_model == RME_MODEL_FIREFACE800) {
128         switch (flags) {
129             case RME_FF_FLASH_ERASE_VOLUME:
130                 addr = RME_FF800_FLASH_ERASE_VOLUME_REG; break;
131             case RME_FF_FLASH_ERASE_SETTINGS:
132                 addr = RME_FF800_FLASH_ERASE_SETTINGS_REG; break;
133             case RME_FF_FLASH_ERASE_CONFIG:
134                 addr = RME_FF800_FLASH_ERASE_CONFIG_REG; break;
135             default:
136                 debugOutput(DEBUG_LEVEL_WARNING, "unknown flag %d\n", flags);
137                 return -1;
138         }
139         data = 0;
140     } else {
141         addr = RME_FF400_FLASH_CMD_REG;
142         switch (flags) {
143             case RME_FF_FLASH_ERASE_VOLUME:
144                 data = RME_FF400_FLASH_CMD_ERASE_VOLUME; break;
145             case RME_FF_FLASH_ERASE_SETTINGS:
146                 data = RME_FF400_FLASH_CMD_ERASE_SETTINGS; break;
147             case RME_FF_FLASH_ERASE_CONFIG:
148                 data = RME_FF400_FLASH_CMD_ERASE_CONFIG; break;
149             default:
150                 debugOutput(DEBUG_LEVEL_WARNING, "unknown flag %d\n", flags);
151                 return -1;
152         }
153     }
154
155     err |= writeRegister(addr, data);
156     if (!err) {
157         wait_while_busy(500);
158         // After the device is ready, wait a further 20 milliseconds.  The purpose
159         // of this is unclear.  Drivers from other OSes do it, so we should too.
160         usleep(20000);
161     }
162
163     return err?-1:0;
164 }
165
166 signed int
167 Device::write_flash(fb_nodeaddr_t addr, quadlet_t *buf, unsigned int n_quads)
168 {
169     // Write "n_quads" quadlets to the Fireface Flash starting at address
170     // addr.  Return 0 on success, -1 on error.  The caller must ensure the
171     // supplied address is appropriate for the device in use.
172
173     unsigned int xfer_size;
174     unsigned int err = 0;
175     quadlet_t block_desc[2];
176     quadlet_t ff400_addr = (addr & 0xffffffff);
177
178     if (m_rme_model == RME_MODEL_FIREFACE800) {
179         err |= readBlock(addr, buf, n_quads);
180         if (!err)
181             wait_while_busy(5);
182     }
183     // FF400 case follows
184     do {
185         xfer_size = (n_quads > 32)?32:n_quads;
186         // Send data to flash buffer
187         err |= writeBlock(RME_FF400_FLASH_WRITE_BUFFER, buf, xfer_size);
188         // Program the destination address and size
189         block_desc[0] = ff400_addr;
190         block_desc[1] = xfer_size * sizeof(quadlet_t);
191         err |= writeBlock(RME_FF400_FLASH_BLOCK_ADDR_REG, block_desc, 2);
192         // Execute the write and wait for its completion
193         err |= writeRegister(RME_FF400_FLASH_CMD_REG, RME_FF400_FLASH_CMD_WRITE);
194         if (!err)
195             wait_while_busy(2);
196
197         n_quads -= xfer_size;
198         ff400_addr += xfer_size*sizeof(quadlet_t);
199         buf += xfer_size;
200     } while (n_quads>0 && !err);
201
202     return err?-1:0;
203 }
204
205
206 signed int
207 Device::read_device_flash_settings(FF_software_settings_t *settings)
208 {
209     // Read the device's configuration flash RAM and use this to set up
210     // the given settings structure.
211
212     FF_device_flash_settings_t hw_settings;
213     signed int i, err = 0;
214     unsigned int rev;
215
216     // FIXME: the debug output in this function is mostly for testing at
217     // present.
218
219     i = get_revision(&rev);
220     if (i != 0) {
221         debugOutput(DEBUG_LEVEL_WARNING, "Error reading hardware revision: %d\n", i);
222     } else {
223         debugOutput(DEBUG_LEVEL_VERBOSE, "Hardware revision: 0x%08x\n", rev);
224     }
225
226     // Read settings flash ram block
227     err = read_flash(m_rme_model==RME_MODEL_FIREFACE800?
228       RME_FF800_FLASH_SETTINGS_ADDR:RME_FF400_FLASH_SETTINGS_ADDR,
229         (quadlet_t *)&hw_settings, sizeof(hw_settings)/sizeof(uint32_t));
230     if (err != 0) {
231         debugOutput(DEBUG_LEVEL_WARNING, "Error reading device flash settings: %d\n", i);
232     } else {
233         debugOutput(DEBUG_LEVEL_VERBOSE, "Device flash settings:\n");
234         if (hw_settings.clock_mode == FF_DEV_FLASH_INVALID) {
235             debugOutput(DEBUG_LEVEL_VERBOSE, "  Clock mode: not set in device flash\n");
236         } else {
237             debugOutput(DEBUG_LEVEL_VERBOSE, "  Clock mode: %s\n",
238               hw_settings.clock_mode==FF_DEV_FLASH_CLOCK_MODE_MASTER?"Master":"Slave");
239         }
240         if (hw_settings.sample_rate == FF_DEV_FLASH_INVALID) {
241             debugOutput(DEBUG_LEVEL_VERBOSE, "  Sample rate: not set in device flash\n");
242         } else
243         if (hw_settings.sample_rate == FF_DEV_FLASH_SRATE_DDS_INACTIVE) {
244             debugOutput(DEBUG_LEVEL_VERBOSE, "  Sample rate: DDS not active\n");
245         } else {
246             debugOutput(DEBUG_LEVEL_VERBOSE, "  Sample rate: %d Hz (DDS active)\n", hw_settings.sample_rate);
247         }
248     }
249
250     if (settings != NULL) {
251         memset(settings, 0, sizeof(*settings));
252         // Copy hardware details to the software settings structure as
253         // appropriate.
254         for (i=0; i<2; i++)
255             settings->mic_phantom[i] = hw_settings.mic_phantom[i];
256         if (m_rme_model == RME_MODEL_FIREFACE800) {
257             for (i=2; i<4; i++)
258                 settings->mic_phantom[i] = hw_settings.mic_phantom[i];
259         } else {
260             // TODO: confirm this is true
261             for (i=2; i<4; i++)
262                 settings->ff400_input_pad[i-2] = hw_settings.mic_phantom[i];
263         }
264         settings->spdif_input_mode = hw_settings.spdif_input_mode;
265         settings->spdif_output_emphasis = hw_settings.spdif_output_emphasis;
266         settings->spdif_output_pro = hw_settings.spdif_output_pro;
267         settings->spdif_output_nonaudio = hw_settings.spdif_output_nonaudio;
268         settings->spdif_output_mode = hw_settings.spdif_output_mode;
269         settings->clock_mode = hw_settings.clock_mode;
270         settings->sync_ref = hw_settings.sync_ref;
271         settings->tms = hw_settings.tms;
272         settings->limit_bandwidth = hw_settings.limit_bandwidth;
273         settings->stop_on_dropout = hw_settings.stop_on_dropout;
274         settings->input_level = hw_settings.input_level;
275         settings->output_level = hw_settings.output_level;
276         if (m_rme_model == RME_MODEL_FIREFACE800) {
277             settings->filter = hw_settings.filter;
278             settings->fuzz = hw_settings.fuzz;
279         } else {
280             // TODO: confirm this is true
281             settings->ff400_instr_input[0] = hw_settings.fuzz;
282             settings->ff400_instr_input[1] = hw_settings.filter;
283         }
284         settings->limiter_disable = (hw_settings.p12db_an[0] == 0)?1:0;
285         settings->sample_rate = hw_settings.sample_rate;
286         settings->word_clock_single_speed = hw_settings.word_clock_single_speed;
287
288         // The FF800 has front/rear selectors for the "instrument" input
289         // (aka channel 1) and the two "mic" channels (aka channels 7 and 8).
290         // The FF400 does not.  The FF400 borrows the mic0 selector field
291         // in the flash configuration structure to use for the "phones"
292         // level which the FF800 doesn't have.
293         // The offset of 1 here is to maintain consistency with the values
294         // used in the flash by other operating systems.
295         if (m_rme_model == RME_MODEL_FIREFACE400)
296             settings->phones_level = hw_settings.mic_plug_select[0] + 1;
297         else {
298             settings->input_opt[0] = hw_settings.instrument_plug_select + 1;
299             settings->input_opt[1] = hw_settings.mic_plug_select[0] + 1;
300             settings->input_opt[2] = hw_settings.mic_plug_select[1] + 1;
301         }
302     }
303
304 {
305 quadlet_t buf[4];
306 signed int i;
307   i = readBlock(RME_FF_STATUS_REG0, buf, 4);
308   fprintf(stderr, "Status read: %d\n", i);
309   for (i=0; i<4; i++)
310     fprintf(stderr,"0x%08x ", buf[i]);
311   fprintf(stderr,"\n");
312 }
313
314 #if 0
315 {
316 // Read mixer volume flash ram block
317 quadlet_t buf[0x800];
318   memset(buf, 0xdb, sizeof(buf));
319   i = read_flash(m_rme_model==RME_MODEL_FIREFACE800?
320         RME_FF800_FLASH_MIXER_VOLUME_ADDR:RME_FF400_FLASH_MIXER_VOLUME_ADDR, buf, 32);
321 fprintf(stderr,"result=%d\n", i);
322 for (i=0; i<32; i++) {
323   fprintf(stderr, "%d: 0x%08x\n", i, buf[i]);
324 }
325 }
326 #endif
327
328     return err!=0?-1:0;
329 }
330
331 signed int
332 Device::write_device_flash_settings(FF_software_settings_t *settings)
333 {
334     // Write the given device settings to the device's configuration flash.
335
336     FF_device_flash_settings_t hw_settings;
337     signed int i, err = 0;
338
339     if (settings == NULL) {
340         debugOutput(DEBUG_LEVEL_WARNING, "NULL settings parameter\n");
341         return -1;
342     }
343
344     memset(&hw_settings, 0, sizeof(hw_settings));
345
346     // Copy software settings to the hardware structure as appropriate.
347     for (i=0; i<4; i++)
348         hw_settings.mic_phantom[i] = settings->mic_phantom[i];
349     hw_settings.spdif_input_mode = settings->spdif_input_mode;
350     hw_settings.spdif_output_emphasis = settings->spdif_output_emphasis;
351     hw_settings.spdif_output_pro = settings->spdif_output_pro;
352     hw_settings.spdif_output_nonaudio = settings->spdif_output_nonaudio;
353     hw_settings.spdif_output_mode = settings->spdif_output_mode;
354     hw_settings.clock_mode = settings->clock_mode;
355     hw_settings.sync_ref = settings->sync_ref;
356     hw_settings.tms = settings->tms;
357     hw_settings.limit_bandwidth = settings->limit_bandwidth;
358     hw_settings.stop_on_dropout = settings->stop_on_dropout;
359     hw_settings.input_level = settings->input_level;
360     hw_settings.output_level = settings->output_level;
361     hw_settings.filter = settings->filter;
362     hw_settings.fuzz = settings->fuzz;
363     if (m_rme_model==RME_MODEL_FIREFACE800 && settings->limiter_disable==1 &&
364             settings->input_opt[0]==FF_SWPARAM_FF800_INPUT_OPT_FRONT)
365         hw_settings.p12db_an[0] = 1;
366     else
367         hw_settings.p12db_an[0] = 0;
368     hw_settings.sample_rate = settings->sample_rate;
369     hw_settings.word_clock_single_speed = settings->word_clock_single_speed;
370
371     // The FF800 has front/rear selectors for the "instrument" input
372     // (aka channel 1) and the two "mic" channels (aka channels 7 and 8).
373     // The FF400 does not.  The FF400 borrows the mic0 selector field
374     // in the flash configuration structure to use for the "phones"
375     // level which the FF800 doesn't have.
376     // The offset of 1 here is to maintain consistency with the values
377     // used in the flash by other operating systems.  See related section of
378     // read_device_flash_settings().
379     if (m_rme_model == RME_MODEL_FIREFACE400)
380         hw_settings.mic_plug_select[0] = settings->phones_level - 1;
381     else {
382         hw_settings.instrument_plug_select = settings->input_opt[0] - 1;
383         hw_settings.mic_plug_select[0] = settings->input_opt[1] - 1;
384         hw_settings.mic_plug_select[1] = settings->input_opt[2] - 1;
385     }
386
387     // The configuration flash block must be erased before we can write to it
388     err = erase_flash(RME_FF_FLASH_ERASE_SETTINGS) != 0;
389     if (err != 0)
390         debugOutput(DEBUG_LEVEL_WARNING, "Error erasing settings flash block: %d\n", i);
391     else {
392         err = write_flash(m_rme_model==RME_MODEL_FIREFACE800?
393                   RME_FF800_FLASH_SETTINGS_ADDR:RME_FF400_FLASH_SETTINGS_ADDR,
394                   (quadlet_t *)&hw_settings, sizeof(hw_settings)/sizeof(uint32_t));
395
396         if (err != 0)
397             debugOutput(DEBUG_LEVEL_WARNING, "Error writing device flash settings: %d\n", i);
398     }
399
400     return err!=0?-1:0;
401 }
402
403 }
Note: See TracBrowser for help on using the browser.