diff options
-rw-r--r-- | sound/firewire/bebob/Makefile | 3 | ||||
-rw-r--r-- | sound/firewire/bebob/bebob.c | 72 | ||||
-rw-r--r-- | sound/firewire/bebob/bebob.h | 33 | ||||
-rw-r--r-- | sound/firewire/bebob/bebob_command.c | 77 | ||||
-rw-r--r-- | sound/firewire/bebob/bebob_pcm.c | 3 | ||||
-rw-r--r-- | sound/firewire/bebob/bebob_proc.c | 57 | ||||
-rw-r--r-- | sound/firewire/bebob/bebob_stream.c | 27 |
7 files changed, 230 insertions, 42 deletions
diff --git a/sound/firewire/bebob/Makefile b/sound/firewire/bebob/Makefile index 78087772a022..e4b08e38dd23 100644 --- a/sound/firewire/bebob/Makefile +++ b/sound/firewire/bebob/Makefile | |||
@@ -1,4 +1,3 @@ | |||
1 | snd-bebob-objs := bebob_command.o bebob_stream.o bebob_proc.o bebob_midi.o \ | 1 | snd-bebob-objs := bebob_command.o bebob_stream.o bebob_proc.o bebob_midi.o \ |
2 | bebob_pcm.o bebob_hwdep.o \ | 2 | bebob_pcm.o bebob_hwdep.o bebob.o |
3 | bebob.o | ||
4 | obj-m += snd-bebob.o | 3 | obj-m += snd-bebob.o |
diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c index b7d70c2e4e87..3d7909036a3c 100644 --- a/sound/firewire/bebob/bebob.c +++ b/sound/firewire/bebob/bebob.c | |||
@@ -126,6 +126,7 @@ bebob_probe(struct fw_unit *unit, | |||
126 | { | 126 | { |
127 | struct snd_card *card; | 127 | struct snd_card *card; |
128 | struct snd_bebob *bebob; | 128 | struct snd_bebob *bebob; |
129 | const struct snd_bebob_spec *spec; | ||
129 | unsigned int card_index; | 130 | unsigned int card_index; |
130 | int err; | 131 | int err; |
131 | 132 | ||
@@ -140,6 +141,12 @@ bebob_probe(struct fw_unit *unit, | |||
140 | goto end; | 141 | goto end; |
141 | } | 142 | } |
142 | 143 | ||
144 | spec = (const struct snd_bebob_spec *)entry->driver_data; | ||
145 | if (spec == NULL) { | ||
146 | err = -ENOSYS; | ||
147 | goto end; | ||
148 | } | ||
149 | |||
143 | err = snd_card_new(&unit->device, index[card_index], id[card_index], | 150 | err = snd_card_new(&unit->device, index[card_index], id[card_index], |
144 | THIS_MODULE, sizeof(struct snd_bebob), &card); | 151 | THIS_MODULE, sizeof(struct snd_bebob), &card); |
145 | if (err < 0) | 152 | if (err < 0) |
@@ -151,6 +158,7 @@ bebob_probe(struct fw_unit *unit, | |||
151 | 158 | ||
152 | bebob->card = card; | 159 | bebob->card = card; |
153 | bebob->unit = unit; | 160 | bebob->unit = unit; |
161 | bebob->spec = spec; | ||
154 | mutex_init(&bebob->mutex); | 162 | mutex_init(&bebob->mutex); |
155 | spin_lock_init(&bebob->lock); | 163 | spin_lock_init(&bebob->lock); |
156 | init_waitqueue_head(&bebob->hwdep_wait); | 164 | init_waitqueue_head(&bebob->hwdep_wait); |
@@ -216,62 +224,72 @@ static void bebob_remove(struct fw_unit *unit) | |||
216 | snd_card_free_when_closed(bebob->card); | 224 | snd_card_free_when_closed(bebob->card); |
217 | } | 225 | } |
218 | 226 | ||
227 | struct snd_bebob_rate_spec normal_rate_spec = { | ||
228 | .get = &snd_bebob_stream_get_rate, | ||
229 | .set = &snd_bebob_stream_set_rate | ||
230 | }; | ||
231 | static const struct snd_bebob_spec spec_normal = { | ||
232 | .clock = NULL, | ||
233 | .rate = &normal_rate_spec, | ||
234 | .meter = NULL | ||
235 | }; | ||
236 | |||
219 | static const struct ieee1394_device_id bebob_id_table[] = { | 237 | static const struct ieee1394_device_id bebob_id_table[] = { |
220 | /* Edirol, FA-66 */ | 238 | /* Edirol, FA-66 */ |
221 | SND_BEBOB_DEV_ENTRY(VEN_EDIROL, 0x00010049), | 239 | SND_BEBOB_DEV_ENTRY(VEN_EDIROL, 0x00010049, &spec_normal), |
222 | /* Edirol, FA-101 */ | 240 | /* Edirol, FA-101 */ |
223 | SND_BEBOB_DEV_ENTRY(VEN_EDIROL, 0x00010048), | 241 | SND_BEBOB_DEV_ENTRY(VEN_EDIROL, 0x00010048, &spec_normal), |
224 | /* Presonus, FIREBOX */ | 242 | /* Presonus, FIREBOX */ |
225 | SND_BEBOB_DEV_ENTRY(VEN_PRESONUS, 0x00010000), | 243 | SND_BEBOB_DEV_ENTRY(VEN_PRESONUS, 0x00010000, &spec_normal), |
226 | /* PreSonus, FIREPOD/FP10 */ | 244 | /* PreSonus, FIREPOD/FP10 */ |
227 | SND_BEBOB_DEV_ENTRY(VEN_PRESONUS, 0x00010066), | 245 | SND_BEBOB_DEV_ENTRY(VEN_PRESONUS, 0x00010066, &spec_normal), |
228 | /* PreSonus, Inspire1394 */ | 246 | /* PreSonus, Inspire1394 */ |
229 | SND_BEBOB_DEV_ENTRY(VEN_PRESONUS, 0x00010001), | 247 | SND_BEBOB_DEV_ENTRY(VEN_PRESONUS, 0x00010001, &spec_normal), |
230 | /* BridgeCo, RDAudio1 */ | 248 | /* BridgeCo, RDAudio1 */ |
231 | SND_BEBOB_DEV_ENTRY(VEN_BRIDGECO, 0x00010048), | 249 | SND_BEBOB_DEV_ENTRY(VEN_BRIDGECO, 0x00010048, &spec_normal), |
232 | /* BridgeCo, Audio5 */ | 250 | /* BridgeCo, Audio5 */ |
233 | SND_BEBOB_DEV_ENTRY(VEN_BRIDGECO, 0x00010049), | 251 | SND_BEBOB_DEV_ENTRY(VEN_BRIDGECO, 0x00010049, &spec_normal), |
234 | /* Mackie, Onyx 1220/1620/1640 (Firewire I/O Card) */ | 252 | /* Mackie, Onyx 1220/1620/1640 (Firewire I/O Card) */ |
235 | SND_BEBOB_DEV_ENTRY(VEN_MACKIE, 0x00010065), | 253 | SND_BEBOB_DEV_ENTRY(VEN_MACKIE, 0x00010065, &spec_normal), |
236 | /* Mackie, d.2 (Firewire Option) */ | 254 | /* Mackie, d.2 (Firewire Option) */ |
237 | SND_BEBOB_DEV_ENTRY(VEN_MACKIE, 0x00010067), | 255 | SND_BEBOB_DEV_ENTRY(VEN_MACKIE, 0x00010067, &spec_normal), |
238 | /* Stanton, ScratchAmp */ | 256 | /* Stanton, ScratchAmp */ |
239 | SND_BEBOB_DEV_ENTRY(VEN_STANTON, 0x00000001), | 257 | SND_BEBOB_DEV_ENTRY(VEN_STANTON, 0x00000001, &spec_normal), |
240 | /* Tascam, IF-FW DM */ | 258 | /* Tascam, IF-FW DM */ |
241 | SND_BEBOB_DEV_ENTRY(VEN_TASCAM, 0x00010067), | 259 | SND_BEBOB_DEV_ENTRY(VEN_TASCAM, 0x00010067, &spec_normal), |
242 | /* Behringer, XENIX UFX 1204 */ | 260 | /* Behringer, XENIX UFX 1204 */ |
243 | SND_BEBOB_DEV_ENTRY(VEN_BEHRINGER, 0x00001204), | 261 | SND_BEBOB_DEV_ENTRY(VEN_BEHRINGER, 0x00001204, &spec_normal), |
244 | /* Behringer, XENIX UFX 1604 */ | 262 | /* Behringer, XENIX UFX 1604 */ |
245 | SND_BEBOB_DEV_ENTRY(VEN_BEHRINGER, 0x00001604), | 263 | SND_BEBOB_DEV_ENTRY(VEN_BEHRINGER, 0x00001604, &spec_normal), |
246 | /* Behringer, Digital Mixer X32 series (X-UF Card) */ | 264 | /* Behringer, Digital Mixer X32 series (X-UF Card) */ |
247 | SND_BEBOB_DEV_ENTRY(VEN_BEHRINGER, 0x00000006), | 265 | SND_BEBOB_DEV_ENTRY(VEN_BEHRINGER, 0x00000006, &spec_normal), |
248 | /* Apogee Electronics, Rosetta 200/400 (X-FireWire card) */ | 266 | /* Apogee Electronics, Rosetta 200/400 (X-FireWire card) */ |
249 | /* Apogee Electronics, DA/AD/DD-16X (X-FireWire card) */ | 267 | /* Apogee Electronics, DA/AD/DD-16X (X-FireWire card) */ |
250 | SND_BEBOB_DEV_ENTRY(VEN_APOGEE, 0x00010048), | 268 | SND_BEBOB_DEV_ENTRY(VEN_APOGEE, 0x00010048, &spec_normal), |
251 | /* Apogee Electronics, Ensemble */ | 269 | /* Apogee Electronics, Ensemble */ |
252 | SND_BEBOB_DEV_ENTRY(VEN_APOGEE, 0x00001eee), | 270 | SND_BEBOB_DEV_ENTRY(VEN_APOGEE, 0x00001eee, &spec_normal), |
253 | /* ESI, Quatafire610 */ | 271 | /* ESI, Quatafire610 */ |
254 | SND_BEBOB_DEV_ENTRY(VEN_ESI, 0x00010064), | 272 | SND_BEBOB_DEV_ENTRY(VEN_ESI, 0x00010064, &spec_normal), |
255 | /* AcousticReality, eARMasterOne */ | 273 | /* AcousticReality, eARMasterOne */ |
256 | SND_BEBOB_DEV_ENTRY(VEN_ACOUSTIC, 0x00000002), | 274 | SND_BEBOB_DEV_ENTRY(VEN_ACOUSTIC, 0x00000002, &spec_normal), |
257 | /* CME, MatrixKFW */ | 275 | /* CME, MatrixKFW */ |
258 | SND_BEBOB_DEV_ENTRY(VEN_CME, 0x00030000), | 276 | SND_BEBOB_DEV_ENTRY(VEN_CME, 0x00030000, &spec_normal), |
259 | /* Phonic, Helix Board 12 MkII */ | 277 | /* Phonic, Helix Board 12 MkII */ |
260 | SND_BEBOB_DEV_ENTRY(VEN_PHONIC, 0x00050000), | 278 | SND_BEBOB_DEV_ENTRY(VEN_PHONIC, 0x00050000, &spec_normal), |
261 | /* Phonic, Helix Board 18 MkII */ | 279 | /* Phonic, Helix Board 18 MkII */ |
262 | SND_BEBOB_DEV_ENTRY(VEN_PHONIC, 0x00060000), | 280 | SND_BEBOB_DEV_ENTRY(VEN_PHONIC, 0x00060000, &spec_normal), |
263 | /* Phonic, Helix Board 24 MkII */ | 281 | /* Phonic, Helix Board 24 MkII */ |
264 | SND_BEBOB_DEV_ENTRY(VEN_PHONIC, 0x00070000), | 282 | SND_BEBOB_DEV_ENTRY(VEN_PHONIC, 0x00070000, &spec_normal), |
265 | /* Phonic, Helix Board 12 Universal/18 Universal/24 Universal */ | 283 | /* Phonic, Helix Board 12 Universal/18 Universal/24 Universal */ |
266 | SND_BEBOB_DEV_ENTRY(VEN_PHONIC, 0x00000000), | 284 | SND_BEBOB_DEV_ENTRY(VEN_PHONIC, 0x00000000, &spec_normal), |
267 | /* Lynx, Aurora 8/16 (LT-FW) */ | 285 | /* Lynx, Aurora 8/16 (LT-FW) */ |
268 | SND_BEBOB_DEV_ENTRY(VEN_LYNX, 0x00000001), | 286 | SND_BEBOB_DEV_ENTRY(VEN_LYNX, 0x00000001, &spec_normal), |
269 | /* ICON, FireXon */ | 287 | /* ICON, FireXon */ |
270 | SND_BEBOB_DEV_ENTRY(VEN_ICON, 0x00000001), | 288 | SND_BEBOB_DEV_ENTRY(VEN_ICON, 0x00000001, &spec_normal), |
271 | /* PrismSound, Orpheus */ | 289 | /* PrismSound, Orpheus */ |
272 | SND_BEBOB_DEV_ENTRY(VEN_PRISMSOUND, 0x00010048), | 290 | SND_BEBOB_DEV_ENTRY(VEN_PRISMSOUND, 0x00010048, &spec_normal), |
273 | /* PrismSound, ADA-8XR */ | 291 | /* PrismSound, ADA-8XR */ |
274 | SND_BEBOB_DEV_ENTRY(VEN_PRISMSOUND, 0x0000ada8), | 292 | SND_BEBOB_DEV_ENTRY(VEN_PRISMSOUND, 0x0000ada8, &spec_normal), |
275 | /* IDs are unknown but able to be supported */ | 293 | /* IDs are unknown but able to be supported */ |
276 | /* Apogee, Mini-ME Firewire */ | 294 | /* Apogee, Mini-ME Firewire */ |
277 | /* Apogee, Mini-DAC Firewire */ | 295 | /* Apogee, Mini-DAC Firewire */ |
diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h index e8a5e447ff17..7365f92a6aed 100644 --- a/sound/firewire/bebob/bebob.h +++ b/sound/firewire/bebob/bebob.h | |||
@@ -48,6 +48,28 @@ struct snd_bebob_stream_formation { | |||
48 | /* this is a lookup table for index of stream formations */ | 48 | /* this is a lookup table for index of stream formations */ |
49 | extern const unsigned int snd_bebob_rate_table[SND_BEBOB_STRM_FMT_ENTRIES]; | 49 | extern const unsigned int snd_bebob_rate_table[SND_BEBOB_STRM_FMT_ENTRIES]; |
50 | 50 | ||
51 | /* device specific operations */ | ||
52 | #define SND_BEBOB_CLOCK_INTERNAL "Internal" | ||
53 | struct snd_bebob_clock_spec { | ||
54 | unsigned int num; | ||
55 | char *const *labels; | ||
56 | int (*get)(struct snd_bebob *bebob, unsigned int *id); | ||
57 | }; | ||
58 | struct snd_bebob_rate_spec { | ||
59 | int (*get)(struct snd_bebob *bebob, unsigned int *rate); | ||
60 | int (*set)(struct snd_bebob *bebob, unsigned int rate); | ||
61 | }; | ||
62 | struct snd_bebob_meter_spec { | ||
63 | unsigned int num; | ||
64 | char *const *labels; | ||
65 | int (*get)(struct snd_bebob *bebob, u32 *target, unsigned int size); | ||
66 | }; | ||
67 | struct snd_bebob_spec { | ||
68 | struct snd_bebob_clock_spec *clock; | ||
69 | struct snd_bebob_rate_spec *rate; | ||
70 | struct snd_bebob_meter_spec *meter; | ||
71 | }; | ||
72 | |||
51 | struct snd_bebob { | 73 | struct snd_bebob { |
52 | struct snd_card *card; | 74 | struct snd_card *card; |
53 | struct fw_unit *unit; | 75 | struct fw_unit *unit; |
@@ -56,6 +78,8 @@ struct snd_bebob { | |||
56 | struct mutex mutex; | 78 | struct mutex mutex; |
57 | spinlock_t lock; | 79 | spinlock_t lock; |
58 | 80 | ||
81 | const struct snd_bebob_spec *spec; | ||
82 | |||
59 | unsigned int midi_input_ports; | 83 | unsigned int midi_input_ports; |
60 | unsigned int midi_output_ports; | 84 | unsigned int midi_output_ports; |
61 | 85 | ||
@@ -100,6 +124,12 @@ snd_bebob_read_quad(struct fw_unit *unit, u64 addr, u32 *buf) | |||
100 | (void *)buf, sizeof(u32), 0); | 124 | (void *)buf, sizeof(u32), 0); |
101 | } | 125 | } |
102 | 126 | ||
127 | /* AV/C Audio Subunit Specification 1.0 (Oct 2000, 1394TA) */ | ||
128 | int avc_audio_set_selector(struct fw_unit *unit, unsigned int subunit_id, | ||
129 | unsigned int fb_id, unsigned int num); | ||
130 | int avc_audio_get_selector(struct fw_unit *unit, unsigned int subunit_id, | ||
131 | unsigned int fb_id, unsigned int *num); | ||
132 | |||
103 | /* | 133 | /* |
104 | * AVC command extensions, AV/C Unit and Subunit, Revision 17 | 134 | * AVC command extensions, AV/C Unit and Subunit, Revision 17 |
105 | * (Nov 2003, BridgeCo) | 135 | * (Nov 2003, BridgeCo) |
@@ -194,12 +224,13 @@ int snd_bebob_create_pcm_devices(struct snd_bebob *bebob); | |||
194 | 224 | ||
195 | int snd_bebob_create_hwdep_device(struct snd_bebob *bebob); | 225 | int snd_bebob_create_hwdep_device(struct snd_bebob *bebob); |
196 | 226 | ||
197 | #define SND_BEBOB_DEV_ENTRY(vendor, model) \ | 227 | #define SND_BEBOB_DEV_ENTRY(vendor, model, data) \ |
198 | { \ | 228 | { \ |
199 | .match_flags = IEEE1394_MATCH_VENDOR_ID | \ | 229 | .match_flags = IEEE1394_MATCH_VENDOR_ID | \ |
200 | IEEE1394_MATCH_MODEL_ID, \ | 230 | IEEE1394_MATCH_MODEL_ID, \ |
201 | .vendor_id = vendor, \ | 231 | .vendor_id = vendor, \ |
202 | .model_id = model, \ | 232 | .model_id = model, \ |
233 | .driver_data = (kernel_ulong_t)data \ | ||
203 | } | 234 | } |
204 | 235 | ||
205 | #endif | 236 | #endif |
diff --git a/sound/firewire/bebob/bebob_command.c b/sound/firewire/bebob/bebob_command.c index 6a017951a888..9402cc15dbc1 100644 --- a/sound/firewire/bebob/bebob_command.c +++ b/sound/firewire/bebob/bebob_command.c | |||
@@ -8,6 +8,83 @@ | |||
8 | 8 | ||
9 | #include "./bebob.h" | 9 | #include "./bebob.h" |
10 | 10 | ||
11 | int avc_audio_set_selector(struct fw_unit *unit, unsigned int subunit_id, | ||
12 | unsigned int fb_id, unsigned int num) | ||
13 | { | ||
14 | u8 *buf; | ||
15 | int err; | ||
16 | |||
17 | buf = kzalloc(12, GFP_KERNEL); | ||
18 | if (buf == NULL) | ||
19 | return -ENOMEM; | ||
20 | |||
21 | buf[0] = 0x00; /* AV/C CONTROL */ | ||
22 | buf[1] = 0x08 | (0x07 & subunit_id); /* AUDIO SUBUNIT ID */ | ||
23 | buf[2] = 0xb8; /* FUNCTION BLOCK */ | ||
24 | buf[3] = 0x80; /* type is 'selector'*/ | ||
25 | buf[4] = 0xff & fb_id; /* function block id */ | ||
26 | buf[5] = 0x10; /* control attribute is CURRENT */ | ||
27 | buf[6] = 0x02; /* selector length is 2 */ | ||
28 | buf[7] = 0xff & num; /* input function block plug number */ | ||
29 | buf[8] = 0x01; /* control selector is SELECTOR_CONTROL */ | ||
30 | |||
31 | err = fcp_avc_transaction(unit, buf, 12, buf, 12, | ||
32 | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | | ||
33 | BIT(6) | BIT(7) | BIT(8)); | ||
34 | if (err > 0 && err < 9) | ||
35 | err = -EIO; | ||
36 | else if (buf[0] == 0x08) /* NOT IMPLEMENTED */ | ||
37 | err = -ENOSYS; | ||
38 | else if (buf[0] == 0x0a) /* REJECTED */ | ||
39 | err = -EINVAL; | ||
40 | else if (err > 0) | ||
41 | err = 0; | ||
42 | |||
43 | kfree(buf); | ||
44 | return err; | ||
45 | } | ||
46 | |||
47 | int avc_audio_get_selector(struct fw_unit *unit, unsigned int subunit_id, | ||
48 | unsigned int fb_id, unsigned int *num) | ||
49 | { | ||
50 | u8 *buf; | ||
51 | int err; | ||
52 | |||
53 | buf = kzalloc(12, GFP_KERNEL); | ||
54 | if (buf == NULL) | ||
55 | return -ENOMEM; | ||
56 | |||
57 | buf[0] = 0x01; /* AV/C STATUS */ | ||
58 | buf[1] = 0x08 | (0x07 & subunit_id); /* AUDIO SUBUNIT ID */ | ||
59 | buf[2] = 0xb8; /* FUNCTION BLOCK */ | ||
60 | buf[3] = 0x80; /* type is 'selector'*/ | ||
61 | buf[4] = 0xff & fb_id; /* function block id */ | ||
62 | buf[5] = 0x10; /* control attribute is CURRENT */ | ||
63 | buf[6] = 0x02; /* selector length is 2 */ | ||
64 | buf[7] = 0xff; /* input function block plug number */ | ||
65 | buf[8] = 0x01; /* control selector is SELECTOR_CONTROL */ | ||
66 | |||
67 | err = fcp_avc_transaction(unit, buf, 12, buf, 12, | ||
68 | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | | ||
69 | BIT(6) | BIT(8)); | ||
70 | if (err > 0 && err < 9) | ||
71 | err = -EIO; | ||
72 | else if (buf[0] == 0x08) /* NOT IMPLEMENTED */ | ||
73 | err = -ENOSYS; | ||
74 | else if (buf[0] == 0x0a) /* REJECTED */ | ||
75 | err = -EINVAL; | ||
76 | else if (buf[0] == 0x0b) /* IN TRANSITION */ | ||
77 | err = -EAGAIN; | ||
78 | if (err < 0) | ||
79 | goto end; | ||
80 | |||
81 | *num = buf[7]; | ||
82 | err = 0; | ||
83 | end: | ||
84 | kfree(buf); | ||
85 | return err; | ||
86 | } | ||
87 | |||
11 | static inline void | 88 | static inline void |
12 | avc_bridgeco_fill_extension_addr(u8 *buf, u8 *addr) | 89 | avc_bridgeco_fill_extension_addr(u8 *buf, u8 *addr) |
13 | { | 90 | { |
diff --git a/sound/firewire/bebob/bebob_pcm.c b/sound/firewire/bebob/bebob_pcm.c index 9d868171db4e..4a55561ed4ec 100644 --- a/sound/firewire/bebob/bebob_pcm.c +++ b/sound/firewire/bebob/bebob_pcm.c | |||
@@ -155,6 +155,7 @@ static int | |||
155 | pcm_open(struct snd_pcm_substream *substream) | 155 | pcm_open(struct snd_pcm_substream *substream) |
156 | { | 156 | { |
157 | struct snd_bebob *bebob = substream->private_data; | 157 | struct snd_bebob *bebob = substream->private_data; |
158 | struct snd_bebob_rate_spec *spec = bebob->spec->rate; | ||
158 | unsigned int sampling_rate; | 159 | unsigned int sampling_rate; |
159 | bool internal; | 160 | bool internal; |
160 | int err; | 161 | int err; |
@@ -178,7 +179,7 @@ pcm_open(struct snd_pcm_substream *substream) | |||
178 | if (!internal || | 179 | if (!internal || |
179 | amdtp_stream_pcm_running(&bebob->tx_stream) || | 180 | amdtp_stream_pcm_running(&bebob->tx_stream) || |
180 | amdtp_stream_pcm_running(&bebob->rx_stream)) { | 181 | amdtp_stream_pcm_running(&bebob->rx_stream)) { |
181 | err = snd_bebob_stream_get_rate(bebob, &sampling_rate); | 182 | err = spec->get(bebob, &sampling_rate); |
182 | if (err < 0) { | 183 | if (err < 0) { |
183 | dev_err(&bebob->unit->device, | 184 | dev_err(&bebob->unit->device, |
184 | "fail to get sampling rate: %d\n", err); | 185 | "fail to get sampling rate: %d\n", err); |
diff --git a/sound/firewire/bebob/bebob_proc.c b/sound/firewire/bebob/bebob_proc.c index c31ca4f42a58..335da64506e0 100644 --- a/sound/firewire/bebob/bebob_proc.c +++ b/sound/firewire/bebob/bebob_proc.c | |||
@@ -69,6 +69,39 @@ end: | |||
69 | } | 69 | } |
70 | 70 | ||
71 | static void | 71 | static void |
72 | proc_read_meters(struct snd_info_entry *entry, | ||
73 | struct snd_info_buffer *buffer) | ||
74 | { | ||
75 | struct snd_bebob *bebob = entry->private_data; | ||
76 | struct snd_bebob_meter_spec *spec = bebob->spec->meter; | ||
77 | u32 *buf; | ||
78 | unsigned int i, c, channels, size; | ||
79 | |||
80 | if (spec == NULL) | ||
81 | return; | ||
82 | |||
83 | channels = spec->num * 2; | ||
84 | size = channels * sizeof(u32); | ||
85 | buf = kmalloc(size, GFP_KERNEL); | ||
86 | if (buf == NULL) | ||
87 | return; | ||
88 | |||
89 | if (spec->get(bebob, buf, size) < 0) | ||
90 | goto end; | ||
91 | |||
92 | for (i = 0, c = 1; i < channels; i++) { | ||
93 | snd_iprintf(buffer, "%s %d:\t%d\n", | ||
94 | spec->labels[i / 2], c++, buf[i]); | ||
95 | if ((i + 1 < channels - 1) && | ||
96 | (strcmp(spec->labels[i / 2], | ||
97 | spec->labels[(i + 1) / 2]) != 0)) | ||
98 | c = 1; | ||
99 | } | ||
100 | end: | ||
101 | kfree(buf); | ||
102 | } | ||
103 | |||
104 | static void | ||
72 | proc_read_formation(struct snd_info_entry *entry, | 105 | proc_read_formation(struct snd_info_entry *entry, |
73 | struct snd_info_buffer *buffer) | 106 | struct snd_info_buffer *buffer) |
74 | { | 107 | { |
@@ -100,16 +133,25 @@ proc_read_clock(struct snd_info_entry *entry, | |||
100 | struct snd_info_buffer *buffer) | 133 | struct snd_info_buffer *buffer) |
101 | { | 134 | { |
102 | struct snd_bebob *bebob = entry->private_data; | 135 | struct snd_bebob *bebob = entry->private_data; |
103 | unsigned int rate; | 136 | struct snd_bebob_rate_spec *rate_spec = bebob->spec->rate; |
137 | struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock; | ||
138 | unsigned int rate, id; | ||
104 | bool internal; | 139 | bool internal; |
105 | 140 | ||
106 | if (snd_bebob_stream_get_rate(bebob, &rate) >= 0) | 141 | if (rate_spec->get(bebob, &rate) >= 0) |
107 | snd_iprintf(buffer, "Sampling rate: %d\n", rate); | 142 | snd_iprintf(buffer, "Sampling rate: %d\n", rate); |
108 | 143 | ||
109 | if (snd_bebob_stream_check_internal_clock(bebob, &internal) >= 0) | 144 | if (clk_spec) { |
110 | snd_iprintf(buffer, "Clock Source: %s (MSU-dest: %d)", | 145 | if (clk_spec->get(bebob, &id) >= 0) |
111 | (internal) ? "Internal" : "External", | 146 | snd_iprintf(buffer, "Clock Source: %s\n", |
112 | bebob->sync_input_plug); | 147 | clk_spec->labels[id]); |
148 | } else { | ||
149 | if (snd_bebob_stream_check_internal_clock(bebob, | ||
150 | &internal) >= 0) | ||
151 | snd_iprintf(buffer, "Clock Source: %s (MSU-dest: %d)\n", | ||
152 | (internal) ? "Internal" : "External", | ||
153 | bebob->sync_input_plug); | ||
154 | } | ||
113 | } | 155 | } |
114 | 156 | ||
115 | static void | 157 | static void |
@@ -148,4 +190,7 @@ void snd_bebob_proc_init(struct snd_bebob *bebob) | |||
148 | add_node(bebob, root, "clock", proc_read_clock); | 190 | add_node(bebob, root, "clock", proc_read_clock); |
149 | add_node(bebob, root, "firmware", proc_read_hw_info); | 191 | add_node(bebob, root, "firmware", proc_read_hw_info); |
150 | add_node(bebob, root, "formation", proc_read_formation); | 192 | add_node(bebob, root, "formation", proc_read_formation); |
193 | |||
194 | if (bebob->spec->meter != NULL) | ||
195 | add_node(bebob, root, "meter", proc_read_meters); | ||
151 | } | 196 | } |
diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index 85b4fd661787..4a21dcf95d95 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c | |||
@@ -119,13 +119,27 @@ end: | |||
119 | int | 119 | int |
120 | snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal) | 120 | snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal) |
121 | { | 121 | { |
122 | struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock; | ||
122 | u8 addr[AVC_BRIDGECO_ADDR_BYTES], input[7]; | 123 | u8 addr[AVC_BRIDGECO_ADDR_BYTES], input[7]; |
124 | unsigned int id; | ||
123 | int err = 0; | 125 | int err = 0; |
124 | 126 | ||
125 | *internal = false; | 127 | *internal = false; |
126 | 128 | ||
129 | /* 1.The device has its own operation to switch source of clock */ | ||
130 | if (clk_spec) { | ||
131 | err = clk_spec->get(bebob, &id); | ||
132 | if (err < 0) | ||
133 | dev_err(&bebob->unit->device, | ||
134 | "fail to get clock source: %d\n", err); | ||
135 | else if (strncmp(clk_spec->labels[id], SND_BEBOB_CLOCK_INTERNAL, | ||
136 | strlen(SND_BEBOB_CLOCK_INTERNAL)) == 0) | ||
137 | *internal = true; | ||
138 | goto end; | ||
139 | } | ||
140 | |||
127 | /* | 141 | /* |
128 | * 1.The device don't support to switch source of clock then assumed | 142 | * 2.The device don't support to switch source of clock then assumed |
129 | * to use internal clock always | 143 | * to use internal clock always |
130 | */ | 144 | */ |
131 | if (bebob->sync_input_plug < 0) { | 145 | if (bebob->sync_input_plug < 0) { |
@@ -134,7 +148,7 @@ snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal) | |||
134 | } | 148 | } |
135 | 149 | ||
136 | /* | 150 | /* |
137 | * 2.The device supports to switch source of clock by an usual way. | 151 | * 3.The device supports to switch source of clock by an usual way. |
138 | * Let's check input for 'Music Sub Unit Sync Input' plug. | 152 | * Let's check input for 'Music Sub Unit Sync Input' plug. |
139 | */ | 153 | */ |
140 | avc_bridgeco_fill_msu_addr(addr, AVC_BRIDGECO_PLUG_DIR_IN, | 154 | avc_bridgeco_fill_msu_addr(addr, AVC_BRIDGECO_PLUG_DIR_IN, |
@@ -442,6 +456,7 @@ end: | |||
442 | 456 | ||
443 | int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, int rate) | 457 | int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, int rate) |
444 | { | 458 | { |
459 | struct snd_bebob_rate_spec *rate_spec = bebob->spec->rate; | ||
445 | struct amdtp_stream *master, *slave; | 460 | struct amdtp_stream *master, *slave; |
446 | atomic_t *slave_substreams; | 461 | atomic_t *slave_substreams; |
447 | enum cip_flags sync_mode; | 462 | enum cip_flags sync_mode; |
@@ -508,7 +523,7 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, int rate) | |||
508 | break_both_connections(bebob); | 523 | break_both_connections(bebob); |
509 | 524 | ||
510 | /* stop streams if rate is different */ | 525 | /* stop streams if rate is different */ |
511 | err = snd_bebob_stream_get_rate(bebob, &curr_rate); | 526 | err = rate_spec->get(bebob, &curr_rate); |
512 | if (err < 0) { | 527 | if (err < 0) { |
513 | dev_err(&bebob->unit->device, | 528 | dev_err(&bebob->unit->device, |
514 | "fail to get sampling rate: %d\n", err); | 529 | "fail to get sampling rate: %d\n", err); |
@@ -532,7 +547,7 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, int rate) | |||
532 | * If establishing connections at first, Yamaha GO46 | 547 | * If establishing connections at first, Yamaha GO46 |
533 | * (and maybe Terratec X24) don't generate sound. | 548 | * (and maybe Terratec X24) don't generate sound. |
534 | */ | 549 | */ |
535 | err = snd_bebob_stream_set_rate(bebob, rate); | 550 | err = rate_spec->set(bebob, rate); |
536 | if (err < 0) { | 551 | if (err < 0) { |
537 | dev_err(&bebob->unit->device, | 552 | dev_err(&bebob->unit->device, |
538 | "fail to set sampling rate: %d\n", | 553 | "fail to set sampling rate: %d\n", |
@@ -822,6 +837,7 @@ end: | |||
822 | 837 | ||
823 | int snd_bebob_stream_discover(struct snd_bebob *bebob) | 838 | int snd_bebob_stream_discover(struct snd_bebob *bebob) |
824 | { | 839 | { |
840 | struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock; | ||
825 | u8 plugs[AVC_PLUG_INFO_BUF_BYTES], addr[AVC_BRIDGECO_ADDR_BYTES]; | 841 | u8 plugs[AVC_PLUG_INFO_BUF_BYTES], addr[AVC_BRIDGECO_ADDR_BYTES]; |
826 | enum avc_bridgeco_plug_type type; | 842 | enum avc_bridgeco_plug_type type; |
827 | unsigned int i; | 843 | unsigned int i; |
@@ -908,7 +924,8 @@ int snd_bebob_stream_discover(struct snd_bebob *bebob) | |||
908 | } | 924 | } |
909 | 925 | ||
910 | /* for check source of clock later */ | 926 | /* for check source of clock later */ |
911 | err = seek_msu_sync_input_plug(bebob); | 927 | if (!clk_spec) |
928 | err = seek_msu_sync_input_plug(bebob); | ||
912 | end: | 929 | end: |
913 | return err; | 930 | return err; |
914 | } | 931 | } |