Merge remote-tracking branch 'moduleh/module.h-split'
[linux-2.6/next.git] / sound / pci / asihpi / asihpi.c
blobeae62ebbd2952d3c0559a08dc7989247c52d56c9
1 /*
2 * Asihpi soundcard
3 * Copyright (c) by AudioScience Inc <alsa@audioscience.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation;
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * The following is not a condition of use, merely a request:
20 * If you modify this program, particularly if you fix errors, AudioScience Inc
21 * would appreciate it if you grant us the right to use those modifications
22 * for any purpose including commercial applications.
25 #include "hpi_internal.h"
26 #include "hpimsginit.h"
27 #include "hpioctl.h"
29 #include <linux/pci.h>
30 #include <linux/init.h>
31 #include <linux/jiffies.h>
32 #include <linux/slab.h>
33 #include <linux/time.h>
34 #include <linux/wait.h>
35 #include <sound/core.h>
36 #include <sound/control.h>
37 #include <sound/pcm.h>
38 #include <sound/pcm_params.h>
39 #include <sound/info.h>
40 #include <sound/initval.h>
41 #include <sound/tlv.h>
42 #include <sound/hwdep.h>
44 MODULE_LICENSE("GPL");
45 MODULE_AUTHOR("AudioScience inc. <support@audioscience.com>");
46 MODULE_DESCRIPTION("AudioScience ALSA ASI5000 ASI6000 ASI87xx ASI89xx");
48 #if defined CONFIG_SND_DEBUG_VERBOSE
49 /**
50 * snd_printddd - very verbose debug printk
51 * @format: format string
53 * Works like snd_printk() for debugging purposes.
54 * Ignored when CONFIG_SND_DEBUG_VERBOSE is not set.
55 * Must set snd module debug parameter to 3 to enable at runtime.
57 #define snd_printddd(format, args...) \
58 __snd_printk(3, __FILE__, __LINE__, format, ##args)
59 #else
60 #define snd_printddd(format, args...) do { } while (0)
61 #endif
63 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* index 0-MAX */
64 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
65 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
66 static int enable_hpi_hwdep = 1;
68 module_param_array(index, int, NULL, S_IRUGO);
69 MODULE_PARM_DESC(index, "ALSA index value for AudioScience soundcard.");
71 module_param_array(id, charp, NULL, S_IRUGO);
72 MODULE_PARM_DESC(id, "ALSA ID string for AudioScience soundcard.");
74 module_param_array(enable, bool, NULL, S_IRUGO);
75 MODULE_PARM_DESC(enable, "ALSA enable AudioScience soundcard.");
77 module_param(enable_hpi_hwdep, bool, S_IRUGO|S_IWUSR);
78 MODULE_PARM_DESC(enable_hpi_hwdep,
79 "ALSA enable HPI hwdep for AudioScience soundcard ");
81 /* identify driver */
82 #ifdef KERNEL_ALSA_BUILD
83 static char *build_info = "Built using headers from kernel source";
84 module_param(build_info, charp, S_IRUGO);
85 MODULE_PARM_DESC(build_info, "built using headers from kernel source");
86 #else
87 static char *build_info = "Built within ALSA source";
88 module_param(build_info, charp, S_IRUGO);
89 MODULE_PARM_DESC(build_info, "built within ALSA source");
90 #endif
92 /* set to 1 to dump every control from adapter to log */
93 static const int mixer_dump;
95 #define DEFAULT_SAMPLERATE 44100
96 static int adapter_fs = DEFAULT_SAMPLERATE;
98 /* defaults */
99 #define PERIODS_MIN 2
100 #define PERIOD_BYTES_MIN 2048
101 #define BUFFER_BYTES_MAX (512 * 1024)
103 #define MAX_CLOCKSOURCES (HPI_SAMPLECLOCK_SOURCE_LAST + 1 + 7)
105 struct clk_source {
106 int source;
107 int index;
108 char *name;
111 struct clk_cache {
112 int count;
113 int has_local;
114 struct clk_source s[MAX_CLOCKSOURCES];
117 /* Per card data */
118 struct snd_card_asihpi {
119 struct snd_card *card;
120 struct pci_dev *pci;
121 u16 adapter_index;
122 u32 serial_number;
123 u16 type;
124 u16 version;
125 u16 num_outstreams;
126 u16 num_instreams;
128 u32 h_mixer;
129 struct clk_cache cc;
131 u16 can_dma;
132 u16 support_grouping;
133 u16 support_mrx;
134 u16 update_interval_frames;
135 u16 in_max_chans;
136 u16 out_max_chans;
139 /* Per stream data */
140 struct snd_card_asihpi_pcm {
141 struct timer_list timer;
142 unsigned int respawn_timer;
143 unsigned int hpi_buffer_attached;
144 unsigned int buffer_bytes;
145 unsigned int period_bytes;
146 unsigned int bytes_per_sec;
147 unsigned int pcm_buf_host_rw_ofs; /* Host R/W pos */
148 unsigned int pcm_buf_dma_ofs; /* DMA R/W offset in buffer */
149 unsigned int pcm_buf_elapsed_dma_ofs; /* DMA R/W offset in buffer */
150 unsigned int drained_count;
151 struct snd_pcm_substream *substream;
152 u32 h_stream;
153 struct hpi_format format;
156 /* universal stream verbs work with out or in stream handles */
158 /* Functions to allow driver to give a buffer to HPI for busmastering */
160 static u16 hpi_stream_host_buffer_attach(
161 u32 h_stream, /* handle to outstream. */
162 u32 size_in_bytes, /* size in bytes of bus mastering buffer */
163 u32 pci_address
166 struct hpi_message hm;
167 struct hpi_response hr;
168 unsigned int obj = hpi_handle_object(h_stream);
170 if (!h_stream)
171 return HPI_ERROR_INVALID_OBJ;
172 hpi_init_message_response(&hm, &hr, obj,
173 obj == HPI_OBJ_OSTREAM ?
174 HPI_OSTREAM_HOSTBUFFER_ALLOC :
175 HPI_ISTREAM_HOSTBUFFER_ALLOC);
177 hpi_handle_to_indexes(h_stream, &hm.adapter_index,
178 &hm.obj_index);
180 hm.u.d.u.buffer.buffer_size = size_in_bytes;
181 hm.u.d.u.buffer.pci_address = pci_address;
182 hm.u.d.u.buffer.command = HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER;
183 hpi_send_recv(&hm, &hr);
184 return hr.error;
187 static u16 hpi_stream_host_buffer_detach(u32 h_stream)
189 struct hpi_message hm;
190 struct hpi_response hr;
191 unsigned int obj = hpi_handle_object(h_stream);
193 if (!h_stream)
194 return HPI_ERROR_INVALID_OBJ;
196 hpi_init_message_response(&hm, &hr, obj,
197 obj == HPI_OBJ_OSTREAM ?
198 HPI_OSTREAM_HOSTBUFFER_FREE :
199 HPI_ISTREAM_HOSTBUFFER_FREE);
201 hpi_handle_to_indexes(h_stream, &hm.adapter_index,
202 &hm.obj_index);
203 hm.u.d.u.buffer.command = HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER;
204 hpi_send_recv(&hm, &hr);
205 return hr.error;
208 static inline u16 hpi_stream_start(u32 h_stream)
210 if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM)
211 return hpi_outstream_start(h_stream);
212 else
213 return hpi_instream_start(h_stream);
216 static inline u16 hpi_stream_stop(u32 h_stream)
218 if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM)
219 return hpi_outstream_stop(h_stream);
220 else
221 return hpi_instream_stop(h_stream);
224 static inline u16 hpi_stream_get_info_ex(
225 u32 h_stream,
226 u16 *pw_state,
227 u32 *pbuffer_size,
228 u32 *pdata_in_buffer,
229 u32 *psample_count,
230 u32 *pauxiliary_data
233 u16 e;
234 if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM)
235 e = hpi_outstream_get_info_ex(h_stream, pw_state,
236 pbuffer_size, pdata_in_buffer,
237 psample_count, pauxiliary_data);
238 else
239 e = hpi_instream_get_info_ex(h_stream, pw_state,
240 pbuffer_size, pdata_in_buffer,
241 psample_count, pauxiliary_data);
242 return e;
245 static inline u16 hpi_stream_group_add(
246 u32 h_master,
247 u32 h_stream)
249 if (hpi_handle_object(h_master) == HPI_OBJ_OSTREAM)
250 return hpi_outstream_group_add(h_master, h_stream);
251 else
252 return hpi_instream_group_add(h_master, h_stream);
255 static inline u16 hpi_stream_group_reset(u32 h_stream)
257 if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM)
258 return hpi_outstream_group_reset(h_stream);
259 else
260 return hpi_instream_group_reset(h_stream);
263 static inline u16 hpi_stream_group_get_map(
264 u32 h_stream, u32 *mo, u32 *mi)
266 if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM)
267 return hpi_outstream_group_get_map(h_stream, mo, mi);
268 else
269 return hpi_instream_group_get_map(h_stream, mo, mi);
272 static u16 handle_error(u16 err, int line, char *filename)
274 if (err)
275 printk(KERN_WARNING
276 "in file %s, line %d: HPI error %d\n",
277 filename, line, err);
278 return err;
281 #define hpi_handle_error(x) handle_error(x, __LINE__, __FILE__)
283 /***************************** GENERAL PCM ****************/
285 static void print_hwparams(struct snd_pcm_substream *substream,
286 struct snd_pcm_hw_params *p)
288 char name[16];
289 snd_pcm_debug_name(substream, name, sizeof(name));
290 snd_printd("%s HWPARAMS\n", name);
291 snd_printd(" samplerate %d Hz\n", params_rate(p));
292 snd_printd(" channels %d\n", params_channels(p));
293 snd_printd(" format %d\n", params_format(p));
294 snd_printd(" subformat %d\n", params_subformat(p));
295 snd_printd(" buffer %d B\n", params_buffer_bytes(p));
296 snd_printd(" period %d B\n", params_period_bytes(p));
297 snd_printd(" access %d\n", params_access(p));
298 snd_printd(" period_size %d\n", params_period_size(p));
299 snd_printd(" periods %d\n", params_periods(p));
300 snd_printd(" buffer_size %d\n", params_buffer_size(p));
301 snd_printd(" %d B/s\n", params_rate(p) *
302 params_channels(p) *
303 snd_pcm_format_width(params_format(p)) / 8);
307 static snd_pcm_format_t hpi_to_alsa_formats[] = {
308 -1, /* INVALID */
309 SNDRV_PCM_FORMAT_U8, /* HPI_FORMAT_PCM8_UNSIGNED 1 */
310 SNDRV_PCM_FORMAT_S16, /* HPI_FORMAT_PCM16_SIGNED 2 */
311 -1, /* HPI_FORMAT_MPEG_L1 3 */
312 SNDRV_PCM_FORMAT_MPEG, /* HPI_FORMAT_MPEG_L2 4 */
313 SNDRV_PCM_FORMAT_MPEG, /* HPI_FORMAT_MPEG_L3 5 */
314 -1, /* HPI_FORMAT_DOLBY_AC2 6 */
315 -1, /* HPI_FORMAT_DOLBY_AC3 7 */
316 SNDRV_PCM_FORMAT_S16_BE,/* HPI_FORMAT_PCM16_BIGENDIAN 8 */
317 -1, /* HPI_FORMAT_AA_TAGIT1_HITS 9 */
318 -1, /* HPI_FORMAT_AA_TAGIT1_INSERTS 10 */
319 SNDRV_PCM_FORMAT_S32, /* HPI_FORMAT_PCM32_SIGNED 11 */
320 -1, /* HPI_FORMAT_RAW_BITSTREAM 12 */
321 -1, /* HPI_FORMAT_AA_TAGIT1_HITS_EX1 13 */
322 SNDRV_PCM_FORMAT_FLOAT, /* HPI_FORMAT_PCM32_FLOAT 14 */
323 #if 1
324 /* ALSA can't handle 3 byte sample size together with power-of-2
325 * constraint on buffer_bytes, so disable this format
328 #else
329 /* SNDRV_PCM_FORMAT_S24_3LE */ /* HPI_FORMAT_PCM24_SIGNED 15 */
330 #endif
334 static int snd_card_asihpi_format_alsa2hpi(snd_pcm_format_t alsa_format,
335 u16 *hpi_format)
337 u16 format;
339 for (format = HPI_FORMAT_PCM8_UNSIGNED;
340 format <= HPI_FORMAT_PCM24_SIGNED; format++) {
341 if (hpi_to_alsa_formats[format] == alsa_format) {
342 *hpi_format = format;
343 return 0;
347 snd_printd(KERN_WARNING "failed match for alsa format %d\n",
348 alsa_format);
349 *hpi_format = 0;
350 return -EINVAL;
353 static void snd_card_asihpi_pcm_samplerates(struct snd_card_asihpi *asihpi,
354 struct snd_pcm_hardware *pcmhw)
356 u16 err;
357 u32 h_control;
358 u32 sample_rate;
359 int idx;
360 unsigned int rate_min = 200000;
361 unsigned int rate_max = 0;
362 unsigned int rates = 0;
364 if (asihpi->support_mrx) {
365 rates |= SNDRV_PCM_RATE_CONTINUOUS;
366 rates |= SNDRV_PCM_RATE_8000_96000;
367 rate_min = 8000;
368 rate_max = 100000;
369 } else {
370 /* on cards without SRC,
371 valid rates are determined by sampleclock */
372 err = hpi_mixer_get_control(asihpi->h_mixer,
373 HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0,
374 HPI_CONTROL_SAMPLECLOCK, &h_control);
375 if (err) {
376 snd_printk(KERN_ERR
377 "No local sampleclock, err %d\n", err);
380 for (idx = -1; idx < 100; idx++) {
381 if (idx == -1) {
382 if (hpi_sample_clock_get_sample_rate(h_control,
383 &sample_rate))
384 continue;
385 } else if (hpi_sample_clock_query_local_rate(h_control,
386 idx, &sample_rate)) {
387 break;
390 rate_min = min(rate_min, sample_rate);
391 rate_max = max(rate_max, sample_rate);
393 switch (sample_rate) {
394 case 5512:
395 rates |= SNDRV_PCM_RATE_5512;
396 break;
397 case 8000:
398 rates |= SNDRV_PCM_RATE_8000;
399 break;
400 case 11025:
401 rates |= SNDRV_PCM_RATE_11025;
402 break;
403 case 16000:
404 rates |= SNDRV_PCM_RATE_16000;
405 break;
406 case 22050:
407 rates |= SNDRV_PCM_RATE_22050;
408 break;
409 case 32000:
410 rates |= SNDRV_PCM_RATE_32000;
411 break;
412 case 44100:
413 rates |= SNDRV_PCM_RATE_44100;
414 break;
415 case 48000:
416 rates |= SNDRV_PCM_RATE_48000;
417 break;
418 case 64000:
419 rates |= SNDRV_PCM_RATE_64000;
420 break;
421 case 88200:
422 rates |= SNDRV_PCM_RATE_88200;
423 break;
424 case 96000:
425 rates |= SNDRV_PCM_RATE_96000;
426 break;
427 case 176400:
428 rates |= SNDRV_PCM_RATE_176400;
429 break;
430 case 192000:
431 rates |= SNDRV_PCM_RATE_192000;
432 break;
433 default: /* some other rate */
434 rates |= SNDRV_PCM_RATE_KNOT;
439 pcmhw->rates = rates;
440 pcmhw->rate_min = rate_min;
441 pcmhw->rate_max = rate_max;
444 static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream,
445 struct snd_pcm_hw_params *params)
447 struct snd_pcm_runtime *runtime = substream->runtime;
448 struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
449 struct snd_card_asihpi *card = snd_pcm_substream_chip(substream);
450 int err;
451 u16 format;
452 int width;
453 unsigned int bytes_per_sec;
455 print_hwparams(substream, params);
456 err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
457 if (err < 0)
458 return err;
459 err = snd_card_asihpi_format_alsa2hpi(params_format(params), &format);
460 if (err)
461 return err;
463 hpi_handle_error(hpi_format_create(&dpcm->format,
464 params_channels(params),
465 format, params_rate(params), 0, 0));
467 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
468 if (hpi_instream_reset(dpcm->h_stream) != 0)
469 return -EINVAL;
471 if (hpi_instream_set_format(
472 dpcm->h_stream, &dpcm->format) != 0)
473 return -EINVAL;
476 dpcm->hpi_buffer_attached = 0;
477 if (card->can_dma) {
478 err = hpi_stream_host_buffer_attach(dpcm->h_stream,
479 params_buffer_bytes(params), runtime->dma_addr);
480 if (err == 0) {
481 snd_printdd(
482 "stream_host_buffer_attach succeeded %u %lu\n",
483 params_buffer_bytes(params),
484 (unsigned long)runtime->dma_addr);
485 } else {
486 snd_printd("stream_host_buffer_attach error %d\n",
487 err);
488 return -ENOMEM;
491 err = hpi_stream_get_info_ex(dpcm->h_stream, NULL,
492 &dpcm->hpi_buffer_attached,
493 NULL, NULL, NULL);
495 snd_printdd("stream_host_buffer_attach status 0x%x\n",
496 dpcm->hpi_buffer_attached);
498 bytes_per_sec = params_rate(params) * params_channels(params);
499 width = snd_pcm_format_width(params_format(params));
500 bytes_per_sec *= width;
501 bytes_per_sec /= 8;
502 if (width < 0 || bytes_per_sec == 0)
503 return -EINVAL;
505 dpcm->bytes_per_sec = bytes_per_sec;
506 dpcm->buffer_bytes = params_buffer_bytes(params);
507 dpcm->period_bytes = params_period_bytes(params);
509 return 0;
512 static int
513 snd_card_asihpi_hw_free(struct snd_pcm_substream *substream)
515 struct snd_pcm_runtime *runtime = substream->runtime;
516 struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
517 if (dpcm->hpi_buffer_attached)
518 hpi_stream_host_buffer_detach(dpcm->h_stream);
520 snd_pcm_lib_free_pages(substream);
521 return 0;
524 static void snd_card_asihpi_runtime_free(struct snd_pcm_runtime *runtime)
526 struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
527 kfree(dpcm);
530 static void snd_card_asihpi_pcm_timer_start(struct snd_pcm_substream *
531 substream)
533 struct snd_pcm_runtime *runtime = substream->runtime;
534 struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
535 int expiry;
537 expiry = HZ / 200;
538 /*? (dpcm->period_bytes * HZ / dpcm->bytes_per_sec); */
539 expiry = max(expiry, 1); /* don't let it be zero! */
540 dpcm->timer.expires = jiffies + expiry;
541 dpcm->respawn_timer = 1;
542 add_timer(&dpcm->timer);
545 static void snd_card_asihpi_pcm_timer_stop(struct snd_pcm_substream *substream)
547 struct snd_pcm_runtime *runtime = substream->runtime;
548 struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
550 dpcm->respawn_timer = 0;
551 del_timer(&dpcm->timer);
554 static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream,
555 int cmd)
557 struct snd_card_asihpi_pcm *dpcm = substream->runtime->private_data;
558 struct snd_card_asihpi *card = snd_pcm_substream_chip(substream);
559 struct snd_pcm_substream *s;
560 u16 e;
561 char name[16];
563 snd_pcm_debug_name(substream, name, sizeof(name));
564 snd_printdd("%s trigger\n", name);
566 switch (cmd) {
567 case SNDRV_PCM_TRIGGER_START:
568 snd_pcm_group_for_each_entry(s, substream) {
569 struct snd_pcm_runtime *runtime = s->runtime;
570 struct snd_card_asihpi_pcm *ds = runtime->private_data;
572 if (snd_pcm_substream_chip(s) != card)
573 continue;
575 /* don't link Cap and Play */
576 if (substream->stream != s->stream)
577 continue;
579 ds->drained_count = 0;
580 if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) {
581 /* How do I know how much valid data is present
582 * in buffer? Must be at least one period!
583 * Guessing 2 periods, but if
584 * buffer is bigger it may contain even more
585 * data??
587 unsigned int preload = ds->period_bytes * 1;
588 snd_printddd("%d preload x%x\n", s->number, preload);
589 hpi_handle_error(hpi_outstream_write_buf(
590 ds->h_stream,
591 &runtime->dma_area[0],
592 preload,
593 &ds->format));
594 ds->pcm_buf_host_rw_ofs = preload;
597 if (card->support_grouping) {
598 snd_printdd("%d group\n", s->number);
599 e = hpi_stream_group_add(
600 dpcm->h_stream,
601 ds->h_stream);
602 if (!e) {
603 snd_pcm_trigger_done(s, substream);
604 } else {
605 hpi_handle_error(e);
606 break;
608 } else
609 break;
611 snd_printdd("start\n");
612 /* start the master stream */
613 snd_card_asihpi_pcm_timer_start(substream);
614 if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE) ||
615 !card->can_dma)
616 hpi_handle_error(hpi_stream_start(dpcm->h_stream));
617 break;
619 case SNDRV_PCM_TRIGGER_STOP:
620 snd_card_asihpi_pcm_timer_stop(substream);
621 snd_pcm_group_for_each_entry(s, substream) {
622 if (snd_pcm_substream_chip(s) != card)
623 continue;
624 /* don't link Cap and Play */
625 if (substream->stream != s->stream)
626 continue;
628 /*? workaround linked streams don't
629 transition to SETUP 20070706*/
630 s->runtime->status->state = SNDRV_PCM_STATE_SETUP;
632 if (card->support_grouping) {
633 snd_printdd("%d group\n", s->number);
634 snd_pcm_trigger_done(s, substream);
635 } else
636 break;
638 snd_printdd("stop\n");
640 /* _prepare and _hwparams reset the stream */
641 hpi_handle_error(hpi_stream_stop(dpcm->h_stream));
642 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
643 hpi_handle_error(
644 hpi_outstream_reset(dpcm->h_stream));
646 if (card->support_grouping)
647 hpi_handle_error(hpi_stream_group_reset(dpcm->h_stream));
648 break;
650 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
651 snd_printdd("pause release\n");
652 hpi_handle_error(hpi_stream_start(dpcm->h_stream));
653 snd_card_asihpi_pcm_timer_start(substream);
654 break;
655 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
656 snd_printdd("pause\n");
657 snd_card_asihpi_pcm_timer_stop(substream);
658 hpi_handle_error(hpi_stream_stop(dpcm->h_stream));
659 break;
660 default:
661 snd_printd(KERN_ERR "\tINVALID\n");
662 return -EINVAL;
665 return 0;
668 /*algorithm outline
669 Without linking degenerates to getting single stream pos etc
670 Without mmap 2nd loop degenerates to snd_pcm_period_elapsed
673 pcm_buf_dma_ofs=get_buf_pos(s);
674 for_each_linked_stream(s) {
675 pcm_buf_dma_ofs=get_buf_pos(s);
676 min_buf_pos = modulo_min(min_buf_pos, pcm_buf_dma_ofs, buffer_bytes)
677 new_data = min(new_data, calc_new_data(pcm_buf_dma_ofs,irq_pos)
679 timer.expires = jiffies + predict_next_period_ready(min_buf_pos);
680 for_each_linked_stream(s) {
681 s->pcm_buf_dma_ofs = min_buf_pos;
682 if (new_data > period_bytes) {
683 if (mmap) {
684 irq_pos = (irq_pos + period_bytes) % buffer_bytes;
685 if (playback) {
686 write(period_bytes);
687 } else {
688 read(period_bytes);
691 snd_pcm_period_elapsed(s);
696 /** Minimum of 2 modulo values. Works correctly when the difference between
697 * the values is less than half the modulus
699 static inline unsigned int modulo_min(unsigned int a, unsigned int b,
700 unsigned long int modulus)
702 unsigned int result;
703 if (((a-b) % modulus) < (modulus/2))
704 result = b;
705 else
706 result = a;
708 return result;
711 /** Timer function, equivalent to interrupt service routine for cards
713 static void snd_card_asihpi_timer_function(unsigned long data)
715 struct snd_card_asihpi_pcm *dpcm = (struct snd_card_asihpi_pcm *)data;
716 struct snd_pcm_substream *substream = dpcm->substream;
717 struct snd_card_asihpi *card = snd_pcm_substream_chip(substream);
718 struct snd_pcm_runtime *runtime;
719 struct snd_pcm_substream *s;
720 unsigned int newdata = 0;
721 unsigned int pcm_buf_dma_ofs, min_buf_pos = 0;
722 unsigned int remdata, xfercount, next_jiffies;
723 int first = 1;
724 int loops = 0;
725 u16 state;
726 u32 buffer_size, bytes_avail, samples_played, on_card_bytes;
727 char name[16];
729 snd_pcm_debug_name(substream, name, sizeof(name));
731 snd_printdd("%s snd_card_asihpi_timer_function\n", name);
733 /* find minimum newdata and buffer pos in group */
734 snd_pcm_group_for_each_entry(s, substream) {
735 struct snd_card_asihpi_pcm *ds = s->runtime->private_data;
736 runtime = s->runtime;
738 if (snd_pcm_substream_chip(s) != card)
739 continue;
741 /* don't link Cap and Play */
742 if (substream->stream != s->stream)
743 continue;
745 hpi_handle_error(hpi_stream_get_info_ex(
746 ds->h_stream, &state,
747 &buffer_size, &bytes_avail,
748 &samples_played, &on_card_bytes));
750 /* number of bytes in on-card buffer */
751 runtime->delay = on_card_bytes;
753 if (!card->can_dma)
754 on_card_bytes = bytes_avail;
756 if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) {
757 pcm_buf_dma_ofs = ds->pcm_buf_host_rw_ofs - bytes_avail;
758 if (state == HPI_STATE_STOPPED) {
759 if ((bytes_avail == 0) &&
760 (on_card_bytes < ds->pcm_buf_host_rw_ofs)) {
761 hpi_handle_error(hpi_stream_start(ds->h_stream));
762 snd_printdd("P%d start\n", s->number);
763 ds->drained_count = 0;
765 } else if (state == HPI_STATE_DRAINED) {
766 snd_printd(KERN_WARNING "P%d drained\n",
767 s->number);
768 ds->drained_count++;
769 if (ds->drained_count > 2) {
770 snd_pcm_stop(s, SNDRV_PCM_STATE_XRUN);
771 continue;
773 } else {
774 ds->drained_count = 0;
776 } else
777 pcm_buf_dma_ofs = bytes_avail + ds->pcm_buf_host_rw_ofs;
779 if (first) {
780 /* can't statically init min when wrap is involved */
781 min_buf_pos = pcm_buf_dma_ofs;
782 newdata = (pcm_buf_dma_ofs - ds->pcm_buf_elapsed_dma_ofs) % ds->buffer_bytes;
783 first = 0;
784 } else {
785 min_buf_pos =
786 modulo_min(min_buf_pos, pcm_buf_dma_ofs, UINT_MAX+1L);
787 newdata = min(
788 (pcm_buf_dma_ofs - ds->pcm_buf_elapsed_dma_ofs) % ds->buffer_bytes,
789 newdata);
792 snd_printdd("hw_ptr 0x%04lX, appl_ptr 0x%04lX\n",
793 (unsigned long)frames_to_bytes(runtime,
794 runtime->status->hw_ptr),
795 (unsigned long)frames_to_bytes(runtime,
796 runtime->control->appl_ptr));
798 snd_printdd("%d S=%d, "
799 "rw=0x%04X, dma=0x%04X, left=0x%04X, "
800 "aux=0x%04X space=0x%04X\n",
801 s->number, state,
802 ds->pcm_buf_host_rw_ofs, pcm_buf_dma_ofs,
803 (int)bytes_avail,
804 (int)on_card_bytes, buffer_size-bytes_avail);
805 loops++;
807 pcm_buf_dma_ofs = min_buf_pos;
809 remdata = newdata % dpcm->period_bytes;
810 xfercount = newdata - remdata; /* a multiple of period_bytes */
811 /* come back when on_card_bytes has decreased enough to allow
812 write to happen, or when data has been consumed to make another
813 period
815 if (xfercount && (on_card_bytes > dpcm->period_bytes))
816 next_jiffies = ((on_card_bytes - dpcm->period_bytes) * HZ / dpcm->bytes_per_sec);
817 else
818 next_jiffies = ((dpcm->period_bytes - remdata) * HZ / dpcm->bytes_per_sec);
820 next_jiffies = max(next_jiffies, 1U);
821 dpcm->timer.expires = jiffies + next_jiffies;
822 snd_printdd("jif %d buf pos 0x%04X newdata 0x%04X xfer 0x%04X\n",
823 next_jiffies, pcm_buf_dma_ofs, newdata, xfercount);
825 snd_pcm_group_for_each_entry(s, substream) {
826 struct snd_card_asihpi_pcm *ds = s->runtime->private_data;
828 /* don't link Cap and Play */
829 if (substream->stream != s->stream)
830 continue;
832 ds->pcm_buf_dma_ofs = pcm_buf_dma_ofs;
834 if (xfercount &&
835 /* Limit use of on card fifo for playback */
836 ((on_card_bytes <= ds->period_bytes) ||
837 (s->stream == SNDRV_PCM_STREAM_CAPTURE)))
841 unsigned int buf_ofs = ds->pcm_buf_host_rw_ofs % ds->buffer_bytes;
842 unsigned int xfer1, xfer2;
843 char *pd = &s->runtime->dma_area[buf_ofs];
845 if (card->can_dma) { /* buffer wrap is handled at lower level */
846 xfer1 = xfercount;
847 xfer2 = 0;
848 } else {
849 xfer1 = min(xfercount, ds->buffer_bytes - buf_ofs);
850 xfer2 = xfercount - xfer1;
853 if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) {
854 snd_printddd("P%d write1 0x%04X 0x%04X\n",
855 s->number, xfer1, buf_ofs);
856 hpi_handle_error(
857 hpi_outstream_write_buf(
858 ds->h_stream, pd, xfer1,
859 &ds->format));
861 if (xfer2) {
862 pd = s->runtime->dma_area;
864 snd_printddd("P%d write2 0x%04X 0x%04X\n",
865 s->number,
866 xfercount - xfer1, buf_ofs);
867 hpi_handle_error(
868 hpi_outstream_write_buf(
869 ds->h_stream, pd,
870 xfercount - xfer1,
871 &ds->format));
873 } else {
874 snd_printddd("C%d read1 0x%04x\n",
875 s->number, xfer1);
876 hpi_handle_error(
877 hpi_instream_read_buf(
878 ds->h_stream,
879 pd, xfer1));
880 if (xfer2) {
881 pd = s->runtime->dma_area;
882 snd_printddd("C%d read2 0x%04x\n",
883 s->number, xfer2);
884 hpi_handle_error(
885 hpi_instream_read_buf(
886 ds->h_stream,
887 pd, xfer2));
890 ds->pcm_buf_host_rw_ofs = ds->pcm_buf_host_rw_ofs + xfercount;
891 ds->pcm_buf_elapsed_dma_ofs = pcm_buf_dma_ofs;
892 snd_pcm_period_elapsed(s);
896 if (dpcm->respawn_timer)
897 add_timer(&dpcm->timer);
900 /***************************** PLAYBACK OPS ****************/
901 static int snd_card_asihpi_playback_ioctl(struct snd_pcm_substream *substream,
902 unsigned int cmd, void *arg)
904 snd_printddd(KERN_INFO "P%d ioctl %d\n", substream->number, cmd);
905 return snd_pcm_lib_ioctl(substream, cmd, arg);
908 static int snd_card_asihpi_playback_prepare(struct snd_pcm_substream *
909 substream)
911 struct snd_pcm_runtime *runtime = substream->runtime;
912 struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
914 snd_printdd("P%d prepare\n", substream->number);
916 hpi_handle_error(hpi_outstream_reset(dpcm->h_stream));
917 dpcm->pcm_buf_host_rw_ofs = 0;
918 dpcm->pcm_buf_dma_ofs = 0;
919 dpcm->pcm_buf_elapsed_dma_ofs = 0;
920 return 0;
923 static snd_pcm_uframes_t
924 snd_card_asihpi_playback_pointer(struct snd_pcm_substream *substream)
926 struct snd_pcm_runtime *runtime = substream->runtime;
927 struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
928 snd_pcm_uframes_t ptr;
930 ptr = bytes_to_frames(runtime, dpcm->pcm_buf_dma_ofs % dpcm->buffer_bytes);
931 snd_printddd("P%d pointer = 0x%04lx\n", substream->number, (unsigned long)ptr);
932 return ptr;
935 static void snd_card_asihpi_playback_format(struct snd_card_asihpi *asihpi,
936 u32 h_stream,
937 struct snd_pcm_hardware *pcmhw)
939 struct hpi_format hpi_format;
940 u16 format;
941 u16 err;
942 u32 h_control;
943 u32 sample_rate = 48000;
945 /* on cards without SRC, must query at valid rate,
946 * maybe set by external sync
948 err = hpi_mixer_get_control(asihpi->h_mixer,
949 HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0,
950 HPI_CONTROL_SAMPLECLOCK, &h_control);
952 if (!err)
953 err = hpi_sample_clock_get_sample_rate(h_control,
954 &sample_rate);
956 for (format = HPI_FORMAT_PCM8_UNSIGNED;
957 format <= HPI_FORMAT_PCM24_SIGNED; format++) {
958 err = hpi_format_create(&hpi_format,
959 2, format, sample_rate, 128000, 0);
960 if (!err)
961 err = hpi_outstream_query_format(h_stream,
962 &hpi_format);
963 if (!err && (hpi_to_alsa_formats[format] != -1))
964 pcmhw->formats |=
965 (1ULL << hpi_to_alsa_formats[format]);
969 static struct snd_pcm_hardware snd_card_asihpi_playback = {
970 .channels_min = 1,
971 .channels_max = 2,
972 .buffer_bytes_max = BUFFER_BYTES_MAX,
973 .period_bytes_min = PERIOD_BYTES_MIN,
974 .period_bytes_max = BUFFER_BYTES_MAX / PERIODS_MIN,
975 .periods_min = PERIODS_MIN,
976 .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN,
977 .fifo_size = 0,
980 static int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream)
982 struct snd_pcm_runtime *runtime = substream->runtime;
983 struct snd_card_asihpi_pcm *dpcm;
984 struct snd_card_asihpi *card = snd_pcm_substream_chip(substream);
985 int err;
987 dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);
988 if (dpcm == NULL)
989 return -ENOMEM;
991 err =
992 hpi_outstream_open(card->adapter_index,
993 substream->number, &dpcm->h_stream);
994 hpi_handle_error(err);
995 if (err)
996 kfree(dpcm);
997 if (err == HPI_ERROR_OBJ_ALREADY_OPEN)
998 return -EBUSY;
999 if (err)
1000 return -EIO;
1002 /*? also check ASI5000 samplerate source
1003 If external, only support external rate.
1004 If internal and other stream playing, can't switch
1007 init_timer(&dpcm->timer);
1008 dpcm->timer.data = (unsigned long) dpcm;
1009 dpcm->timer.function = snd_card_asihpi_timer_function;
1010 dpcm->substream = substream;
1011 runtime->private_data = dpcm;
1012 runtime->private_free = snd_card_asihpi_runtime_free;
1014 snd_card_asihpi_playback.channels_max = card->out_max_chans;
1015 /*?snd_card_asihpi_playback.period_bytes_min =
1016 card->out_max_chans * 4096; */
1018 snd_card_asihpi_playback_format(card, dpcm->h_stream,
1019 &snd_card_asihpi_playback);
1021 snd_card_asihpi_pcm_samplerates(card, &snd_card_asihpi_playback);
1023 snd_card_asihpi_playback.info = SNDRV_PCM_INFO_INTERLEAVED |
1024 SNDRV_PCM_INFO_DOUBLE |
1025 SNDRV_PCM_INFO_BATCH |
1026 SNDRV_PCM_INFO_BLOCK_TRANSFER |
1027 SNDRV_PCM_INFO_PAUSE |
1028 SNDRV_PCM_INFO_MMAP |
1029 SNDRV_PCM_INFO_MMAP_VALID;
1031 if (card->support_grouping)
1032 snd_card_asihpi_playback.info |= SNDRV_PCM_INFO_SYNC_START;
1034 /* struct is copied, so can create initializer dynamically */
1035 runtime->hw = snd_card_asihpi_playback;
1037 if (card->can_dma)
1038 err = snd_pcm_hw_constraint_pow2(runtime, 0,
1039 SNDRV_PCM_HW_PARAM_BUFFER_BYTES);
1040 if (err < 0)
1041 return err;
1043 snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
1044 card->update_interval_frames);
1046 snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
1047 card->update_interval_frames * 2, UINT_MAX);
1049 snd_pcm_set_sync(substream);
1051 snd_printdd("playback open\n");
1053 return 0;
1056 static int snd_card_asihpi_playback_close(struct snd_pcm_substream *substream)
1058 struct snd_pcm_runtime *runtime = substream->runtime;
1059 struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
1061 hpi_handle_error(hpi_outstream_close(dpcm->h_stream));
1062 snd_printdd("playback close\n");
1064 return 0;
1067 static struct snd_pcm_ops snd_card_asihpi_playback_mmap_ops = {
1068 .open = snd_card_asihpi_playback_open,
1069 .close = snd_card_asihpi_playback_close,
1070 .ioctl = snd_card_asihpi_playback_ioctl,
1071 .hw_params = snd_card_asihpi_pcm_hw_params,
1072 .hw_free = snd_card_asihpi_hw_free,
1073 .prepare = snd_card_asihpi_playback_prepare,
1074 .trigger = snd_card_asihpi_trigger,
1075 .pointer = snd_card_asihpi_playback_pointer,
1078 /***************************** CAPTURE OPS ****************/
1079 static snd_pcm_uframes_t
1080 snd_card_asihpi_capture_pointer(struct snd_pcm_substream *substream)
1082 struct snd_pcm_runtime *runtime = substream->runtime;
1083 struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
1085 snd_printddd("capture pointer %d=%d\n",
1086 substream->number, dpcm->pcm_buf_dma_ofs);
1087 /* NOTE Unlike playback can't use actual samples_played
1088 for the capture position, because those samples aren't yet in
1089 the local buffer available for reading.
1091 return bytes_to_frames(runtime, dpcm->pcm_buf_dma_ofs % dpcm->buffer_bytes);
1094 static int snd_card_asihpi_capture_ioctl(struct snd_pcm_substream *substream,
1095 unsigned int cmd, void *arg)
1097 return snd_pcm_lib_ioctl(substream, cmd, arg);
1100 static int snd_card_asihpi_capture_prepare(struct snd_pcm_substream *substream)
1102 struct snd_pcm_runtime *runtime = substream->runtime;
1103 struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
1105 hpi_handle_error(hpi_instream_reset(dpcm->h_stream));
1106 dpcm->pcm_buf_host_rw_ofs = 0;
1107 dpcm->pcm_buf_dma_ofs = 0;
1108 dpcm->pcm_buf_elapsed_dma_ofs = 0;
1110 snd_printdd("Capture Prepare %d\n", substream->number);
1111 return 0;
1116 static void snd_card_asihpi_capture_format(struct snd_card_asihpi *asihpi,
1117 u32 h_stream,
1118 struct snd_pcm_hardware *pcmhw)
1120 struct hpi_format hpi_format;
1121 u16 format;
1122 u16 err;
1123 u32 h_control;
1124 u32 sample_rate = 48000;
1126 /* on cards without SRC, must query at valid rate,
1127 maybe set by external sync */
1128 err = hpi_mixer_get_control(asihpi->h_mixer,
1129 HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0,
1130 HPI_CONTROL_SAMPLECLOCK, &h_control);
1132 if (!err)
1133 err = hpi_sample_clock_get_sample_rate(h_control,
1134 &sample_rate);
1136 for (format = HPI_FORMAT_PCM8_UNSIGNED;
1137 format <= HPI_FORMAT_PCM24_SIGNED; format++) {
1139 err = hpi_format_create(&hpi_format, 2, format,
1140 sample_rate, 128000, 0);
1141 if (!err)
1142 err = hpi_instream_query_format(h_stream,
1143 &hpi_format);
1144 if (!err)
1145 pcmhw->formats |=
1146 (1ULL << hpi_to_alsa_formats[format]);
1151 static struct snd_pcm_hardware snd_card_asihpi_capture = {
1152 .channels_min = 1,
1153 .channels_max = 2,
1154 .buffer_bytes_max = BUFFER_BYTES_MAX,
1155 .period_bytes_min = PERIOD_BYTES_MIN,
1156 .period_bytes_max = BUFFER_BYTES_MAX / PERIODS_MIN,
1157 .periods_min = PERIODS_MIN,
1158 .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN,
1159 .fifo_size = 0,
1162 static int snd_card_asihpi_capture_open(struct snd_pcm_substream *substream)
1164 struct snd_pcm_runtime *runtime = substream->runtime;
1165 struct snd_card_asihpi *card = snd_pcm_substream_chip(substream);
1166 struct snd_card_asihpi_pcm *dpcm;
1167 int err;
1169 dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);
1170 if (dpcm == NULL)
1171 return -ENOMEM;
1173 snd_printdd("capture open adapter %d stream %d\n",
1174 card->adapter_index, substream->number);
1176 err = hpi_handle_error(
1177 hpi_instream_open(card->adapter_index,
1178 substream->number, &dpcm->h_stream));
1179 if (err)
1180 kfree(dpcm);
1181 if (err == HPI_ERROR_OBJ_ALREADY_OPEN)
1182 return -EBUSY;
1183 if (err)
1184 return -EIO;
1187 init_timer(&dpcm->timer);
1188 dpcm->timer.data = (unsigned long) dpcm;
1189 dpcm->timer.function = snd_card_asihpi_timer_function;
1190 dpcm->substream = substream;
1191 runtime->private_data = dpcm;
1192 runtime->private_free = snd_card_asihpi_runtime_free;
1194 snd_card_asihpi_capture.channels_max = card->in_max_chans;
1195 snd_card_asihpi_capture_format(card, dpcm->h_stream,
1196 &snd_card_asihpi_capture);
1197 snd_card_asihpi_pcm_samplerates(card, &snd_card_asihpi_capture);
1198 snd_card_asihpi_capture.info = SNDRV_PCM_INFO_INTERLEAVED |
1199 SNDRV_PCM_INFO_MMAP |
1200 SNDRV_PCM_INFO_MMAP_VALID;
1202 if (card->support_grouping)
1203 snd_card_asihpi_capture.info |= SNDRV_PCM_INFO_SYNC_START;
1205 runtime->hw = snd_card_asihpi_capture;
1207 if (card->can_dma)
1208 err = snd_pcm_hw_constraint_pow2(runtime, 0,
1209 SNDRV_PCM_HW_PARAM_BUFFER_BYTES);
1210 if (err < 0)
1211 return err;
1213 snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
1214 card->update_interval_frames);
1215 snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
1216 card->update_interval_frames * 2, UINT_MAX);
1218 snd_pcm_set_sync(substream);
1220 return 0;
1223 static int snd_card_asihpi_capture_close(struct snd_pcm_substream *substream)
1225 struct snd_card_asihpi_pcm *dpcm = substream->runtime->private_data;
1227 hpi_handle_error(hpi_instream_close(dpcm->h_stream));
1228 return 0;
1231 static struct snd_pcm_ops snd_card_asihpi_capture_mmap_ops = {
1232 .open = snd_card_asihpi_capture_open,
1233 .close = snd_card_asihpi_capture_close,
1234 .ioctl = snd_card_asihpi_capture_ioctl,
1235 .hw_params = snd_card_asihpi_pcm_hw_params,
1236 .hw_free = snd_card_asihpi_hw_free,
1237 .prepare = snd_card_asihpi_capture_prepare,
1238 .trigger = snd_card_asihpi_trigger,
1239 .pointer = snd_card_asihpi_capture_pointer,
1242 static int __devinit snd_card_asihpi_pcm_new(struct snd_card_asihpi *asihpi,
1243 int device, int substreams)
1245 struct snd_pcm *pcm;
1246 int err;
1248 err = snd_pcm_new(asihpi->card, "Asihpi PCM", device,
1249 asihpi->num_outstreams, asihpi->num_instreams,
1250 &pcm);
1251 if (err < 0)
1252 return err;
1253 /* pointer to ops struct is stored, dont change ops afterwards! */
1254 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
1255 &snd_card_asihpi_playback_mmap_ops);
1256 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
1257 &snd_card_asihpi_capture_mmap_ops);
1259 pcm->private_data = asihpi;
1260 pcm->info_flags = 0;
1261 strcpy(pcm->name, "Asihpi PCM");
1263 /*? do we want to emulate MMAP for non-BBM cards?
1264 Jack doesn't work with ALSAs MMAP emulation - WHY NOT? */
1265 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
1266 snd_dma_pci_data(asihpi->pci),
1267 64*1024, BUFFER_BYTES_MAX);
1269 return 0;
1272 /***************************** MIXER CONTROLS ****************/
1273 struct hpi_control {
1274 u32 h_control;
1275 u16 control_type;
1276 u16 src_node_type;
1277 u16 src_node_index;
1278 u16 dst_node_type;
1279 u16 dst_node_index;
1280 u16 band;
1281 char name[44]; /* copied to snd_ctl_elem_id.name[44]; */
1284 static const char * const asihpi_tuner_band_names[] = {
1285 "invalid",
1286 "AM",
1287 "FM mono",
1288 "TV NTSC-M",
1289 "FM stereo",
1290 "AUX",
1291 "TV PAL BG",
1292 "TV PAL I",
1293 "TV PAL DK",
1294 "TV SECAM",
1297 compile_time_assert(
1298 (ARRAY_SIZE(asihpi_tuner_band_names) ==
1299 (HPI_TUNER_BAND_LAST+1)),
1300 assert_tuner_band_names_size);
1302 static const char * const asihpi_src_names[] = {
1303 "no source",
1304 "PCM",
1305 "Line",
1306 "Digital",
1307 "Tuner",
1308 "RF",
1309 "Clock",
1310 "Bitstream",
1311 "Mic",
1312 "Net",
1313 "Analog",
1314 "Adapter",
1315 "RTP",
1316 "GPI",
1319 compile_time_assert(
1320 (ARRAY_SIZE(asihpi_src_names) ==
1321 (HPI_SOURCENODE_LAST_INDEX-HPI_SOURCENODE_NONE+1)),
1322 assert_src_names_size);
1324 static const char * const asihpi_dst_names[] = {
1325 "no destination",
1326 "PCM",
1327 "Line",
1328 "Digital",
1329 "RF",
1330 "Speaker",
1331 "Net",
1332 "Analog",
1333 "RTP",
1334 "GPO",
1337 compile_time_assert(
1338 (ARRAY_SIZE(asihpi_dst_names) ==
1339 (HPI_DESTNODE_LAST_INDEX-HPI_DESTNODE_NONE+1)),
1340 assert_dst_names_size);
1342 static inline int ctl_add(struct snd_card *card, struct snd_kcontrol_new *ctl,
1343 struct snd_card_asihpi *asihpi)
1345 int err;
1347 err = snd_ctl_add(card, snd_ctl_new1(ctl, asihpi));
1348 if (err < 0)
1349 return err;
1350 else if (mixer_dump)
1351 snd_printk(KERN_INFO "added %s(%d)\n", ctl->name, ctl->index);
1353 return 0;
1356 /* Convert HPI control name and location into ALSA control name */
1357 static void asihpi_ctl_init(struct snd_kcontrol_new *snd_control,
1358 struct hpi_control *hpi_ctl,
1359 char *name)
1361 char *dir;
1362 memset(snd_control, 0, sizeof(*snd_control));
1363 snd_control->name = hpi_ctl->name;
1364 snd_control->private_value = hpi_ctl->h_control;
1365 snd_control->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1366 snd_control->index = 0;
1368 if (hpi_ctl->src_node_type + HPI_SOURCENODE_NONE == HPI_SOURCENODE_CLOCK_SOURCE)
1369 dir = ""; /* clock is neither capture nor playback */
1370 else if (hpi_ctl->dst_node_type + HPI_DESTNODE_NONE == HPI_DESTNODE_ISTREAM)
1371 dir = "Capture "; /* On or towards a PCM capture destination*/
1372 else if ((hpi_ctl->src_node_type + HPI_SOURCENODE_NONE != HPI_SOURCENODE_OSTREAM) &&
1373 (!hpi_ctl->dst_node_type))
1374 dir = "Capture "; /* On a source node that is not PCM playback */
1375 else if (hpi_ctl->src_node_type &&
1376 (hpi_ctl->src_node_type + HPI_SOURCENODE_NONE != HPI_SOURCENODE_OSTREAM) &&
1377 (hpi_ctl->dst_node_type))
1378 dir = "Monitor Playback "; /* Between an input and an output */
1379 else
1380 dir = "Playback "; /* PCM Playback source, or output node */
1382 if (hpi_ctl->src_node_type && hpi_ctl->dst_node_type)
1383 sprintf(hpi_ctl->name, "%s %d %s %d %s%s",
1384 asihpi_src_names[hpi_ctl->src_node_type],
1385 hpi_ctl->src_node_index,
1386 asihpi_dst_names[hpi_ctl->dst_node_type],
1387 hpi_ctl->dst_node_index,
1388 dir, name);
1389 else if (hpi_ctl->dst_node_type) {
1390 sprintf(hpi_ctl->name, "%s %d %s%s",
1391 asihpi_dst_names[hpi_ctl->dst_node_type],
1392 hpi_ctl->dst_node_index,
1393 dir, name);
1394 } else {
1395 sprintf(hpi_ctl->name, "%s %d %s%s",
1396 asihpi_src_names[hpi_ctl->src_node_type],
1397 hpi_ctl->src_node_index,
1398 dir, name);
1400 /* printk(KERN_INFO "Adding %s %d to %d ", hpi_ctl->name,
1401 hpi_ctl->wSrcNodeType, hpi_ctl->wDstNodeType); */
1404 /*------------------------------------------------------------
1405 Volume controls
1406 ------------------------------------------------------------*/
1407 #define VOL_STEP_mB 1
1408 static int snd_asihpi_volume_info(struct snd_kcontrol *kcontrol,
1409 struct snd_ctl_elem_info *uinfo)
1411 u32 h_control = kcontrol->private_value;
1412 u16 err;
1413 /* native gains are in millibels */
1414 short min_gain_mB;
1415 short max_gain_mB;
1416 short step_gain_mB;
1418 err = hpi_volume_query_range(h_control,
1419 &min_gain_mB, &max_gain_mB, &step_gain_mB);
1420 if (err) {
1421 max_gain_mB = 0;
1422 min_gain_mB = -10000;
1423 step_gain_mB = VOL_STEP_mB;
1426 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1427 uinfo->count = 2;
1428 uinfo->value.integer.min = min_gain_mB / VOL_STEP_mB;
1429 uinfo->value.integer.max = max_gain_mB / VOL_STEP_mB;
1430 uinfo->value.integer.step = step_gain_mB / VOL_STEP_mB;
1431 return 0;
1434 static int snd_asihpi_volume_get(struct snd_kcontrol *kcontrol,
1435 struct snd_ctl_elem_value *ucontrol)
1437 u32 h_control = kcontrol->private_value;
1438 short an_gain_mB[HPI_MAX_CHANNELS];
1440 hpi_handle_error(hpi_volume_get_gain(h_control, an_gain_mB));
1441 ucontrol->value.integer.value[0] = an_gain_mB[0] / VOL_STEP_mB;
1442 ucontrol->value.integer.value[1] = an_gain_mB[1] / VOL_STEP_mB;
1444 return 0;
1447 static int snd_asihpi_volume_put(struct snd_kcontrol *kcontrol,
1448 struct snd_ctl_elem_value *ucontrol)
1450 int change;
1451 u32 h_control = kcontrol->private_value;
1452 short an_gain_mB[HPI_MAX_CHANNELS];
1454 an_gain_mB[0] =
1455 (ucontrol->value.integer.value[0]) * VOL_STEP_mB;
1456 an_gain_mB[1] =
1457 (ucontrol->value.integer.value[1]) * VOL_STEP_mB;
1458 /* change = asihpi->mixer_volume[addr][0] != left ||
1459 asihpi->mixer_volume[addr][1] != right;
1461 change = 1;
1462 hpi_handle_error(hpi_volume_set_gain(h_control, an_gain_mB));
1463 return change;
1466 static const DECLARE_TLV_DB_SCALE(db_scale_100, -10000, VOL_STEP_mB, 0);
1468 #define snd_asihpi_volume_mute_info snd_ctl_boolean_mono_info
1470 static int snd_asihpi_volume_mute_get(struct snd_kcontrol *kcontrol,
1471 struct snd_ctl_elem_value *ucontrol)
1473 u32 h_control = kcontrol->private_value;
1474 u32 mute;
1476 hpi_handle_error(hpi_volume_get_mute(h_control, &mute));
1477 ucontrol->value.integer.value[0] = mute ? 0 : 1;
1479 return 0;
1482 static int snd_asihpi_volume_mute_put(struct snd_kcontrol *kcontrol,
1483 struct snd_ctl_elem_value *ucontrol)
1485 u32 h_control = kcontrol->private_value;
1486 int change = 1;
1487 /* HPI currently only supports all or none muting of multichannel volume
1488 ALSA Switch element has opposite sense to HPI mute: on==unmuted, off=muted
1490 int mute = ucontrol->value.integer.value[0] ? 0 : HPI_BITMASK_ALL_CHANNELS;
1491 hpi_handle_error(hpi_volume_set_mute(h_control, mute));
1492 return change;
1495 static int __devinit snd_asihpi_volume_add(struct snd_card_asihpi *asihpi,
1496 struct hpi_control *hpi_ctl)
1498 struct snd_card *card = asihpi->card;
1499 struct snd_kcontrol_new snd_control;
1500 int err;
1501 u32 mute;
1503 asihpi_ctl_init(&snd_control, hpi_ctl, "Volume");
1504 snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
1505 SNDRV_CTL_ELEM_ACCESS_TLV_READ;
1506 snd_control.info = snd_asihpi_volume_info;
1507 snd_control.get = snd_asihpi_volume_get;
1508 snd_control.put = snd_asihpi_volume_put;
1509 snd_control.tlv.p = db_scale_100;
1511 err = ctl_add(card, &snd_control, asihpi);
1512 if (err)
1513 return err;
1515 if (hpi_volume_get_mute(hpi_ctl->h_control, &mute) == 0) {
1516 asihpi_ctl_init(&snd_control, hpi_ctl, "Switch");
1517 snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
1518 snd_control.info = snd_asihpi_volume_mute_info;
1519 snd_control.get = snd_asihpi_volume_mute_get;
1520 snd_control.put = snd_asihpi_volume_mute_put;
1521 err = ctl_add(card, &snd_control, asihpi);
1523 return err;
1526 /*------------------------------------------------------------
1527 Level controls
1528 ------------------------------------------------------------*/
1529 static int snd_asihpi_level_info(struct snd_kcontrol *kcontrol,
1530 struct snd_ctl_elem_info *uinfo)
1532 u32 h_control = kcontrol->private_value;
1533 u16 err;
1534 short min_gain_mB;
1535 short max_gain_mB;
1536 short step_gain_mB;
1538 err =
1539 hpi_level_query_range(h_control, &min_gain_mB,
1540 &max_gain_mB, &step_gain_mB);
1541 if (err) {
1542 max_gain_mB = 2400;
1543 min_gain_mB = -1000;
1544 step_gain_mB = 100;
1547 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1548 uinfo->count = 2;
1549 uinfo->value.integer.min = min_gain_mB / HPI_UNITS_PER_dB;
1550 uinfo->value.integer.max = max_gain_mB / HPI_UNITS_PER_dB;
1551 uinfo->value.integer.step = step_gain_mB / HPI_UNITS_PER_dB;
1552 return 0;
1555 static int snd_asihpi_level_get(struct snd_kcontrol *kcontrol,
1556 struct snd_ctl_elem_value *ucontrol)
1558 u32 h_control = kcontrol->private_value;
1559 short an_gain_mB[HPI_MAX_CHANNELS];
1561 hpi_handle_error(hpi_level_get_gain(h_control, an_gain_mB));
1562 ucontrol->value.integer.value[0] =
1563 an_gain_mB[0] / HPI_UNITS_PER_dB;
1564 ucontrol->value.integer.value[1] =
1565 an_gain_mB[1] / HPI_UNITS_PER_dB;
1567 return 0;
1570 static int snd_asihpi_level_put(struct snd_kcontrol *kcontrol,
1571 struct snd_ctl_elem_value *ucontrol)
1573 int change;
1574 u32 h_control = kcontrol->private_value;
1575 short an_gain_mB[HPI_MAX_CHANNELS];
1577 an_gain_mB[0] =
1578 (ucontrol->value.integer.value[0]) * HPI_UNITS_PER_dB;
1579 an_gain_mB[1] =
1580 (ucontrol->value.integer.value[1]) * HPI_UNITS_PER_dB;
1581 /* change = asihpi->mixer_level[addr][0] != left ||
1582 asihpi->mixer_level[addr][1] != right;
1584 change = 1;
1585 hpi_handle_error(hpi_level_set_gain(h_control, an_gain_mB));
1586 return change;
1589 static const DECLARE_TLV_DB_SCALE(db_scale_level, -1000, 100, 0);
1591 static int __devinit snd_asihpi_level_add(struct snd_card_asihpi *asihpi,
1592 struct hpi_control *hpi_ctl)
1594 struct snd_card *card = asihpi->card;
1595 struct snd_kcontrol_new snd_control;
1597 /* can't use 'volume' cos some nodes have volume as well */
1598 asihpi_ctl_init(&snd_control, hpi_ctl, "Level");
1599 snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
1600 SNDRV_CTL_ELEM_ACCESS_TLV_READ;
1601 snd_control.info = snd_asihpi_level_info;
1602 snd_control.get = snd_asihpi_level_get;
1603 snd_control.put = snd_asihpi_level_put;
1604 snd_control.tlv.p = db_scale_level;
1606 return ctl_add(card, &snd_control, asihpi);
1609 /*------------------------------------------------------------
1610 AESEBU controls
1611 ------------------------------------------------------------*/
1613 /* AESEBU format */
1614 static const char * const asihpi_aesebu_format_names[] = {
1615 "N/A", "S/PDIF", "AES/EBU" };
1617 static int snd_asihpi_aesebu_format_info(struct snd_kcontrol *kcontrol,
1618 struct snd_ctl_elem_info *uinfo)
1620 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1621 uinfo->count = 1;
1622 uinfo->value.enumerated.items = 3;
1624 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1625 uinfo->value.enumerated.item =
1626 uinfo->value.enumerated.items - 1;
1628 strcpy(uinfo->value.enumerated.name,
1629 asihpi_aesebu_format_names[uinfo->value.enumerated.item]);
1631 return 0;
1634 static int snd_asihpi_aesebu_format_get(struct snd_kcontrol *kcontrol,
1635 struct snd_ctl_elem_value *ucontrol,
1636 u16 (*func)(u32, u16 *))
1638 u32 h_control = kcontrol->private_value;
1639 u16 source, err;
1641 err = func(h_control, &source);
1643 /* default to N/A */
1644 ucontrol->value.enumerated.item[0] = 0;
1645 /* return success but set the control to N/A */
1646 if (err)
1647 return 0;
1648 if (source == HPI_AESEBU_FORMAT_SPDIF)
1649 ucontrol->value.enumerated.item[0] = 1;
1650 if (source == HPI_AESEBU_FORMAT_AESEBU)
1651 ucontrol->value.enumerated.item[0] = 2;
1653 return 0;
1656 static int snd_asihpi_aesebu_format_put(struct snd_kcontrol *kcontrol,
1657 struct snd_ctl_elem_value *ucontrol,
1658 u16 (*func)(u32, u16))
1660 u32 h_control = kcontrol->private_value;
1662 /* default to S/PDIF */
1663 u16 source = HPI_AESEBU_FORMAT_SPDIF;
1665 if (ucontrol->value.enumerated.item[0] == 1)
1666 source = HPI_AESEBU_FORMAT_SPDIF;
1667 if (ucontrol->value.enumerated.item[0] == 2)
1668 source = HPI_AESEBU_FORMAT_AESEBU;
1670 if (func(h_control, source) != 0)
1671 return -EINVAL;
1673 return 1;
1676 static int snd_asihpi_aesebu_rx_format_get(struct snd_kcontrol *kcontrol,
1677 struct snd_ctl_elem_value *ucontrol) {
1678 return snd_asihpi_aesebu_format_get(kcontrol, ucontrol,
1679 hpi_aesebu_receiver_get_format);
1682 static int snd_asihpi_aesebu_rx_format_put(struct snd_kcontrol *kcontrol,
1683 struct snd_ctl_elem_value *ucontrol) {
1684 return snd_asihpi_aesebu_format_put(kcontrol, ucontrol,
1685 hpi_aesebu_receiver_set_format);
1688 static int snd_asihpi_aesebu_rxstatus_info(struct snd_kcontrol *kcontrol,
1689 struct snd_ctl_elem_info *uinfo)
1691 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1692 uinfo->count = 1;
1694 uinfo->value.integer.min = 0;
1695 uinfo->value.integer.max = 0X1F;
1696 uinfo->value.integer.step = 1;
1698 return 0;
1701 static int snd_asihpi_aesebu_rxstatus_get(struct snd_kcontrol *kcontrol,
1702 struct snd_ctl_elem_value *ucontrol) {
1704 u32 h_control = kcontrol->private_value;
1705 u16 status;
1707 hpi_handle_error(hpi_aesebu_receiver_get_error_status(
1708 h_control, &status));
1709 ucontrol->value.integer.value[0] = status;
1710 return 0;
1713 static int __devinit snd_asihpi_aesebu_rx_add(struct snd_card_asihpi *asihpi,
1714 struct hpi_control *hpi_ctl)
1716 struct snd_card *card = asihpi->card;
1717 struct snd_kcontrol_new snd_control;
1719 asihpi_ctl_init(&snd_control, hpi_ctl, "Format");
1720 snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
1721 snd_control.info = snd_asihpi_aesebu_format_info;
1722 snd_control.get = snd_asihpi_aesebu_rx_format_get;
1723 snd_control.put = snd_asihpi_aesebu_rx_format_put;
1726 if (ctl_add(card, &snd_control, asihpi) < 0)
1727 return -EINVAL;
1729 asihpi_ctl_init(&snd_control, hpi_ctl, "Status");
1730 snd_control.access =
1731 SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ;
1732 snd_control.info = snd_asihpi_aesebu_rxstatus_info;
1733 snd_control.get = snd_asihpi_aesebu_rxstatus_get;
1735 return ctl_add(card, &snd_control, asihpi);
1738 static int snd_asihpi_aesebu_tx_format_get(struct snd_kcontrol *kcontrol,
1739 struct snd_ctl_elem_value *ucontrol) {
1740 return snd_asihpi_aesebu_format_get(kcontrol, ucontrol,
1741 hpi_aesebu_transmitter_get_format);
1744 static int snd_asihpi_aesebu_tx_format_put(struct snd_kcontrol *kcontrol,
1745 struct snd_ctl_elem_value *ucontrol) {
1746 return snd_asihpi_aesebu_format_put(kcontrol, ucontrol,
1747 hpi_aesebu_transmitter_set_format);
1751 static int __devinit snd_asihpi_aesebu_tx_add(struct snd_card_asihpi *asihpi,
1752 struct hpi_control *hpi_ctl)
1754 struct snd_card *card = asihpi->card;
1755 struct snd_kcontrol_new snd_control;
1757 asihpi_ctl_init(&snd_control, hpi_ctl, "Format");
1758 snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
1759 snd_control.info = snd_asihpi_aesebu_format_info;
1760 snd_control.get = snd_asihpi_aesebu_tx_format_get;
1761 snd_control.put = snd_asihpi_aesebu_tx_format_put;
1763 return ctl_add(card, &snd_control, asihpi);
1766 /*------------------------------------------------------------
1767 Tuner controls
1768 ------------------------------------------------------------*/
1770 /* Gain */
1772 static int snd_asihpi_tuner_gain_info(struct snd_kcontrol *kcontrol,
1773 struct snd_ctl_elem_info *uinfo)
1775 u32 h_control = kcontrol->private_value;
1776 u16 err;
1777 short idx;
1778 u16 gain_range[3];
1780 for (idx = 0; idx < 3; idx++) {
1781 err = hpi_tuner_query_gain(h_control,
1782 idx, &gain_range[idx]);
1783 if (err != 0)
1784 return err;
1787 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1788 uinfo->count = 1;
1789 uinfo->value.integer.min = ((int)gain_range[0]) / HPI_UNITS_PER_dB;
1790 uinfo->value.integer.max = ((int)gain_range[1]) / HPI_UNITS_PER_dB;
1791 uinfo->value.integer.step = ((int) gain_range[2]) / HPI_UNITS_PER_dB;
1792 return 0;
1795 static int snd_asihpi_tuner_gain_get(struct snd_kcontrol *kcontrol,
1796 struct snd_ctl_elem_value *ucontrol)
1799 struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol);
1801 u32 h_control = kcontrol->private_value;
1802 short gain;
1804 hpi_handle_error(hpi_tuner_get_gain(h_control, &gain));
1805 ucontrol->value.integer.value[0] = gain / HPI_UNITS_PER_dB;
1807 return 0;
1810 static int snd_asihpi_tuner_gain_put(struct snd_kcontrol *kcontrol,
1811 struct snd_ctl_elem_value *ucontrol)
1814 struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol);
1816 u32 h_control = kcontrol->private_value;
1817 short gain;
1819 gain = (ucontrol->value.integer.value[0]) * HPI_UNITS_PER_dB;
1820 hpi_handle_error(hpi_tuner_set_gain(h_control, gain));
1822 return 1;
1825 /* Band */
1827 static int asihpi_tuner_band_query(struct snd_kcontrol *kcontrol,
1828 u16 *band_list, u32 len) {
1829 u32 h_control = kcontrol->private_value;
1830 u16 err = 0;
1831 u32 i;
1833 for (i = 0; i < len; i++) {
1834 err = hpi_tuner_query_band(
1835 h_control, i, &band_list[i]);
1836 if (err != 0)
1837 break;
1840 if (err && (err != HPI_ERROR_INVALID_OBJ_INDEX))
1841 return -EIO;
1843 return i;
1846 static int snd_asihpi_tuner_band_info(struct snd_kcontrol *kcontrol,
1847 struct snd_ctl_elem_info *uinfo)
1849 u16 tuner_bands[HPI_TUNER_BAND_LAST];
1850 int num_bands = 0;
1852 num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands,
1853 HPI_TUNER_BAND_LAST);
1855 if (num_bands < 0)
1856 return num_bands;
1858 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1859 uinfo->count = 1;
1860 uinfo->value.enumerated.items = num_bands;
1862 if (num_bands > 0) {
1863 if (uinfo->value.enumerated.item >=
1864 uinfo->value.enumerated.items)
1865 uinfo->value.enumerated.item =
1866 uinfo->value.enumerated.items - 1;
1868 strcpy(uinfo->value.enumerated.name,
1869 asihpi_tuner_band_names[
1870 tuner_bands[uinfo->value.enumerated.item]]);
1873 return 0;
1876 static int snd_asihpi_tuner_band_get(struct snd_kcontrol *kcontrol,
1877 struct snd_ctl_elem_value *ucontrol)
1879 u32 h_control = kcontrol->private_value;
1881 struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol);
1883 u16 band, idx;
1884 u16 tuner_bands[HPI_TUNER_BAND_LAST];
1885 u32 num_bands = 0;
1887 num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands,
1888 HPI_TUNER_BAND_LAST);
1890 hpi_handle_error(hpi_tuner_get_band(h_control, &band));
1892 ucontrol->value.enumerated.item[0] = -1;
1893 for (idx = 0; idx < HPI_TUNER_BAND_LAST; idx++)
1894 if (tuner_bands[idx] == band) {
1895 ucontrol->value.enumerated.item[0] = idx;
1896 break;
1899 return 0;
1902 static int snd_asihpi_tuner_band_put(struct snd_kcontrol *kcontrol,
1903 struct snd_ctl_elem_value *ucontrol)
1906 struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol);
1908 u32 h_control = kcontrol->private_value;
1909 u16 band;
1910 u16 tuner_bands[HPI_TUNER_BAND_LAST];
1911 u32 num_bands = 0;
1913 num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands,
1914 HPI_TUNER_BAND_LAST);
1916 band = tuner_bands[ucontrol->value.enumerated.item[0]];
1917 hpi_handle_error(hpi_tuner_set_band(h_control, band));
1919 return 1;
1922 /* Freq */
1924 static int snd_asihpi_tuner_freq_info(struct snd_kcontrol *kcontrol,
1925 struct snd_ctl_elem_info *uinfo)
1927 u32 h_control = kcontrol->private_value;
1928 u16 err;
1929 u16 tuner_bands[HPI_TUNER_BAND_LAST];
1930 u16 num_bands = 0, band_iter, idx;
1931 u32 freq_range[3], temp_freq_range[3];
1933 num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands,
1934 HPI_TUNER_BAND_LAST);
1936 freq_range[0] = INT_MAX;
1937 freq_range[1] = 0;
1938 freq_range[2] = INT_MAX;
1940 for (band_iter = 0; band_iter < num_bands; band_iter++) {
1941 for (idx = 0; idx < 3; idx++) {
1942 err = hpi_tuner_query_frequency(h_control,
1943 idx, tuner_bands[band_iter],
1944 &temp_freq_range[idx]);
1945 if (err != 0)
1946 return err;
1949 /* skip band with bogus stepping */
1950 if (temp_freq_range[2] <= 0)
1951 continue;
1953 if (temp_freq_range[0] < freq_range[0])
1954 freq_range[0] = temp_freq_range[0];
1955 if (temp_freq_range[1] > freq_range[1])
1956 freq_range[1] = temp_freq_range[1];
1957 if (temp_freq_range[2] < freq_range[2])
1958 freq_range[2] = temp_freq_range[2];
1961 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1962 uinfo->count = 1;
1963 uinfo->value.integer.min = ((int)freq_range[0]);
1964 uinfo->value.integer.max = ((int)freq_range[1]);
1965 uinfo->value.integer.step = ((int)freq_range[2]);
1966 return 0;
1969 static int snd_asihpi_tuner_freq_get(struct snd_kcontrol *kcontrol,
1970 struct snd_ctl_elem_value *ucontrol)
1972 u32 h_control = kcontrol->private_value;
1973 u32 freq;
1975 hpi_handle_error(hpi_tuner_get_frequency(h_control, &freq));
1976 ucontrol->value.integer.value[0] = freq;
1978 return 0;
1981 static int snd_asihpi_tuner_freq_put(struct snd_kcontrol *kcontrol,
1982 struct snd_ctl_elem_value *ucontrol)
1984 u32 h_control = kcontrol->private_value;
1985 u32 freq;
1987 freq = ucontrol->value.integer.value[0];
1988 hpi_handle_error(hpi_tuner_set_frequency(h_control, freq));
1990 return 1;
1993 /* Tuner control group initializer */
1994 static int __devinit snd_asihpi_tuner_add(struct snd_card_asihpi *asihpi,
1995 struct hpi_control *hpi_ctl)
1997 struct snd_card *card = asihpi->card;
1998 struct snd_kcontrol_new snd_control;
2000 snd_control.private_value = hpi_ctl->h_control;
2001 snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
2003 if (!hpi_tuner_get_gain(hpi_ctl->h_control, NULL)) {
2004 asihpi_ctl_init(&snd_control, hpi_ctl, "Gain");
2005 snd_control.info = snd_asihpi_tuner_gain_info;
2006 snd_control.get = snd_asihpi_tuner_gain_get;
2007 snd_control.put = snd_asihpi_tuner_gain_put;
2009 if (ctl_add(card, &snd_control, asihpi) < 0)
2010 return -EINVAL;
2013 asihpi_ctl_init(&snd_control, hpi_ctl, "Band");
2014 snd_control.info = snd_asihpi_tuner_band_info;
2015 snd_control.get = snd_asihpi_tuner_band_get;
2016 snd_control.put = snd_asihpi_tuner_band_put;
2018 if (ctl_add(card, &snd_control, asihpi) < 0)
2019 return -EINVAL;
2021 asihpi_ctl_init(&snd_control, hpi_ctl, "Freq");
2022 snd_control.info = snd_asihpi_tuner_freq_info;
2023 snd_control.get = snd_asihpi_tuner_freq_get;
2024 snd_control.put = snd_asihpi_tuner_freq_put;
2026 return ctl_add(card, &snd_control, asihpi);
2029 /*------------------------------------------------------------
2030 Meter controls
2031 ------------------------------------------------------------*/
2032 static int snd_asihpi_meter_info(struct snd_kcontrol *kcontrol,
2033 struct snd_ctl_elem_info *uinfo)
2035 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2036 uinfo->count = HPI_MAX_CHANNELS;
2037 uinfo->value.integer.min = 0;
2038 uinfo->value.integer.max = 0x7FFFFFFF;
2039 return 0;
2042 /* linear values for 10dB steps */
2043 static int log2lin[] = {
2044 0x7FFFFFFF, /* 0dB */
2045 679093956,
2046 214748365,
2047 67909396,
2048 21474837,
2049 6790940,
2050 2147484, /* -60dB */
2051 679094,
2052 214748, /* -80 */
2053 67909,
2054 21475, /* -100 */
2055 6791,
2056 2147,
2057 679,
2058 214,
2065 static int snd_asihpi_meter_get(struct snd_kcontrol *kcontrol,
2066 struct snd_ctl_elem_value *ucontrol)
2068 u32 h_control = kcontrol->private_value;
2069 short an_gain_mB[HPI_MAX_CHANNELS], i;
2070 u16 err;
2072 err = hpi_meter_get_peak(h_control, an_gain_mB);
2074 for (i = 0; i < HPI_MAX_CHANNELS; i++) {
2075 if (err) {
2076 ucontrol->value.integer.value[i] = 0;
2077 } else if (an_gain_mB[i] >= 0) {
2078 ucontrol->value.integer.value[i] =
2079 an_gain_mB[i] << 16;
2080 } else {
2081 /* -ve is log value in millibels < -60dB,
2082 * convert to (roughly!) linear,
2084 ucontrol->value.integer.value[i] =
2085 log2lin[an_gain_mB[i] / -1000];
2088 return 0;
2091 static int __devinit snd_asihpi_meter_add(struct snd_card_asihpi *asihpi,
2092 struct hpi_control *hpi_ctl, int subidx)
2094 struct snd_card *card = asihpi->card;
2095 struct snd_kcontrol_new snd_control;
2097 asihpi_ctl_init(&snd_control, hpi_ctl, "Meter");
2098 snd_control.access =
2099 SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ;
2100 snd_control.info = snd_asihpi_meter_info;
2101 snd_control.get = snd_asihpi_meter_get;
2103 snd_control.index = subidx;
2105 return ctl_add(card, &snd_control, asihpi);
2108 /*------------------------------------------------------------
2109 Multiplexer controls
2110 ------------------------------------------------------------*/
2111 static int snd_card_asihpi_mux_count_sources(struct snd_kcontrol *snd_control)
2113 u32 h_control = snd_control->private_value;
2114 struct hpi_control hpi_ctl;
2115 int s, err;
2116 for (s = 0; s < 32; s++) {
2117 err = hpi_multiplexer_query_source(h_control, s,
2118 &hpi_ctl.
2119 src_node_type,
2120 &hpi_ctl.
2121 src_node_index);
2122 if (err)
2123 break;
2125 return s;
2128 static int snd_asihpi_mux_info(struct snd_kcontrol *kcontrol,
2129 struct snd_ctl_elem_info *uinfo)
2131 int err;
2132 u16 src_node_type, src_node_index;
2133 u32 h_control = kcontrol->private_value;
2135 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2136 uinfo->count = 1;
2137 uinfo->value.enumerated.items =
2138 snd_card_asihpi_mux_count_sources(kcontrol);
2140 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2141 uinfo->value.enumerated.item =
2142 uinfo->value.enumerated.items - 1;
2144 err =
2145 hpi_multiplexer_query_source(h_control,
2146 uinfo->value.enumerated.item,
2147 &src_node_type, &src_node_index);
2149 sprintf(uinfo->value.enumerated.name, "%s %d",
2150 asihpi_src_names[src_node_type - HPI_SOURCENODE_NONE],
2151 src_node_index);
2152 return 0;
2155 static int snd_asihpi_mux_get(struct snd_kcontrol *kcontrol,
2156 struct snd_ctl_elem_value *ucontrol)
2158 u32 h_control = kcontrol->private_value;
2159 u16 source_type, source_index;
2160 u16 src_node_type, src_node_index;
2161 int s;
2163 hpi_handle_error(hpi_multiplexer_get_source(h_control,
2164 &source_type, &source_index));
2165 /* Should cache this search result! */
2166 for (s = 0; s < 256; s++) {
2167 if (hpi_multiplexer_query_source(h_control, s,
2168 &src_node_type, &src_node_index))
2169 break;
2171 if ((source_type == src_node_type)
2172 && (source_index == src_node_index)) {
2173 ucontrol->value.enumerated.item[0] = s;
2174 return 0;
2177 snd_printd(KERN_WARNING
2178 "Control %x failed to match mux source %hu %hu\n",
2179 h_control, source_type, source_index);
2180 ucontrol->value.enumerated.item[0] = 0;
2181 return 0;
2184 static int snd_asihpi_mux_put(struct snd_kcontrol *kcontrol,
2185 struct snd_ctl_elem_value *ucontrol)
2187 int change;
2188 u32 h_control = kcontrol->private_value;
2189 u16 source_type, source_index;
2190 u16 e;
2192 change = 1;
2194 e = hpi_multiplexer_query_source(h_control,
2195 ucontrol->value.enumerated.item[0],
2196 &source_type, &source_index);
2197 if (!e)
2198 hpi_handle_error(
2199 hpi_multiplexer_set_source(h_control,
2200 source_type, source_index));
2201 return change;
2205 static int __devinit snd_asihpi_mux_add(struct snd_card_asihpi *asihpi,
2206 struct hpi_control *hpi_ctl)
2208 struct snd_card *card = asihpi->card;
2209 struct snd_kcontrol_new snd_control;
2211 asihpi_ctl_init(&snd_control, hpi_ctl, "Route");
2212 snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
2213 snd_control.info = snd_asihpi_mux_info;
2214 snd_control.get = snd_asihpi_mux_get;
2215 snd_control.put = snd_asihpi_mux_put;
2217 return ctl_add(card, &snd_control, asihpi);
2221 /*------------------------------------------------------------
2222 Channel mode controls
2223 ------------------------------------------------------------*/
2224 static int snd_asihpi_cmode_info(struct snd_kcontrol *kcontrol,
2225 struct snd_ctl_elem_info *uinfo)
2227 static const char * const mode_names[HPI_CHANNEL_MODE_LAST + 1] = {
2228 "invalid",
2229 "Normal", "Swap",
2230 "From Left", "From Right",
2231 "To Left", "To Right"
2234 u32 h_control = kcontrol->private_value;
2235 u16 mode;
2236 int i;
2237 u16 mode_map[6];
2238 int valid_modes = 0;
2240 /* HPI channel mode values can be from 1 to 6
2241 Some adapters only support a contiguous subset
2243 for (i = 0; i < HPI_CHANNEL_MODE_LAST; i++)
2244 if (!hpi_channel_mode_query_mode(
2245 h_control, i, &mode)) {
2246 mode_map[valid_modes] = mode;
2247 valid_modes++;
2250 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2251 uinfo->count = 1;
2252 uinfo->value.enumerated.items = valid_modes;
2254 if (uinfo->value.enumerated.item >= valid_modes)
2255 uinfo->value.enumerated.item = valid_modes - 1;
2257 strcpy(uinfo->value.enumerated.name,
2258 mode_names[mode_map[uinfo->value.enumerated.item]]);
2260 return 0;
2263 static int snd_asihpi_cmode_get(struct snd_kcontrol *kcontrol,
2264 struct snd_ctl_elem_value *ucontrol)
2266 u32 h_control = kcontrol->private_value;
2267 u16 mode;
2269 if (hpi_channel_mode_get(h_control, &mode))
2270 mode = 1;
2272 ucontrol->value.enumerated.item[0] = mode - 1;
2274 return 0;
2277 static int snd_asihpi_cmode_put(struct snd_kcontrol *kcontrol,
2278 struct snd_ctl_elem_value *ucontrol)
2280 int change;
2281 u32 h_control = kcontrol->private_value;
2283 change = 1;
2285 hpi_handle_error(hpi_channel_mode_set(h_control,
2286 ucontrol->value.enumerated.item[0] + 1));
2287 return change;
2291 static int __devinit snd_asihpi_cmode_add(struct snd_card_asihpi *asihpi,
2292 struct hpi_control *hpi_ctl)
2294 struct snd_card *card = asihpi->card;
2295 struct snd_kcontrol_new snd_control;
2297 asihpi_ctl_init(&snd_control, hpi_ctl, "Mode");
2298 snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
2299 snd_control.info = snd_asihpi_cmode_info;
2300 snd_control.get = snd_asihpi_cmode_get;
2301 snd_control.put = snd_asihpi_cmode_put;
2303 return ctl_add(card, &snd_control, asihpi);
2306 /*------------------------------------------------------------
2307 Sampleclock source controls
2308 ------------------------------------------------------------*/
2309 static char *sampleclock_sources[MAX_CLOCKSOURCES] = {
2310 "N/A", "Local PLL", "Digital Sync", "Word External", "Word Header",
2311 "SMPTE", "Digital1", "Auto", "Network", "Invalid",
2312 "Prev Module",
2313 "Digital2", "Digital3", "Digital4", "Digital5",
2314 "Digital6", "Digital7", "Digital8"};
2316 static int snd_asihpi_clksrc_info(struct snd_kcontrol *kcontrol,
2317 struct snd_ctl_elem_info *uinfo)
2319 struct snd_card_asihpi *asihpi =
2320 (struct snd_card_asihpi *)(kcontrol->private_data);
2321 struct clk_cache *clkcache = &asihpi->cc;
2322 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2323 uinfo->count = 1;
2324 uinfo->value.enumerated.items = clkcache->count;
2326 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2327 uinfo->value.enumerated.item =
2328 uinfo->value.enumerated.items - 1;
2330 strcpy(uinfo->value.enumerated.name,
2331 clkcache->s[uinfo->value.enumerated.item].name);
2332 return 0;
2335 static int snd_asihpi_clksrc_get(struct snd_kcontrol *kcontrol,
2336 struct snd_ctl_elem_value *ucontrol)
2338 struct snd_card_asihpi *asihpi =
2339 (struct snd_card_asihpi *)(kcontrol->private_data);
2340 struct clk_cache *clkcache = &asihpi->cc;
2341 u32 h_control = kcontrol->private_value;
2342 u16 source, srcindex = 0;
2343 int i;
2345 ucontrol->value.enumerated.item[0] = 0;
2346 if (hpi_sample_clock_get_source(h_control, &source))
2347 source = 0;
2349 if (source == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT)
2350 if (hpi_sample_clock_get_source_index(h_control, &srcindex))
2351 srcindex = 0;
2353 for (i = 0; i < clkcache->count; i++)
2354 if ((clkcache->s[i].source == source) &&
2355 (clkcache->s[i].index == srcindex))
2356 break;
2358 ucontrol->value.enumerated.item[0] = i;
2360 return 0;
2363 static int snd_asihpi_clksrc_put(struct snd_kcontrol *kcontrol,
2364 struct snd_ctl_elem_value *ucontrol)
2366 struct snd_card_asihpi *asihpi =
2367 (struct snd_card_asihpi *)(kcontrol->private_data);
2368 struct clk_cache *clkcache = &asihpi->cc;
2369 int change, item;
2370 u32 h_control = kcontrol->private_value;
2372 change = 1;
2373 item = ucontrol->value.enumerated.item[0];
2374 if (item >= clkcache->count)
2375 item = clkcache->count-1;
2377 hpi_handle_error(hpi_sample_clock_set_source(
2378 h_control, clkcache->s[item].source));
2380 if (clkcache->s[item].source == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT)
2381 hpi_handle_error(hpi_sample_clock_set_source_index(
2382 h_control, clkcache->s[item].index));
2383 return change;
2386 /*------------------------------------------------------------
2387 Clkrate controls
2388 ------------------------------------------------------------*/
2389 /* Need to change this to enumerated control with list of rates */
2390 static int snd_asihpi_clklocal_info(struct snd_kcontrol *kcontrol,
2391 struct snd_ctl_elem_info *uinfo)
2393 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2394 uinfo->count = 1;
2395 uinfo->value.integer.min = 8000;
2396 uinfo->value.integer.max = 192000;
2397 uinfo->value.integer.step = 100;
2399 return 0;
2402 static int snd_asihpi_clklocal_get(struct snd_kcontrol *kcontrol,
2403 struct snd_ctl_elem_value *ucontrol)
2405 u32 h_control = kcontrol->private_value;
2406 u32 rate;
2407 u16 e;
2409 e = hpi_sample_clock_get_local_rate(h_control, &rate);
2410 if (!e)
2411 ucontrol->value.integer.value[0] = rate;
2412 else
2413 ucontrol->value.integer.value[0] = 0;
2414 return 0;
2417 static int snd_asihpi_clklocal_put(struct snd_kcontrol *kcontrol,
2418 struct snd_ctl_elem_value *ucontrol)
2420 int change;
2421 u32 h_control = kcontrol->private_value;
2423 /* change = asihpi->mixer_clkrate[addr][0] != left ||
2424 asihpi->mixer_clkrate[addr][1] != right;
2426 change = 1;
2427 hpi_handle_error(hpi_sample_clock_set_local_rate(h_control,
2428 ucontrol->value.integer.value[0]));
2429 return change;
2432 static int snd_asihpi_clkrate_info(struct snd_kcontrol *kcontrol,
2433 struct snd_ctl_elem_info *uinfo)
2435 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2436 uinfo->count = 1;
2437 uinfo->value.integer.min = 8000;
2438 uinfo->value.integer.max = 192000;
2439 uinfo->value.integer.step = 100;
2441 return 0;
2444 static int snd_asihpi_clkrate_get(struct snd_kcontrol *kcontrol,
2445 struct snd_ctl_elem_value *ucontrol)
2447 u32 h_control = kcontrol->private_value;
2448 u32 rate;
2449 u16 e;
2451 e = hpi_sample_clock_get_sample_rate(h_control, &rate);
2452 if (!e)
2453 ucontrol->value.integer.value[0] = rate;
2454 else
2455 ucontrol->value.integer.value[0] = 0;
2456 return 0;
2459 static int __devinit snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi,
2460 struct hpi_control *hpi_ctl)
2462 struct snd_card *card = asihpi->card;
2463 struct snd_kcontrol_new snd_control;
2465 struct clk_cache *clkcache = &asihpi->cc;
2466 u32 hSC = hpi_ctl->h_control;
2467 int has_aes_in = 0;
2468 int i, j;
2469 u16 source;
2471 snd_control.private_value = hpi_ctl->h_control;
2473 clkcache->has_local = 0;
2475 for (i = 0; i <= HPI_SAMPLECLOCK_SOURCE_LAST; i++) {
2476 if (hpi_sample_clock_query_source(hSC,
2477 i, &source))
2478 break;
2479 clkcache->s[i].source = source;
2480 clkcache->s[i].index = 0;
2481 clkcache->s[i].name = sampleclock_sources[source];
2482 if (source == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT)
2483 has_aes_in = 1;
2484 if (source == HPI_SAMPLECLOCK_SOURCE_LOCAL)
2485 clkcache->has_local = 1;
2487 if (has_aes_in)
2488 /* already will have picked up index 0 above */
2489 for (j = 1; j < 8; j++) {
2490 if (hpi_sample_clock_query_source_index(hSC,
2491 j, HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT,
2492 &source))
2493 break;
2494 clkcache->s[i].source =
2495 HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT;
2496 clkcache->s[i].index = j;
2497 clkcache->s[i].name = sampleclock_sources[
2498 j+HPI_SAMPLECLOCK_SOURCE_LAST];
2499 i++;
2501 clkcache->count = i;
2503 asihpi_ctl_init(&snd_control, hpi_ctl, "Source");
2504 snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE ;
2505 snd_control.info = snd_asihpi_clksrc_info;
2506 snd_control.get = snd_asihpi_clksrc_get;
2507 snd_control.put = snd_asihpi_clksrc_put;
2508 if (ctl_add(card, &snd_control, asihpi) < 0)
2509 return -EINVAL;
2512 if (clkcache->has_local) {
2513 asihpi_ctl_init(&snd_control, hpi_ctl, "Localrate");
2514 snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE ;
2515 snd_control.info = snd_asihpi_clklocal_info;
2516 snd_control.get = snd_asihpi_clklocal_get;
2517 snd_control.put = snd_asihpi_clklocal_put;
2520 if (ctl_add(card, &snd_control, asihpi) < 0)
2521 return -EINVAL;
2524 asihpi_ctl_init(&snd_control, hpi_ctl, "Rate");
2525 snd_control.access =
2526 SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ;
2527 snd_control.info = snd_asihpi_clkrate_info;
2528 snd_control.get = snd_asihpi_clkrate_get;
2530 return ctl_add(card, &snd_control, asihpi);
2532 /*------------------------------------------------------------
2533 Mixer
2534 ------------------------------------------------------------*/
2536 static int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi)
2538 struct snd_card *card = asihpi->card;
2539 unsigned int idx = 0;
2540 unsigned int subindex = 0;
2541 int err;
2542 struct hpi_control hpi_ctl, prev_ctl;
2544 if (snd_BUG_ON(!asihpi))
2545 return -EINVAL;
2546 strcpy(card->mixername, "Asihpi Mixer");
2548 err =
2549 hpi_mixer_open(asihpi->adapter_index,
2550 &asihpi->h_mixer);
2551 hpi_handle_error(err);
2552 if (err)
2553 return -err;
2555 memset(&prev_ctl, 0, sizeof(prev_ctl));
2556 prev_ctl.control_type = -1;
2558 for (idx = 0; idx < 2000; idx++) {
2559 err = hpi_mixer_get_control_by_index(
2560 asihpi->h_mixer,
2561 idx,
2562 &hpi_ctl.src_node_type,
2563 &hpi_ctl.src_node_index,
2564 &hpi_ctl.dst_node_type,
2565 &hpi_ctl.dst_node_index,
2566 &hpi_ctl.control_type,
2567 &hpi_ctl.h_control);
2568 if (err) {
2569 if (err == HPI_ERROR_CONTROL_DISABLED) {
2570 if (mixer_dump)
2571 snd_printk(KERN_INFO
2572 "Disabled HPI Control(%d)\n",
2573 idx);
2574 continue;
2575 } else
2576 break;
2580 hpi_ctl.src_node_type -= HPI_SOURCENODE_NONE;
2581 hpi_ctl.dst_node_type -= HPI_DESTNODE_NONE;
2583 /* ASI50xx in SSX mode has multiple meters on the same node.
2584 Use subindex to create distinct ALSA controls
2585 for any duplicated controls.
2587 if ((hpi_ctl.control_type == prev_ctl.control_type) &&
2588 (hpi_ctl.src_node_type == prev_ctl.src_node_type) &&
2589 (hpi_ctl.src_node_index == prev_ctl.src_node_index) &&
2590 (hpi_ctl.dst_node_type == prev_ctl.dst_node_type) &&
2591 (hpi_ctl.dst_node_index == prev_ctl.dst_node_index))
2592 subindex++;
2593 else
2594 subindex = 0;
2596 prev_ctl = hpi_ctl;
2598 switch (hpi_ctl.control_type) {
2599 case HPI_CONTROL_VOLUME:
2600 err = snd_asihpi_volume_add(asihpi, &hpi_ctl);
2601 break;
2602 case HPI_CONTROL_LEVEL:
2603 err = snd_asihpi_level_add(asihpi, &hpi_ctl);
2604 break;
2605 case HPI_CONTROL_MULTIPLEXER:
2606 err = snd_asihpi_mux_add(asihpi, &hpi_ctl);
2607 break;
2608 case HPI_CONTROL_CHANNEL_MODE:
2609 err = snd_asihpi_cmode_add(asihpi, &hpi_ctl);
2610 break;
2611 case HPI_CONTROL_METER:
2612 err = snd_asihpi_meter_add(asihpi, &hpi_ctl, subindex);
2613 break;
2614 case HPI_CONTROL_SAMPLECLOCK:
2615 err = snd_asihpi_sampleclock_add(
2616 asihpi, &hpi_ctl);
2617 break;
2618 case HPI_CONTROL_CONNECTION: /* ignore these */
2619 continue;
2620 case HPI_CONTROL_TUNER:
2621 err = snd_asihpi_tuner_add(asihpi, &hpi_ctl);
2622 break;
2623 case HPI_CONTROL_AESEBU_TRANSMITTER:
2624 err = snd_asihpi_aesebu_tx_add(asihpi, &hpi_ctl);
2625 break;
2626 case HPI_CONTROL_AESEBU_RECEIVER:
2627 err = snd_asihpi_aesebu_rx_add(asihpi, &hpi_ctl);
2628 break;
2629 case HPI_CONTROL_VOX:
2630 case HPI_CONTROL_BITSTREAM:
2631 case HPI_CONTROL_MICROPHONE:
2632 case HPI_CONTROL_PARAMETRIC_EQ:
2633 case HPI_CONTROL_COMPANDER:
2634 default:
2635 if (mixer_dump)
2636 snd_printk(KERN_INFO
2637 "Untranslated HPI Control"
2638 "(%d) %d %d %d %d %d\n",
2639 idx,
2640 hpi_ctl.control_type,
2641 hpi_ctl.src_node_type,
2642 hpi_ctl.src_node_index,
2643 hpi_ctl.dst_node_type,
2644 hpi_ctl.dst_node_index);
2645 continue;
2647 if (err < 0)
2648 return err;
2650 if (HPI_ERROR_INVALID_OBJ_INDEX != err)
2651 hpi_handle_error(err);
2653 snd_printk(KERN_INFO "%d mixer controls found\n", idx);
2655 return 0;
2658 /*------------------------------------------------------------
2659 /proc interface
2660 ------------------------------------------------------------*/
2662 static void
2663 snd_asihpi_proc_read(struct snd_info_entry *entry,
2664 struct snd_info_buffer *buffer)
2666 struct snd_card_asihpi *asihpi = entry->private_data;
2667 u16 version;
2668 u32 h_control;
2669 u32 rate = 0;
2670 u16 source = 0;
2671 int err;
2673 snd_iprintf(buffer, "ASIHPI driver proc file\n");
2674 snd_iprintf(buffer,
2675 "adapter ID=%4X\n_index=%d\n"
2676 "num_outstreams=%d\n_num_instreams=%d\n",
2677 asihpi->type, asihpi->adapter_index,
2678 asihpi->num_outstreams, asihpi->num_instreams);
2680 version = asihpi->version;
2681 snd_iprintf(buffer,
2682 "serial#=%d\n_hw version %c%d\nDSP code version %03d\n",
2683 asihpi->serial_number, ((version >> 3) & 0xf) + 'A',
2684 version & 0x7,
2685 ((version >> 13) * 100) + ((version >> 7) & 0x3f));
2687 err = hpi_mixer_get_control(asihpi->h_mixer,
2688 HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0,
2689 HPI_CONTROL_SAMPLECLOCK, &h_control);
2691 if (!err) {
2692 err = hpi_sample_clock_get_sample_rate(
2693 h_control, &rate);
2694 err += hpi_sample_clock_get_source(h_control, &source);
2696 if (!err)
2697 snd_iprintf(buffer, "sample_clock=%d_hz, source %s\n",
2698 rate, sampleclock_sources[source]);
2704 static void __devinit snd_asihpi_proc_init(struct snd_card_asihpi *asihpi)
2706 struct snd_info_entry *entry;
2708 if (!snd_card_proc_new(asihpi->card, "info", &entry))
2709 snd_info_set_text_ops(entry, asihpi, snd_asihpi_proc_read);
2712 /*------------------------------------------------------------
2713 HWDEP
2714 ------------------------------------------------------------*/
2716 static int snd_asihpi_hpi_open(struct snd_hwdep *hw, struct file *file)
2718 if (enable_hpi_hwdep)
2719 return 0;
2720 else
2721 return -ENODEV;
2725 static int snd_asihpi_hpi_release(struct snd_hwdep *hw, struct file *file)
2727 if (enable_hpi_hwdep)
2728 return asihpi_hpi_release(file);
2729 else
2730 return -ENODEV;
2733 static int snd_asihpi_hpi_ioctl(struct snd_hwdep *hw, struct file *file,
2734 unsigned int cmd, unsigned long arg)
2736 if (enable_hpi_hwdep)
2737 return asihpi_hpi_ioctl(file, cmd, arg);
2738 else
2739 return -ENODEV;
2743 /* results in /dev/snd/hwC#D0 file for each card with index #
2744 also /proc/asound/hwdep will contain '#-00: asihpi (HPI) for each card'
2746 static int __devinit snd_asihpi_hpi_new(struct snd_card_asihpi *asihpi,
2747 int device, struct snd_hwdep **rhwdep)
2749 struct snd_hwdep *hw;
2750 int err;
2752 if (rhwdep)
2753 *rhwdep = NULL;
2754 err = snd_hwdep_new(asihpi->card, "HPI", device, &hw);
2755 if (err < 0)
2756 return err;
2757 strcpy(hw->name, "asihpi (HPI)");
2758 hw->iface = SNDRV_HWDEP_IFACE_LAST;
2759 hw->ops.open = snd_asihpi_hpi_open;
2760 hw->ops.ioctl = snd_asihpi_hpi_ioctl;
2761 hw->ops.release = snd_asihpi_hpi_release;
2762 hw->private_data = asihpi;
2763 if (rhwdep)
2764 *rhwdep = hw;
2765 return 0;
2768 /*------------------------------------------------------------
2769 CARD
2770 ------------------------------------------------------------*/
2771 static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev,
2772 const struct pci_device_id *pci_id)
2774 int err;
2776 u16 version;
2777 int pcm_substreams;
2779 struct hpi_adapter *hpi_card;
2780 struct snd_card *card;
2781 struct snd_card_asihpi *asihpi;
2783 u32 h_control;
2784 u32 h_stream;
2786 static int dev;
2787 if (dev >= SNDRV_CARDS)
2788 return -ENODEV;
2790 /* Should this be enable[hpi_card->index] ? */
2791 if (!enable[dev]) {
2792 dev++;
2793 return -ENOENT;
2796 err = asihpi_adapter_probe(pci_dev, pci_id);
2797 if (err < 0)
2798 return err;
2800 hpi_card = pci_get_drvdata(pci_dev);
2801 /* first try to give the card the same index as its hardware index */
2802 err = snd_card_create(hpi_card->index,
2803 id[hpi_card->index], THIS_MODULE,
2804 sizeof(struct snd_card_asihpi),
2805 &card);
2806 if (err < 0) {
2807 /* if that fails, try the default index==next available */
2808 err =
2809 snd_card_create(index[dev], id[dev],
2810 THIS_MODULE,
2811 sizeof(struct snd_card_asihpi),
2812 &card);
2813 if (err < 0)
2814 return err;
2815 snd_printk(KERN_WARNING
2816 "**** WARNING **** Adapter index %d->ALSA index %d\n",
2817 hpi_card->index, card->number);
2820 snd_card_set_dev(card, &pci_dev->dev);
2822 asihpi = (struct snd_card_asihpi *) card->private_data;
2823 asihpi->card = card;
2824 asihpi->pci = pci_dev;
2825 asihpi->adapter_index = hpi_card->index;
2826 hpi_handle_error(hpi_adapter_get_info(
2827 asihpi->adapter_index,
2828 &asihpi->num_outstreams,
2829 &asihpi->num_instreams,
2830 &asihpi->version,
2831 &asihpi->serial_number, &asihpi->type));
2833 version = asihpi->version;
2834 snd_printk(KERN_INFO "adapter ID=%4X index=%d num_outstreams=%d "
2835 "num_instreams=%d S/N=%d\n"
2836 "Hw Version %c%d DSP code version %03d\n",
2837 asihpi->type, asihpi->adapter_index,
2838 asihpi->num_outstreams,
2839 asihpi->num_instreams, asihpi->serial_number,
2840 ((version >> 3) & 0xf) + 'A',
2841 version & 0x7,
2842 ((version >> 13) * 100) + ((version >> 7) & 0x3f));
2844 pcm_substreams = asihpi->num_outstreams;
2845 if (pcm_substreams < asihpi->num_instreams)
2846 pcm_substreams = asihpi->num_instreams;
2848 err = hpi_adapter_get_property(asihpi->adapter_index,
2849 HPI_ADAPTER_PROPERTY_CAPS1,
2850 NULL, &asihpi->support_grouping);
2851 if (err)
2852 asihpi->support_grouping = 0;
2854 err = hpi_adapter_get_property(asihpi->adapter_index,
2855 HPI_ADAPTER_PROPERTY_CAPS2,
2856 &asihpi->support_mrx, NULL);
2857 if (err)
2858 asihpi->support_mrx = 0;
2860 err = hpi_adapter_get_property(asihpi->adapter_index,
2861 HPI_ADAPTER_PROPERTY_INTERVAL,
2862 NULL, &asihpi->update_interval_frames);
2863 if (err)
2864 asihpi->update_interval_frames = 512;
2866 if (!asihpi->can_dma)
2867 asihpi->update_interval_frames *= 2;
2869 hpi_handle_error(hpi_instream_open(asihpi->adapter_index,
2870 0, &h_stream));
2872 err = hpi_instream_host_buffer_free(h_stream);
2873 asihpi->can_dma = (!err);
2875 hpi_handle_error(hpi_instream_close(h_stream));
2877 err = hpi_adapter_get_property(asihpi->adapter_index,
2878 HPI_ADAPTER_PROPERTY_CURCHANNELS,
2879 &asihpi->in_max_chans, &asihpi->out_max_chans);
2880 if (err) {
2881 asihpi->in_max_chans = 2;
2882 asihpi->out_max_chans = 2;
2885 snd_printk(KERN_INFO "has dma:%d, grouping:%d, mrx:%d\n",
2886 asihpi->can_dma,
2887 asihpi->support_grouping,
2888 asihpi->support_mrx
2891 err = snd_card_asihpi_pcm_new(asihpi, 0, pcm_substreams);
2892 if (err < 0) {
2893 snd_printk(KERN_ERR "pcm_new failed\n");
2894 goto __nodev;
2896 err = snd_card_asihpi_mixer_new(asihpi);
2897 if (err < 0) {
2898 snd_printk(KERN_ERR "mixer_new failed\n");
2899 goto __nodev;
2902 err = hpi_mixer_get_control(asihpi->h_mixer,
2903 HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0,
2904 HPI_CONTROL_SAMPLECLOCK, &h_control);
2906 if (!err)
2907 err = hpi_sample_clock_set_local_rate(
2908 h_control, adapter_fs);
2910 snd_asihpi_proc_init(asihpi);
2912 /* always create, can be enabled or disabled dynamically
2913 by enable_hwdep module param*/
2914 snd_asihpi_hpi_new(asihpi, 0, NULL);
2916 strcpy(card->driver, "ASIHPI");
2918 sprintf(card->shortname, "AudioScience ASI%4X", asihpi->type);
2919 sprintf(card->longname, "%s %i",
2920 card->shortname, asihpi->adapter_index);
2921 err = snd_card_register(card);
2923 if (!err) {
2924 hpi_card->snd_card_asihpi = card;
2925 dev++;
2926 return 0;
2928 __nodev:
2929 snd_card_free(card);
2930 snd_printk(KERN_ERR "snd_asihpi_probe error %d\n", err);
2931 return err;
2935 static void __devexit snd_asihpi_remove(struct pci_dev *pci_dev)
2937 struct hpi_adapter *hpi_card = pci_get_drvdata(pci_dev);
2939 snd_card_free(hpi_card->snd_card_asihpi);
2940 hpi_card->snd_card_asihpi = NULL;
2941 asihpi_adapter_remove(pci_dev);
2944 static DEFINE_PCI_DEVICE_TABLE(asihpi_pci_tbl) = {
2945 {HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_DSP6205,
2946 HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID, 0, 0,
2947 (kernel_ulong_t)HPI_6205},
2948 {HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_PCI2040,
2949 HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID, 0, 0,
2950 (kernel_ulong_t)HPI_6000},
2951 {0,}
2953 MODULE_DEVICE_TABLE(pci, asihpi_pci_tbl);
2955 static struct pci_driver driver = {
2956 .name = KBUILD_MODNAME,
2957 .id_table = asihpi_pci_tbl,
2958 .probe = snd_asihpi_probe,
2959 .remove = __devexit_p(snd_asihpi_remove),
2960 #ifdef CONFIG_PM
2961 /* .suspend = snd_asihpi_suspend,
2962 .resume = snd_asihpi_resume, */
2963 #endif
2966 static int __init snd_asihpi_init(void)
2968 asihpi_init();
2969 return pci_register_driver(&driver);
2972 static void __exit snd_asihpi_exit(void)
2975 pci_unregister_driver(&driver);
2976 asihpi_exit();
2979 module_init(snd_asihpi_init)
2980 module_exit(snd_asihpi_exit)