diff options
author | Takashi Sakamoto <o-takashi@sakamocchi.jp> | 2014-04-25 09:45:29 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2014-05-26 08:32:58 -0400 |
commit | a2b2a7798fb6a5c639189e5c8f608a56fdc7a222 (patch) | |
tree | 7b0acc20b8d300e0ffa2b0e8b9322b1402254731 /sound | |
parent | c495a4a36e763de3eb164280fd7445f1bf666a52 (diff) |
ALSA: bebob: Send a cue to load firmware for M-Audio Firewire series
Just powering on, these devices below wait to download firmware.
- Firewire Audiophile
- Firewire 410
- Firewire 1814
- ProjectMix I/O
But firmware version 5058 or later, flash memory in the device stores the
firmware. So this driver can enable these devices by sending a certain cue to
load the firmware.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/firewire/bebob/bebob.c | 23 | ||||
-rw-r--r-- | sound/firewire/bebob/bebob.h | 1 | ||||
-rw-r--r-- | sound/firewire/bebob/bebob_maudio.c | 64 |
3 files changed, 79 insertions, 9 deletions
diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c index ffb042b1f19f..e1dd4219ea6c 100644 --- a/sound/firewire/bebob/bebob.c +++ b/sound/firewire/bebob/bebob.c | |||
@@ -177,18 +177,21 @@ bebob_probe(struct fw_unit *unit, | |||
177 | } | 177 | } |
178 | 178 | ||
179 | if ((entry->vendor_id == VEN_FOCUSRITE) && | 179 | if ((entry->vendor_id == VEN_FOCUSRITE) && |
180 | (entry->model_id == MODEL_FOCUSRITE_SAFFIRE_BOTH)) { | 180 | (entry->model_id == MODEL_FOCUSRITE_SAFFIRE_BOTH)) |
181 | spec = get_saffire_spec(unit); | 181 | spec = get_saffire_spec(unit); |
182 | } else if ((entry->vendor_id == VEN_MAUDIO1) && | 182 | else if ((entry->vendor_id == VEN_MAUDIO1) && |
183 | (entry->model_id == MODEL_MAUDIO_AUDIOPHILE_BOTH) && | 183 | (entry->model_id == MODEL_MAUDIO_AUDIOPHILE_BOTH) && |
184 | !check_audiophile_booted(unit)) { | 184 | !check_audiophile_booted(unit)) |
185 | err = 0; | 185 | spec = NULL; |
186 | goto end; | 186 | else |
187 | } else { | ||
188 | spec = (const struct snd_bebob_spec *)entry->driver_data; | 187 | spec = (const struct snd_bebob_spec *)entry->driver_data; |
189 | } | 188 | |
190 | if (spec == NULL) { | 189 | if (spec == NULL) { |
191 | err = -ENOSYS; | 190 | if ((entry->vendor_id == VEN_MAUDIO1) || |
191 | (entry->vendor_id == VEN_MAUDIO2)) | ||
192 | err = snd_bebob_maudio_load_firmware(unit); | ||
193 | else | ||
194 | err = -ENOSYS; | ||
192 | goto end; | 195 | goto end; |
193 | } | 196 | } |
194 | 197 | ||
@@ -374,6 +377,7 @@ static const struct ieee1394_device_id bebob_id_table[] = { | |||
374 | SND_BEBOB_DEV_ENTRY(VEN_FOCUSRITE, MODEL_FOCUSRITE_SAFFIRE_BOTH, | 377 | SND_BEBOB_DEV_ENTRY(VEN_FOCUSRITE, MODEL_FOCUSRITE_SAFFIRE_BOTH, |
375 | &saffire_spec), | 378 | &saffire_spec), |
376 | /* M-Audio, Firewire 410 */ | 379 | /* M-Audio, Firewire 410 */ |
380 | SND_BEBOB_DEV_ENTRY(VEN_MAUDIO2, 0x00010058, NULL), /* bootloader */ | ||
377 | SND_BEBOB_DEV_ENTRY(VEN_MAUDIO2, 0x00010046, &maudio_fw410_spec), | 381 | SND_BEBOB_DEV_ENTRY(VEN_MAUDIO2, 0x00010046, &maudio_fw410_spec), |
378 | /* M-Audio, Firewire Audiophile */ | 382 | /* M-Audio, Firewire Audiophile */ |
379 | SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, MODEL_MAUDIO_AUDIOPHILE_BOTH, | 383 | SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, MODEL_MAUDIO_AUDIOPHILE_BOTH, |
@@ -387,6 +391,7 @@ static const struct ieee1394_device_id bebob_id_table[] = { | |||
387 | /* M-Audio, ProFireLightbridge */ | 391 | /* M-Audio, ProFireLightbridge */ |
388 | SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, 0x000100a1, &spec_normal), | 392 | SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, 0x000100a1, &spec_normal), |
389 | /* Firewire 1814 */ | 393 | /* Firewire 1814 */ |
394 | SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, 0x00010070, NULL), /* bootloader */ | ||
390 | SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, MODEL_MAUDIO_FW1814, | 395 | SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, MODEL_MAUDIO_FW1814, |
391 | &maudio_special_spec), | 396 | &maudio_special_spec), |
392 | /* M-Audio ProjectMix */ | 397 | /* M-Audio ProjectMix */ |
diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h index eba012958b5c..4a54e746c5c6 100644 --- a/sound/firewire/bebob/bebob.h +++ b/sound/firewire/bebob/bebob.h | |||
@@ -242,6 +242,7 @@ extern struct snd_bebob_spec maudio_ozonic_spec; | |||
242 | extern struct snd_bebob_spec maudio_nrv10_spec; | 242 | extern struct snd_bebob_spec maudio_nrv10_spec; |
243 | extern struct snd_bebob_spec maudio_special_spec; | 243 | extern struct snd_bebob_spec maudio_special_spec; |
244 | int snd_bebob_maudio_special_discover(struct snd_bebob *bebob, bool is1814); | 244 | int snd_bebob_maudio_special_discover(struct snd_bebob *bebob, bool is1814); |
245 | int snd_bebob_maudio_load_firmware(struct fw_unit *unit); | ||
245 | 246 | ||
246 | #define SND_BEBOB_DEV_ENTRY(vendor, model, data) \ | 247 | #define SND_BEBOB_DEV_ENTRY(vendor, model, data) \ |
247 | { \ | 248 | { \ |
diff --git a/sound/firewire/bebob/bebob_maudio.c b/sound/firewire/bebob/bebob_maudio.c index 544094b22c6d..52b1a40e5e13 100644 --- a/sound/firewire/bebob/bebob_maudio.c +++ b/sound/firewire/bebob/bebob_maudio.c | |||
@@ -16,6 +16,10 @@ | |||
16 | * settings when completing uploading. Then these devices generate bus reset | 16 | * settings when completing uploading. Then these devices generate bus reset |
17 | * and are recognized as new devices with the firmware. | 17 | * and are recognized as new devices with the firmware. |
18 | * | 18 | * |
19 | * But with firmware version 5058 or later, the firmware is stored to flash | ||
20 | * memory in the device and drivers can tell bootloader to load the firmware | ||
21 | * by sending a cue. This cue must be sent one time. | ||
22 | * | ||
19 | * For streaming, both of output and input streams are needed for Firewire 410 | 23 | * For streaming, both of output and input streams are needed for Firewire 410 |
20 | * and Ozonic. The single stream is OK for the other devices even if the clock | 24 | * and Ozonic. The single stream is OK for the other devices even if the clock |
21 | * source is not SYT-Match (I note no devices use SYT-Match). | 25 | * source is not SYT-Match (I note no devices use SYT-Match). |
@@ -31,6 +35,20 @@ | |||
31 | * functionality is between 0xffc700700000 to 0xffc70070009c. | 35 | * functionality is between 0xffc700700000 to 0xffc70070009c. |
32 | */ | 36 | */ |
33 | 37 | ||
38 | /* Offset from information register */ | ||
39 | #define INFO_OFFSET_SW_DATE 0x20 | ||
40 | |||
41 | /* Bootloader Protocol Version 1 */ | ||
42 | #define MAUDIO_BOOTLOADER_CUE1 0x00000001 | ||
43 | /* | ||
44 | * Initializing configuration to factory settings (= 0x1101), (swapped in line), | ||
45 | * Command code is zero (= 0x00), | ||
46 | * the number of operands is zero (= 0x00)(at least significant byte) | ||
47 | */ | ||
48 | #define MAUDIO_BOOTLOADER_CUE2 0x01110000 | ||
49 | /* padding */ | ||
50 | #define MAUDIO_BOOTLOADER_CUE3 0x00000000 | ||
51 | |||
34 | #define MAUDIO_SPECIFIC_ADDRESS 0xffc700000000 | 52 | #define MAUDIO_SPECIFIC_ADDRESS 0xffc700000000 |
35 | 53 | ||
36 | #define METER_OFFSET 0x00600000 | 54 | #define METER_OFFSET 0x00600000 |
@@ -67,6 +85,52 @@ struct special_params { | |||
67 | struct snd_ctl_elem_id *ctl_id_sync; | 85 | struct snd_ctl_elem_id *ctl_id_sync; |
68 | }; | 86 | }; |
69 | 87 | ||
88 | /* | ||
89 | * For some M-Audio devices, this module just send cue to load firmware. After | ||
90 | * loading, the device generates bus reset and newly detected. | ||
91 | * | ||
92 | * If we make any transactions to load firmware, the operation may failed. | ||
93 | */ | ||
94 | int snd_bebob_maudio_load_firmware(struct fw_unit *unit) | ||
95 | { | ||
96 | struct fw_device *device = fw_parent_device(unit); | ||
97 | int err, rcode; | ||
98 | u64 date; | ||
99 | __be32 cues[3] = { | ||
100 | MAUDIO_BOOTLOADER_CUE1, | ||
101 | MAUDIO_BOOTLOADER_CUE2, | ||
102 | MAUDIO_BOOTLOADER_CUE3 | ||
103 | }; | ||
104 | |||
105 | /* check date of software used to build */ | ||
106 | err = snd_bebob_read_block(unit, INFO_OFFSET_SW_DATE, | ||
107 | &date, sizeof(u64)); | ||
108 | if (err < 0) | ||
109 | goto end; | ||
110 | /* | ||
111 | * firmware version 5058 or later has date later than "20070401", but | ||
112 | * 'date' is not null-terminated. | ||
113 | */ | ||
114 | if (date < 0x3230303730343031) { | ||
115 | dev_err(&unit->device, | ||
116 | "Use firmware version 5058 or later\n"); | ||
117 | err = -ENOSYS; | ||
118 | goto end; | ||
119 | } | ||
120 | |||
121 | rcode = fw_run_transaction(device->card, TCODE_WRITE_BLOCK_REQUEST, | ||
122 | device->node_id, device->generation, | ||
123 | device->max_speed, BEBOB_ADDR_REG_REQ, | ||
124 | cues, sizeof(cues)); | ||
125 | if (rcode != RCODE_COMPLETE) { | ||
126 | dev_err(&unit->device, | ||
127 | "Failed to send a cue to load firmware\n"); | ||
128 | err = -EIO; | ||
129 | } | ||
130 | end: | ||
131 | return err; | ||
132 | } | ||
133 | |||
70 | static inline int | 134 | static inline int |
71 | get_meter(struct snd_bebob *bebob, void *buf, unsigned int size) | 135 | get_meter(struct snd_bebob *bebob, void *buf, unsigned int size) |
72 | { | 136 | { |