diff options
Diffstat (limited to 'sound/pci/asihpi/asihpi.c')
-rw-r--r-- | sound/pci/asihpi/asihpi.c | 1054 |
1 files changed, 499 insertions, 555 deletions
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index c80b0b863c54..e3569bdd3b64 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c | |||
@@ -21,25 +21,6 @@ | |||
21 | * would appreciate it if you grant us the right to use those modifications | 21 | * would appreciate it if you grant us the right to use those modifications |
22 | * for any purpose including commercial applications. | 22 | * for any purpose including commercial applications. |
23 | */ | 23 | */ |
24 | /* >0: print Hw params, timer vars. >1: print stream write/copy sizes */ | ||
25 | #define REALLY_VERBOSE_LOGGING 0 | ||
26 | |||
27 | #if REALLY_VERBOSE_LOGGING | ||
28 | #define VPRINTK1 snd_printd | ||
29 | #else | ||
30 | #define VPRINTK1(...) | ||
31 | #endif | ||
32 | |||
33 | #if REALLY_VERBOSE_LOGGING > 1 | ||
34 | #define VPRINTK2 snd_printd | ||
35 | #else | ||
36 | #define VPRINTK2(...) | ||
37 | #endif | ||
38 | |||
39 | #ifndef ASI_STYLE_NAMES | ||
40 | /* not sure how ALSA style name should look */ | ||
41 | #define ASI_STYLE_NAMES 1 | ||
42 | #endif | ||
43 | 24 | ||
44 | #include "hpi_internal.h" | 25 | #include "hpi_internal.h" |
45 | #include "hpimsginit.h" | 26 | #include "hpimsginit.h" |
@@ -65,6 +46,39 @@ MODULE_LICENSE("GPL"); | |||
65 | MODULE_AUTHOR("AudioScience inc. <support@audioscience.com>"); | 46 | MODULE_AUTHOR("AudioScience inc. <support@audioscience.com>"); |
66 | MODULE_DESCRIPTION("AudioScience ALSA ASI5000 ASI6000 ASI87xx ASI89xx"); | 47 | MODULE_DESCRIPTION("AudioScience ALSA ASI5000 ASI6000 ASI87xx ASI89xx"); |
67 | 48 | ||
49 | #if defined CONFIG_SND_DEBUG | ||
50 | /* copied from pcm_lib.c, hope later patch will make that version public | ||
51 | and this copy can be removed */ | ||
52 | static void pcm_debug_name(struct snd_pcm_substream *substream, | ||
53 | char *name, size_t len) | ||
54 | { | ||
55 | snprintf(name, len, "pcmC%dD%d%c:%d", | ||
56 | substream->pcm->card->number, | ||
57 | substream->pcm->device, | ||
58 | substream->stream ? 'c' : 'p', | ||
59 | substream->number); | ||
60 | } | ||
61 | #define DEBUG_NAME(substream, name) char name[16]; pcm_debug_name(substream, name, sizeof(name)) | ||
62 | #else | ||
63 | #define pcm_debug_name(s, n, l) do { } while (0) | ||
64 | #define DEBUG_NAME(name, substream) do { } while (0) | ||
65 | #endif | ||
66 | |||
67 | #if defined CONFIG_SND_DEBUG_VERBOSE | ||
68 | /** | ||
69 | * snd_printddd - very verbose debug printk | ||
70 | * @format: format string | ||
71 | * | ||
72 | * Works like snd_printk() for debugging purposes. | ||
73 | * Ignored when CONFIG_SND_DEBUG_VERBOSE is not set. | ||
74 | * Must set snd module debug parameter to 3 to enable at runtime. | ||
75 | */ | ||
76 | #define snd_printddd(format, args...) \ | ||
77 | __snd_printk(3, __FILE__, __LINE__, format, ##args) | ||
78 | #else | ||
79 | #define snd_printddd(format, args...) do { } while (0) | ||
80 | #endif | ||
81 | |||
68 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* index 0-MAX */ | 82 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* index 0-MAX */ |
69 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | 83 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ |
70 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; | 84 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; |
@@ -85,11 +99,11 @@ MODULE_PARM_DESC(enable_hpi_hwdep, | |||
85 | 99 | ||
86 | /* identify driver */ | 100 | /* identify driver */ |
87 | #ifdef KERNEL_ALSA_BUILD | 101 | #ifdef KERNEL_ALSA_BUILD |
88 | static char *build_info = "built using headers from kernel source"; | 102 | static char *build_info = "Built using headers from kernel source"; |
89 | module_param(build_info, charp, S_IRUGO); | 103 | module_param(build_info, charp, S_IRUGO); |
90 | MODULE_PARM_DESC(build_info, "built using headers from kernel source"); | 104 | MODULE_PARM_DESC(build_info, "built using headers from kernel source"); |
91 | #else | 105 | #else |
92 | static char *build_info = "built within ALSA source"; | 106 | static char *build_info = "Built within ALSA source"; |
93 | module_param(build_info, charp, S_IRUGO); | 107 | module_param(build_info, charp, S_IRUGO); |
94 | MODULE_PARM_DESC(build_info, "built within ALSA source"); | 108 | MODULE_PARM_DESC(build_info, "built within ALSA source"); |
95 | #endif | 109 | #endif |
@@ -100,17 +114,11 @@ static const int mixer_dump; | |||
100 | #define DEFAULT_SAMPLERATE 44100 | 114 | #define DEFAULT_SAMPLERATE 44100 |
101 | static int adapter_fs = DEFAULT_SAMPLERATE; | 115 | static int adapter_fs = DEFAULT_SAMPLERATE; |
102 | 116 | ||
103 | static struct hpi_hsubsys *ss; /* handle to HPI audio subsystem */ | ||
104 | |||
105 | /* defaults */ | 117 | /* defaults */ |
106 | #define PERIODS_MIN 2 | 118 | #define PERIODS_MIN 2 |
107 | #define PERIOD_BYTES_MIN 2304 | 119 | #define PERIOD_BYTES_MIN 2048 |
108 | #define BUFFER_BYTES_MAX (512 * 1024) | 120 | #define BUFFER_BYTES_MAX (512 * 1024) |
109 | 121 | ||
110 | /*#define TIMER_MILLISECONDS 20 | ||
111 | #define FORCE_TIMER_JIFFIES ((TIMER_MILLISECONDS * HZ + 999)/1000) | ||
112 | */ | ||
113 | |||
114 | #define MAX_CLOCKSOURCES (HPI_SAMPLECLOCK_SOURCE_LAST + 1 + 7) | 122 | #define MAX_CLOCKSOURCES (HPI_SAMPLECLOCK_SOURCE_LAST + 1 + 7) |
115 | 123 | ||
116 | struct clk_source { | 124 | struct clk_source { |
@@ -139,7 +147,7 @@ struct snd_card_asihpi { | |||
139 | u32 h_mixer; | 147 | u32 h_mixer; |
140 | struct clk_cache cc; | 148 | struct clk_cache cc; |
141 | 149 | ||
142 | u16 support_mmap; | 150 | u16 can_dma; |
143 | u16 support_grouping; | 151 | u16 support_grouping; |
144 | u16 support_mrx; | 152 | u16 support_mrx; |
145 | u16 update_interval_frames; | 153 | u16 update_interval_frames; |
@@ -152,11 +160,13 @@ struct snd_card_asihpi_pcm { | |||
152 | struct timer_list timer; | 160 | struct timer_list timer; |
153 | unsigned int respawn_timer; | 161 | unsigned int respawn_timer; |
154 | unsigned int hpi_buffer_attached; | 162 | unsigned int hpi_buffer_attached; |
155 | unsigned int pcm_size; | 163 | unsigned int buffer_bytes; |
156 | unsigned int pcm_count; | 164 | unsigned int period_bytes; |
157 | unsigned int bytes_per_sec; | 165 | unsigned int bytes_per_sec; |
158 | unsigned int pcm_irq_pos; /* IRQ position */ | 166 | unsigned int pcm_buf_host_rw_ofs; /* Host R/W pos */ |
159 | unsigned int pcm_buf_pos; /* position in buffer */ | 167 | unsigned int pcm_buf_dma_ofs; /* DMA R/W offset in buffer */ |
168 | unsigned int pcm_buf_elapsed_dma_ofs; /* DMA R/W offset in buffer */ | ||
169 | unsigned int drained_count; | ||
160 | struct snd_pcm_substream *substream; | 170 | struct snd_pcm_substream *substream; |
161 | u32 h_stream; | 171 | u32 h_stream; |
162 | struct hpi_format format; | 172 | struct hpi_format format; |
@@ -167,7 +177,6 @@ struct snd_card_asihpi_pcm { | |||
167 | /* Functions to allow driver to give a buffer to HPI for busmastering */ | 177 | /* Functions to allow driver to give a buffer to HPI for busmastering */ |
168 | 178 | ||
169 | static u16 hpi_stream_host_buffer_attach( | 179 | static u16 hpi_stream_host_buffer_attach( |
170 | struct hpi_hsubsys *hS, | ||
171 | u32 h_stream, /* handle to outstream. */ | 180 | u32 h_stream, /* handle to outstream. */ |
172 | u32 size_in_bytes, /* size in bytes of bus mastering buffer */ | 181 | u32 size_in_bytes, /* size in bytes of bus mastering buffer */ |
173 | u32 pci_address | 182 | u32 pci_address |
@@ -194,10 +203,7 @@ static u16 hpi_stream_host_buffer_attach( | |||
194 | return hr.error; | 203 | return hr.error; |
195 | } | 204 | } |
196 | 205 | ||
197 | static u16 hpi_stream_host_buffer_detach( | 206 | static u16 hpi_stream_host_buffer_detach(u32 h_stream) |
198 | struct hpi_hsubsys *hS, | ||
199 | u32 h_stream | ||
200 | ) | ||
201 | { | 207 | { |
202 | struct hpi_message hm; | 208 | struct hpi_message hm; |
203 | struct hpi_response hr; | 209 | struct hpi_response hr; |
@@ -218,24 +224,23 @@ static u16 hpi_stream_host_buffer_detach( | |||
218 | return hr.error; | 224 | return hr.error; |
219 | } | 225 | } |
220 | 226 | ||
221 | static inline u16 hpi_stream_start(struct hpi_hsubsys *hS, u32 h_stream) | 227 | static inline u16 hpi_stream_start(u32 h_stream) |
222 | { | 228 | { |
223 | if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) | 229 | if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) |
224 | return hpi_outstream_start(hS, h_stream); | 230 | return hpi_outstream_start(h_stream); |
225 | else | 231 | else |
226 | return hpi_instream_start(hS, h_stream); | 232 | return hpi_instream_start(h_stream); |
227 | } | 233 | } |
228 | 234 | ||
229 | static inline u16 hpi_stream_stop(struct hpi_hsubsys *hS, u32 h_stream) | 235 | static inline u16 hpi_stream_stop(u32 h_stream) |
230 | { | 236 | { |
231 | if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) | 237 | if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) |
232 | return hpi_outstream_stop(hS, h_stream); | 238 | return hpi_outstream_stop(h_stream); |
233 | else | 239 | else |
234 | return hpi_instream_stop(hS, h_stream); | 240 | return hpi_instream_stop(h_stream); |
235 | } | 241 | } |
236 | 242 | ||
237 | static inline u16 hpi_stream_get_info_ex( | 243 | static inline u16 hpi_stream_get_info_ex( |
238 | struct hpi_hsubsys *hS, | ||
239 | u32 h_stream, | 244 | u32 h_stream, |
240 | u16 *pw_state, | 245 | u16 *pw_state, |
241 | u32 *pbuffer_size, | 246 | u32 *pbuffer_size, |
@@ -244,42 +249,43 @@ static inline u16 hpi_stream_get_info_ex( | |||
244 | u32 *pauxiliary_data | 249 | u32 *pauxiliary_data |
245 | ) | 250 | ) |
246 | { | 251 | { |
252 | u16 e; | ||
247 | if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) | 253 | if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) |
248 | return hpi_outstream_get_info_ex(hS, h_stream, pw_state, | 254 | e = hpi_outstream_get_info_ex(h_stream, pw_state, |
249 | pbuffer_size, pdata_in_buffer, | 255 | pbuffer_size, pdata_in_buffer, |
250 | psample_count, pauxiliary_data); | 256 | psample_count, pauxiliary_data); |
251 | else | 257 | else |
252 | return hpi_instream_get_info_ex(hS, h_stream, pw_state, | 258 | e = hpi_instream_get_info_ex(h_stream, pw_state, |
253 | pbuffer_size, pdata_in_buffer, | 259 | pbuffer_size, pdata_in_buffer, |
254 | psample_count, pauxiliary_data); | 260 | psample_count, pauxiliary_data); |
261 | return e; | ||
255 | } | 262 | } |
256 | 263 | ||
257 | static inline u16 hpi_stream_group_add(struct hpi_hsubsys *hS, | 264 | static inline u16 hpi_stream_group_add( |
258 | u32 h_master, | 265 | u32 h_master, |
259 | u32 h_stream) | 266 | u32 h_stream) |
260 | { | 267 | { |
261 | if (hpi_handle_object(h_master) == HPI_OBJ_OSTREAM) | 268 | if (hpi_handle_object(h_master) == HPI_OBJ_OSTREAM) |
262 | return hpi_outstream_group_add(hS, h_master, h_stream); | 269 | return hpi_outstream_group_add(h_master, h_stream); |
263 | else | 270 | else |
264 | return hpi_instream_group_add(hS, h_master, h_stream); | 271 | return hpi_instream_group_add(h_master, h_stream); |
265 | } | 272 | } |
266 | 273 | ||
267 | static inline u16 hpi_stream_group_reset(struct hpi_hsubsys *hS, | 274 | static inline u16 hpi_stream_group_reset(u32 h_stream) |
268 | u32 h_stream) | ||
269 | { | 275 | { |
270 | if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) | 276 | if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) |
271 | return hpi_outstream_group_reset(hS, h_stream); | 277 | return hpi_outstream_group_reset(h_stream); |
272 | else | 278 | else |
273 | return hpi_instream_group_reset(hS, h_stream); | 279 | return hpi_instream_group_reset(h_stream); |
274 | } | 280 | } |
275 | 281 | ||
276 | static inline u16 hpi_stream_group_get_map(struct hpi_hsubsys *hS, | 282 | static inline u16 hpi_stream_group_get_map( |
277 | u32 h_stream, u32 *mo, u32 *mi) | 283 | u32 h_stream, u32 *mo, u32 *mi) |
278 | { | 284 | { |
279 | if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) | 285 | if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) |
280 | return hpi_outstream_group_get_map(hS, h_stream, mo, mi); | 286 | return hpi_outstream_group_get_map(h_stream, mo, mi); |
281 | else | 287 | else |
282 | return hpi_instream_group_get_map(hS, h_stream, mo, mi); | 288 | return hpi_instream_group_get_map(h_stream, mo, mi); |
283 | } | 289 | } |
284 | 290 | ||
285 | static u16 handle_error(u16 err, int line, char *filename) | 291 | static u16 handle_error(u16 err, int line, char *filename) |
@@ -294,24 +300,27 @@ static u16 handle_error(u16 err, int line, char *filename) | |||
294 | #define hpi_handle_error(x) handle_error(x, __LINE__, __FILE__) | 300 | #define hpi_handle_error(x) handle_error(x, __LINE__, __FILE__) |
295 | 301 | ||
296 | /***************************** GENERAL PCM ****************/ | 302 | /***************************** GENERAL PCM ****************/ |
297 | #if REALLY_VERBOSE_LOGGING | 303 | |
298 | static void print_hwparams(struct snd_pcm_hw_params *p) | 304 | static void print_hwparams(struct snd_pcm_substream *substream, |
299 | { | 305 | struct snd_pcm_hw_params *p) |
300 | snd_printd("HWPARAMS \n"); | 306 | { |
301 | snd_printd("samplerate %d \n", params_rate(p)); | 307 | DEBUG_NAME(substream, name); |
302 | snd_printd("channels %d \n", params_channels(p)); | 308 | snd_printd("%s HWPARAMS\n", name); |
303 | snd_printd("format %d \n", params_format(p)); | 309 | snd_printd(" samplerate %d Hz\n", params_rate(p)); |
304 | snd_printd("subformat %d \n", params_subformat(p)); | 310 | snd_printd(" channels %d\n", params_channels(p)); |
305 | snd_printd("buffer bytes %d \n", params_buffer_bytes(p)); | 311 | snd_printd(" format %d\n", params_format(p)); |
306 | snd_printd("period bytes %d \n", params_period_bytes(p)); | 312 | snd_printd(" subformat %d\n", params_subformat(p)); |
307 | snd_printd("access %d \n", params_access(p)); | 313 | snd_printd(" buffer %d B\n", params_buffer_bytes(p)); |
308 | snd_printd("period_size %d \n", params_period_size(p)); | 314 | snd_printd(" period %d B\n", params_period_bytes(p)); |
309 | snd_printd("periods %d \n", params_periods(p)); | 315 | snd_printd(" access %d\n", params_access(p)); |
310 | snd_printd("buffer_size %d \n", params_buffer_size(p)); | 316 | snd_printd(" period_size %d\n", params_period_size(p)); |
317 | snd_printd(" periods %d\n", params_periods(p)); | ||
318 | snd_printd(" buffer_size %d\n", params_buffer_size(p)); | ||
319 | snd_printd(" %d B/s\n", params_rate(p) * | ||
320 | params_channels(p) * | ||
321 | snd_pcm_format_width(params_format(p)) / 8); | ||
322 | |||
311 | } | 323 | } |
312 | #else | ||
313 | #define print_hwparams(x) | ||
314 | #endif | ||
315 | 324 | ||
316 | static snd_pcm_format_t hpi_to_alsa_formats[] = { | 325 | static snd_pcm_format_t hpi_to_alsa_formats[] = { |
317 | -1, /* INVALID */ | 326 | -1, /* INVALID */ |
@@ -335,7 +344,7 @@ static snd_pcm_format_t hpi_to_alsa_formats[] = { | |||
335 | */ | 344 | */ |
336 | -1 | 345 | -1 |
337 | #else | 346 | #else |
338 | /* SNDRV_PCM_FORMAT_S24_3LE */ /* { HPI_FORMAT_PCM24_SIGNED 15 */ | 347 | /* SNDRV_PCM_FORMAT_S24_3LE */ /* HPI_FORMAT_PCM24_SIGNED 15 */ |
339 | #endif | 348 | #endif |
340 | }; | 349 | }; |
341 | 350 | ||
@@ -378,21 +387,21 @@ static void snd_card_asihpi_pcm_samplerates(struct snd_card_asihpi *asihpi, | |||
378 | } else { | 387 | } else { |
379 | /* on cards without SRC, | 388 | /* on cards without SRC, |
380 | valid rates are determined by sampleclock */ | 389 | valid rates are determined by sampleclock */ |
381 | err = hpi_mixer_get_control(ss, asihpi->h_mixer, | 390 | err = hpi_mixer_get_control(asihpi->h_mixer, |
382 | HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, | 391 | HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, |
383 | HPI_CONTROL_SAMPLECLOCK, &h_control); | 392 | HPI_CONTROL_SAMPLECLOCK, &h_control); |
384 | if (err) { | 393 | if (err) { |
385 | snd_printk(KERN_ERR | 394 | snd_printk(KERN_ERR |
386 | "no local sampleclock, err %d\n", err); | 395 | "No local sampleclock, err %d\n", err); |
387 | } | 396 | } |
388 | 397 | ||
389 | for (idx = 0; idx < 100; idx++) { | 398 | for (idx = -1; idx < 100; idx++) { |
390 | if (hpi_sample_clock_query_local_rate(ss, | 399 | if (idx == -1) { |
391 | h_control, idx, &sample_rate)) { | 400 | if (hpi_sample_clock_get_sample_rate(h_control, |
392 | if (!idx) | 401 | &sample_rate)) |
393 | snd_printk(KERN_ERR | 402 | continue; |
394 | "local rate query failed\n"); | 403 | } else if (hpi_sample_clock_query_local_rate(h_control, |
395 | 404 | idx, &sample_rate)) { | |
396 | break; | 405 | break; |
397 | } | 406 | } |
398 | 407 | ||
@@ -445,8 +454,6 @@ static void snd_card_asihpi_pcm_samplerates(struct snd_card_asihpi *asihpi, | |||
445 | } | 454 | } |
446 | } | 455 | } |
447 | 456 | ||
448 | /* printk(KERN_INFO "Supported rates %X %d %d\n", | ||
449 | rates, rate_min, rate_max); */ | ||
450 | pcmhw->rates = rates; | 457 | pcmhw->rates = rates; |
451 | pcmhw->rate_min = rate_min; | 458 | pcmhw->rate_min = rate_min; |
452 | pcmhw->rate_max = rate_max; | 459 | pcmhw->rate_max = rate_max; |
@@ -463,7 +470,7 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream, | |||
463 | int width; | 470 | int width; |
464 | unsigned int bytes_per_sec; | 471 | unsigned int bytes_per_sec; |
465 | 472 | ||
466 | print_hwparams(params); | 473 | print_hwparams(substream, params); |
467 | err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); | 474 | err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); |
468 | if (err < 0) | 475 | if (err < 0) |
469 | return err; | 476 | return err; |
@@ -471,45 +478,39 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream, | |||
471 | if (err) | 478 | if (err) |
472 | return err; | 479 | return err; |
473 | 480 | ||
474 | VPRINTK1(KERN_INFO "format %d, %d chans, %d_hz\n", | ||
475 | format, params_channels(params), | ||
476 | params_rate(params)); | ||
477 | |||
478 | hpi_handle_error(hpi_format_create(&dpcm->format, | 481 | hpi_handle_error(hpi_format_create(&dpcm->format, |
479 | params_channels(params), | 482 | params_channels(params), |
480 | format, params_rate(params), 0, 0)); | 483 | format, params_rate(params), 0, 0)); |
481 | 484 | ||
482 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { | 485 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { |
483 | if (hpi_instream_reset(ss, dpcm->h_stream) != 0) | 486 | if (hpi_instream_reset(dpcm->h_stream) != 0) |
484 | return -EINVAL; | 487 | return -EINVAL; |
485 | 488 | ||
486 | if (hpi_instream_set_format(ss, | 489 | if (hpi_instream_set_format( |
487 | dpcm->h_stream, &dpcm->format) != 0) | 490 | dpcm->h_stream, &dpcm->format) != 0) |
488 | return -EINVAL; | 491 | return -EINVAL; |
489 | } | 492 | } |
490 | 493 | ||
491 | dpcm->hpi_buffer_attached = 0; | 494 | dpcm->hpi_buffer_attached = 0; |
492 | if (card->support_mmap) { | 495 | if (card->can_dma) { |
493 | 496 | err = hpi_stream_host_buffer_attach(dpcm->h_stream, | |
494 | err = hpi_stream_host_buffer_attach(ss, dpcm->h_stream, | ||
495 | params_buffer_bytes(params), runtime->dma_addr); | 497 | params_buffer_bytes(params), runtime->dma_addr); |
496 | if (err == 0) { | 498 | if (err == 0) { |
497 | snd_printd(KERN_INFO | 499 | snd_printdd( |
498 | "stream_host_buffer_attach succeeded %u %lu\n", | 500 | "stream_host_buffer_attach succeeded %u %lu\n", |
499 | params_buffer_bytes(params), | 501 | params_buffer_bytes(params), |
500 | (unsigned long)runtime->dma_addr); | 502 | (unsigned long)runtime->dma_addr); |
501 | } else { | 503 | } else { |
502 | snd_printd(KERN_INFO | 504 | snd_printd("stream_host_buffer_attach error %d\n", |
503 | "stream_host_buffer_attach error %d\n", | ||
504 | err); | 505 | err); |
505 | return -ENOMEM; | 506 | return -ENOMEM; |
506 | } | 507 | } |
507 | 508 | ||
508 | err = hpi_stream_get_info_ex(ss, dpcm->h_stream, NULL, | 509 | err = hpi_stream_get_info_ex(dpcm->h_stream, NULL, |
509 | &dpcm->hpi_buffer_attached, | 510 | &dpcm->hpi_buffer_attached, |
510 | NULL, NULL, NULL); | 511 | NULL, NULL, NULL); |
511 | 512 | ||
512 | snd_printd(KERN_INFO "stream_host_buffer_attach status 0x%x\n", | 513 | snd_printdd("stream_host_buffer_attach status 0x%x\n", |
513 | dpcm->hpi_buffer_attached); | 514 | dpcm->hpi_buffer_attached); |
514 | } | 515 | } |
515 | bytes_per_sec = params_rate(params) * params_channels(params); | 516 | bytes_per_sec = params_rate(params) * params_channels(params); |
@@ -520,16 +521,30 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream, | |||
520 | return -EINVAL; | 521 | return -EINVAL; |
521 | 522 | ||
522 | dpcm->bytes_per_sec = bytes_per_sec; | 523 | dpcm->bytes_per_sec = bytes_per_sec; |
523 | dpcm->pcm_size = params_buffer_bytes(params); | 524 | dpcm->buffer_bytes = params_buffer_bytes(params); |
524 | dpcm->pcm_count = params_period_bytes(params); | 525 | dpcm->period_bytes = params_period_bytes(params); |
525 | snd_printd(KERN_INFO "pcm_size=%d, pcm_count=%d, bps=%d\n", | ||
526 | dpcm->pcm_size, dpcm->pcm_count, bytes_per_sec); | ||
527 | 526 | ||
528 | dpcm->pcm_irq_pos = 0; | ||
529 | dpcm->pcm_buf_pos = 0; | ||
530 | return 0; | 527 | return 0; |
531 | } | 528 | } |
532 | 529 | ||
530 | static int | ||
531 | snd_card_asihpi_hw_free(struct snd_pcm_substream *substream) | ||
532 | { | ||
533 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
534 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; | ||
535 | if (dpcm->hpi_buffer_attached) | ||
536 | hpi_stream_host_buffer_detach(dpcm->h_stream); | ||
537 | |||
538 | snd_pcm_lib_free_pages(substream); | ||
539 | return 0; | ||
540 | } | ||
541 | |||
542 | static void snd_card_asihpi_runtime_free(struct snd_pcm_runtime *runtime) | ||
543 | { | ||
544 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; | ||
545 | kfree(dpcm); | ||
546 | } | ||
547 | |||
533 | static void snd_card_asihpi_pcm_timer_start(struct snd_pcm_substream * | 548 | static void snd_card_asihpi_pcm_timer_start(struct snd_pcm_substream * |
534 | substream) | 549 | substream) |
535 | { | 550 | { |
@@ -537,9 +552,9 @@ static void snd_card_asihpi_pcm_timer_start(struct snd_pcm_substream * | |||
537 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; | 552 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; |
538 | int expiry; | 553 | int expiry; |
539 | 554 | ||
540 | expiry = (dpcm->pcm_count * HZ / dpcm->bytes_per_sec); | 555 | expiry = HZ / 200; |
541 | /* wait longer the first time, for samples to propagate */ | 556 | /*? (dpcm->period_bytes * HZ / dpcm->bytes_per_sec); */ |
542 | expiry = max(expiry, 20); | 557 | expiry = max(expiry, 1); /* don't let it be zero! */ |
543 | dpcm->timer.expires = jiffies + expiry; | 558 | dpcm->timer.expires = jiffies + expiry; |
544 | dpcm->respawn_timer = 1; | 559 | dpcm->respawn_timer = 1; |
545 | add_timer(&dpcm->timer); | 560 | add_timer(&dpcm->timer); |
@@ -561,38 +576,44 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream, | |||
561 | struct snd_card_asihpi *card = snd_pcm_substream_chip(substream); | 576 | struct snd_card_asihpi *card = snd_pcm_substream_chip(substream); |
562 | struct snd_pcm_substream *s; | 577 | struct snd_pcm_substream *s; |
563 | u16 e; | 578 | u16 e; |
579 | DEBUG_NAME(substream, name); | ||
580 | |||
581 | snd_printdd("%s trigger\n", name); | ||
564 | 582 | ||
565 | snd_printd("trigger %dstream %d\n", | ||
566 | substream->stream, substream->number); | ||
567 | switch (cmd) { | 583 | switch (cmd) { |
568 | case SNDRV_PCM_TRIGGER_START: | 584 | case SNDRV_PCM_TRIGGER_START: |
569 | snd_pcm_group_for_each_entry(s, substream) { | 585 | snd_pcm_group_for_each_entry(s, substream) { |
570 | struct snd_card_asihpi_pcm *ds; | 586 | struct snd_pcm_runtime *runtime = s->runtime; |
571 | ds = s->runtime->private_data; | 587 | struct snd_card_asihpi_pcm *ds = runtime->private_data; |
572 | 588 | ||
573 | if (snd_pcm_substream_chip(s) != card) | 589 | if (snd_pcm_substream_chip(s) != card) |
574 | continue; | 590 | continue; |
575 | 591 | ||
576 | if ((s->stream == SNDRV_PCM_STREAM_PLAYBACK) && | 592 | /* don't link Cap and Play */ |
577 | (card->support_mmap)) { | 593 | if (substream->stream != s->stream) |
594 | continue; | ||
595 | |||
596 | ds->drained_count = 0; | ||
597 | if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
578 | /* How do I know how much valid data is present | 598 | /* How do I know how much valid data is present |
579 | * in buffer? Just guessing 2 periods, but if | 599 | * in buffer? Must be at least one period! |
600 | * Guessing 2 periods, but if | ||
580 | * buffer is bigger it may contain even more | 601 | * buffer is bigger it may contain even more |
581 | * data?? | 602 | * data?? |
582 | */ | 603 | */ |
583 | unsigned int preload = ds->pcm_count * 2; | 604 | unsigned int preload = ds->period_bytes * 1; |
584 | VPRINTK2("preload %d\n", preload); | 605 | snd_printddd("%d preload x%x\n", s->number, preload); |
585 | hpi_handle_error(hpi_outstream_write_buf( | 606 | hpi_handle_error(hpi_outstream_write_buf( |
586 | ss, ds->h_stream, | 607 | ds->h_stream, |
587 | &s->runtime->dma_area[0], | 608 | &runtime->dma_area[0], |
588 | preload, | 609 | preload, |
589 | &ds->format)); | 610 | &ds->format)); |
611 | ds->pcm_buf_host_rw_ofs = preload; | ||
590 | } | 612 | } |
591 | 613 | ||
592 | if (card->support_grouping) { | 614 | if (card->support_grouping) { |
593 | VPRINTK1("\t_group %dstream %d\n", s->stream, | 615 | snd_printdd("%d group\n", s->number); |
594 | s->number); | 616 | e = hpi_stream_group_add( |
595 | e = hpi_stream_group_add(ss, | ||
596 | dpcm->h_stream, | 617 | dpcm->h_stream, |
597 | ds->h_stream); | 618 | ds->h_stream); |
598 | if (!e) { | 619 | if (!e) { |
@@ -604,10 +625,12 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream, | |||
604 | } else | 625 | } else |
605 | break; | 626 | break; |
606 | } | 627 | } |
607 | snd_printd("start\n"); | 628 | snd_printdd("start\n"); |
608 | /* start the master stream */ | 629 | /* start the master stream */ |
609 | snd_card_asihpi_pcm_timer_start(substream); | 630 | snd_card_asihpi_pcm_timer_start(substream); |
610 | hpi_handle_error(hpi_stream_start(ss, dpcm->h_stream)); | 631 | if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE) || |
632 | !card->can_dma) | ||
633 | hpi_handle_error(hpi_stream_start(dpcm->h_stream)); | ||
611 | break; | 634 | break; |
612 | 635 | ||
613 | case SNDRV_PCM_TRIGGER_STOP: | 636 | case SNDRV_PCM_TRIGGER_STOP: |
@@ -615,88 +638,71 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream, | |||
615 | snd_pcm_group_for_each_entry(s, substream) { | 638 | snd_pcm_group_for_each_entry(s, substream) { |
616 | if (snd_pcm_substream_chip(s) != card) | 639 | if (snd_pcm_substream_chip(s) != card) |
617 | continue; | 640 | continue; |
641 | /* don't link Cap and Play */ | ||
642 | if (substream->stream != s->stream) | ||
643 | continue; | ||
618 | 644 | ||
619 | /*? workaround linked streams don't | 645 | /*? workaround linked streams don't |
620 | transition to SETUP 20070706*/ | 646 | transition to SETUP 20070706*/ |
621 | s->runtime->status->state = SNDRV_PCM_STATE_SETUP; | 647 | s->runtime->status->state = SNDRV_PCM_STATE_SETUP; |
622 | 648 | ||
623 | if (card->support_grouping) { | 649 | if (card->support_grouping) { |
624 | VPRINTK1("\t_group %dstream %d\n", s->stream, | 650 | snd_printdd("%d group\n", s->number); |
625 | s->number); | ||
626 | snd_pcm_trigger_done(s, substream); | 651 | snd_pcm_trigger_done(s, substream); |
627 | } else | 652 | } else |
628 | break; | 653 | break; |
629 | } | 654 | } |
630 | snd_printd("stop\n"); | 655 | snd_printdd("stop\n"); |
631 | 656 | ||
632 | /* _prepare and _hwparams reset the stream */ | 657 | /* _prepare and _hwparams reset the stream */ |
633 | hpi_handle_error(hpi_stream_stop(ss, dpcm->h_stream)); | 658 | hpi_handle_error(hpi_stream_stop(dpcm->h_stream)); |
634 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 659 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
635 | hpi_handle_error( | 660 | hpi_handle_error( |
636 | hpi_outstream_reset(ss, dpcm->h_stream)); | 661 | hpi_outstream_reset(dpcm->h_stream)); |
637 | 662 | ||
638 | if (card->support_grouping) | 663 | if (card->support_grouping) |
639 | hpi_handle_error(hpi_stream_group_reset(ss, | 664 | hpi_handle_error(hpi_stream_group_reset(dpcm->h_stream)); |
640 | dpcm->h_stream)); | ||
641 | break; | 665 | break; |
642 | 666 | ||
643 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 667 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
644 | snd_printd("pause release\n"); | 668 | snd_printdd("pause release\n"); |
645 | hpi_handle_error(hpi_stream_start(ss, dpcm->h_stream)); | 669 | hpi_handle_error(hpi_stream_start(dpcm->h_stream)); |
646 | snd_card_asihpi_pcm_timer_start(substream); | 670 | snd_card_asihpi_pcm_timer_start(substream); |
647 | break; | 671 | break; |
648 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 672 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
649 | snd_printd("pause\n"); | 673 | snd_printdd("pause\n"); |
650 | snd_card_asihpi_pcm_timer_stop(substream); | 674 | snd_card_asihpi_pcm_timer_stop(substream); |
651 | hpi_handle_error(hpi_stream_stop(ss, dpcm->h_stream)); | 675 | hpi_handle_error(hpi_stream_stop(dpcm->h_stream)); |
652 | break; | 676 | break; |
653 | default: | 677 | default: |
654 | snd_printd("\tINVALID\n"); | 678 | snd_printd(KERN_ERR "\tINVALID\n"); |
655 | return -EINVAL; | 679 | return -EINVAL; |
656 | } | 680 | } |
657 | 681 | ||
658 | return 0; | 682 | return 0; |
659 | } | 683 | } |
660 | 684 | ||
661 | static int | ||
662 | snd_card_asihpi_hw_free(struct snd_pcm_substream *substream) | ||
663 | { | ||
664 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
665 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; | ||
666 | if (dpcm->hpi_buffer_attached) | ||
667 | hpi_stream_host_buffer_detach(ss, dpcm->h_stream); | ||
668 | |||
669 | snd_pcm_lib_free_pages(substream); | ||
670 | return 0; | ||
671 | } | ||
672 | |||
673 | static void snd_card_asihpi_runtime_free(struct snd_pcm_runtime *runtime) | ||
674 | { | ||
675 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; | ||
676 | kfree(dpcm); | ||
677 | } | ||
678 | |||
679 | /*algorithm outline | 685 | /*algorithm outline |
680 | Without linking degenerates to getting single stream pos etc | 686 | Without linking degenerates to getting single stream pos etc |
681 | Without mmap 2nd loop degenerates to snd_pcm_period_elapsed | 687 | Without mmap 2nd loop degenerates to snd_pcm_period_elapsed |
682 | */ | 688 | */ |
683 | /* | 689 | /* |
684 | buf_pos=get_buf_pos(s); | 690 | pcm_buf_dma_ofs=get_buf_pos(s); |
685 | for_each_linked_stream(s) { | 691 | for_each_linked_stream(s) { |
686 | buf_pos=get_buf_pos(s); | 692 | pcm_buf_dma_ofs=get_buf_pos(s); |
687 | min_buf_pos = modulo_min(min_buf_pos, buf_pos, pcm_size) | 693 | min_buf_pos = modulo_min(min_buf_pos, pcm_buf_dma_ofs, buffer_bytes) |
688 | new_data = min(new_data, calc_new_data(buf_pos,irq_pos) | 694 | new_data = min(new_data, calc_new_data(pcm_buf_dma_ofs,irq_pos) |
689 | } | 695 | } |
690 | timer.expires = jiffies + predict_next_period_ready(min_buf_pos); | 696 | timer.expires = jiffies + predict_next_period_ready(min_buf_pos); |
691 | for_each_linked_stream(s) { | 697 | for_each_linked_stream(s) { |
692 | s->buf_pos = min_buf_pos; | 698 | s->pcm_buf_dma_ofs = min_buf_pos; |
693 | if (new_data > pcm_count) { | 699 | if (new_data > period_bytes) { |
694 | if (mmap) { | 700 | if (mmap) { |
695 | irq_pos = (irq_pos + pcm_count) % pcm_size; | 701 | irq_pos = (irq_pos + period_bytes) % buffer_bytes; |
696 | if (playback) { | 702 | if (playback) { |
697 | write(pcm_count); | 703 | write(period_bytes); |
698 | } else { | 704 | } else { |
699 | read(pcm_count); | 705 | read(period_bytes); |
700 | } | 706 | } |
701 | } | 707 | } |
702 | snd_pcm_period_elapsed(s); | 708 | snd_pcm_period_elapsed(s); |
@@ -724,105 +730,180 @@ static inline unsigned int modulo_min(unsigned int a, unsigned int b, | |||
724 | static void snd_card_asihpi_timer_function(unsigned long data) | 730 | static void snd_card_asihpi_timer_function(unsigned long data) |
725 | { | 731 | { |
726 | struct snd_card_asihpi_pcm *dpcm = (struct snd_card_asihpi_pcm *)data; | 732 | struct snd_card_asihpi_pcm *dpcm = (struct snd_card_asihpi_pcm *)data; |
727 | struct snd_card_asihpi *card = snd_pcm_substream_chip(dpcm->substream); | 733 | struct snd_pcm_substream *substream = dpcm->substream; |
734 | struct snd_card_asihpi *card = snd_pcm_substream_chip(substream); | ||
728 | struct snd_pcm_runtime *runtime; | 735 | struct snd_pcm_runtime *runtime; |
729 | struct snd_pcm_substream *s; | 736 | struct snd_pcm_substream *s; |
730 | unsigned int newdata = 0; | 737 | unsigned int newdata = 0; |
731 | unsigned int buf_pos, min_buf_pos = 0; | 738 | unsigned int pcm_buf_dma_ofs, min_buf_pos = 0; |
732 | unsigned int remdata, xfercount, next_jiffies; | 739 | unsigned int remdata, xfercount, next_jiffies; |
733 | int first = 1; | 740 | int first = 1; |
741 | int loops = 0; | ||
734 | u16 state; | 742 | u16 state; |
735 | u32 buffer_size, data_avail, samples_played, aux; | 743 | u32 buffer_size, bytes_avail, samples_played, on_card_bytes; |
744 | DEBUG_NAME(substream, name); | ||
745 | |||
746 | snd_printdd("%s snd_card_asihpi_timer_function\n", name); | ||
736 | 747 | ||
737 | /* find minimum newdata and buffer pos in group */ | 748 | /* find minimum newdata and buffer pos in group */ |
738 | snd_pcm_group_for_each_entry(s, dpcm->substream) { | 749 | snd_pcm_group_for_each_entry(s, substream) { |
739 | struct snd_card_asihpi_pcm *ds = s->runtime->private_data; | 750 | struct snd_card_asihpi_pcm *ds = s->runtime->private_data; |
740 | runtime = s->runtime; | 751 | runtime = s->runtime; |
741 | 752 | ||
742 | if (snd_pcm_substream_chip(s) != card) | 753 | if (snd_pcm_substream_chip(s) != card) |
743 | continue; | 754 | continue; |
744 | 755 | ||
745 | hpi_handle_error(hpi_stream_get_info_ex(ss, | 756 | /* don't link Cap and Play */ |
757 | if (substream->stream != s->stream) | ||
758 | continue; | ||
759 | |||
760 | hpi_handle_error(hpi_stream_get_info_ex( | ||
746 | ds->h_stream, &state, | 761 | ds->h_stream, &state, |
747 | &buffer_size, &data_avail, | 762 | &buffer_size, &bytes_avail, |
748 | &samples_played, &aux)); | 763 | &samples_played, &on_card_bytes)); |
749 | 764 | ||
750 | /* number of bytes in on-card buffer */ | 765 | /* number of bytes in on-card buffer */ |
751 | runtime->delay = aux; | 766 | runtime->delay = on_card_bytes; |
752 | 767 | ||
753 | if (state == HPI_STATE_DRAINED) { | 768 | if (!card->can_dma) |
754 | snd_printd(KERN_WARNING "outstream %d drained\n", | 769 | on_card_bytes = bytes_avail; |
755 | s->number); | ||
756 | snd_pcm_stop(s, SNDRV_PCM_STATE_XRUN); | ||
757 | return; | ||
758 | } | ||
759 | 770 | ||
760 | if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 771 | if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
761 | buf_pos = frames_to_bytes(runtime, samples_played); | 772 | pcm_buf_dma_ofs = ds->pcm_buf_host_rw_ofs - bytes_avail; |
762 | } else { | 773 | if (state == HPI_STATE_STOPPED) { |
763 | buf_pos = data_avail + ds->pcm_irq_pos; | 774 | if ((bytes_avail == 0) && |
764 | } | 775 | (on_card_bytes < ds->pcm_buf_host_rw_ofs)) { |
776 | hpi_handle_error(hpi_stream_start(ds->h_stream)); | ||
777 | snd_printdd("P%d start\n", s->number); | ||
778 | ds->drained_count = 0; | ||
779 | } | ||
780 | } else if (state == HPI_STATE_DRAINED) { | ||
781 | snd_printd(KERN_WARNING "P%d drained\n", | ||
782 | s->number); | ||
783 | ds->drained_count++; | ||
784 | if (ds->drained_count > 2) { | ||
785 | snd_pcm_stop(s, SNDRV_PCM_STATE_XRUN); | ||
786 | continue; | ||
787 | } | ||
788 | } else { | ||
789 | ds->drained_count = 0; | ||
790 | } | ||
791 | } else | ||
792 | pcm_buf_dma_ofs = bytes_avail + ds->pcm_buf_host_rw_ofs; | ||
765 | 793 | ||
766 | if (first) { | 794 | if (first) { |
767 | /* can't statically init min when wrap is involved */ | 795 | /* can't statically init min when wrap is involved */ |
768 | min_buf_pos = buf_pos; | 796 | min_buf_pos = pcm_buf_dma_ofs; |
769 | newdata = (buf_pos - ds->pcm_irq_pos) % ds->pcm_size; | 797 | newdata = (pcm_buf_dma_ofs - ds->pcm_buf_elapsed_dma_ofs) % ds->buffer_bytes; |
770 | first = 0; | 798 | first = 0; |
771 | } else { | 799 | } else { |
772 | min_buf_pos = | 800 | min_buf_pos = |
773 | modulo_min(min_buf_pos, buf_pos, UINT_MAX+1L); | 801 | modulo_min(min_buf_pos, pcm_buf_dma_ofs, UINT_MAX+1L); |
774 | newdata = min( | 802 | newdata = min( |
775 | (buf_pos - ds->pcm_irq_pos) % ds->pcm_size, | 803 | (pcm_buf_dma_ofs - ds->pcm_buf_elapsed_dma_ofs) % ds->buffer_bytes, |
776 | newdata); | 804 | newdata); |
777 | } | 805 | } |
778 | 806 | ||
779 | VPRINTK1("PB timer hw_ptr x%04lX, appl_ptr x%04lX\n", | 807 | snd_printdd("hw_ptr 0x%04lX, appl_ptr 0x%04lX\n", |
780 | (unsigned long)frames_to_bytes(runtime, | 808 | (unsigned long)frames_to_bytes(runtime, |
781 | runtime->status->hw_ptr), | 809 | runtime->status->hw_ptr), |
782 | (unsigned long)frames_to_bytes(runtime, | 810 | (unsigned long)frames_to_bytes(runtime, |
783 | runtime->control->appl_ptr)); | 811 | runtime->control->appl_ptr)); |
784 | VPRINTK1("%d S=%d, irq=%04X, pos=x%04X, left=x%04X," | 812 | |
785 | " aux=x%04X space=x%04X\n", s->number, | 813 | snd_printdd("%d S=%d, " |
786 | state, ds->pcm_irq_pos, buf_pos, (int)data_avail, | 814 | "rw=0x%04X, dma=0x%04X, left=0x%04X, " |
787 | (int)aux, buffer_size-data_avail); | 815 | "aux=0x%04X space=0x%04X\n", |
816 | s->number, state, | ||
817 | ds->pcm_buf_host_rw_ofs, pcm_buf_dma_ofs, | ||
818 | (int)bytes_avail, | ||
819 | (int)on_card_bytes, buffer_size-bytes_avail); | ||
820 | loops++; | ||
788 | } | 821 | } |
822 | pcm_buf_dma_ofs = min_buf_pos; | ||
823 | |||
824 | remdata = newdata % dpcm->period_bytes; | ||
825 | xfercount = newdata - remdata; /* a multiple of period_bytes */ | ||
826 | /* come back when on_card_bytes has decreased enough to allow | ||
827 | write to happen, or when data has been consumed to make another | ||
828 | period | ||
829 | */ | ||
830 | if (xfercount && (on_card_bytes > dpcm->period_bytes)) | ||
831 | next_jiffies = ((on_card_bytes - dpcm->period_bytes) * HZ / dpcm->bytes_per_sec); | ||
832 | else | ||
833 | next_jiffies = ((dpcm->period_bytes - remdata) * HZ / dpcm->bytes_per_sec); | ||
789 | 834 | ||
790 | remdata = newdata % dpcm->pcm_count; | 835 | next_jiffies = max(next_jiffies, 1U); |
791 | xfercount = newdata - remdata; /* a multiple of pcm_count */ | ||
792 | next_jiffies = ((dpcm->pcm_count-remdata) * HZ / dpcm->bytes_per_sec)+1; | ||
793 | next_jiffies = max(next_jiffies, 2U * HZ / 1000U); | ||
794 | dpcm->timer.expires = jiffies + next_jiffies; | 836 | dpcm->timer.expires = jiffies + next_jiffies; |
795 | VPRINTK1("jif %d buf pos x%04X newdata x%04X xc x%04X\n", | 837 | snd_printdd("jif %d buf pos 0x%04X newdata 0x%04X xfer 0x%04X\n", |
796 | next_jiffies, min_buf_pos, newdata, xfercount); | 838 | next_jiffies, pcm_buf_dma_ofs, newdata, xfercount); |
797 | 839 | ||
798 | snd_pcm_group_for_each_entry(s, dpcm->substream) { | 840 | snd_pcm_group_for_each_entry(s, substream) { |
799 | struct snd_card_asihpi_pcm *ds = s->runtime->private_data; | 841 | struct snd_card_asihpi_pcm *ds = s->runtime->private_data; |
800 | ds->pcm_buf_pos = min_buf_pos; | ||
801 | 842 | ||
802 | if (xfercount) { | 843 | /* don't link Cap and Play */ |
803 | if (card->support_mmap) { | 844 | if (substream->stream != s->stream) |
804 | ds->pcm_irq_pos = ds->pcm_irq_pos + xfercount; | 845 | continue; |
805 | if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 846 | |
806 | VPRINTK2("write OS%d x%04x\n", | 847 | ds->pcm_buf_dma_ofs = pcm_buf_dma_ofs; |
848 | |||
849 | if (xfercount && | ||
850 | /* Limit use of on card fifo for playback */ | ||
851 | ((on_card_bytes <= ds->period_bytes) || | ||
852 | (s->stream == SNDRV_PCM_STREAM_CAPTURE))) | ||
853 | |||
854 | { | ||
855 | |||
856 | unsigned int buf_ofs = ds->pcm_buf_host_rw_ofs % ds->buffer_bytes; | ||
857 | unsigned int xfer1, xfer2; | ||
858 | char *pd = &s->runtime->dma_area[buf_ofs]; | ||
859 | |||
860 | if (card->can_dma) { /* buffer wrap is handled at lower level */ | ||
861 | xfer1 = xfercount; | ||
862 | xfer2 = 0; | ||
863 | } else { | ||
864 | xfer1 = min(xfercount, ds->buffer_bytes - buf_ofs); | ||
865 | xfer2 = xfercount - xfer1; | ||
866 | } | ||
867 | |||
868 | if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
869 | snd_printddd("P%d write1 0x%04X 0x%04X\n", | ||
870 | s->number, xfer1, buf_ofs); | ||
871 | hpi_handle_error( | ||
872 | hpi_outstream_write_buf( | ||
873 | ds->h_stream, pd, xfer1, | ||
874 | &ds->format)); | ||
875 | |||
876 | if (xfer2) { | ||
877 | pd = s->runtime->dma_area; | ||
878 | |||
879 | snd_printddd("P%d write2 0x%04X 0x%04X\n", | ||
807 | s->number, | 880 | s->number, |
808 | ds->pcm_count); | 881 | xfercount - xfer1, buf_ofs); |
809 | hpi_handle_error( | 882 | hpi_handle_error( |
810 | hpi_outstream_write_buf( | 883 | hpi_outstream_write_buf( |
811 | ss, ds->h_stream, | 884 | ds->h_stream, pd, |
812 | &s->runtime-> | 885 | xfercount - xfer1, |
813 | dma_area[0], | ||
814 | xfercount, | ||
815 | &ds->format)); | 886 | &ds->format)); |
816 | } else { | 887 | } |
817 | VPRINTK2("read IS%d x%04x\n", | 888 | } else { |
818 | s->number, | 889 | snd_printddd("C%d read1 0x%04x\n", |
819 | dpcm->pcm_count); | 890 | s->number, xfer1); |
891 | hpi_handle_error( | ||
892 | hpi_instream_read_buf( | ||
893 | ds->h_stream, | ||
894 | pd, xfer1)); | ||
895 | if (xfer2) { | ||
896 | pd = s->runtime->dma_area; | ||
897 | snd_printddd("C%d read2 0x%04x\n", | ||
898 | s->number, xfer2); | ||
820 | hpi_handle_error( | 899 | hpi_handle_error( |
821 | hpi_instream_read_buf( | 900 | hpi_instream_read_buf( |
822 | ss, ds->h_stream, | 901 | ds->h_stream, |
823 | NULL, xfercount)); | 902 | pd, xfer2)); |
824 | } | 903 | } |
825 | } /* else R/W will be handled by read/write callbacks */ | 904 | } |
905 | ds->pcm_buf_host_rw_ofs = ds->pcm_buf_host_rw_ofs + xfercount; | ||
906 | ds->pcm_buf_elapsed_dma_ofs = pcm_buf_dma_ofs; | ||
826 | snd_pcm_period_elapsed(s); | 907 | snd_pcm_period_elapsed(s); |
827 | } | 908 | } |
828 | } | 909 | } |
@@ -835,7 +916,7 @@ static void snd_card_asihpi_timer_function(unsigned long data) | |||
835 | static int snd_card_asihpi_playback_ioctl(struct snd_pcm_substream *substream, | 916 | static int snd_card_asihpi_playback_ioctl(struct snd_pcm_substream *substream, |
836 | unsigned int cmd, void *arg) | 917 | unsigned int cmd, void *arg) |
837 | { | 918 | { |
838 | /* snd_printd(KERN_INFO "Playback ioctl %d\n", cmd); */ | 919 | snd_printddd(KERN_INFO "P%d ioctl %d\n", substream->number, cmd); |
839 | return snd_pcm_lib_ioctl(substream, cmd, arg); | 920 | return snd_pcm_lib_ioctl(substream, cmd, arg); |
840 | } | 921 | } |
841 | 922 | ||
@@ -845,12 +926,12 @@ static int snd_card_asihpi_playback_prepare(struct snd_pcm_substream * | |||
845 | struct snd_pcm_runtime *runtime = substream->runtime; | 926 | struct snd_pcm_runtime *runtime = substream->runtime; |
846 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; | 927 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; |
847 | 928 | ||
848 | snd_printd(KERN_INFO "playback prepare %d\n", substream->number); | 929 | snd_printdd("P%d prepare\n", substream->number); |
849 | |||
850 | hpi_handle_error(hpi_outstream_reset(ss, dpcm->h_stream)); | ||
851 | dpcm->pcm_irq_pos = 0; | ||
852 | dpcm->pcm_buf_pos = 0; | ||
853 | 930 | ||
931 | hpi_handle_error(hpi_outstream_reset(dpcm->h_stream)); | ||
932 | dpcm->pcm_buf_host_rw_ofs = 0; | ||
933 | dpcm->pcm_buf_dma_ofs = 0; | ||
934 | dpcm->pcm_buf_elapsed_dma_ofs = 0; | ||
854 | return 0; | 935 | return 0; |
855 | } | 936 | } |
856 | 937 | ||
@@ -861,27 +942,8 @@ snd_card_asihpi_playback_pointer(struct snd_pcm_substream *substream) | |||
861 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; | 942 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; |
862 | snd_pcm_uframes_t ptr; | 943 | snd_pcm_uframes_t ptr; |
863 | 944 | ||
864 | u32 samples_played; | 945 | ptr = bytes_to_frames(runtime, dpcm->pcm_buf_dma_ofs % dpcm->buffer_bytes); |
865 | u16 err; | 946 | snd_printddd("P%d pointer = 0x%04lx\n", substream->number, (unsigned long)ptr); |
866 | |||
867 | if (!snd_pcm_stream_linked(substream)) { | ||
868 | /* NOTE, can use samples played for playback position here and | ||
869 | * in timer fn because it LAGS the actual read pointer, and is a | ||
870 | * better representation of actual playout position | ||
871 | */ | ||
872 | err = hpi_outstream_get_info_ex(ss, dpcm->h_stream, NULL, | ||
873 | NULL, NULL, | ||
874 | &samples_played, NULL); | ||
875 | hpi_handle_error(err); | ||
876 | |||
877 | dpcm->pcm_buf_pos = frames_to_bytes(runtime, samples_played); | ||
878 | } | ||
879 | /* else must return most conservative value found in timer func | ||
880 | * by looping over all streams | ||
881 | */ | ||
882 | |||
883 | ptr = bytes_to_frames(runtime, dpcm->pcm_buf_pos % dpcm->pcm_size); | ||
884 | VPRINTK2("playback_pointer=%04ld\n", (unsigned long)ptr); | ||
885 | return ptr; | 947 | return ptr; |
886 | } | 948 | } |
887 | 949 | ||
@@ -898,12 +960,12 @@ static void snd_card_asihpi_playback_format(struct snd_card_asihpi *asihpi, | |||
898 | /* on cards without SRC, must query at valid rate, | 960 | /* on cards without SRC, must query at valid rate, |
899 | * maybe set by external sync | 961 | * maybe set by external sync |
900 | */ | 962 | */ |
901 | err = hpi_mixer_get_control(ss, asihpi->h_mixer, | 963 | err = hpi_mixer_get_control(asihpi->h_mixer, |
902 | HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, | 964 | HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, |
903 | HPI_CONTROL_SAMPLECLOCK, &h_control); | 965 | HPI_CONTROL_SAMPLECLOCK, &h_control); |
904 | 966 | ||
905 | if (!err) | 967 | if (!err) |
906 | err = hpi_sample_clock_get_sample_rate(ss, h_control, | 968 | err = hpi_sample_clock_get_sample_rate(h_control, |
907 | &sample_rate); | 969 | &sample_rate); |
908 | 970 | ||
909 | for (format = HPI_FORMAT_PCM8_UNSIGNED; | 971 | for (format = HPI_FORMAT_PCM8_UNSIGNED; |
@@ -911,7 +973,7 @@ static void snd_card_asihpi_playback_format(struct snd_card_asihpi *asihpi, | |||
911 | err = hpi_format_create(&hpi_format, | 973 | err = hpi_format_create(&hpi_format, |
912 | 2, format, sample_rate, 128000, 0); | 974 | 2, format, sample_rate, 128000, 0); |
913 | if (!err) | 975 | if (!err) |
914 | err = hpi_outstream_query_format(ss, h_stream, | 976 | err = hpi_outstream_query_format(h_stream, |
915 | &hpi_format); | 977 | &hpi_format); |
916 | if (!err && (hpi_to_alsa_formats[format] != -1)) | 978 | if (!err && (hpi_to_alsa_formats[format] != -1)) |
917 | pcmhw->formats |= | 979 | pcmhw->formats |= |
@@ -942,7 +1004,7 @@ static int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream) | |||
942 | return -ENOMEM; | 1004 | return -ENOMEM; |
943 | 1005 | ||
944 | err = | 1006 | err = |
945 | hpi_outstream_open(ss, card->adapter_index, | 1007 | hpi_outstream_open(card->adapter_index, |
946 | substream->number, &dpcm->h_stream); | 1008 | substream->number, &dpcm->h_stream); |
947 | hpi_handle_error(err); | 1009 | hpi_handle_error(err); |
948 | if (err) | 1010 | if (err) |
@@ -954,7 +1016,7 @@ static int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream) | |||
954 | 1016 | ||
955 | /*? also check ASI5000 samplerate source | 1017 | /*? also check ASI5000 samplerate source |
956 | If external, only support external rate. | 1018 | If external, only support external rate. |
957 | If internal and other stream playing, cant switch | 1019 | If internal and other stream playing, can't switch |
958 | */ | 1020 | */ |
959 | 1021 | ||
960 | init_timer(&dpcm->timer); | 1022 | init_timer(&dpcm->timer); |
@@ -977,11 +1039,9 @@ static int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream) | |||
977 | SNDRV_PCM_INFO_DOUBLE | | 1039 | SNDRV_PCM_INFO_DOUBLE | |
978 | SNDRV_PCM_INFO_BATCH | | 1040 | SNDRV_PCM_INFO_BATCH | |
979 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 1041 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
980 | SNDRV_PCM_INFO_PAUSE; | 1042 | SNDRV_PCM_INFO_PAUSE | |
981 | 1043 | SNDRV_PCM_INFO_MMAP | | |
982 | if (card->support_mmap) | 1044 | SNDRV_PCM_INFO_MMAP_VALID; |
983 | snd_card_asihpi_playback.info |= SNDRV_PCM_INFO_MMAP | | ||
984 | SNDRV_PCM_INFO_MMAP_VALID; | ||
985 | 1045 | ||
986 | if (card->support_grouping) | 1046 | if (card->support_grouping) |
987 | snd_card_asihpi_playback.info |= SNDRV_PCM_INFO_SYNC_START; | 1047 | snd_card_asihpi_playback.info |= SNDRV_PCM_INFO_SYNC_START; |
@@ -989,7 +1049,7 @@ static int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream) | |||
989 | /* struct is copied, so can create initializer dynamically */ | 1049 | /* struct is copied, so can create initializer dynamically */ |
990 | runtime->hw = snd_card_asihpi_playback; | 1050 | runtime->hw = snd_card_asihpi_playback; |
991 | 1051 | ||
992 | if (card->support_mmap) | 1052 | if (card->can_dma) |
993 | err = snd_pcm_hw_constraint_pow2(runtime, 0, | 1053 | err = snd_pcm_hw_constraint_pow2(runtime, 0, |
994 | SNDRV_PCM_HW_PARAM_BUFFER_BYTES); | 1054 | SNDRV_PCM_HW_PARAM_BUFFER_BYTES); |
995 | if (err < 0) | 1055 | if (err < 0) |
@@ -997,12 +1057,13 @@ static int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream) | |||
997 | 1057 | ||
998 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, | 1058 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, |
999 | card->update_interval_frames); | 1059 | card->update_interval_frames); |
1060 | |||
1000 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, | 1061 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, |
1001 | card->update_interval_frames * 4, UINT_MAX); | 1062 | card->update_interval_frames * 2, UINT_MAX); |
1002 | 1063 | ||
1003 | snd_pcm_set_sync(substream); | 1064 | snd_pcm_set_sync(substream); |
1004 | 1065 | ||
1005 | snd_printd(KERN_INFO "playback open\n"); | 1066 | snd_printdd("playback open\n"); |
1006 | 1067 | ||
1007 | return 0; | 1068 | return 0; |
1008 | } | 1069 | } |
@@ -1012,67 +1073,12 @@ static int snd_card_asihpi_playback_close(struct snd_pcm_substream *substream) | |||
1012 | struct snd_pcm_runtime *runtime = substream->runtime; | 1073 | struct snd_pcm_runtime *runtime = substream->runtime; |
1013 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; | 1074 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; |
1014 | 1075 | ||
1015 | hpi_handle_error(hpi_outstream_close(ss, dpcm->h_stream)); | 1076 | hpi_handle_error(hpi_outstream_close(dpcm->h_stream)); |
1016 | snd_printd(KERN_INFO "playback close\n"); | 1077 | snd_printdd("playback close\n"); |
1017 | |||
1018 | return 0; | ||
1019 | } | ||
1020 | |||
1021 | static int snd_card_asihpi_playback_copy(struct snd_pcm_substream *substream, | ||
1022 | int channel, | ||
1023 | snd_pcm_uframes_t pos, | ||
1024 | void __user *src, | ||
1025 | snd_pcm_uframes_t count) | ||
1026 | { | ||
1027 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
1028 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; | ||
1029 | unsigned int len; | ||
1030 | |||
1031 | len = frames_to_bytes(runtime, count); | ||
1032 | |||
1033 | if (copy_from_user(runtime->dma_area, src, len)) | ||
1034 | return -EFAULT; | ||
1035 | |||
1036 | VPRINTK2(KERN_DEBUG "playback copy%d %u bytes\n", | ||
1037 | substream->number, len); | ||
1038 | |||
1039 | hpi_handle_error(hpi_outstream_write_buf(ss, dpcm->h_stream, | ||
1040 | runtime->dma_area, len, &dpcm->format)); | ||
1041 | |||
1042 | return 0; | ||
1043 | } | ||
1044 | |||
1045 | static int snd_card_asihpi_playback_silence(struct snd_pcm_substream * | ||
1046 | substream, int channel, | ||
1047 | snd_pcm_uframes_t pos, | ||
1048 | snd_pcm_uframes_t count) | ||
1049 | { | ||
1050 | unsigned int len; | ||
1051 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
1052 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; | ||
1053 | |||
1054 | len = frames_to_bytes(runtime, count); | ||
1055 | snd_printd(KERN_INFO "playback silence %u bytes\n", len); | ||
1056 | 1078 | ||
1057 | memset(runtime->dma_area, 0, len); | ||
1058 | hpi_handle_error(hpi_outstream_write_buf(ss, dpcm->h_stream, | ||
1059 | runtime->dma_area, len, &dpcm->format)); | ||
1060 | return 0; | 1079 | return 0; |
1061 | } | 1080 | } |
1062 | 1081 | ||
1063 | static struct snd_pcm_ops snd_card_asihpi_playback_ops = { | ||
1064 | .open = snd_card_asihpi_playback_open, | ||
1065 | .close = snd_card_asihpi_playback_close, | ||
1066 | .ioctl = snd_card_asihpi_playback_ioctl, | ||
1067 | .hw_params = snd_card_asihpi_pcm_hw_params, | ||
1068 | .hw_free = snd_card_asihpi_hw_free, | ||
1069 | .prepare = snd_card_asihpi_playback_prepare, | ||
1070 | .trigger = snd_card_asihpi_trigger, | ||
1071 | .pointer = snd_card_asihpi_playback_pointer, | ||
1072 | .copy = snd_card_asihpi_playback_copy, | ||
1073 | .silence = snd_card_asihpi_playback_silence, | ||
1074 | }; | ||
1075 | |||
1076 | static struct snd_pcm_ops snd_card_asihpi_playback_mmap_ops = { | 1082 | static struct snd_pcm_ops snd_card_asihpi_playback_mmap_ops = { |
1077 | .open = snd_card_asihpi_playback_open, | 1083 | .open = snd_card_asihpi_playback_open, |
1078 | .close = snd_card_asihpi_playback_close, | 1084 | .close = snd_card_asihpi_playback_close, |
@@ -1091,13 +1097,13 @@ snd_card_asihpi_capture_pointer(struct snd_pcm_substream *substream) | |||
1091 | struct snd_pcm_runtime *runtime = substream->runtime; | 1097 | struct snd_pcm_runtime *runtime = substream->runtime; |
1092 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; | 1098 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; |
1093 | 1099 | ||
1094 | VPRINTK2("capture pointer %d=%d\n", | 1100 | snd_printddd("capture pointer %d=%d\n", |
1095 | substream->number, dpcm->pcm_buf_pos); | 1101 | substream->number, dpcm->pcm_buf_dma_ofs); |
1096 | /* NOTE Unlike playback can't use actual dwSamplesPlayed | 1102 | /* NOTE Unlike playback can't use actual samples_played |
1097 | for the capture position, because those samples aren't yet in | 1103 | for the capture position, because those samples aren't yet in |
1098 | the local buffer available for reading. | 1104 | the local buffer available for reading. |
1099 | */ | 1105 | */ |
1100 | return bytes_to_frames(runtime, dpcm->pcm_buf_pos % dpcm->pcm_size); | 1106 | return bytes_to_frames(runtime, dpcm->pcm_buf_dma_ofs % dpcm->buffer_bytes); |
1101 | } | 1107 | } |
1102 | 1108 | ||
1103 | static int snd_card_asihpi_capture_ioctl(struct snd_pcm_substream *substream, | 1109 | static int snd_card_asihpi_capture_ioctl(struct snd_pcm_substream *substream, |
@@ -1111,11 +1117,12 @@ static int snd_card_asihpi_capture_prepare(struct snd_pcm_substream *substream) | |||
1111 | struct snd_pcm_runtime *runtime = substream->runtime; | 1117 | struct snd_pcm_runtime *runtime = substream->runtime; |
1112 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; | 1118 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; |
1113 | 1119 | ||
1114 | hpi_handle_error(hpi_instream_reset(ss, dpcm->h_stream)); | 1120 | hpi_handle_error(hpi_instream_reset(dpcm->h_stream)); |
1115 | dpcm->pcm_irq_pos = 0; | 1121 | dpcm->pcm_buf_host_rw_ofs = 0; |
1116 | dpcm->pcm_buf_pos = 0; | 1122 | dpcm->pcm_buf_dma_ofs = 0; |
1123 | dpcm->pcm_buf_elapsed_dma_ofs = 0; | ||
1117 | 1124 | ||
1118 | snd_printd("capture prepare %d\n", substream->number); | 1125 | snd_printdd("Capture Prepare %d\n", substream->number); |
1119 | return 0; | 1126 | return 0; |
1120 | } | 1127 | } |
1121 | 1128 | ||
@@ -1133,12 +1140,12 @@ static void snd_card_asihpi_capture_format(struct snd_card_asihpi *asihpi, | |||
1133 | 1140 | ||
1134 | /* on cards without SRC, must query at valid rate, | 1141 | /* on cards without SRC, must query at valid rate, |
1135 | maybe set by external sync */ | 1142 | maybe set by external sync */ |
1136 | err = hpi_mixer_get_control(ss, asihpi->h_mixer, | 1143 | err = hpi_mixer_get_control(asihpi->h_mixer, |
1137 | HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, | 1144 | HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, |
1138 | HPI_CONTROL_SAMPLECLOCK, &h_control); | 1145 | HPI_CONTROL_SAMPLECLOCK, &h_control); |
1139 | 1146 | ||
1140 | if (!err) | 1147 | if (!err) |
1141 | err = hpi_sample_clock_get_sample_rate(ss, h_control, | 1148 | err = hpi_sample_clock_get_sample_rate(h_control, |
1142 | &sample_rate); | 1149 | &sample_rate); |
1143 | 1150 | ||
1144 | for (format = HPI_FORMAT_PCM8_UNSIGNED; | 1151 | for (format = HPI_FORMAT_PCM8_UNSIGNED; |
@@ -1147,7 +1154,7 @@ static void snd_card_asihpi_capture_format(struct snd_card_asihpi *asihpi, | |||
1147 | err = hpi_format_create(&hpi_format, 2, format, | 1154 | err = hpi_format_create(&hpi_format, 2, format, |
1148 | sample_rate, 128000, 0); | 1155 | sample_rate, 128000, 0); |
1149 | if (!err) | 1156 | if (!err) |
1150 | err = hpi_instream_query_format(ss, h_stream, | 1157 | err = hpi_instream_query_format(h_stream, |
1151 | &hpi_format); | 1158 | &hpi_format); |
1152 | if (!err) | 1159 | if (!err) |
1153 | pcmhw->formats |= | 1160 | pcmhw->formats |= |
@@ -1178,11 +1185,11 @@ static int snd_card_asihpi_capture_open(struct snd_pcm_substream *substream) | |||
1178 | if (dpcm == NULL) | 1185 | if (dpcm == NULL) |
1179 | return -ENOMEM; | 1186 | return -ENOMEM; |
1180 | 1187 | ||
1181 | snd_printd("hpi_instream_open adapter %d stream %d\n", | 1188 | snd_printdd("capture open adapter %d stream %d\n", |
1182 | card->adapter_index, substream->number); | 1189 | card->adapter_index, substream->number); |
1183 | 1190 | ||
1184 | err = hpi_handle_error( | 1191 | err = hpi_handle_error( |
1185 | hpi_instream_open(ss, card->adapter_index, | 1192 | hpi_instream_open(card->adapter_index, |
1186 | substream->number, &dpcm->h_stream)); | 1193 | substream->number, &dpcm->h_stream)); |
1187 | if (err) | 1194 | if (err) |
1188 | kfree(dpcm); | 1195 | kfree(dpcm); |
@@ -1203,15 +1210,16 @@ static int snd_card_asihpi_capture_open(struct snd_pcm_substream *substream) | |||
1203 | snd_card_asihpi_capture_format(card, dpcm->h_stream, | 1210 | snd_card_asihpi_capture_format(card, dpcm->h_stream, |
1204 | &snd_card_asihpi_capture); | 1211 | &snd_card_asihpi_capture); |
1205 | snd_card_asihpi_pcm_samplerates(card, &snd_card_asihpi_capture); | 1212 | snd_card_asihpi_pcm_samplerates(card, &snd_card_asihpi_capture); |
1206 | snd_card_asihpi_capture.info = SNDRV_PCM_INFO_INTERLEAVED; | 1213 | snd_card_asihpi_capture.info = SNDRV_PCM_INFO_INTERLEAVED | |
1214 | SNDRV_PCM_INFO_MMAP | | ||
1215 | SNDRV_PCM_INFO_MMAP_VALID; | ||
1207 | 1216 | ||
1208 | if (card->support_mmap) | 1217 | if (card->support_grouping) |
1209 | snd_card_asihpi_capture.info |= SNDRV_PCM_INFO_MMAP | | 1218 | snd_card_asihpi_capture.info |= SNDRV_PCM_INFO_SYNC_START; |
1210 | SNDRV_PCM_INFO_MMAP_VALID; | ||
1211 | 1219 | ||
1212 | runtime->hw = snd_card_asihpi_capture; | 1220 | runtime->hw = snd_card_asihpi_capture; |
1213 | 1221 | ||
1214 | if (card->support_mmap) | 1222 | if (card->can_dma) |
1215 | err = snd_pcm_hw_constraint_pow2(runtime, 0, | 1223 | err = snd_pcm_hw_constraint_pow2(runtime, 0, |
1216 | SNDRV_PCM_HW_PARAM_BUFFER_BYTES); | 1224 | SNDRV_PCM_HW_PARAM_BUFFER_BYTES); |
1217 | if (err < 0) | 1225 | if (err < 0) |
@@ -1231,30 +1239,7 @@ static int snd_card_asihpi_capture_close(struct snd_pcm_substream *substream) | |||
1231 | { | 1239 | { |
1232 | struct snd_card_asihpi_pcm *dpcm = substream->runtime->private_data; | 1240 | struct snd_card_asihpi_pcm *dpcm = substream->runtime->private_data; |
1233 | 1241 | ||
1234 | hpi_handle_error(hpi_instream_close(ss, dpcm->h_stream)); | 1242 | hpi_handle_error(hpi_instream_close(dpcm->h_stream)); |
1235 | return 0; | ||
1236 | } | ||
1237 | |||
1238 | static int snd_card_asihpi_capture_copy(struct snd_pcm_substream *substream, | ||
1239 | int channel, snd_pcm_uframes_t pos, | ||
1240 | void __user *dst, snd_pcm_uframes_t count) | ||
1241 | { | ||
1242 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
1243 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; | ||
1244 | u32 data_size; | ||
1245 | |||
1246 | data_size = frames_to_bytes(runtime, count); | ||
1247 | |||
1248 | VPRINTK2("capture copy%d %d bytes\n", substream->number, data_size); | ||
1249 | hpi_handle_error(hpi_instream_read_buf(ss, dpcm->h_stream, | ||
1250 | runtime->dma_area, data_size)); | ||
1251 | |||
1252 | /* Used by capture_pointer */ | ||
1253 | dpcm->pcm_irq_pos = dpcm->pcm_irq_pos + data_size; | ||
1254 | |||
1255 | if (copy_to_user(dst, runtime->dma_area, data_size)) | ||
1256 | return -EFAULT; | ||
1257 | |||
1258 | return 0; | 1243 | return 0; |
1259 | } | 1244 | } |
1260 | 1245 | ||
@@ -1269,45 +1254,26 @@ static struct snd_pcm_ops snd_card_asihpi_capture_mmap_ops = { | |||
1269 | .pointer = snd_card_asihpi_capture_pointer, | 1254 | .pointer = snd_card_asihpi_capture_pointer, |
1270 | }; | 1255 | }; |
1271 | 1256 | ||
1272 | static struct snd_pcm_ops snd_card_asihpi_capture_ops = { | ||
1273 | .open = snd_card_asihpi_capture_open, | ||
1274 | .close = snd_card_asihpi_capture_close, | ||
1275 | .ioctl = snd_card_asihpi_capture_ioctl, | ||
1276 | .hw_params = snd_card_asihpi_pcm_hw_params, | ||
1277 | .hw_free = snd_card_asihpi_hw_free, | ||
1278 | .prepare = snd_card_asihpi_capture_prepare, | ||
1279 | .trigger = snd_card_asihpi_trigger, | ||
1280 | .pointer = snd_card_asihpi_capture_pointer, | ||
1281 | .copy = snd_card_asihpi_capture_copy | ||
1282 | }; | ||
1283 | |||
1284 | static int __devinit snd_card_asihpi_pcm_new(struct snd_card_asihpi *asihpi, | 1257 | static int __devinit snd_card_asihpi_pcm_new(struct snd_card_asihpi *asihpi, |
1285 | int device, int substreams) | 1258 | int device, int substreams) |
1286 | { | 1259 | { |
1287 | struct snd_pcm *pcm; | 1260 | struct snd_pcm *pcm; |
1288 | int err; | 1261 | int err; |
1289 | 1262 | ||
1290 | err = snd_pcm_new(asihpi->card, "asihpi PCM", device, | 1263 | err = snd_pcm_new(asihpi->card, "Asihpi PCM", device, |
1291 | asihpi->num_outstreams, asihpi->num_instreams, | 1264 | asihpi->num_outstreams, asihpi->num_instreams, |
1292 | &pcm); | 1265 | &pcm); |
1293 | if (err < 0) | 1266 | if (err < 0) |
1294 | return err; | 1267 | return err; |
1295 | /* pointer to ops struct is stored, dont change ops afterwards! */ | 1268 | /* pointer to ops struct is stored, dont change ops afterwards! */ |
1296 | if (asihpi->support_mmap) { | ||
1297 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, | 1269 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, |
1298 | &snd_card_asihpi_playback_mmap_ops); | 1270 | &snd_card_asihpi_playback_mmap_ops); |
1299 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, | 1271 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, |
1300 | &snd_card_asihpi_capture_mmap_ops); | 1272 | &snd_card_asihpi_capture_mmap_ops); |
1301 | } else { | ||
1302 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
1303 | &snd_card_asihpi_playback_ops); | ||
1304 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, | ||
1305 | &snd_card_asihpi_capture_ops); | ||
1306 | } | ||
1307 | 1273 | ||
1308 | pcm->private_data = asihpi; | 1274 | pcm->private_data = asihpi; |
1309 | pcm->info_flags = 0; | 1275 | pcm->info_flags = 0; |
1310 | strcpy(pcm->name, "asihpi PCM"); | 1276 | strcpy(pcm->name, "Asihpi PCM"); |
1311 | 1277 | ||
1312 | /*? do we want to emulate MMAP for non-BBM cards? | 1278 | /*? do we want to emulate MMAP for non-BBM cards? |
1313 | Jack doesn't work with ALSAs MMAP emulation - WHY NOT? */ | 1279 | Jack doesn't work with ALSAs MMAP emulation - WHY NOT? */ |
@@ -1330,8 +1296,7 @@ struct hpi_control { | |||
1330 | char name[44]; /* copied to snd_ctl_elem_id.name[44]; */ | 1296 | char name[44]; /* copied to snd_ctl_elem_id.name[44]; */ |
1331 | }; | 1297 | }; |
1332 | 1298 | ||
1333 | static char *asihpi_tuner_band_names[] = | 1299 | static const char * const asihpi_tuner_band_names[] = { |
1334 | { | ||
1335 | "invalid", | 1300 | "invalid", |
1336 | "AM", | 1301 | "AM", |
1337 | "FM mono", | 1302 | "FM mono", |
@@ -1349,70 +1314,36 @@ compile_time_assert( | |||
1349 | (HPI_TUNER_BAND_LAST+1)), | 1314 | (HPI_TUNER_BAND_LAST+1)), |
1350 | assert_tuner_band_names_size); | 1315 | assert_tuner_band_names_size); |
1351 | 1316 | ||
1352 | #if ASI_STYLE_NAMES | 1317 | static const char * const asihpi_src_names[] = { |
1353 | static char *asihpi_src_names[] = | ||
1354 | { | ||
1355 | "no source", | ||
1356 | "outstream", | ||
1357 | "line_in", | ||
1358 | "aes_in", | ||
1359 | "tuner", | ||
1360 | "RF", | ||
1361 | "clock", | ||
1362 | "bitstr", | ||
1363 | "mic", | ||
1364 | "cobranet", | ||
1365 | "analog_in", | ||
1366 | "adapter", | ||
1367 | }; | ||
1368 | #else | ||
1369 | static char *asihpi_src_names[] = | ||
1370 | { | ||
1371 | "no source", | 1318 | "no source", |
1372 | "PCM playback", | 1319 | "PCM", |
1373 | "line in", | 1320 | "Line", |
1374 | "digital in", | 1321 | "Digital", |
1375 | "tuner", | 1322 | "Tuner", |
1376 | "RF", | 1323 | "RF", |
1377 | "clock", | 1324 | "Clock", |
1378 | "bitstream", | 1325 | "Bitstream", |
1379 | "mic", | 1326 | "Microphone", |
1380 | "cobranet in", | 1327 | "Cobranet", |
1381 | "analog in", | 1328 | "Analog", |
1382 | "adapter", | 1329 | "Adapter", |
1383 | }; | 1330 | }; |
1384 | #endif | ||
1385 | 1331 | ||
1386 | compile_time_assert( | 1332 | compile_time_assert( |
1387 | (ARRAY_SIZE(asihpi_src_names) == | 1333 | (ARRAY_SIZE(asihpi_src_names) == |
1388 | (HPI_SOURCENODE_LAST_INDEX-HPI_SOURCENODE_NONE+1)), | 1334 | (HPI_SOURCENODE_LAST_INDEX-HPI_SOURCENODE_NONE+1)), |
1389 | assert_src_names_size); | 1335 | assert_src_names_size); |
1390 | 1336 | ||
1391 | #if ASI_STYLE_NAMES | 1337 | static const char * const asihpi_dst_names[] = { |
1392 | static char *asihpi_dst_names[] = | ||
1393 | { | ||
1394 | "no destination", | 1338 | "no destination", |
1395 | "instream", | 1339 | "PCM", |
1396 | "line_out", | 1340 | "Line", |
1397 | "aes_out", | 1341 | "Digital", |
1398 | "RF", | 1342 | "RF", |
1399 | "speaker" , | 1343 | "Speaker", |
1400 | "cobranet", | 1344 | "Cobranet Out", |
1401 | "analog_out", | 1345 | "Analog" |
1402 | }; | 1346 | }; |
1403 | #else | ||
1404 | static char *asihpi_dst_names[] = | ||
1405 | { | ||
1406 | "no destination", | ||
1407 | "PCM capture", | ||
1408 | "line out", | ||
1409 | "digital out", | ||
1410 | "RF", | ||
1411 | "speaker", | ||
1412 | "cobranet out", | ||
1413 | "analog out" | ||
1414 | }; | ||
1415 | #endif | ||
1416 | 1347 | ||
1417 | compile_time_assert( | 1348 | compile_time_assert( |
1418 | (ARRAY_SIZE(asihpi_dst_names) == | 1349 | (ARRAY_SIZE(asihpi_dst_names) == |
@@ -1438,30 +1369,47 @@ static void asihpi_ctl_init(struct snd_kcontrol_new *snd_control, | |||
1438 | struct hpi_control *hpi_ctl, | 1369 | struct hpi_control *hpi_ctl, |
1439 | char *name) | 1370 | char *name) |
1440 | { | 1371 | { |
1372 | char *dir; | ||
1441 | memset(snd_control, 0, sizeof(*snd_control)); | 1373 | memset(snd_control, 0, sizeof(*snd_control)); |
1442 | snd_control->name = hpi_ctl->name; | 1374 | snd_control->name = hpi_ctl->name; |
1443 | snd_control->private_value = hpi_ctl->h_control; | 1375 | snd_control->private_value = hpi_ctl->h_control; |
1444 | snd_control->iface = SNDRV_CTL_ELEM_IFACE_MIXER; | 1376 | snd_control->iface = SNDRV_CTL_ELEM_IFACE_MIXER; |
1445 | snd_control->index = 0; | 1377 | snd_control->index = 0; |
1446 | 1378 | ||
1379 | if (hpi_ctl->src_node_type + HPI_SOURCENODE_NONE == HPI_SOURCENODE_CLOCK_SOURCE) | ||
1380 | dir = ""; /* clock is neither capture nor playback */ | ||
1381 | else if (hpi_ctl->dst_node_type + HPI_DESTNODE_NONE == HPI_DESTNODE_ISTREAM) | ||
1382 | dir = "Capture "; /* On or towards a PCM capture destination*/ | ||
1383 | else if ((hpi_ctl->src_node_type + HPI_SOURCENODE_NONE != HPI_SOURCENODE_OSTREAM) && | ||
1384 | (!hpi_ctl->dst_node_type)) | ||
1385 | dir = "Capture "; /* On a source node that is not PCM playback */ | ||
1386 | else if (hpi_ctl->src_node_type && | ||
1387 | (hpi_ctl->src_node_type + HPI_SOURCENODE_NONE != HPI_SOURCENODE_OSTREAM) && | ||
1388 | (hpi_ctl->dst_node_type)) | ||
1389 | dir = "Monitor Playback "; /* Between an input and an output */ | ||
1390 | else | ||
1391 | dir = "Playback "; /* PCM Playback source, or output node */ | ||
1392 | |||
1447 | if (hpi_ctl->src_node_type && hpi_ctl->dst_node_type) | 1393 | if (hpi_ctl->src_node_type && hpi_ctl->dst_node_type) |
1448 | sprintf(hpi_ctl->name, "%s%d to %s%d %s", | 1394 | sprintf(hpi_ctl->name, "%s %d %s %d %s%s", |
1449 | asihpi_src_names[hpi_ctl->src_node_type], | 1395 | asihpi_src_names[hpi_ctl->src_node_type], |
1450 | hpi_ctl->src_node_index, | 1396 | hpi_ctl->src_node_index, |
1451 | asihpi_dst_names[hpi_ctl->dst_node_type], | 1397 | asihpi_dst_names[hpi_ctl->dst_node_type], |
1452 | hpi_ctl->dst_node_index, | 1398 | hpi_ctl->dst_node_index, |
1453 | name); | 1399 | dir, name); |
1454 | else if (hpi_ctl->dst_node_type) { | 1400 | else if (hpi_ctl->dst_node_type) { |
1455 | sprintf(hpi_ctl->name, "%s%d %s", | 1401 | sprintf(hpi_ctl->name, "%s %d %s%s", |
1456 | asihpi_dst_names[hpi_ctl->dst_node_type], | 1402 | asihpi_dst_names[hpi_ctl->dst_node_type], |
1457 | hpi_ctl->dst_node_index, | 1403 | hpi_ctl->dst_node_index, |
1458 | name); | 1404 | dir, name); |
1459 | } else { | 1405 | } else { |
1460 | sprintf(hpi_ctl->name, "%s%d %s", | 1406 | sprintf(hpi_ctl->name, "%s %d %s%s", |
1461 | asihpi_src_names[hpi_ctl->src_node_type], | 1407 | asihpi_src_names[hpi_ctl->src_node_type], |
1462 | hpi_ctl->src_node_index, | 1408 | hpi_ctl->src_node_index, |
1463 | name); | 1409 | dir, name); |
1464 | } | 1410 | } |
1411 | /* printk(KERN_INFO "Adding %s %d to %d ", hpi_ctl->name, | ||
1412 | hpi_ctl->wSrcNodeType, hpi_ctl->wDstNodeType); */ | ||
1465 | } | 1413 | } |
1466 | 1414 | ||
1467 | /*------------------------------------------------------------ | 1415 | /*------------------------------------------------------------ |
@@ -1478,7 +1426,7 @@ static int snd_asihpi_volume_info(struct snd_kcontrol *kcontrol, | |||
1478 | short max_gain_mB; | 1426 | short max_gain_mB; |
1479 | short step_gain_mB; | 1427 | short step_gain_mB; |
1480 | 1428 | ||
1481 | err = hpi_volume_query_range(ss, h_control, | 1429 | err = hpi_volume_query_range(h_control, |
1482 | &min_gain_mB, &max_gain_mB, &step_gain_mB); | 1430 | &min_gain_mB, &max_gain_mB, &step_gain_mB); |
1483 | if (err) { | 1431 | if (err) { |
1484 | max_gain_mB = 0; | 1432 | max_gain_mB = 0; |
@@ -1500,7 +1448,7 @@ static int snd_asihpi_volume_get(struct snd_kcontrol *kcontrol, | |||
1500 | u32 h_control = kcontrol->private_value; | 1448 | u32 h_control = kcontrol->private_value; |
1501 | short an_gain_mB[HPI_MAX_CHANNELS]; | 1449 | short an_gain_mB[HPI_MAX_CHANNELS]; |
1502 | 1450 | ||
1503 | hpi_handle_error(hpi_volume_get_gain(ss, h_control, an_gain_mB)); | 1451 | hpi_handle_error(hpi_volume_get_gain(h_control, an_gain_mB)); |
1504 | ucontrol->value.integer.value[0] = an_gain_mB[0] / VOL_STEP_mB; | 1452 | ucontrol->value.integer.value[0] = an_gain_mB[0] / VOL_STEP_mB; |
1505 | ucontrol->value.integer.value[1] = an_gain_mB[1] / VOL_STEP_mB; | 1453 | ucontrol->value.integer.value[1] = an_gain_mB[1] / VOL_STEP_mB; |
1506 | 1454 | ||
@@ -1522,7 +1470,7 @@ static int snd_asihpi_volume_put(struct snd_kcontrol *kcontrol, | |||
1522 | asihpi->mixer_volume[addr][1] != right; | 1470 | asihpi->mixer_volume[addr][1] != right; |
1523 | */ | 1471 | */ |
1524 | change = 1; | 1472 | change = 1; |
1525 | hpi_handle_error(hpi_volume_set_gain(ss, h_control, an_gain_mB)); | 1473 | hpi_handle_error(hpi_volume_set_gain(h_control, an_gain_mB)); |
1526 | return change; | 1474 | return change; |
1527 | } | 1475 | } |
1528 | 1476 | ||
@@ -1534,7 +1482,7 @@ static int __devinit snd_asihpi_volume_add(struct snd_card_asihpi *asihpi, | |||
1534 | struct snd_card *card = asihpi->card; | 1482 | struct snd_card *card = asihpi->card; |
1535 | struct snd_kcontrol_new snd_control; | 1483 | struct snd_kcontrol_new snd_control; |
1536 | 1484 | ||
1537 | asihpi_ctl_init(&snd_control, hpi_ctl, "volume"); | 1485 | asihpi_ctl_init(&snd_control, hpi_ctl, "Volume"); |
1538 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | 1486 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | |
1539 | SNDRV_CTL_ELEM_ACCESS_TLV_READ; | 1487 | SNDRV_CTL_ELEM_ACCESS_TLV_READ; |
1540 | snd_control.info = snd_asihpi_volume_info; | 1488 | snd_control.info = snd_asihpi_volume_info; |
@@ -1558,7 +1506,7 @@ static int snd_asihpi_level_info(struct snd_kcontrol *kcontrol, | |||
1558 | short step_gain_mB; | 1506 | short step_gain_mB; |
1559 | 1507 | ||
1560 | err = | 1508 | err = |
1561 | hpi_level_query_range(ss, h_control, &min_gain_mB, | 1509 | hpi_level_query_range(h_control, &min_gain_mB, |
1562 | &max_gain_mB, &step_gain_mB); | 1510 | &max_gain_mB, &step_gain_mB); |
1563 | if (err) { | 1511 | if (err) { |
1564 | max_gain_mB = 2400; | 1512 | max_gain_mB = 2400; |
@@ -1580,7 +1528,7 @@ static int snd_asihpi_level_get(struct snd_kcontrol *kcontrol, | |||
1580 | u32 h_control = kcontrol->private_value; | 1528 | u32 h_control = kcontrol->private_value; |
1581 | short an_gain_mB[HPI_MAX_CHANNELS]; | 1529 | short an_gain_mB[HPI_MAX_CHANNELS]; |
1582 | 1530 | ||
1583 | hpi_handle_error(hpi_level_get_gain(ss, h_control, an_gain_mB)); | 1531 | hpi_handle_error(hpi_level_get_gain(h_control, an_gain_mB)); |
1584 | ucontrol->value.integer.value[0] = | 1532 | ucontrol->value.integer.value[0] = |
1585 | an_gain_mB[0] / HPI_UNITS_PER_dB; | 1533 | an_gain_mB[0] / HPI_UNITS_PER_dB; |
1586 | ucontrol->value.integer.value[1] = | 1534 | ucontrol->value.integer.value[1] = |
@@ -1604,7 +1552,7 @@ static int snd_asihpi_level_put(struct snd_kcontrol *kcontrol, | |||
1604 | asihpi->mixer_level[addr][1] != right; | 1552 | asihpi->mixer_level[addr][1] != right; |
1605 | */ | 1553 | */ |
1606 | change = 1; | 1554 | change = 1; |
1607 | hpi_handle_error(hpi_level_set_gain(ss, h_control, an_gain_mB)); | 1555 | hpi_handle_error(hpi_level_set_gain(h_control, an_gain_mB)); |
1608 | return change; | 1556 | return change; |
1609 | } | 1557 | } |
1610 | 1558 | ||
@@ -1617,7 +1565,7 @@ static int __devinit snd_asihpi_level_add(struct snd_card_asihpi *asihpi, | |||
1617 | struct snd_kcontrol_new snd_control; | 1565 | struct snd_kcontrol_new snd_control; |
1618 | 1566 | ||
1619 | /* can't use 'volume' cos some nodes have volume as well */ | 1567 | /* can't use 'volume' cos some nodes have volume as well */ |
1620 | asihpi_ctl_init(&snd_control, hpi_ctl, "level"); | 1568 | asihpi_ctl_init(&snd_control, hpi_ctl, "Level"); |
1621 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | 1569 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | |
1622 | SNDRV_CTL_ELEM_ACCESS_TLV_READ; | 1570 | SNDRV_CTL_ELEM_ACCESS_TLV_READ; |
1623 | snd_control.info = snd_asihpi_level_info; | 1571 | snd_control.info = snd_asihpi_level_info; |
@@ -1633,12 +1581,8 @@ static int __devinit snd_asihpi_level_add(struct snd_card_asihpi *asihpi, | |||
1633 | ------------------------------------------------------------*/ | 1581 | ------------------------------------------------------------*/ |
1634 | 1582 | ||
1635 | /* AESEBU format */ | 1583 | /* AESEBU format */ |
1636 | static char *asihpi_aesebu_format_names[] = | 1584 | static const char * const asihpi_aesebu_format_names[] = { |
1637 | { | 1585 | "N/A", "S/PDIF", "AES/EBU" }; |
1638 | "N/A", | ||
1639 | "S/PDIF", | ||
1640 | "AES/EBU", | ||
1641 | }; | ||
1642 | 1586 | ||
1643 | static int snd_asihpi_aesebu_format_info(struct snd_kcontrol *kcontrol, | 1587 | static int snd_asihpi_aesebu_format_info(struct snd_kcontrol *kcontrol, |
1644 | struct snd_ctl_elem_info *uinfo) | 1588 | struct snd_ctl_elem_info *uinfo) |
@@ -1659,12 +1603,12 @@ static int snd_asihpi_aesebu_format_info(struct snd_kcontrol *kcontrol, | |||
1659 | 1603 | ||
1660 | static int snd_asihpi_aesebu_format_get(struct snd_kcontrol *kcontrol, | 1604 | static int snd_asihpi_aesebu_format_get(struct snd_kcontrol *kcontrol, |
1661 | struct snd_ctl_elem_value *ucontrol, | 1605 | struct snd_ctl_elem_value *ucontrol, |
1662 | u16 (*func)(const struct hpi_hsubsys *, u32, u16 *)) | 1606 | u16 (*func)(u32, u16 *)) |
1663 | { | 1607 | { |
1664 | u32 h_control = kcontrol->private_value; | 1608 | u32 h_control = kcontrol->private_value; |
1665 | u16 source, err; | 1609 | u16 source, err; |
1666 | 1610 | ||
1667 | err = func(ss, h_control, &source); | 1611 | err = func(h_control, &source); |
1668 | 1612 | ||
1669 | /* default to N/A */ | 1613 | /* default to N/A */ |
1670 | ucontrol->value.enumerated.item[0] = 0; | 1614 | ucontrol->value.enumerated.item[0] = 0; |
@@ -1681,7 +1625,7 @@ static int snd_asihpi_aesebu_format_get(struct snd_kcontrol *kcontrol, | |||
1681 | 1625 | ||
1682 | static int snd_asihpi_aesebu_format_put(struct snd_kcontrol *kcontrol, | 1626 | static int snd_asihpi_aesebu_format_put(struct snd_kcontrol *kcontrol, |
1683 | struct snd_ctl_elem_value *ucontrol, | 1627 | struct snd_ctl_elem_value *ucontrol, |
1684 | u16 (*func)(const struct hpi_hsubsys *, u32, u16)) | 1628 | u16 (*func)(u32, u16)) |
1685 | { | 1629 | { |
1686 | u32 h_control = kcontrol->private_value; | 1630 | u32 h_control = kcontrol->private_value; |
1687 | 1631 | ||
@@ -1693,7 +1637,7 @@ static int snd_asihpi_aesebu_format_put(struct snd_kcontrol *kcontrol, | |||
1693 | if (ucontrol->value.enumerated.item[0] == 2) | 1637 | if (ucontrol->value.enumerated.item[0] == 2) |
1694 | source = HPI_AESEBU_FORMAT_AESEBU; | 1638 | source = HPI_AESEBU_FORMAT_AESEBU; |
1695 | 1639 | ||
1696 | if (func(ss, h_control, source) != 0) | 1640 | if (func(h_control, source) != 0) |
1697 | return -EINVAL; | 1641 | return -EINVAL; |
1698 | 1642 | ||
1699 | return 1; | 1643 | return 1; |
@@ -1702,13 +1646,13 @@ static int snd_asihpi_aesebu_format_put(struct snd_kcontrol *kcontrol, | |||
1702 | static int snd_asihpi_aesebu_rx_format_get(struct snd_kcontrol *kcontrol, | 1646 | static int snd_asihpi_aesebu_rx_format_get(struct snd_kcontrol *kcontrol, |
1703 | struct snd_ctl_elem_value *ucontrol) { | 1647 | struct snd_ctl_elem_value *ucontrol) { |
1704 | return snd_asihpi_aesebu_format_get(kcontrol, ucontrol, | 1648 | return snd_asihpi_aesebu_format_get(kcontrol, ucontrol, |
1705 | HPI_AESEBU__receiver_get_format); | 1649 | hpi_aesebu_receiver_get_format); |
1706 | } | 1650 | } |
1707 | 1651 | ||
1708 | static int snd_asihpi_aesebu_rx_format_put(struct snd_kcontrol *kcontrol, | 1652 | static int snd_asihpi_aesebu_rx_format_put(struct snd_kcontrol *kcontrol, |
1709 | struct snd_ctl_elem_value *ucontrol) { | 1653 | struct snd_ctl_elem_value *ucontrol) { |
1710 | return snd_asihpi_aesebu_format_put(kcontrol, ucontrol, | 1654 | return snd_asihpi_aesebu_format_put(kcontrol, ucontrol, |
1711 | HPI_AESEBU__receiver_set_format); | 1655 | hpi_aesebu_receiver_set_format); |
1712 | } | 1656 | } |
1713 | 1657 | ||
1714 | static int snd_asihpi_aesebu_rxstatus_info(struct snd_kcontrol *kcontrol, | 1658 | static int snd_asihpi_aesebu_rxstatus_info(struct snd_kcontrol *kcontrol, |
@@ -1730,8 +1674,8 @@ static int snd_asihpi_aesebu_rxstatus_get(struct snd_kcontrol *kcontrol, | |||
1730 | u32 h_control = kcontrol->private_value; | 1674 | u32 h_control = kcontrol->private_value; |
1731 | u16 status; | 1675 | u16 status; |
1732 | 1676 | ||
1733 | hpi_handle_error(HPI_AESEBU__receiver_get_error_status( | 1677 | hpi_handle_error(hpi_aesebu_receiver_get_error_status( |
1734 | ss, h_control, &status)); | 1678 | h_control, &status)); |
1735 | ucontrol->value.integer.value[0] = status; | 1679 | ucontrol->value.integer.value[0] = status; |
1736 | return 0; | 1680 | return 0; |
1737 | } | 1681 | } |
@@ -1742,7 +1686,7 @@ static int __devinit snd_asihpi_aesebu_rx_add(struct snd_card_asihpi *asihpi, | |||
1742 | struct snd_card *card = asihpi->card; | 1686 | struct snd_card *card = asihpi->card; |
1743 | struct snd_kcontrol_new snd_control; | 1687 | struct snd_kcontrol_new snd_control; |
1744 | 1688 | ||
1745 | asihpi_ctl_init(&snd_control, hpi_ctl, "format"); | 1689 | asihpi_ctl_init(&snd_control, hpi_ctl, "Format"); |
1746 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; | 1690 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; |
1747 | snd_control.info = snd_asihpi_aesebu_format_info; | 1691 | snd_control.info = snd_asihpi_aesebu_format_info; |
1748 | snd_control.get = snd_asihpi_aesebu_rx_format_get; | 1692 | snd_control.get = snd_asihpi_aesebu_rx_format_get; |
@@ -1752,7 +1696,7 @@ static int __devinit snd_asihpi_aesebu_rx_add(struct snd_card_asihpi *asihpi, | |||
1752 | if (ctl_add(card, &snd_control, asihpi) < 0) | 1696 | if (ctl_add(card, &snd_control, asihpi) < 0) |
1753 | return -EINVAL; | 1697 | return -EINVAL; |
1754 | 1698 | ||
1755 | asihpi_ctl_init(&snd_control, hpi_ctl, "status"); | 1699 | asihpi_ctl_init(&snd_control, hpi_ctl, "Status"); |
1756 | snd_control.access = | 1700 | snd_control.access = |
1757 | SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ; | 1701 | SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ; |
1758 | snd_control.info = snd_asihpi_aesebu_rxstatus_info; | 1702 | snd_control.info = snd_asihpi_aesebu_rxstatus_info; |
@@ -1764,13 +1708,13 @@ static int __devinit snd_asihpi_aesebu_rx_add(struct snd_card_asihpi *asihpi, | |||
1764 | static int snd_asihpi_aesebu_tx_format_get(struct snd_kcontrol *kcontrol, | 1708 | static int snd_asihpi_aesebu_tx_format_get(struct snd_kcontrol *kcontrol, |
1765 | struct snd_ctl_elem_value *ucontrol) { | 1709 | struct snd_ctl_elem_value *ucontrol) { |
1766 | return snd_asihpi_aesebu_format_get(kcontrol, ucontrol, | 1710 | return snd_asihpi_aesebu_format_get(kcontrol, ucontrol, |
1767 | HPI_AESEBU__transmitter_get_format); | 1711 | hpi_aesebu_transmitter_get_format); |
1768 | } | 1712 | } |
1769 | 1713 | ||
1770 | static int snd_asihpi_aesebu_tx_format_put(struct snd_kcontrol *kcontrol, | 1714 | static int snd_asihpi_aesebu_tx_format_put(struct snd_kcontrol *kcontrol, |
1771 | struct snd_ctl_elem_value *ucontrol) { | 1715 | struct snd_ctl_elem_value *ucontrol) { |
1772 | return snd_asihpi_aesebu_format_put(kcontrol, ucontrol, | 1716 | return snd_asihpi_aesebu_format_put(kcontrol, ucontrol, |
1773 | HPI_AESEBU__transmitter_set_format); | 1717 | hpi_aesebu_transmitter_set_format); |
1774 | } | 1718 | } |
1775 | 1719 | ||
1776 | 1720 | ||
@@ -1780,7 +1724,7 @@ static int __devinit snd_asihpi_aesebu_tx_add(struct snd_card_asihpi *asihpi, | |||
1780 | struct snd_card *card = asihpi->card; | 1724 | struct snd_card *card = asihpi->card; |
1781 | struct snd_kcontrol_new snd_control; | 1725 | struct snd_kcontrol_new snd_control; |
1782 | 1726 | ||
1783 | asihpi_ctl_init(&snd_control, hpi_ctl, "format"); | 1727 | asihpi_ctl_init(&snd_control, hpi_ctl, "Format"); |
1784 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; | 1728 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; |
1785 | snd_control.info = snd_asihpi_aesebu_format_info; | 1729 | snd_control.info = snd_asihpi_aesebu_format_info; |
1786 | snd_control.get = snd_asihpi_aesebu_tx_format_get; | 1730 | snd_control.get = snd_asihpi_aesebu_tx_format_get; |
@@ -1804,7 +1748,7 @@ static int snd_asihpi_tuner_gain_info(struct snd_kcontrol *kcontrol, | |||
1804 | u16 gain_range[3]; | 1748 | u16 gain_range[3]; |
1805 | 1749 | ||
1806 | for (idx = 0; idx < 3; idx++) { | 1750 | for (idx = 0; idx < 3; idx++) { |
1807 | err = hpi_tuner_query_gain(ss, h_control, | 1751 | err = hpi_tuner_query_gain(h_control, |
1808 | idx, &gain_range[idx]); | 1752 | idx, &gain_range[idx]); |
1809 | if (err != 0) | 1753 | if (err != 0) |
1810 | return err; | 1754 | return err; |
@@ -1827,7 +1771,7 @@ static int snd_asihpi_tuner_gain_get(struct snd_kcontrol *kcontrol, | |||
1827 | u32 h_control = kcontrol->private_value; | 1771 | u32 h_control = kcontrol->private_value; |
1828 | short gain; | 1772 | short gain; |
1829 | 1773 | ||
1830 | hpi_handle_error(hpi_tuner_get_gain(ss, h_control, &gain)); | 1774 | hpi_handle_error(hpi_tuner_get_gain(h_control, &gain)); |
1831 | ucontrol->value.integer.value[0] = gain / HPI_UNITS_PER_dB; | 1775 | ucontrol->value.integer.value[0] = gain / HPI_UNITS_PER_dB; |
1832 | 1776 | ||
1833 | return 0; | 1777 | return 0; |
@@ -1843,7 +1787,7 @@ static int snd_asihpi_tuner_gain_put(struct snd_kcontrol *kcontrol, | |||
1843 | short gain; | 1787 | short gain; |
1844 | 1788 | ||
1845 | gain = (ucontrol->value.integer.value[0]) * HPI_UNITS_PER_dB; | 1789 | gain = (ucontrol->value.integer.value[0]) * HPI_UNITS_PER_dB; |
1846 | hpi_handle_error(hpi_tuner_set_gain(ss, h_control, gain)); | 1790 | hpi_handle_error(hpi_tuner_set_gain(h_control, gain)); |
1847 | 1791 | ||
1848 | return 1; | 1792 | return 1; |
1849 | } | 1793 | } |
@@ -1857,7 +1801,7 @@ static int asihpi_tuner_band_query(struct snd_kcontrol *kcontrol, | |||
1857 | u32 i; | 1801 | u32 i; |
1858 | 1802 | ||
1859 | for (i = 0; i < len; i++) { | 1803 | for (i = 0; i < len; i++) { |
1860 | err = hpi_tuner_query_band(ss, | 1804 | err = hpi_tuner_query_band( |
1861 | h_control, i, &band_list[i]); | 1805 | h_control, i, &band_list[i]); |
1862 | if (err != 0) | 1806 | if (err != 0) |
1863 | break; | 1807 | break; |
@@ -1913,7 +1857,7 @@ static int snd_asihpi_tuner_band_get(struct snd_kcontrol *kcontrol, | |||
1913 | num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands, | 1857 | num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands, |
1914 | HPI_TUNER_BAND_LAST); | 1858 | HPI_TUNER_BAND_LAST); |
1915 | 1859 | ||
1916 | hpi_handle_error(hpi_tuner_get_band(ss, h_control, &band)); | 1860 | hpi_handle_error(hpi_tuner_get_band(h_control, &band)); |
1917 | 1861 | ||
1918 | ucontrol->value.enumerated.item[0] = -1; | 1862 | ucontrol->value.enumerated.item[0] = -1; |
1919 | for (idx = 0; idx < HPI_TUNER_BAND_LAST; idx++) | 1863 | for (idx = 0; idx < HPI_TUNER_BAND_LAST; idx++) |
@@ -1940,7 +1884,7 @@ static int snd_asihpi_tuner_band_put(struct snd_kcontrol *kcontrol, | |||
1940 | HPI_TUNER_BAND_LAST); | 1884 | HPI_TUNER_BAND_LAST); |
1941 | 1885 | ||
1942 | band = tuner_bands[ucontrol->value.enumerated.item[0]]; | 1886 | band = tuner_bands[ucontrol->value.enumerated.item[0]]; |
1943 | hpi_handle_error(hpi_tuner_set_band(ss, h_control, band)); | 1887 | hpi_handle_error(hpi_tuner_set_band(h_control, band)); |
1944 | 1888 | ||
1945 | return 1; | 1889 | return 1; |
1946 | } | 1890 | } |
@@ -1965,7 +1909,7 @@ static int snd_asihpi_tuner_freq_info(struct snd_kcontrol *kcontrol, | |||
1965 | 1909 | ||
1966 | for (band_iter = 0; band_iter < num_bands; band_iter++) { | 1910 | for (band_iter = 0; band_iter < num_bands; band_iter++) { |
1967 | for (idx = 0; idx < 3; idx++) { | 1911 | for (idx = 0; idx < 3; idx++) { |
1968 | err = hpi_tuner_query_frequency(ss, h_control, | 1912 | err = hpi_tuner_query_frequency(h_control, |
1969 | idx, tuner_bands[band_iter], | 1913 | idx, tuner_bands[band_iter], |
1970 | &temp_freq_range[idx]); | 1914 | &temp_freq_range[idx]); |
1971 | if (err != 0) | 1915 | if (err != 0) |
@@ -1998,7 +1942,7 @@ static int snd_asihpi_tuner_freq_get(struct snd_kcontrol *kcontrol, | |||
1998 | u32 h_control = kcontrol->private_value; | 1942 | u32 h_control = kcontrol->private_value; |
1999 | u32 freq; | 1943 | u32 freq; |
2000 | 1944 | ||
2001 | hpi_handle_error(hpi_tuner_get_frequency(ss, h_control, &freq)); | 1945 | hpi_handle_error(hpi_tuner_get_frequency(h_control, &freq)); |
2002 | ucontrol->value.integer.value[0] = freq; | 1946 | ucontrol->value.integer.value[0] = freq; |
2003 | 1947 | ||
2004 | return 0; | 1948 | return 0; |
@@ -2011,7 +1955,7 @@ static int snd_asihpi_tuner_freq_put(struct snd_kcontrol *kcontrol, | |||
2011 | u32 freq; | 1955 | u32 freq; |
2012 | 1956 | ||
2013 | freq = ucontrol->value.integer.value[0]; | 1957 | freq = ucontrol->value.integer.value[0]; |
2014 | hpi_handle_error(hpi_tuner_set_frequency(ss, h_control, freq)); | 1958 | hpi_handle_error(hpi_tuner_set_frequency(h_control, freq)); |
2015 | 1959 | ||
2016 | return 1; | 1960 | return 1; |
2017 | } | 1961 | } |
@@ -2026,8 +1970,8 @@ static int __devinit snd_asihpi_tuner_add(struct snd_card_asihpi *asihpi, | |||
2026 | snd_control.private_value = hpi_ctl->h_control; | 1970 | snd_control.private_value = hpi_ctl->h_control; |
2027 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; | 1971 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; |
2028 | 1972 | ||
2029 | if (!hpi_tuner_get_gain(ss, hpi_ctl->h_control, NULL)) { | 1973 | if (!hpi_tuner_get_gain(hpi_ctl->h_control, NULL)) { |
2030 | asihpi_ctl_init(&snd_control, hpi_ctl, "gain"); | 1974 | asihpi_ctl_init(&snd_control, hpi_ctl, "Gain"); |
2031 | snd_control.info = snd_asihpi_tuner_gain_info; | 1975 | snd_control.info = snd_asihpi_tuner_gain_info; |
2032 | snd_control.get = snd_asihpi_tuner_gain_get; | 1976 | snd_control.get = snd_asihpi_tuner_gain_get; |
2033 | snd_control.put = snd_asihpi_tuner_gain_put; | 1977 | snd_control.put = snd_asihpi_tuner_gain_put; |
@@ -2036,7 +1980,7 @@ static int __devinit snd_asihpi_tuner_add(struct snd_card_asihpi *asihpi, | |||
2036 | return -EINVAL; | 1980 | return -EINVAL; |
2037 | } | 1981 | } |
2038 | 1982 | ||
2039 | asihpi_ctl_init(&snd_control, hpi_ctl, "band"); | 1983 | asihpi_ctl_init(&snd_control, hpi_ctl, "Band"); |
2040 | snd_control.info = snd_asihpi_tuner_band_info; | 1984 | snd_control.info = snd_asihpi_tuner_band_info; |
2041 | snd_control.get = snd_asihpi_tuner_band_get; | 1985 | snd_control.get = snd_asihpi_tuner_band_get; |
2042 | snd_control.put = snd_asihpi_tuner_band_put; | 1986 | snd_control.put = snd_asihpi_tuner_band_put; |
@@ -2044,7 +1988,7 @@ static int __devinit snd_asihpi_tuner_add(struct snd_card_asihpi *asihpi, | |||
2044 | if (ctl_add(card, &snd_control, asihpi) < 0) | 1988 | if (ctl_add(card, &snd_control, asihpi) < 0) |
2045 | return -EINVAL; | 1989 | return -EINVAL; |
2046 | 1990 | ||
2047 | asihpi_ctl_init(&snd_control, hpi_ctl, "freq"); | 1991 | asihpi_ctl_init(&snd_control, hpi_ctl, "Freq"); |
2048 | snd_control.info = snd_asihpi_tuner_freq_info; | 1992 | snd_control.info = snd_asihpi_tuner_freq_info; |
2049 | snd_control.get = snd_asihpi_tuner_freq_get; | 1993 | snd_control.get = snd_asihpi_tuner_freq_get; |
2050 | snd_control.put = snd_asihpi_tuner_freq_put; | 1994 | snd_control.put = snd_asihpi_tuner_freq_put; |
@@ -2095,7 +2039,7 @@ static int snd_asihpi_meter_get(struct snd_kcontrol *kcontrol, | |||
2095 | short an_gain_mB[HPI_MAX_CHANNELS], i; | 2039 | short an_gain_mB[HPI_MAX_CHANNELS], i; |
2096 | u16 err; | 2040 | u16 err; |
2097 | 2041 | ||
2098 | err = hpi_meter_get_peak(ss, h_control, an_gain_mB); | 2042 | err = hpi_meter_get_peak(h_control, an_gain_mB); |
2099 | 2043 | ||
2100 | for (i = 0; i < HPI_MAX_CHANNELS; i++) { | 2044 | for (i = 0; i < HPI_MAX_CHANNELS; i++) { |
2101 | if (err) { | 2045 | if (err) { |
@@ -2120,7 +2064,7 @@ static int __devinit snd_asihpi_meter_add(struct snd_card_asihpi *asihpi, | |||
2120 | struct snd_card *card = asihpi->card; | 2064 | struct snd_card *card = asihpi->card; |
2121 | struct snd_kcontrol_new snd_control; | 2065 | struct snd_kcontrol_new snd_control; |
2122 | 2066 | ||
2123 | asihpi_ctl_init(&snd_control, hpi_ctl, "meter"); | 2067 | asihpi_ctl_init(&snd_control, hpi_ctl, "Meter"); |
2124 | snd_control.access = | 2068 | snd_control.access = |
2125 | SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ; | 2069 | SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ; |
2126 | snd_control.info = snd_asihpi_meter_info; | 2070 | snd_control.info = snd_asihpi_meter_info; |
@@ -2140,7 +2084,7 @@ static int snd_card_asihpi_mux_count_sources(struct snd_kcontrol *snd_control) | |||
2140 | struct hpi_control hpi_ctl; | 2084 | struct hpi_control hpi_ctl; |
2141 | int s, err; | 2085 | int s, err; |
2142 | for (s = 0; s < 32; s++) { | 2086 | for (s = 0; s < 32; s++) { |
2143 | err = hpi_multiplexer_query_source(ss, h_control, s, | 2087 | err = hpi_multiplexer_query_source(h_control, s, |
2144 | &hpi_ctl. | 2088 | &hpi_ctl. |
2145 | src_node_type, | 2089 | src_node_type, |
2146 | &hpi_ctl. | 2090 | &hpi_ctl. |
@@ -2168,7 +2112,7 @@ static int snd_asihpi_mux_info(struct snd_kcontrol *kcontrol, | |||
2168 | uinfo->value.enumerated.items - 1; | 2112 | uinfo->value.enumerated.items - 1; |
2169 | 2113 | ||
2170 | err = | 2114 | err = |
2171 | hpi_multiplexer_query_source(ss, h_control, | 2115 | hpi_multiplexer_query_source(h_control, |
2172 | uinfo->value.enumerated.item, | 2116 | uinfo->value.enumerated.item, |
2173 | &src_node_type, &src_node_index); | 2117 | &src_node_type, &src_node_index); |
2174 | 2118 | ||
@@ -2186,11 +2130,11 @@ static int snd_asihpi_mux_get(struct snd_kcontrol *kcontrol, | |||
2186 | u16 src_node_type, src_node_index; | 2130 | u16 src_node_type, src_node_index; |
2187 | int s; | 2131 | int s; |
2188 | 2132 | ||
2189 | hpi_handle_error(hpi_multiplexer_get_source(ss, h_control, | 2133 | hpi_handle_error(hpi_multiplexer_get_source(h_control, |
2190 | &source_type, &source_index)); | 2134 | &source_type, &source_index)); |
2191 | /* Should cache this search result! */ | 2135 | /* Should cache this search result! */ |
2192 | for (s = 0; s < 256; s++) { | 2136 | for (s = 0; s < 256; s++) { |
2193 | if (hpi_multiplexer_query_source(ss, h_control, s, | 2137 | if (hpi_multiplexer_query_source(h_control, s, |
2194 | &src_node_type, &src_node_index)) | 2138 | &src_node_type, &src_node_index)) |
2195 | break; | 2139 | break; |
2196 | 2140 | ||
@@ -2201,7 +2145,7 @@ static int snd_asihpi_mux_get(struct snd_kcontrol *kcontrol, | |||
2201 | } | 2145 | } |
2202 | } | 2146 | } |
2203 | snd_printd(KERN_WARNING | 2147 | snd_printd(KERN_WARNING |
2204 | "control %x failed to match mux source %hu %hu\n", | 2148 | "Control %x failed to match mux source %hu %hu\n", |
2205 | h_control, source_type, source_index); | 2149 | h_control, source_type, source_index); |
2206 | ucontrol->value.enumerated.item[0] = 0; | 2150 | ucontrol->value.enumerated.item[0] = 0; |
2207 | return 0; | 2151 | return 0; |
@@ -2217,12 +2161,12 @@ static int snd_asihpi_mux_put(struct snd_kcontrol *kcontrol, | |||
2217 | 2161 | ||
2218 | change = 1; | 2162 | change = 1; |
2219 | 2163 | ||
2220 | e = hpi_multiplexer_query_source(ss, h_control, | 2164 | e = hpi_multiplexer_query_source(h_control, |
2221 | ucontrol->value.enumerated.item[0], | 2165 | ucontrol->value.enumerated.item[0], |
2222 | &source_type, &source_index); | 2166 | &source_type, &source_index); |
2223 | if (!e) | 2167 | if (!e) |
2224 | hpi_handle_error( | 2168 | hpi_handle_error( |
2225 | hpi_multiplexer_set_source(ss, h_control, | 2169 | hpi_multiplexer_set_source(h_control, |
2226 | source_type, source_index)); | 2170 | source_type, source_index)); |
2227 | return change; | 2171 | return change; |
2228 | } | 2172 | } |
@@ -2234,11 +2178,7 @@ static int __devinit snd_asihpi_mux_add(struct snd_card_asihpi *asihpi, | |||
2234 | struct snd_card *card = asihpi->card; | 2178 | struct snd_card *card = asihpi->card; |
2235 | struct snd_kcontrol_new snd_control; | 2179 | struct snd_kcontrol_new snd_control; |
2236 | 2180 | ||
2237 | #if ASI_STYLE_NAMES | 2181 | asihpi_ctl_init(&snd_control, hpi_ctl, "Route"); |
2238 | asihpi_ctl_init(&snd_control, hpi_ctl, "multiplexer"); | ||
2239 | #else | ||
2240 | asihpi_ctl_init(&snd_control, hpi_ctl, "route"); | ||
2241 | #endif | ||
2242 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; | 2182 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; |
2243 | snd_control.info = snd_asihpi_mux_info; | 2183 | snd_control.info = snd_asihpi_mux_info; |
2244 | snd_control.get = snd_asihpi_mux_get; | 2184 | snd_control.get = snd_asihpi_mux_get; |
@@ -2254,33 +2194,38 @@ static int __devinit snd_asihpi_mux_add(struct snd_card_asihpi *asihpi, | |||
2254 | static int snd_asihpi_cmode_info(struct snd_kcontrol *kcontrol, | 2194 | static int snd_asihpi_cmode_info(struct snd_kcontrol *kcontrol, |
2255 | struct snd_ctl_elem_info *uinfo) | 2195 | struct snd_ctl_elem_info *uinfo) |
2256 | { | 2196 | { |
2257 | static char *mode_names[HPI_CHANNEL_MODE_LAST] = { | 2197 | static const char * const mode_names[HPI_CHANNEL_MODE_LAST + 1] = { |
2258 | "normal", "swap", | 2198 | "invalid", |
2259 | "from_left", "from_right", | 2199 | "Normal", "Swap", |
2260 | "to_left", "to_right" | 2200 | "From Left", "From Right", |
2201 | "To Left", "To Right" | ||
2261 | }; | 2202 | }; |
2262 | 2203 | ||
2263 | u32 h_control = kcontrol->private_value; | 2204 | u32 h_control = kcontrol->private_value; |
2264 | u16 mode; | 2205 | u16 mode; |
2265 | int i; | 2206 | int i; |
2207 | u16 mode_map[6]; | ||
2208 | int valid_modes = 0; | ||
2266 | 2209 | ||
2267 | /* HPI channel mode values can be from 1 to 6 | 2210 | /* HPI channel mode values can be from 1 to 6 |
2268 | Some adapters only support a contiguous subset | 2211 | Some adapters only support a contiguous subset |
2269 | */ | 2212 | */ |
2270 | for (i = 0; i < HPI_CHANNEL_MODE_LAST; i++) | 2213 | for (i = 0; i < HPI_CHANNEL_MODE_LAST; i++) |
2271 | if (hpi_channel_mode_query_mode( | 2214 | if (!hpi_channel_mode_query_mode( |
2272 | ss, h_control, i, &mode)) | 2215 | h_control, i, &mode)) { |
2273 | break; | 2216 | mode_map[valid_modes] = mode; |
2217 | valid_modes++; | ||
2218 | } | ||
2274 | 2219 | ||
2275 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 2220 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
2276 | uinfo->count = 1; | 2221 | uinfo->count = 1; |
2277 | uinfo->value.enumerated.items = i; | 2222 | uinfo->value.enumerated.items = valid_modes; |
2278 | 2223 | ||
2279 | if (uinfo->value.enumerated.item >= i) | 2224 | if (uinfo->value.enumerated.item >= valid_modes) |
2280 | uinfo->value.enumerated.item = i - 1; | 2225 | uinfo->value.enumerated.item = valid_modes - 1; |
2281 | 2226 | ||
2282 | strcpy(uinfo->value.enumerated.name, | 2227 | strcpy(uinfo->value.enumerated.name, |
2283 | mode_names[uinfo->value.enumerated.item]); | 2228 | mode_names[mode_map[uinfo->value.enumerated.item]]); |
2284 | 2229 | ||
2285 | return 0; | 2230 | return 0; |
2286 | } | 2231 | } |
@@ -2291,7 +2236,7 @@ static int snd_asihpi_cmode_get(struct snd_kcontrol *kcontrol, | |||
2291 | u32 h_control = kcontrol->private_value; | 2236 | u32 h_control = kcontrol->private_value; |
2292 | u16 mode; | 2237 | u16 mode; |
2293 | 2238 | ||
2294 | if (hpi_channel_mode_get(ss, h_control, &mode)) | 2239 | if (hpi_channel_mode_get(h_control, &mode)) |
2295 | mode = 1; | 2240 | mode = 1; |
2296 | 2241 | ||
2297 | ucontrol->value.enumerated.item[0] = mode - 1; | 2242 | ucontrol->value.enumerated.item[0] = mode - 1; |
@@ -2307,7 +2252,7 @@ static int snd_asihpi_cmode_put(struct snd_kcontrol *kcontrol, | |||
2307 | 2252 | ||
2308 | change = 1; | 2253 | change = 1; |
2309 | 2254 | ||
2310 | hpi_handle_error(hpi_channel_mode_set(ss, h_control, | 2255 | hpi_handle_error(hpi_channel_mode_set(h_control, |
2311 | ucontrol->value.enumerated.item[0] + 1)); | 2256 | ucontrol->value.enumerated.item[0] + 1)); |
2312 | return change; | 2257 | return change; |
2313 | } | 2258 | } |
@@ -2319,7 +2264,7 @@ static int __devinit snd_asihpi_cmode_add(struct snd_card_asihpi *asihpi, | |||
2319 | struct snd_card *card = asihpi->card; | 2264 | struct snd_card *card = asihpi->card; |
2320 | struct snd_kcontrol_new snd_control; | 2265 | struct snd_kcontrol_new snd_control; |
2321 | 2266 | ||
2322 | asihpi_ctl_init(&snd_control, hpi_ctl, "channel mode"); | 2267 | asihpi_ctl_init(&snd_control, hpi_ctl, "Mode"); |
2323 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; | 2268 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; |
2324 | snd_control.info = snd_asihpi_cmode_info; | 2269 | snd_control.info = snd_asihpi_cmode_info; |
2325 | snd_control.get = snd_asihpi_cmode_get; | 2270 | snd_control.get = snd_asihpi_cmode_get; |
@@ -2331,15 +2276,12 @@ static int __devinit snd_asihpi_cmode_add(struct snd_card_asihpi *asihpi, | |||
2331 | /*------------------------------------------------------------ | 2276 | /*------------------------------------------------------------ |
2332 | Sampleclock source controls | 2277 | Sampleclock source controls |
2333 | ------------------------------------------------------------*/ | 2278 | ------------------------------------------------------------*/ |
2334 | 2279 | static char *sampleclock_sources[MAX_CLOCKSOURCES] = { | |
2335 | static char *sampleclock_sources[MAX_CLOCKSOURCES] = | 2280 | "N/A", "Local PLL", "Digital Sync", "Word External", "Word Header", |
2336 | { "N/A", "local PLL", "AES/EBU sync", "word external", "word header", | 2281 | "SMPTE", "Digital1", "Auto", "Network", "Invalid", |
2337 | "SMPTE", "AES/EBU in1", "auto", "network", "invalid", | 2282 | "Prev Module", |
2338 | "prev module", | 2283 | "Digital2", "Digital3", "Digital4", "Digital5", |
2339 | "AES/EBU in2", "AES/EBU in3", "AES/EBU in4", "AES/EBU in5", | 2284 | "Digital6", "Digital7", "Digital8"}; |
2340 | "AES/EBU in6", "AES/EBU in7", "AES/EBU in8"}; | ||
2341 | |||
2342 | |||
2343 | 2285 | ||
2344 | static int snd_asihpi_clksrc_info(struct snd_kcontrol *kcontrol, | 2286 | static int snd_asihpi_clksrc_info(struct snd_kcontrol *kcontrol, |
2345 | struct snd_ctl_elem_info *uinfo) | 2287 | struct snd_ctl_elem_info *uinfo) |
@@ -2371,11 +2313,11 @@ static int snd_asihpi_clksrc_get(struct snd_kcontrol *kcontrol, | |||
2371 | int i; | 2313 | int i; |
2372 | 2314 | ||
2373 | ucontrol->value.enumerated.item[0] = 0; | 2315 | ucontrol->value.enumerated.item[0] = 0; |
2374 | if (hpi_sample_clock_get_source(ss, h_control, &source)) | 2316 | if (hpi_sample_clock_get_source(h_control, &source)) |
2375 | source = 0; | 2317 | source = 0; |
2376 | 2318 | ||
2377 | if (source == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT) | 2319 | if (source == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT) |
2378 | if (hpi_sample_clock_get_source_index(ss, h_control, &srcindex)) | 2320 | if (hpi_sample_clock_get_source_index(h_control, &srcindex)) |
2379 | srcindex = 0; | 2321 | srcindex = 0; |
2380 | 2322 | ||
2381 | for (i = 0; i < clkcache->count; i++) | 2323 | for (i = 0; i < clkcache->count; i++) |
@@ -2402,11 +2344,11 @@ static int snd_asihpi_clksrc_put(struct snd_kcontrol *kcontrol, | |||
2402 | if (item >= clkcache->count) | 2344 | if (item >= clkcache->count) |
2403 | item = clkcache->count-1; | 2345 | item = clkcache->count-1; |
2404 | 2346 | ||
2405 | hpi_handle_error(hpi_sample_clock_set_source(ss, | 2347 | hpi_handle_error(hpi_sample_clock_set_source( |
2406 | h_control, clkcache->s[item].source)); | 2348 | h_control, clkcache->s[item].source)); |
2407 | 2349 | ||
2408 | if (clkcache->s[item].source == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT) | 2350 | if (clkcache->s[item].source == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT) |
2409 | hpi_handle_error(hpi_sample_clock_set_source_index(ss, | 2351 | hpi_handle_error(hpi_sample_clock_set_source_index( |
2410 | h_control, clkcache->s[item].index)); | 2352 | h_control, clkcache->s[item].index)); |
2411 | return change; | 2353 | return change; |
2412 | } | 2354 | } |
@@ -2434,7 +2376,7 @@ static int snd_asihpi_clklocal_get(struct snd_kcontrol *kcontrol, | |||
2434 | u32 rate; | 2376 | u32 rate; |
2435 | u16 e; | 2377 | u16 e; |
2436 | 2378 | ||
2437 | e = hpi_sample_clock_get_local_rate(ss, h_control, &rate); | 2379 | e = hpi_sample_clock_get_local_rate(h_control, &rate); |
2438 | if (!e) | 2380 | if (!e) |
2439 | ucontrol->value.integer.value[0] = rate; | 2381 | ucontrol->value.integer.value[0] = rate; |
2440 | else | 2382 | else |
@@ -2452,7 +2394,7 @@ static int snd_asihpi_clklocal_put(struct snd_kcontrol *kcontrol, | |||
2452 | asihpi->mixer_clkrate[addr][1] != right; | 2394 | asihpi->mixer_clkrate[addr][1] != right; |
2453 | */ | 2395 | */ |
2454 | change = 1; | 2396 | change = 1; |
2455 | hpi_handle_error(hpi_sample_clock_set_local_rate(ss, h_control, | 2397 | hpi_handle_error(hpi_sample_clock_set_local_rate(h_control, |
2456 | ucontrol->value.integer.value[0])); | 2398 | ucontrol->value.integer.value[0])); |
2457 | return change; | 2399 | return change; |
2458 | } | 2400 | } |
@@ -2476,7 +2418,7 @@ static int snd_asihpi_clkrate_get(struct snd_kcontrol *kcontrol, | |||
2476 | u32 rate; | 2418 | u32 rate; |
2477 | u16 e; | 2419 | u16 e; |
2478 | 2420 | ||
2479 | e = hpi_sample_clock_get_sample_rate(ss, h_control, &rate); | 2421 | e = hpi_sample_clock_get_sample_rate(h_control, &rate); |
2480 | if (!e) | 2422 | if (!e) |
2481 | ucontrol->value.integer.value[0] = rate; | 2423 | ucontrol->value.integer.value[0] = rate; |
2482 | else | 2424 | else |
@@ -2501,7 +2443,7 @@ static int __devinit snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi, | |||
2501 | clkcache->has_local = 0; | 2443 | clkcache->has_local = 0; |
2502 | 2444 | ||
2503 | for (i = 0; i <= HPI_SAMPLECLOCK_SOURCE_LAST; i++) { | 2445 | for (i = 0; i <= HPI_SAMPLECLOCK_SOURCE_LAST; i++) { |
2504 | if (hpi_sample_clock_query_source(ss, hSC, | 2446 | if (hpi_sample_clock_query_source(hSC, |
2505 | i, &source)) | 2447 | i, &source)) |
2506 | break; | 2448 | break; |
2507 | clkcache->s[i].source = source; | 2449 | clkcache->s[i].source = source; |
@@ -2515,7 +2457,7 @@ static int __devinit snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi, | |||
2515 | if (has_aes_in) | 2457 | if (has_aes_in) |
2516 | /* already will have picked up index 0 above */ | 2458 | /* already will have picked up index 0 above */ |
2517 | for (j = 1; j < 8; j++) { | 2459 | for (j = 1; j < 8; j++) { |
2518 | if (hpi_sample_clock_query_source_index(ss, hSC, | 2460 | if (hpi_sample_clock_query_source_index(hSC, |
2519 | j, HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT, | 2461 | j, HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT, |
2520 | &source)) | 2462 | &source)) |
2521 | break; | 2463 | break; |
@@ -2528,7 +2470,7 @@ static int __devinit snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi, | |||
2528 | } | 2470 | } |
2529 | clkcache->count = i; | 2471 | clkcache->count = i; |
2530 | 2472 | ||
2531 | asihpi_ctl_init(&snd_control, hpi_ctl, "source"); | 2473 | asihpi_ctl_init(&snd_control, hpi_ctl, "Source"); |
2532 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE ; | 2474 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE ; |
2533 | snd_control.info = snd_asihpi_clksrc_info; | 2475 | snd_control.info = snd_asihpi_clksrc_info; |
2534 | snd_control.get = snd_asihpi_clksrc_get; | 2476 | snd_control.get = snd_asihpi_clksrc_get; |
@@ -2538,7 +2480,7 @@ static int __devinit snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi, | |||
2538 | 2480 | ||
2539 | 2481 | ||
2540 | if (clkcache->has_local) { | 2482 | if (clkcache->has_local) { |
2541 | asihpi_ctl_init(&snd_control, hpi_ctl, "local_rate"); | 2483 | asihpi_ctl_init(&snd_control, hpi_ctl, "Localrate"); |
2542 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE ; | 2484 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE ; |
2543 | snd_control.info = snd_asihpi_clklocal_info; | 2485 | snd_control.info = snd_asihpi_clklocal_info; |
2544 | snd_control.get = snd_asihpi_clklocal_get; | 2486 | snd_control.get = snd_asihpi_clklocal_get; |
@@ -2549,7 +2491,7 @@ static int __devinit snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi, | |||
2549 | return -EINVAL; | 2491 | return -EINVAL; |
2550 | } | 2492 | } |
2551 | 2493 | ||
2552 | asihpi_ctl_init(&snd_control, hpi_ctl, "rate"); | 2494 | asihpi_ctl_init(&snd_control, hpi_ctl, "Rate"); |
2553 | snd_control.access = | 2495 | snd_control.access = |
2554 | SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ; | 2496 | SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ; |
2555 | snd_control.info = snd_asihpi_clkrate_info; | 2497 | snd_control.info = snd_asihpi_clkrate_info; |
@@ -2571,10 +2513,10 @@ static int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi) | |||
2571 | 2513 | ||
2572 | if (snd_BUG_ON(!asihpi)) | 2514 | if (snd_BUG_ON(!asihpi)) |
2573 | return -EINVAL; | 2515 | return -EINVAL; |
2574 | strcpy(card->mixername, "asihpi mixer"); | 2516 | strcpy(card->mixername, "Asihpi Mixer"); |
2575 | 2517 | ||
2576 | err = | 2518 | err = |
2577 | hpi_mixer_open(ss, asihpi->adapter_index, | 2519 | hpi_mixer_open(asihpi->adapter_index, |
2578 | &asihpi->h_mixer); | 2520 | &asihpi->h_mixer); |
2579 | hpi_handle_error(err); | 2521 | hpi_handle_error(err); |
2580 | if (err) | 2522 | if (err) |
@@ -2585,7 +2527,7 @@ static int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi) | |||
2585 | 2527 | ||
2586 | for (idx = 0; idx < 2000; idx++) { | 2528 | for (idx = 0; idx < 2000; idx++) { |
2587 | err = hpi_mixer_get_control_by_index( | 2529 | err = hpi_mixer_get_control_by_index( |
2588 | ss, asihpi->h_mixer, | 2530 | asihpi->h_mixer, |
2589 | idx, | 2531 | idx, |
2590 | &hpi_ctl.src_node_type, | 2532 | &hpi_ctl.src_node_type, |
2591 | &hpi_ctl.src_node_index, | 2533 | &hpi_ctl.src_node_index, |
@@ -2597,7 +2539,7 @@ static int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi) | |||
2597 | if (err == HPI_ERROR_CONTROL_DISABLED) { | 2539 | if (err == HPI_ERROR_CONTROL_DISABLED) { |
2598 | if (mixer_dump) | 2540 | if (mixer_dump) |
2599 | snd_printk(KERN_INFO | 2541 | snd_printk(KERN_INFO |
2600 | "disabled HPI control(%d)\n", | 2542 | "Disabled HPI Control(%d)\n", |
2601 | idx); | 2543 | idx); |
2602 | continue; | 2544 | continue; |
2603 | } else | 2545 | } else |
@@ -2662,7 +2604,7 @@ static int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi) | |||
2662 | default: | 2604 | default: |
2663 | if (mixer_dump) | 2605 | if (mixer_dump) |
2664 | snd_printk(KERN_INFO | 2606 | snd_printk(KERN_INFO |
2665 | "untranslated HPI control" | 2607 | "Untranslated HPI Control" |
2666 | "(%d) %d %d %d %d %d\n", | 2608 | "(%d) %d %d %d %d %d\n", |
2667 | idx, | 2609 | idx, |
2668 | hpi_ctl.control_type, | 2610 | hpi_ctl.control_type, |
@@ -2712,14 +2654,14 @@ snd_asihpi_proc_read(struct snd_info_entry *entry, | |||
2712 | version & 0x7, | 2654 | version & 0x7, |
2713 | ((version >> 13) * 100) + ((version >> 7) & 0x3f)); | 2655 | ((version >> 13) * 100) + ((version >> 7) & 0x3f)); |
2714 | 2656 | ||
2715 | err = hpi_mixer_get_control(ss, asihpi->h_mixer, | 2657 | err = hpi_mixer_get_control(asihpi->h_mixer, |
2716 | HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, | 2658 | HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, |
2717 | HPI_CONTROL_SAMPLECLOCK, &h_control); | 2659 | HPI_CONTROL_SAMPLECLOCK, &h_control); |
2718 | 2660 | ||
2719 | if (!err) { | 2661 | if (!err) { |
2720 | err = hpi_sample_clock_get_sample_rate(ss, | 2662 | err = hpi_sample_clock_get_sample_rate( |
2721 | h_control, &rate); | 2663 | h_control, &rate); |
2722 | err += hpi_sample_clock_get_source(ss, h_control, &source); | 2664 | err += hpi_sample_clock_get_source(h_control, &source); |
2723 | 2665 | ||
2724 | if (!err) | 2666 | if (!err) |
2725 | snd_iprintf(buffer, "sample_clock=%d_hz, source %s\n", | 2667 | snd_iprintf(buffer, "sample_clock=%d_hz, source %s\n", |
@@ -2841,15 +2783,17 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev, | |||
2841 | if (err < 0) | 2783 | if (err < 0) |
2842 | return err; | 2784 | return err; |
2843 | snd_printk(KERN_WARNING | 2785 | snd_printk(KERN_WARNING |
2844 | "**** WARNING **** adapter index %d->ALSA index %d\n", | 2786 | "**** WARNING **** Adapter index %d->ALSA index %d\n", |
2845 | hpi_card->index, card->number); | 2787 | hpi_card->index, card->number); |
2846 | } | 2788 | } |
2847 | 2789 | ||
2790 | snd_card_set_dev(card, &pci_dev->dev); | ||
2791 | |||
2848 | asihpi = (struct snd_card_asihpi *) card->private_data; | 2792 | asihpi = (struct snd_card_asihpi *) card->private_data; |
2849 | asihpi->card = card; | 2793 | asihpi->card = card; |
2850 | asihpi->pci = hpi_card->pci; | 2794 | asihpi->pci = pci_dev; |
2851 | asihpi->adapter_index = hpi_card->index; | 2795 | asihpi->adapter_index = hpi_card->index; |
2852 | hpi_handle_error(hpi_adapter_get_info(ss, | 2796 | hpi_handle_error(hpi_adapter_get_info( |
2853 | asihpi->adapter_index, | 2797 | asihpi->adapter_index, |
2854 | &asihpi->num_outstreams, | 2798 | &asihpi->num_outstreams, |
2855 | &asihpi->num_instreams, | 2799 | &asihpi->num_instreams, |
@@ -2859,7 +2803,7 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev, | |||
2859 | version = asihpi->version; | 2803 | version = asihpi->version; |
2860 | snd_printk(KERN_INFO "adapter ID=%4X index=%d num_outstreams=%d " | 2804 | snd_printk(KERN_INFO "adapter ID=%4X index=%d num_outstreams=%d " |
2861 | "num_instreams=%d S/N=%d\n" | 2805 | "num_instreams=%d S/N=%d\n" |
2862 | "hw version %c%d DSP code version %03d\n", | 2806 | "Hw Version %c%d DSP code version %03d\n", |
2863 | asihpi->type, asihpi->adapter_index, | 2807 | asihpi->type, asihpi->adapter_index, |
2864 | asihpi->num_outstreams, | 2808 | asihpi->num_outstreams, |
2865 | asihpi->num_instreams, asihpi->serial_number, | 2809 | asihpi->num_instreams, asihpi->serial_number, |
@@ -2871,33 +2815,36 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev, | |||
2871 | if (pcm_substreams < asihpi->num_instreams) | 2815 | if (pcm_substreams < asihpi->num_instreams) |
2872 | pcm_substreams = asihpi->num_instreams; | 2816 | pcm_substreams = asihpi->num_instreams; |
2873 | 2817 | ||
2874 | err = hpi_adapter_get_property(ss, asihpi->adapter_index, | 2818 | err = hpi_adapter_get_property(asihpi->adapter_index, |
2875 | HPI_ADAPTER_PROPERTY_CAPS1, | 2819 | HPI_ADAPTER_PROPERTY_CAPS1, |
2876 | NULL, &asihpi->support_grouping); | 2820 | NULL, &asihpi->support_grouping); |
2877 | if (err) | 2821 | if (err) |
2878 | asihpi->support_grouping = 0; | 2822 | asihpi->support_grouping = 0; |
2879 | 2823 | ||
2880 | err = hpi_adapter_get_property(ss, asihpi->adapter_index, | 2824 | err = hpi_adapter_get_property(asihpi->adapter_index, |
2881 | HPI_ADAPTER_PROPERTY_CAPS2, | 2825 | HPI_ADAPTER_PROPERTY_CAPS2, |
2882 | &asihpi->support_mrx, NULL); | 2826 | &asihpi->support_mrx, NULL); |
2883 | if (err) | 2827 | if (err) |
2884 | asihpi->support_mrx = 0; | 2828 | asihpi->support_mrx = 0; |
2885 | 2829 | ||
2886 | err = hpi_adapter_get_property(ss, asihpi->adapter_index, | 2830 | err = hpi_adapter_get_property(asihpi->adapter_index, |
2887 | HPI_ADAPTER_PROPERTY_INTERVAL, | 2831 | HPI_ADAPTER_PROPERTY_INTERVAL, |
2888 | NULL, &asihpi->update_interval_frames); | 2832 | NULL, &asihpi->update_interval_frames); |
2889 | if (err) | 2833 | if (err) |
2890 | asihpi->update_interval_frames = 512; | 2834 | asihpi->update_interval_frames = 512; |
2891 | 2835 | ||
2892 | hpi_handle_error(hpi_instream_open(ss, asihpi->adapter_index, | 2836 | if (!asihpi->can_dma) |
2837 | asihpi->update_interval_frames *= 2; | ||
2838 | |||
2839 | hpi_handle_error(hpi_instream_open(asihpi->adapter_index, | ||
2893 | 0, &h_stream)); | 2840 | 0, &h_stream)); |
2894 | 2841 | ||
2895 | err = hpi_instream_host_buffer_free(ss, h_stream); | 2842 | err = hpi_instream_host_buffer_free(h_stream); |
2896 | asihpi->support_mmap = (!err); | 2843 | asihpi->can_dma = (!err); |
2897 | 2844 | ||
2898 | hpi_handle_error(hpi_instream_close(ss, h_stream)); | 2845 | hpi_handle_error(hpi_instream_close(h_stream)); |
2899 | 2846 | ||
2900 | err = hpi_adapter_get_property(ss, asihpi->adapter_index, | 2847 | err = hpi_adapter_get_property(asihpi->adapter_index, |
2901 | HPI_ADAPTER_PROPERTY_CURCHANNELS, | 2848 | HPI_ADAPTER_PROPERTY_CURCHANNELS, |
2902 | &asihpi->in_max_chans, &asihpi->out_max_chans); | 2849 | &asihpi->in_max_chans, &asihpi->out_max_chans); |
2903 | if (err) { | 2850 | if (err) { |
@@ -2905,13 +2852,12 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev, | |||
2905 | asihpi->out_max_chans = 2; | 2852 | asihpi->out_max_chans = 2; |
2906 | } | 2853 | } |
2907 | 2854 | ||
2908 | snd_printk(KERN_INFO "supports mmap:%d grouping:%d mrx:%d\n", | 2855 | snd_printk(KERN_INFO "has dma:%d, grouping:%d, mrx:%d\n", |
2909 | asihpi->support_mmap, | 2856 | asihpi->can_dma, |
2910 | asihpi->support_grouping, | 2857 | asihpi->support_grouping, |
2911 | asihpi->support_mrx | 2858 | asihpi->support_mrx |
2912 | ); | 2859 | ); |
2913 | 2860 | ||
2914 | |||
2915 | err = snd_card_asihpi_pcm_new(asihpi, 0, pcm_substreams); | 2861 | err = snd_card_asihpi_pcm_new(asihpi, 0, pcm_substreams); |
2916 | if (err < 0) { | 2862 | if (err < 0) { |
2917 | snd_printk(KERN_ERR "pcm_new failed\n"); | 2863 | snd_printk(KERN_ERR "pcm_new failed\n"); |
@@ -2923,13 +2869,13 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev, | |||
2923 | goto __nodev; | 2869 | goto __nodev; |
2924 | } | 2870 | } |
2925 | 2871 | ||
2926 | err = hpi_mixer_get_control(ss, asihpi->h_mixer, | 2872 | err = hpi_mixer_get_control(asihpi->h_mixer, |
2927 | HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, | 2873 | HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, |
2928 | HPI_CONTROL_SAMPLECLOCK, &h_control); | 2874 | HPI_CONTROL_SAMPLECLOCK, &h_control); |
2929 | 2875 | ||
2930 | if (!err) | 2876 | if (!err) |
2931 | err = hpi_sample_clock_set_local_rate( | 2877 | err = hpi_sample_clock_set_local_rate( |
2932 | ss, h_control, adapter_fs); | 2878 | h_control, adapter_fs); |
2933 | 2879 | ||
2934 | snd_asihpi_proc_init(asihpi); | 2880 | snd_asihpi_proc_init(asihpi); |
2935 | 2881 | ||
@@ -2937,15 +2883,13 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev, | |||
2937 | by enable_hwdep module param*/ | 2883 | by enable_hwdep module param*/ |
2938 | snd_asihpi_hpi_new(asihpi, 0, NULL); | 2884 | snd_asihpi_hpi_new(asihpi, 0, NULL); |
2939 | 2885 | ||
2940 | if (asihpi->support_mmap) | 2886 | strcpy(card->driver, "ASIHPI"); |
2941 | strcpy(card->driver, "ASIHPI-MMAP"); | ||
2942 | else | ||
2943 | strcpy(card->driver, "ASIHPI"); | ||
2944 | 2887 | ||
2945 | sprintf(card->shortname, "AudioScience ASI%4X", asihpi->type); | 2888 | sprintf(card->shortname, "AudioScience ASI%4X", asihpi->type); |
2946 | sprintf(card->longname, "%s %i", | 2889 | sprintf(card->longname, "%s %i", |
2947 | card->shortname, asihpi->adapter_index); | 2890 | card->shortname, asihpi->adapter_index); |
2948 | err = snd_card_register(card); | 2891 | err = snd_card_register(card); |
2892 | |||
2949 | if (!err) { | 2893 | if (!err) { |
2950 | hpi_card->snd_card_asihpi = card; | 2894 | hpi_card->snd_card_asihpi = card; |
2951 | dev++; | 2895 | dev++; |