diff options
author | Takashi Sakamoto <o-takashi@sakamocchi.jp> | 2014-12-08 10:10:42 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2014-12-10 04:47:37 -0500 |
commit | 5cd1d3f47a6321612a51ab88ffe8ef65120fcbe0 (patch) | |
tree | f2f537e9ec9185754441c37f7896788a76795312 /sound/firewire | |
parent | 5b59d8098d2a3fa8ea4ad07b96f62c00c3b3e8d3 (diff) |
ALSA: oxfw: Change the way to make PCM rules/constraints
In previous commit, this driver can get to know stream formations at
each supported sampling rates. This commit uses it to make PCM
rules/constraints and obsoletes hard-coded rules/constraints.
For this purpose, this commit adds 'struct snd_oxfw_stream_formation' and
snd_oxfw_stream_parse_format() to parse data channel formation of data
block.
According to datasheet of OXFW970/971, they support 32.0kHz to 196.0kHz.
As long as developers investigate, some devices are confirmed to have
several formats for the same sampling rate.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Acked-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/firewire')
-rw-r--r-- | sound/firewire/oxfw/oxfw-pcm.c | 197 | ||||
-rw-r--r-- | sound/firewire/oxfw/oxfw-stream.c | 268 | ||||
-rw-r--r-- | sound/firewire/oxfw/oxfw.c | 10 | ||||
-rw-r--r-- | sound/firewire/oxfw/oxfw.h | 21 |
4 files changed, 410 insertions, 86 deletions
diff --git a/sound/firewire/oxfw/oxfw-pcm.c b/sound/firewire/oxfw/oxfw-pcm.c index d39f17a8f8c0..0c0be984edce 100644 --- a/sound/firewire/oxfw/oxfw-pcm.c +++ b/sound/firewire/oxfw/oxfw-pcm.c | |||
@@ -7,117 +7,152 @@ | |||
7 | 7 | ||
8 | #include "oxfw.h" | 8 | #include "oxfw.h" |
9 | 9 | ||
10 | static int firewave_rate_constraint(struct snd_pcm_hw_params *params, | 10 | static int hw_rule_rate(struct snd_pcm_hw_params *params, |
11 | struct snd_pcm_hw_rule *rule) | 11 | struct snd_pcm_hw_rule *rule) |
12 | { | 12 | { |
13 | static unsigned int stereo_rates[] = { 48000, 96000 }; | 13 | u8 **formats = rule->private; |
14 | struct snd_interval *channels = | 14 | struct snd_interval *r = |
15 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); | 15 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); |
16 | struct snd_interval *rate = | 16 | const struct snd_interval *c = |
17 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | 17 | hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS); |
18 | 18 | struct snd_interval t = { | |
19 | /* two channels work only at 48/96 kHz */ | 19 | .min = UINT_MAX, .max = 0, .integer = 1 |
20 | if (snd_interval_max(channels) < 6) | 20 | }; |
21 | return snd_interval_list(rate, 2, stereo_rates, 0); | 21 | struct snd_oxfw_stream_formation formation; |
22 | return 0; | 22 | unsigned int i, err; |
23 | |||
24 | for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) { | ||
25 | if (formats[i] == NULL) | ||
26 | continue; | ||
27 | |||
28 | err = snd_oxfw_stream_parse_format(formats[i], &formation); | ||
29 | if (err < 0) | ||
30 | continue; | ||
31 | if (!snd_interval_test(c, formation.pcm)) | ||
32 | continue; | ||
33 | |||
34 | t.min = min(t.min, formation.rate); | ||
35 | t.max = max(t.max, formation.rate); | ||
36 | |||
37 | } | ||
38 | return snd_interval_refine(r, &t); | ||
23 | } | 39 | } |
24 | 40 | ||
25 | static int firewave_channels_constraint(struct snd_pcm_hw_params *params, | 41 | static int hw_rule_channels(struct snd_pcm_hw_params *params, |
26 | struct snd_pcm_hw_rule *rule) | 42 | struct snd_pcm_hw_rule *rule) |
27 | { | 43 | { |
28 | static const struct snd_interval all_channels = { .min = 6, .max = 6 }; | 44 | u8 **formats = rule->private; |
29 | struct snd_interval *rate = | 45 | struct snd_interval *c = |
30 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | 46 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); |
31 | struct snd_interval *channels = | 47 | const struct snd_interval *r = |
32 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); | 48 | hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE); |
33 | 49 | struct snd_oxfw_stream_formation formation; | |
34 | /* 32/44.1 kHz work only with all six channels */ | 50 | unsigned int i, j, err; |
35 | if (snd_interval_max(rate) < 48000) | 51 | unsigned int count, list[SND_OXFW_STREAM_FORMAT_ENTRIES] = {0}; |
36 | return snd_interval_refine(channels, &all_channels); | 52 | |
37 | return 0; | 53 | count = 0; |
54 | for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) { | ||
55 | if (formats[i] == NULL) | ||
56 | break; | ||
57 | |||
58 | err = snd_oxfw_stream_parse_format(formats[i], &formation); | ||
59 | if (err < 0) | ||
60 | continue; | ||
61 | if (!snd_interval_test(r, formation.rate)) | ||
62 | continue; | ||
63 | if (list[count] == formation.pcm) | ||
64 | continue; | ||
65 | |||
66 | for (j = 0; j < ARRAY_SIZE(list); j++) { | ||
67 | if (list[j] == formation.pcm) | ||
68 | break; | ||
69 | } | ||
70 | if (j == ARRAY_SIZE(list)) { | ||
71 | list[count] = formation.pcm; | ||
72 | if (++count == ARRAY_SIZE(list)) | ||
73 | break; | ||
74 | } | ||
75 | } | ||
76 | |||
77 | return snd_interval_list(c, count, list, 0); | ||
38 | } | 78 | } |
39 | 79 | ||
40 | int firewave_constraints(struct snd_pcm_runtime *runtime) | 80 | static void limit_channels_and_rates(struct snd_pcm_hardware *hw, u8 **formats) |
41 | { | 81 | { |
42 | static unsigned int channels_list[] = { 2, 6 }; | 82 | struct snd_oxfw_stream_formation formation; |
43 | static struct snd_pcm_hw_constraint_list channels_list_constraint = { | 83 | unsigned int i, err; |
44 | .count = 2, | ||
45 | .list = channels_list, | ||
46 | }; | ||
47 | int err; | ||
48 | 84 | ||
49 | runtime->hw.rates = SNDRV_PCM_RATE_32000 | | 85 | hw->channels_min = UINT_MAX; |
50 | SNDRV_PCM_RATE_44100 | | 86 | hw->channels_max = 0; |
51 | SNDRV_PCM_RATE_48000 | | ||
52 | SNDRV_PCM_RATE_96000; | ||
53 | runtime->hw.channels_max = 6; | ||
54 | 87 | ||
55 | err = snd_pcm_hw_constraint_list(runtime, 0, | 88 | hw->rate_min = UINT_MAX; |
56 | SNDRV_PCM_HW_PARAM_CHANNELS, | 89 | hw->rate_max = 0; |
57 | &channels_list_constraint); | 90 | hw->rates = 0; |
58 | if (err < 0) | ||
59 | return err; | ||
60 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | ||
61 | firewave_rate_constraint, NULL, | ||
62 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | ||
63 | if (err < 0) | ||
64 | return err; | ||
65 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
66 | firewave_channels_constraint, NULL, | ||
67 | SNDRV_PCM_HW_PARAM_RATE, -1); | ||
68 | if (err < 0) | ||
69 | return err; | ||
70 | 91 | ||
71 | return 0; | 92 | for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) { |
93 | if (formats[i] == NULL) | ||
94 | break; | ||
95 | |||
96 | err = snd_oxfw_stream_parse_format(formats[i], &formation); | ||
97 | if (err < 0) | ||
98 | continue; | ||
99 | |||
100 | hw->channels_min = min(hw->channels_min, formation.pcm); | ||
101 | hw->channels_max = max(hw->channels_max, formation.pcm); | ||
102 | |||
103 | hw->rate_min = min(hw->rate_min, formation.rate); | ||
104 | hw->rate_max = max(hw->rate_max, formation.rate); | ||
105 | hw->rates |= snd_pcm_rate_to_rate_bit(formation.rate); | ||
106 | } | ||
72 | } | 107 | } |
73 | 108 | ||
74 | int lacie_speakers_constraints(struct snd_pcm_runtime *runtime) | 109 | static void limit_period_and_buffer(struct snd_pcm_hardware *hw) |
75 | { | 110 | { |
76 | runtime->hw.rates = SNDRV_PCM_RATE_32000 | | 111 | hw->periods_min = 2; /* SNDRV_PCM_INFO_BATCH */ |
77 | SNDRV_PCM_RATE_44100 | | 112 | hw->periods_max = UINT_MAX; |
78 | SNDRV_PCM_RATE_48000 | | ||
79 | SNDRV_PCM_RATE_88200 | | ||
80 | SNDRV_PCM_RATE_96000; | ||
81 | 113 | ||
82 | return 0; | 114 | hw->period_bytes_min = 4 * hw->channels_max; /* bytes for a frame */ |
115 | |||
116 | /* Just to prevent from allocating much pages. */ | ||
117 | hw->period_bytes_max = hw->period_bytes_min * 2048; | ||
118 | hw->buffer_bytes_max = hw->period_bytes_max * hw->periods_min; | ||
83 | } | 119 | } |
84 | 120 | ||
85 | static int pcm_open(struct snd_pcm_substream *substream) | 121 | static int pcm_open(struct snd_pcm_substream *substream) |
86 | { | 122 | { |
87 | static const struct snd_pcm_hardware hardware = { | ||
88 | .info = SNDRV_PCM_INFO_MMAP | | ||
89 | SNDRV_PCM_INFO_MMAP_VALID | | ||
90 | SNDRV_PCM_INFO_BATCH | | ||
91 | SNDRV_PCM_INFO_INTERLEAVED | | ||
92 | SNDRV_PCM_INFO_BLOCK_TRANSFER, | ||
93 | .formats = AMDTP_OUT_PCM_FORMAT_BITS, | ||
94 | .channels_min = 2, | ||
95 | .channels_max = 2, | ||
96 | .buffer_bytes_max = 4 * 1024 * 1024, | ||
97 | .period_bytes_min = 1, | ||
98 | .period_bytes_max = UINT_MAX, | ||
99 | .periods_min = 1, | ||
100 | .periods_max = UINT_MAX, | ||
101 | }; | ||
102 | struct snd_oxfw *oxfw = substream->private_data; | 123 | struct snd_oxfw *oxfw = substream->private_data; |
103 | struct snd_pcm_runtime *runtime = substream->runtime; | 124 | struct snd_pcm_runtime *runtime = substream->runtime; |
104 | bool used; | 125 | u8 **formats; |
105 | int err; | 126 | int err; |
106 | 127 | ||
107 | err = cmp_connection_check_used(&oxfw->in_conn, &used); | 128 | formats = oxfw->rx_stream_formats; |
108 | if ((err < 0) || used) | 129 | |
109 | goto end; | 130 | runtime->hw.info = SNDRV_PCM_INFO_BATCH | |
131 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
132 | SNDRV_PCM_INFO_INTERLEAVED | | ||
133 | SNDRV_PCM_INFO_MMAP | | ||
134 | SNDRV_PCM_INFO_MMAP_VALID; | ||
110 | 135 | ||
111 | runtime->hw = hardware; | 136 | limit_channels_and_rates(&runtime->hw, formats); |
137 | limit_period_and_buffer(&runtime->hw); | ||
112 | 138 | ||
113 | err = oxfw->device_info->pcm_constraints(runtime); | 139 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, |
140 | hw_rule_channels, formats, | ||
141 | SNDRV_PCM_HW_PARAM_RATE, -1); | ||
114 | if (err < 0) | 142 | if (err < 0) |
115 | goto end; | 143 | goto end; |
116 | err = snd_pcm_limit_hw_rates(runtime); | 144 | |
145 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | ||
146 | hw_rule_rate, formats, | ||
147 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | ||
117 | if (err < 0) | 148 | if (err < 0) |
118 | goto end; | 149 | goto end; |
119 | 150 | ||
120 | err = amdtp_stream_add_pcm_hw_constraints(&oxfw->rx_stream, runtime); | 151 | err = amdtp_stream_add_pcm_hw_constraints(&oxfw->rx_stream, runtime); |
152 | if (err < 0) | ||
153 | goto end; | ||
154 | |||
155 | snd_pcm_set_sync(substream); | ||
121 | end: | 156 | end: |
122 | return err; | 157 | return err; |
123 | } | 158 | } |
diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c index ebd156f3e29d..17e3802e6ac2 100644 --- a/sound/firewire/oxfw/oxfw-stream.c +++ b/sound/firewire/oxfw/oxfw-stream.c | |||
@@ -8,6 +8,35 @@ | |||
8 | 8 | ||
9 | #include "oxfw.h" | 9 | #include "oxfw.h" |
10 | 10 | ||
11 | #define AVC_GENERIC_FRAME_MAXIMUM_BYTES 512 | ||
12 | |||
13 | /* | ||
14 | * According to datasheet of Oxford Semiconductor: | ||
15 | * OXFW970: 32.0/44.1/48.0/96.0 Khz, 8 audio channels I/O | ||
16 | * OXFW971: 32.0/44.1/48.0/88.2/96.0/192.0 kHz, 16 audio channels I/O, MIDI I/O | ||
17 | */ | ||
18 | static const unsigned int oxfw_rate_table[] = { | ||
19 | [0] = 32000, | ||
20 | [1] = 44100, | ||
21 | [2] = 48000, | ||
22 | [3] = 88200, | ||
23 | [4] = 96000, | ||
24 | [5] = 192000, | ||
25 | }; | ||
26 | |||
27 | /* | ||
28 | * See Table 5.7 – Sampling frequency for Multi-bit Audio | ||
29 | * in AV/C Stream Format Information Specification 1.1 (Apr 2005, 1394TA) | ||
30 | */ | ||
31 | static const unsigned int avc_stream_rate_table[] = { | ||
32 | [0] = 0x02, | ||
33 | [1] = 0x03, | ||
34 | [2] = 0x04, | ||
35 | [3] = 0x0a, | ||
36 | [4] = 0x05, | ||
37 | [5] = 0x07, | ||
38 | }; | ||
39 | |||
11 | int snd_oxfw_stream_init_simplex(struct snd_oxfw *oxfw) | 40 | int snd_oxfw_stream_init_simplex(struct snd_oxfw *oxfw) |
12 | { | 41 | { |
13 | int err; | 42 | int err; |
@@ -78,3 +107,242 @@ void snd_oxfw_stream_update_simplex(struct snd_oxfw *oxfw) | |||
78 | else | 107 | else |
79 | amdtp_stream_update(&oxfw->rx_stream); | 108 | amdtp_stream_update(&oxfw->rx_stream); |
80 | } | 109 | } |
110 | |||
111 | /* | ||
112 | * See Table 6.16 - AM824 Stream Format | ||
113 | * Figure 6.19 - format_information field for AM824 Compound | ||
114 | * in AV/C Stream Format Information Specification 1.1 (Apr 2005, 1394TA) | ||
115 | * Also 'Clause 12 AM824 sequence adaption layers' in IEC 61883-6:2005 | ||
116 | */ | ||
117 | int snd_oxfw_stream_parse_format(u8 *format, | ||
118 | struct snd_oxfw_stream_formation *formation) | ||
119 | { | ||
120 | unsigned int i, e, channels, type; | ||
121 | |||
122 | memset(formation, 0, sizeof(struct snd_oxfw_stream_formation)); | ||
123 | |||
124 | /* | ||
125 | * this module can support a hierarchy combination that: | ||
126 | * Root: Audio and Music (0x90) | ||
127 | * Level 1: AM824 Compound (0x40) | ||
128 | */ | ||
129 | if ((format[0] != 0x90) || (format[1] != 0x40)) | ||
130 | return -ENOSYS; | ||
131 | |||
132 | /* check the sampling rate */ | ||
133 | for (i = 0; i < ARRAY_SIZE(avc_stream_rate_table); i++) { | ||
134 | if (format[2] == avc_stream_rate_table[i]) | ||
135 | break; | ||
136 | } | ||
137 | if (i == ARRAY_SIZE(avc_stream_rate_table)) | ||
138 | return -ENOSYS; | ||
139 | |||
140 | formation->rate = oxfw_rate_table[i]; | ||
141 | |||
142 | for (e = 0; e < format[4]; e++) { | ||
143 | channels = format[5 + e * 2]; | ||
144 | type = format[6 + e * 2]; | ||
145 | |||
146 | switch (type) { | ||
147 | /* IEC 60958 Conformant, currently handled as MBLA */ | ||
148 | case 0x00: | ||
149 | /* Multi Bit Linear Audio (Raw) */ | ||
150 | case 0x06: | ||
151 | formation->pcm += channels; | ||
152 | break; | ||
153 | /* MIDI Conformant */ | ||
154 | case 0x0d: | ||
155 | formation->midi = channels; | ||
156 | break; | ||
157 | /* IEC 61937-3 to 7 */ | ||
158 | case 0x01: | ||
159 | case 0x02: | ||
160 | case 0x03: | ||
161 | case 0x04: | ||
162 | case 0x05: | ||
163 | /* Multi Bit Linear Audio */ | ||
164 | case 0x07: /* DVD-Audio */ | ||
165 | case 0x0c: /* High Precision */ | ||
166 | /* One Bit Audio */ | ||
167 | case 0x08: /* (Plain) Raw */ | ||
168 | case 0x09: /* (Plain) SACD */ | ||
169 | case 0x0a: /* (Encoded) Raw */ | ||
170 | case 0x0b: /* (Encoded) SACD */ | ||
171 | /* SMPTE Time-Code conformant */ | ||
172 | case 0x0e: | ||
173 | /* Sample Count */ | ||
174 | case 0x0f: | ||
175 | /* Anciliary Data */ | ||
176 | case 0x10: | ||
177 | /* Synchronization Stream (Stereo Raw audio) */ | ||
178 | case 0x40: | ||
179 | /* Don't care */ | ||
180 | case 0xff: | ||
181 | default: | ||
182 | return -ENOSYS; /* not supported */ | ||
183 | } | ||
184 | } | ||
185 | |||
186 | if (formation->pcm > AMDTP_MAX_CHANNELS_FOR_PCM || | ||
187 | formation->midi > AMDTP_MAX_CHANNELS_FOR_MIDI) | ||
188 | return -ENOSYS; | ||
189 | |||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | static int | ||
194 | assume_stream_formats(struct snd_oxfw *oxfw, enum avc_general_plug_dir dir, | ||
195 | unsigned int pid, u8 *buf, unsigned int *len, | ||
196 | u8 **formats) | ||
197 | { | ||
198 | struct snd_oxfw_stream_formation formation; | ||
199 | unsigned int i, eid; | ||
200 | int err; | ||
201 | |||
202 | /* get format at current sampling rate */ | ||
203 | err = avc_stream_get_format_single(oxfw->unit, dir, pid, buf, len); | ||
204 | if (err < 0) { | ||
205 | dev_err(&oxfw->unit->device, | ||
206 | "fail to get current stream format for isoc %s plug %d:%d\n", | ||
207 | (dir == AVC_GENERAL_PLUG_DIR_IN) ? "in" : "out", | ||
208 | pid, err); | ||
209 | goto end; | ||
210 | } | ||
211 | |||
212 | /* parse and set stream format */ | ||
213 | eid = 0; | ||
214 | err = snd_oxfw_stream_parse_format(buf, &formation); | ||
215 | if (err < 0) | ||
216 | goto end; | ||
217 | |||
218 | formats[eid] = kmalloc(*len, GFP_KERNEL); | ||
219 | if (formats[eid] == NULL) { | ||
220 | err = -ENOMEM; | ||
221 | goto end; | ||
222 | } | ||
223 | memcpy(formats[eid], buf, *len); | ||
224 | |||
225 | /* apply the format for each available sampling rate */ | ||
226 | for (i = 0; i < ARRAY_SIZE(oxfw_rate_table); i++) { | ||
227 | if (formation.rate == oxfw_rate_table[i]) | ||
228 | continue; | ||
229 | |||
230 | err = avc_general_inquiry_sig_fmt(oxfw->unit, | ||
231 | oxfw_rate_table[i], | ||
232 | dir, pid); | ||
233 | if (err < 0) | ||
234 | continue; | ||
235 | |||
236 | eid++; | ||
237 | formats[eid] = kmalloc(*len, GFP_KERNEL); | ||
238 | if (formats[eid] == NULL) { | ||
239 | err = -ENOMEM; | ||
240 | goto end; | ||
241 | } | ||
242 | memcpy(formats[eid], buf, *len); | ||
243 | formats[eid][2] = avc_stream_rate_table[i]; | ||
244 | } | ||
245 | |||
246 | err = 0; | ||
247 | oxfw->assumed = true; | ||
248 | end: | ||
249 | return err; | ||
250 | } | ||
251 | |||
252 | static int fill_stream_formats(struct snd_oxfw *oxfw, | ||
253 | enum avc_general_plug_dir dir, | ||
254 | unsigned short pid) | ||
255 | { | ||
256 | u8 *buf, **formats; | ||
257 | unsigned int len, eid = 0; | ||
258 | struct snd_oxfw_stream_formation dummy; | ||
259 | int err; | ||
260 | |||
261 | buf = kmalloc(AVC_GENERIC_FRAME_MAXIMUM_BYTES, GFP_KERNEL); | ||
262 | if (buf == NULL) | ||
263 | return -ENOMEM; | ||
264 | |||
265 | formats = oxfw->rx_stream_formats; | ||
266 | |||
267 | /* get first entry */ | ||
268 | len = AVC_GENERIC_FRAME_MAXIMUM_BYTES; | ||
269 | err = avc_stream_get_format_list(oxfw->unit, dir, 0, buf, &len, 0); | ||
270 | if (err == -ENOSYS) { | ||
271 | /* LIST subfunction is not implemented */ | ||
272 | len = AVC_GENERIC_FRAME_MAXIMUM_BYTES; | ||
273 | err = assume_stream_formats(oxfw, dir, pid, buf, &len, | ||
274 | formats); | ||
275 | goto end; | ||
276 | } else if (err < 0) { | ||
277 | dev_err(&oxfw->unit->device, | ||
278 | "fail to get stream format %d for isoc %s plug %d:%d\n", | ||
279 | eid, (dir == AVC_GENERAL_PLUG_DIR_IN) ? "in" : "out", | ||
280 | pid, err); | ||
281 | goto end; | ||
282 | } | ||
283 | |||
284 | /* LIST subfunction is implemented */ | ||
285 | while (eid < SND_OXFW_STREAM_FORMAT_ENTRIES) { | ||
286 | /* The format is too short. */ | ||
287 | if (len < 3) { | ||
288 | err = -EIO; | ||
289 | break; | ||
290 | } | ||
291 | |||
292 | /* parse and set stream format */ | ||
293 | err = snd_oxfw_stream_parse_format(buf, &dummy); | ||
294 | if (err < 0) | ||
295 | break; | ||
296 | |||
297 | formats[eid] = kmalloc(len, GFP_KERNEL); | ||
298 | if (formats[eid] == NULL) { | ||
299 | err = -ENOMEM; | ||
300 | break; | ||
301 | } | ||
302 | memcpy(formats[eid], buf, len); | ||
303 | |||
304 | /* get next entry */ | ||
305 | len = AVC_GENERIC_FRAME_MAXIMUM_BYTES; | ||
306 | err = avc_stream_get_format_list(oxfw->unit, dir, 0, | ||
307 | buf, &len, ++eid); | ||
308 | /* No entries remained. */ | ||
309 | if (err == -EINVAL) { | ||
310 | err = 0; | ||
311 | break; | ||
312 | } else if (err < 0) { | ||
313 | dev_err(&oxfw->unit->device, | ||
314 | "fail to get stream format %d for isoc %s plug %d:%d\n", | ||
315 | eid, (dir == AVC_GENERAL_PLUG_DIR_IN) ? "in" : | ||
316 | "out", | ||
317 | pid, err); | ||
318 | break; | ||
319 | } | ||
320 | } | ||
321 | end: | ||
322 | kfree(buf); | ||
323 | return err; | ||
324 | } | ||
325 | |||
326 | int snd_oxfw_stream_discover(struct snd_oxfw *oxfw) | ||
327 | { | ||
328 | u8 plugs[AVC_PLUG_INFO_BUF_BYTES]; | ||
329 | int err; | ||
330 | |||
331 | /* the number of plugs for isoc in/out, ext in/out */ | ||
332 | err = avc_general_get_plug_info(oxfw->unit, 0x1f, 0x07, 0x00, plugs); | ||
333 | if (err < 0) { | ||
334 | dev_err(&oxfw->unit->device, | ||
335 | "fail to get info for isoc/external in/out plugs: %d\n", | ||
336 | err); | ||
337 | goto end; | ||
338 | } else if (plugs[0] == 0) { | ||
339 | err = -ENOSYS; | ||
340 | goto end; | ||
341 | } | ||
342 | |||
343 | /* use iPCR[0] if exists */ | ||
344 | if (plugs[0] > 0) | ||
345 | err = fill_stream_formats(oxfw, AVC_GENERAL_PLUG_DIR_IN, 0); | ||
346 | end: | ||
347 | return err; | ||
348 | } | ||
diff --git a/sound/firewire/oxfw/oxfw.c b/sound/firewire/oxfw/oxfw.c index dd576bf61c37..a8f9062b2884 100644 --- a/sound/firewire/oxfw/oxfw.c +++ b/sound/firewire/oxfw/oxfw.c | |||
@@ -58,6 +58,10 @@ end: | |||
58 | static void oxfw_card_free(struct snd_card *card) | 58 | static void oxfw_card_free(struct snd_card *card) |
59 | { | 59 | { |
60 | struct snd_oxfw *oxfw = card->private_data; | 60 | struct snd_oxfw *oxfw = card->private_data; |
61 | unsigned int i; | ||
62 | |||
63 | for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) | ||
64 | kfree(oxfw->rx_stream_formats[i]); | ||
61 | 65 | ||
62 | mutex_destroy(&oxfw->mutex); | 66 | mutex_destroy(&oxfw->mutex); |
63 | } | 67 | } |
@@ -81,6 +85,10 @@ static int oxfw_probe(struct fw_unit *unit, | |||
81 | oxfw->unit = unit; | 85 | oxfw->unit = unit; |
82 | oxfw->device_info = (const struct device_info *)id->driver_data; | 86 | oxfw->device_info = (const struct device_info *)id->driver_data; |
83 | 87 | ||
88 | err = snd_oxfw_stream_discover(oxfw); | ||
89 | if (err < 0) | ||
90 | goto error; | ||
91 | |||
84 | err = name_card(oxfw); | 92 | err = name_card(oxfw); |
85 | if (err < 0) | 93 | if (err < 0) |
86 | goto error; | 94 | goto error; |
@@ -136,7 +144,6 @@ static const struct device_info griffin_firewave = { | |||
136 | .driver_name = "FireWave", | 144 | .driver_name = "FireWave", |
137 | .vendor_name = "Griffin", | 145 | .vendor_name = "Griffin", |
138 | .model_name = "FireWave", | 146 | .model_name = "FireWave", |
139 | .pcm_constraints = firewave_constraints, | ||
140 | .mixer_channels = 6, | 147 | .mixer_channels = 6, |
141 | .mute_fb_id = 0x01, | 148 | .mute_fb_id = 0x01, |
142 | .volume_fb_id = 0x02, | 149 | .volume_fb_id = 0x02, |
@@ -146,7 +153,6 @@ static const struct device_info lacie_speakers = { | |||
146 | .driver_name = "FWSpeakers", | 153 | .driver_name = "FWSpeakers", |
147 | .vendor_name = "LaCie", | 154 | .vendor_name = "LaCie", |
148 | .model_name = "FireWire Speakers", | 155 | .model_name = "FireWire Speakers", |
149 | .pcm_constraints = lacie_speakers_constraints, | ||
150 | .mixer_channels = 1, | 156 | .mixer_channels = 1, |
151 | .mute_fb_id = 0x01, | 157 | .mute_fb_id = 0x01, |
152 | .volume_fb_id = 0x01, | 158 | .volume_fb_id = 0x01, |
diff --git a/sound/firewire/oxfw/oxfw.h b/sound/firewire/oxfw/oxfw.h index a7031d414441..9c3d3e352665 100644 --- a/sound/firewire/oxfw/oxfw.h +++ b/sound/firewire/oxfw/oxfw.h | |||
@@ -30,19 +30,24 @@ struct device_info { | |||
30 | const char *driver_name; | 30 | const char *driver_name; |
31 | const char *vendor_name; | 31 | const char *vendor_name; |
32 | const char *model_name; | 32 | const char *model_name; |
33 | int (*pcm_constraints)(struct snd_pcm_runtime *runtime); | ||
34 | unsigned int mixer_channels; | 33 | unsigned int mixer_channels; |
35 | u8 mute_fb_id; | 34 | u8 mute_fb_id; |
36 | u8 volume_fb_id; | 35 | u8 volume_fb_id; |
37 | }; | 36 | }; |
38 | 37 | ||
38 | /* This is an arbitrary number for convinience. */ | ||
39 | #define SND_OXFW_STREAM_FORMAT_ENTRIES 10 | ||
39 | struct snd_oxfw { | 40 | struct snd_oxfw { |
40 | struct snd_card *card; | 41 | struct snd_card *card; |
41 | struct fw_unit *unit; | 42 | struct fw_unit *unit; |
42 | const struct device_info *device_info; | 43 | const struct device_info *device_info; |
43 | struct mutex mutex; | 44 | struct mutex mutex; |
45 | |||
46 | u8 *rx_stream_formats[SND_OXFW_STREAM_FORMAT_ENTRIES]; | ||
47 | bool assumed; | ||
44 | struct cmp_connection in_conn; | 48 | struct cmp_connection in_conn; |
45 | struct amdtp_stream rx_stream; | 49 | struct amdtp_stream rx_stream; |
50 | |||
46 | bool mute; | 51 | bool mute; |
47 | s16 volume[6]; | 52 | s16 volume[6]; |
48 | s16 volume_min; | 53 | s16 volume_min; |
@@ -88,8 +93,18 @@ void snd_oxfw_stream_stop_simplex(struct snd_oxfw *oxfw); | |||
88 | void snd_oxfw_stream_destroy_simplex(struct snd_oxfw *oxfw); | 93 | void snd_oxfw_stream_destroy_simplex(struct snd_oxfw *oxfw); |
89 | void snd_oxfw_stream_update_simplex(struct snd_oxfw *oxfw); | 94 | void snd_oxfw_stream_update_simplex(struct snd_oxfw *oxfw); |
90 | 95 | ||
91 | int firewave_constraints(struct snd_pcm_runtime *runtime); | 96 | struct snd_oxfw_stream_formation { |
92 | int lacie_speakers_constraints(struct snd_pcm_runtime *runtime); | 97 | unsigned int rate; |
98 | unsigned int pcm; | ||
99 | unsigned int midi; | ||
100 | }; | ||
101 | int snd_oxfw_stream_parse_format(u8 *format, | ||
102 | struct snd_oxfw_stream_formation *formation); | ||
103 | int snd_oxfw_stream_get_current_formation(struct snd_oxfw *oxfw, | ||
104 | enum avc_general_plug_dir dir, | ||
105 | struct snd_oxfw_stream_formation *formation); | ||
106 | int snd_oxfw_stream_discover(struct snd_oxfw *oxfw); | ||
107 | |||
93 | int snd_oxfw_create_pcm(struct snd_oxfw *oxfw); | 108 | int snd_oxfw_create_pcm(struct snd_oxfw *oxfw); |
94 | 109 | ||
95 | int snd_oxfw_create_mixer(struct snd_oxfw *oxfw); | 110 | int snd_oxfw_create_mixer(struct snd_oxfw *oxfw); |