1dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/*
2dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini *  ALSA driver for Echoaudio soundcards.
3dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini *  Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it>
4dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini *
5dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini *  This program is free software; you can redistribute it and/or modify
6dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini *  it under the terms of the GNU General Public License as published by
7dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini *  the Free Software Foundation; version 2 of the License.
8dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini *
9dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini *  This program is distributed in the hope that it will be useful,
10dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini *  GNU General Public License for more details.
13dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini *
14dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini *  You should have received a copy of the GNU General Public License
15dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini *  along with this program; if not, write to the Free Software
16dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini */
18dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
19dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano PochiniMODULE_AUTHOR("Giuliano Pochini <pochini@shiny.it>");
20dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano PochiniMODULE_LICENSE("GPL v2");
21dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano PochiniMODULE_DESCRIPTION("Echoaudio " ECHOCARD_NAME " soundcards driver");
22dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano PochiniMODULE_SUPPORTED_DEVICE("{{Echoaudio," ECHOCARD_NAME "}}");
23dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano PochiniMODULE_DEVICE_TABLE(pci, snd_echo_ids);
24dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
25dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
26dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
27dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
28dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
29dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinimodule_param_array(index, int, NULL, 0444);
30dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano PochiniMODULE_PARM_DESC(index, "Index value for " ECHOCARD_NAME " soundcard.");
31dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinimodule_param_array(id, charp, NULL, 0444);
32dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano PochiniMODULE_PARM_DESC(id, "ID string for " ECHOCARD_NAME " soundcard.");
33dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinimodule_param_array(enable, bool, NULL, 0444);
34dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano PochiniMODULE_PARM_DESC(enable, "Enable " ECHOCARD_NAME " soundcard.");
35dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
36dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic unsigned int channels_list[10] = {1, 2, 4, 6, 8, 10, 12, 14, 16, 999999};
370cb29ea0d449d7c0ecc9649a08ab63476389701dTakashi Iwaistatic const DECLARE_TLV_DB_SCALE(db_scale_output_gain, -12800, 100, 1);
38dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
3919b50063780953563e3c3a2867c39aad7b9e64cfGiuliano Pochini
4019b50063780953563e3c3a2867c39aad7b9e64cfGiuliano Pochini
41dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int get_firmware(const struct firmware **fw_entry,
4219b50063780953563e3c3a2867c39aad7b9e64cfGiuliano Pochini			struct echoaudio *chip, const short fw_index)
43dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
44dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int err;
45dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	char name[30];
4619b50063780953563e3c3a2867c39aad7b9e64cfGiuliano Pochini
474f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini#ifdef CONFIG_PM
484f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini	if (chip->fw_cache[fw_index]) {
494f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini		DE_ACT(("firmware requested: %s is cached\n", card_fw[fw_index].data));
504f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini		*fw_entry = chip->fw_cache[fw_index];
514f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini		return 0;
524f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini	}
534f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini#endif
544f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini
554f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini	DE_ACT(("firmware requested: %s\n", card_fw[fw_index].data));
564f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini	snprintf(name, sizeof(name), "ea/%s", card_fw[fw_index].data);
574f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini	err = request_firmware(fw_entry, name, pci_device(chip));
584f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini	if (err < 0)
59dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		snd_printk(KERN_ERR "get_firmware(): Firmware not available (%d)\n", err);
604f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini#ifdef CONFIG_PM
614f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini	else
624f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini		chip->fw_cache[fw_index] = *fw_entry;
634f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini#endif
64dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return err;
65dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
66dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
6719b50063780953563e3c3a2867c39aad7b9e64cfGiuliano Pochini
6819b50063780953563e3c3a2867c39aad7b9e64cfGiuliano Pochini
69dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic void free_firmware(const struct firmware *fw_entry)
70dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
714f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini#ifdef CONFIG_PM
724f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini	DE_ACT(("firmware not released (kept in cache)\n"));
734f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini#else
74dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	release_firmware(fw_entry);
75dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	DE_ACT(("firmware released\n"));
764f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini#endif
774f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini}
784f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini
794f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini
804f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini
814f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochinistatic void free_firmware_cache(struct echoaudio *chip)
824f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini{
834f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini#ifdef CONFIG_PM
844f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini	int i;
854f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini
864f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini	for (i = 0; i < 8 ; i++)
874f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini		if (chip->fw_cache[i]) {
884f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini			release_firmware(chip->fw_cache[i]);
894f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini			DE_ACT(("release_firmware(%d)\n", i));
904f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini		}
914f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini
924f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini	DE_ACT(("firmware_cache released\n"));
934f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini#endif
94dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
95dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
96dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
97dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
98dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/******************************************************************************
99dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	PCM interface
100dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini******************************************************************************/
101dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
102dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic void audiopipe_free(struct snd_pcm_runtime *runtime)
103dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
104dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct audiopipe *pipe = runtime->private_data;
105dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
106dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (pipe->sgpage.area)
107dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		snd_dma_free_pages(&pipe->sgpage);
108dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	kfree(pipe);
109dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
110dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
111dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
112dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
113dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int hw_rule_capture_format_by_channels(struct snd_pcm_hw_params *params,
114dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini					      struct snd_pcm_hw_rule *rule)
115dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
116dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct snd_interval *c = hw_param_interval(params,
117dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini						   SNDRV_PCM_HW_PARAM_CHANNELS);
118dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
119dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct snd_mask fmt;
120dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
121dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	snd_mask_any(&fmt);
122dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
123dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifndef ECHOCARD_HAS_STEREO_BIG_ENDIAN32
124dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* >=2 channels cannot be S32_BE */
125dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (c->min == 2) {
126dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		fmt.bits[0] &= ~SNDRV_PCM_FMTBIT_S32_BE;
127dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return snd_mask_refine(f, &fmt);
128dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
129dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif
130dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* > 2 channels cannot be U8 and S32_BE */
131dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (c->min > 2) {
132dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		fmt.bits[0] &= ~(SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_BE);
133dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return snd_mask_refine(f, &fmt);
134dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
135dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* Mono is ok with any format */
136dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
137dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
138dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
139dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
140dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
141dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int hw_rule_capture_channels_by_format(struct snd_pcm_hw_params *params,
142dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini					      struct snd_pcm_hw_rule *rule)
143dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
144dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct snd_interval *c = hw_param_interval(params,
145dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini						   SNDRV_PCM_HW_PARAM_CHANNELS);
146dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
147dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct snd_interval ch;
148dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
149dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	snd_interval_any(&ch);
150dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
151dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* S32_BE is mono (and stereo) only */
152dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (f->bits[0] == SNDRV_PCM_FMTBIT_S32_BE) {
153dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		ch.min = 1;
154dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_STEREO_BIG_ENDIAN32
155dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		ch.max = 2;
156dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#else
157dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		ch.max = 1;
158dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif
159dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		ch.integer = 1;
160dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return snd_interval_refine(c, &ch);
161dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
162dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* U8 can be only mono or stereo */
163dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (f->bits[0] == SNDRV_PCM_FMTBIT_U8) {
164dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		ch.min = 1;
165dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		ch.max = 2;
166dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		ch.integer = 1;
167dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return snd_interval_refine(c, &ch);
168dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
169dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* S16_LE, S24_3LE and S32_LE support any number of channels. */
170dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
171dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
172dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
173dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
174dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
175dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int hw_rule_playback_format_by_channels(struct snd_pcm_hw_params *params,
176dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini					       struct snd_pcm_hw_rule *rule)
177dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
178dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct snd_interval *c = hw_param_interval(params,
179dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini						   SNDRV_PCM_HW_PARAM_CHANNELS);
180dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
181dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct snd_mask fmt;
182dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	u64 fmask;
183dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	snd_mask_any(&fmt);
184dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
185dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	fmask = fmt.bits[0] + ((u64)fmt.bits[1] << 32);
186dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
187dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* >2 channels must be S16_LE, S24_3LE or S32_LE */
188dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (c->min > 2) {
189dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		fmask &= SNDRV_PCM_FMTBIT_S16_LE |
190dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			 SNDRV_PCM_FMTBIT_S24_3LE |
191dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			 SNDRV_PCM_FMTBIT_S32_LE;
192dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* 1 channel must be S32_BE or S32_LE */
193dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	} else if (c->max == 1)
194dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		fmask &= SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE;
195dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifndef ECHOCARD_HAS_STEREO_BIG_ENDIAN32
196dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* 2 channels cannot be S32_BE */
197dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	else if (c->min == 2 && c->max == 2)
198dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		fmask &= ~SNDRV_PCM_FMTBIT_S32_BE;
199dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif
200dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	else
201dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return 0;
202dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
203dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	fmt.bits[0] &= (u32)fmask;
204dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	fmt.bits[1] &= (u32)(fmask >> 32);
205dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return snd_mask_refine(f, &fmt);
206dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
207dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
208dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
209dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
210dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int hw_rule_playback_channels_by_format(struct snd_pcm_hw_params *params,
211dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini					       struct snd_pcm_hw_rule *rule)
212dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
213dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct snd_interval *c = hw_param_interval(params,
214dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini						   SNDRV_PCM_HW_PARAM_CHANNELS);
215dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
216dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct snd_interval ch;
217dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	u64 fmask;
218dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
219dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	snd_interval_any(&ch);
220dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	ch.integer = 1;
221dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	fmask = f->bits[0] + ((u64)f->bits[1] << 32);
222dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
223dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* S32_BE is mono (and stereo) only */
224dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (fmask == SNDRV_PCM_FMTBIT_S32_BE) {
225dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		ch.min = 1;
226dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_STEREO_BIG_ENDIAN32
227dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		ch.max = 2;
228dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#else
229dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		ch.max = 1;
230dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif
231dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* U8 is stereo only */
232dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	} else if (fmask == SNDRV_PCM_FMTBIT_U8)
233dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		ch.min = ch.max = 2;
234dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* S16_LE and S24_3LE must be at least stereo */
235dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	else if (!(fmask & ~(SNDRV_PCM_FMTBIT_S16_LE |
236dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			       SNDRV_PCM_FMTBIT_S24_3LE)))
237dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		ch.min = 2;
238dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	else
239dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return 0;
240dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
241dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return snd_interval_refine(c, &ch);
242dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
243dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
244dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
245dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
246dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/* Since the sample rate is a global setting, do allow the user to change the
247dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinisample rate only if there is only one pcm device open. */
248dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int hw_rule_sample_rate(struct snd_pcm_hw_params *params,
249dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			       struct snd_pcm_hw_rule *rule)
250dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
251dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct snd_interval *rate = hw_param_interval(params,
252dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini						      SNDRV_PCM_HW_PARAM_RATE);
253dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip = rule->private;
254dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct snd_interval fixed;
255dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
256dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (!chip->can_set_rate) {
257dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		snd_interval_any(&fixed);
258dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		fixed.min = fixed.max = chip->sample_rate;
259dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return snd_interval_refine(rate, &fixed);
260dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
261dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
262dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
263dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
264dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
265dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int pcm_open(struct snd_pcm_substream *substream,
266dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		    signed char max_channels)
267dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
268dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
269dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct snd_pcm_runtime *runtime;
270dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct audiopipe *pipe;
271dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int err, i;
272dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
273dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (max_channels <= 0)
274dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return -EAGAIN;
275dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
276dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_pcm_substream_chip(substream);
277dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	runtime = substream->runtime;
278dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
27959feddb25f9d925e86ee22596802405788bc050fPanagiotis Issaris	pipe = kzalloc(sizeof(struct audiopipe), GFP_KERNEL);
28059feddb25f9d925e86ee22596802405788bc050fPanagiotis Issaris	if (!pipe)
281dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return -ENOMEM;
282dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	pipe->index = -1;		/* Not configured yet */
283dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
284dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* Set up hw capabilities and contraints */
285dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	memcpy(&pipe->hw, &pcm_hardware_skel, sizeof(struct snd_pcm_hardware));
286dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	DE_HWP(("max_channels=%d\n", max_channels));
287dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	pipe->constr.list = channels_list;
288dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	pipe->constr.mask = 0;
289dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	for (i = 0; channels_list[i] <= max_channels; i++);
290dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	pipe->constr.count = i;
291dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (pipe->hw.channels_max > max_channels)
292dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		pipe->hw.channels_max = max_channels;
293dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (chip->digital_mode == DIGITAL_MODE_ADAT) {
294dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		pipe->hw.rate_max = 48000;
295dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		pipe->hw.rates &= SNDRV_PCM_RATE_8000_48000;
296dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
297dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
298dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	runtime->hw = pipe->hw;
299dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	runtime->private_data = pipe;
300dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	runtime->private_free = audiopipe_free;
301dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	snd_pcm_set_sync(substream);
302dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
303dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* Only mono and any even number of channels are allowed */
304dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_pcm_hw_constraint_list(runtime, 0,
305dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini					      SNDRV_PCM_HW_PARAM_CHANNELS,
306dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini					      &pipe->constr)) < 0)
307dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return err;
308dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
309dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* All periods should have the same size */
310dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_pcm_hw_constraint_integer(runtime,
311dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini						 SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
312dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return err;
313dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
314dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* The hw accesses memory in chunks 32 frames long and they should be
315dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	32-bytes-aligned. It's not a requirement, but it seems that IRQs are
316dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	generated with a resolution of 32 frames. Thus we need the following */
317dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_pcm_hw_constraint_step(runtime, 0,
318dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini					      SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
319dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini					      32)) < 0)
320dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return err;
321dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_pcm_hw_constraint_step(runtime, 0,
322dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini					      SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
323dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini					      32)) < 0)
324dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return err;
325dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
326dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_pcm_hw_rule_add(substream->runtime, 0,
327dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       SNDRV_PCM_HW_PARAM_RATE,
328dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini					hw_rule_sample_rate, chip,
329dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       SNDRV_PCM_HW_PARAM_RATE, -1)) < 0)
330dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return err;
331dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
332dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* Finally allocate a page for the scatter-gather list */
333dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
334dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       snd_dma_pci_data(chip->pci),
335dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       PAGE_SIZE, &pipe->sgpage)) < 0) {
336dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		DE_HWP(("s-g list allocation failed\n"));
337dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return err;
338dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
339dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
340dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
341dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
342dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
343dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
344dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
345dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int pcm_analog_in_open(struct snd_pcm_substream *substream)
346dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
347dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip = snd_pcm_substream_chip(substream);
348dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int err;
349dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
350dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	DE_ACT(("pcm_analog_in_open\n"));
351dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = pcm_open(substream, num_analog_busses_in(chip) -
352dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			    substream->number)) < 0)
353dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return err;
354dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_pcm_hw_rule_add(substream->runtime, 0,
355dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       SNDRV_PCM_HW_PARAM_CHANNELS,
356dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       hw_rule_capture_channels_by_format, NULL,
357dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       SNDRV_PCM_HW_PARAM_FORMAT, -1)) < 0)
358dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return err;
359dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_pcm_hw_rule_add(substream->runtime, 0,
360dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       SNDRV_PCM_HW_PARAM_FORMAT,
361dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       hw_rule_capture_format_by_channels, NULL,
362dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       SNDRV_PCM_HW_PARAM_CHANNELS, -1)) < 0)
363dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return err;
364dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	atomic_inc(&chip->opencount);
365dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (atomic_read(&chip->opencount) > 1 && chip->rate_set)
366dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		chip->can_set_rate=0;
367dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	DE_HWP(("pcm_analog_in_open  cs=%d  oc=%d  r=%d\n",
368dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		chip->can_set_rate, atomic_read(&chip->opencount),
369dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		chip->sample_rate));
370dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
371dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
372dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
373dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
374dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
375dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int pcm_analog_out_open(struct snd_pcm_substream *substream)
376dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
377dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip = snd_pcm_substream_chip(substream);
378dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int max_channels, err;
379dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
380dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_VMIXER
381dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	max_channels = num_pipes_out(chip);
382dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#else
383dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	max_channels = num_analog_busses_out(chip);
384dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif
385dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	DE_ACT(("pcm_analog_out_open\n"));
386dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = pcm_open(substream, max_channels - substream->number)) < 0)
387dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return err;
388dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_pcm_hw_rule_add(substream->runtime, 0,
389dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       SNDRV_PCM_HW_PARAM_CHANNELS,
390dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       hw_rule_playback_channels_by_format,
391dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       NULL,
392dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       SNDRV_PCM_HW_PARAM_FORMAT, -1)) < 0)
393dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return err;
394dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_pcm_hw_rule_add(substream->runtime, 0,
395dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       SNDRV_PCM_HW_PARAM_FORMAT,
396dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       hw_rule_playback_format_by_channels,
397dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       NULL,
398dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       SNDRV_PCM_HW_PARAM_CHANNELS, -1)) < 0)
399dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return err;
400dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	atomic_inc(&chip->opencount);
401dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (atomic_read(&chip->opencount) > 1 && chip->rate_set)
402dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		chip->can_set_rate=0;
403dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	DE_HWP(("pcm_analog_out_open  cs=%d  oc=%d  r=%d\n",
404dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		chip->can_set_rate, atomic_read(&chip->opencount),
405dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		chip->sample_rate));
406dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
407dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
408dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
409dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
410dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
411dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_DIGITAL_IO
412dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
413dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int pcm_digital_in_open(struct snd_pcm_substream *substream)
414dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
415dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip = snd_pcm_substream_chip(substream);
416dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int err, max_channels;
417dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
418dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	DE_ACT(("pcm_digital_in_open\n"));
419dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	max_channels = num_digital_busses_in(chip) - substream->number;
420befceea90b17792cb03cc4e22f3329c89621bba3Takashi Iwai	mutex_lock(&chip->mode_mutex);
421dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (chip->digital_mode == DIGITAL_MODE_ADAT)
422dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		err = pcm_open(substream, max_channels);
423dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	else	/* If the card has ADAT, subtract the 6 channels
424dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		 * that S/PDIF doesn't have
425dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		 */
426dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		err = pcm_open(substream, max_channels - ECHOCARD_HAS_ADAT);
427dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
428dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (err < 0)
429dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		goto din_exit;
430dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
431dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_pcm_hw_rule_add(substream->runtime, 0,
432dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       SNDRV_PCM_HW_PARAM_CHANNELS,
433dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       hw_rule_capture_channels_by_format, NULL,
434dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       SNDRV_PCM_HW_PARAM_FORMAT, -1)) < 0)
435dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		goto din_exit;
436dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_pcm_hw_rule_add(substream->runtime, 0,
437dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       SNDRV_PCM_HW_PARAM_FORMAT,
438dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       hw_rule_capture_format_by_channels, NULL,
439dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       SNDRV_PCM_HW_PARAM_CHANNELS, -1)) < 0)
440dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		goto din_exit;
441dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
442dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	atomic_inc(&chip->opencount);
443dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (atomic_read(&chip->opencount) > 1 && chip->rate_set)
444dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		chip->can_set_rate=0;
445dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
446dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinidin_exit:
447befceea90b17792cb03cc4e22f3329c89621bba3Takashi Iwai	mutex_unlock(&chip->mode_mutex);
448dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return err;
449dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
450dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
451dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
452dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
453dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifndef ECHOCARD_HAS_VMIXER	/* See the note in snd_echo_new_pcm() */
454dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
455dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int pcm_digital_out_open(struct snd_pcm_substream *substream)
456dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
457dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip = snd_pcm_substream_chip(substream);
458dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int err, max_channels;
459dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
460dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	DE_ACT(("pcm_digital_out_open\n"));
461dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	max_channels = num_digital_busses_out(chip) - substream->number;
462befceea90b17792cb03cc4e22f3329c89621bba3Takashi Iwai	mutex_lock(&chip->mode_mutex);
463dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (chip->digital_mode == DIGITAL_MODE_ADAT)
464dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		err = pcm_open(substream, max_channels);
465dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	else	/* If the card has ADAT, subtract the 6 channels
466dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		 * that S/PDIF doesn't have
467dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		 */
468dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		err = pcm_open(substream, max_channels - ECHOCARD_HAS_ADAT);
469dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
470dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (err < 0)
471dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		goto dout_exit;
472dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
473dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_pcm_hw_rule_add(substream->runtime, 0,
474dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       SNDRV_PCM_HW_PARAM_CHANNELS,
475dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       hw_rule_playback_channels_by_format,
476dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       NULL, SNDRV_PCM_HW_PARAM_FORMAT,
477dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       -1)) < 0)
478dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		goto dout_exit;
479dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_pcm_hw_rule_add(substream->runtime, 0,
480dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       SNDRV_PCM_HW_PARAM_FORMAT,
481dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       hw_rule_playback_format_by_channels,
482dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       NULL, SNDRV_PCM_HW_PARAM_CHANNELS,
483dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       -1)) < 0)
484dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		goto dout_exit;
485dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	atomic_inc(&chip->opencount);
486dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (atomic_read(&chip->opencount) > 1 && chip->rate_set)
487dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		chip->can_set_rate=0;
488dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinidout_exit:
489befceea90b17792cb03cc4e22f3329c89621bba3Takashi Iwai	mutex_unlock(&chip->mode_mutex);
490dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return err;
491dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
492dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
493dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif /* !ECHOCARD_HAS_VMIXER */
494dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
495dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif /* ECHOCARD_HAS_DIGITAL_IO */
496dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
497dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
498dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
499dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int pcm_close(struct snd_pcm_substream *substream)
500dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
501dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip = snd_pcm_substream_chip(substream);
502dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int oc;
503dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
504dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* Nothing to do here. Audio is already off and pipe will be
505dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	 * freed by its callback
506dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	 */
507dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	DE_ACT(("pcm_close\n"));
508dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
509dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	atomic_dec(&chip->opencount);
510dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	oc = atomic_read(&chip->opencount);
511dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	DE_ACT(("pcm_close  oc=%d  cs=%d  rs=%d\n", oc,
512dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		chip->can_set_rate, chip->rate_set));
513dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (oc < 2)
514dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		chip->can_set_rate = 1;
515dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (oc == 0)
516dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		chip->rate_set = 0;
517dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	DE_ACT(("pcm_close2 oc=%d  cs=%d  rs=%d\n", oc,
518dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		chip->can_set_rate,chip->rate_set));
519dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
520dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
521dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
522dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
523dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
524dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
525dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/* Channel allocation and scatter-gather list setup */
526dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int init_engine(struct snd_pcm_substream *substream,
527dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		       struct snd_pcm_hw_params *hw_params,
528dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		       int pipe_index, int interleave)
529dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
530dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
531dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int err, per, rest, page, edge, offs;
532dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct audiopipe *pipe;
533dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
534dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_pcm_substream_chip(substream);
535dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	pipe = (struct audiopipe *) substream->runtime->private_data;
536dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
537dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* Sets up che hardware. If it's already initialized, reset and
538dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	 * redo with the new parameters
539dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	 */
540dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	spin_lock_irq(&chip->lock);
541dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (pipe->index >= 0) {
542dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		DE_HWP(("hwp_ie free(%d)\n", pipe->index));
543dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		err = free_pipes(chip, pipe);
544da3cec35dd3c31d8706db4bf379372ce70d92118Takashi Iwai		snd_BUG_ON(err);
545dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		chip->substream[pipe->index] = NULL;
546dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
547dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
548dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	err = allocate_pipes(chip, pipe, pipe_index, interleave);
549dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (err < 0) {
550dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		spin_unlock_irq(&chip->lock);
551dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		DE_ACT((KERN_NOTICE "allocate_pipes(%d) err=%d\n",
552dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			pipe_index, err));
553dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return err;
554dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
555dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	spin_unlock_irq(&chip->lock);
556dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	DE_ACT((KERN_NOTICE "allocate_pipes()=%d\n", pipe_index));
557dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
558dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	DE_HWP(("pcm_hw_params (bufsize=%dB periods=%d persize=%dB)\n",
559dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		params_buffer_bytes(hw_params), params_periods(hw_params),
560dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		params_period_bytes(hw_params)));
561dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	err = snd_pcm_lib_malloc_pages(substream,
562dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       params_buffer_bytes(hw_params));
563dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (err < 0) {
564dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		snd_printk(KERN_ERR "malloc_pages err=%d\n", err);
565dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		spin_lock_irq(&chip->lock);
566dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		free_pipes(chip, pipe);
567dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		spin_unlock_irq(&chip->lock);
568dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		pipe->index = -1;
569dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return err;
570dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
571dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
572dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	sglist_init(chip, pipe);
573dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	edge = PAGE_SIZE;
574dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	for (offs = page = per = 0; offs < params_buffer_bytes(hw_params);
575dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	     per++) {
576dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		rest = params_period_bytes(hw_params);
577dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		if (offs + rest > params_buffer_bytes(hw_params))
578dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			rest = params_buffer_bytes(hw_params) - offs;
579dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		while (rest) {
58077a23f2695bb2de0cd74599400dc55109c531b72Takashi Iwai			dma_addr_t addr;
58177a23f2695bb2de0cd74599400dc55109c531b72Takashi Iwai			addr = snd_pcm_sgbuf_get_addr(substream, offs);
582dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			if (rest <= edge - offs) {
58377a23f2695bb2de0cd74599400dc55109c531b72Takashi Iwai				sglist_add_mapping(chip, pipe, addr, rest);
584dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				sglist_add_irq(chip, pipe);
585dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				offs += rest;
586dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				rest = 0;
587dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			} else {
58877a23f2695bb2de0cd74599400dc55109c531b72Takashi Iwai				sglist_add_mapping(chip, pipe, addr,
589dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini						   edge - offs);
590dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				rest -= edge - offs;
591dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				offs = edge;
592dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			}
593dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			if (offs == edge) {
594dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				edge += PAGE_SIZE;
595dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				page++;
596dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			}
597dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		}
598dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
599dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
600dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* Close the ring buffer */
601dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	sglist_wrap(chip, pipe);
602dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
603dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* This stuff is used by the irq handler, so it must be
604dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	 * initialized before chip->substream
605dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	 */
606dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip->last_period[pipe_index] = 0;
607dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	pipe->last_counter = 0;
608dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	pipe->position = 0;
609dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	smp_wmb();
610dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip->substream[pipe_index] = substream;
611dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip->rate_set = 1;
612dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	spin_lock_irq(&chip->lock);
613dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	set_sample_rate(chip, hw_params->rate_num / hw_params->rate_den);
614dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	spin_unlock_irq(&chip->lock);
615dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	DE_HWP(("pcm_hw_params ok\n"));
616dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
617dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
618dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
619dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
620dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
621dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int pcm_analog_in_hw_params(struct snd_pcm_substream *substream,
622dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				   struct snd_pcm_hw_params *hw_params)
623dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
624dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip = snd_pcm_substream_chip(substream);
625dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
626dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return init_engine(substream, hw_params, px_analog_in(chip) +
627dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			substream->number, params_channels(hw_params));
628dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
629dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
630dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
631dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
632dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int pcm_analog_out_hw_params(struct snd_pcm_substream *substream,
633dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				    struct snd_pcm_hw_params *hw_params)
634dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
635dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return init_engine(substream, hw_params, substream->number,
636dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			   params_channels(hw_params));
637dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
638dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
639dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
640dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
641dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_DIGITAL_IO
642dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
643dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int pcm_digital_in_hw_params(struct snd_pcm_substream *substream,
644dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				    struct snd_pcm_hw_params *hw_params)
645dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
646dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip = snd_pcm_substream_chip(substream);
647dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
648dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return init_engine(substream, hw_params, px_digital_in(chip) +
649dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			substream->number, params_channels(hw_params));
650dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
651dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
652dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
653dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
654dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifndef ECHOCARD_HAS_VMIXER	/* See the note in snd_echo_new_pcm() */
655dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int pcm_digital_out_hw_params(struct snd_pcm_substream *substream,
656dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				     struct snd_pcm_hw_params *hw_params)
657dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
658dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip = snd_pcm_substream_chip(substream);
659dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
660dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return init_engine(substream, hw_params, px_digital_out(chip) +
661dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			substream->number, params_channels(hw_params));
662dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
663dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif /* !ECHOCARD_HAS_VMIXER */
664dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
665dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif /* ECHOCARD_HAS_DIGITAL_IO */
666dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
667dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
668dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
669dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int pcm_hw_free(struct snd_pcm_substream *substream)
670dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
671dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
672dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct audiopipe *pipe;
673dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
674dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_pcm_substream_chip(substream);
675dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	pipe = (struct audiopipe *) substream->runtime->private_data;
676dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
677dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	spin_lock_irq(&chip->lock);
678dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (pipe->index >= 0) {
679dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		DE_HWP(("pcm_hw_free(%d)\n", pipe->index));
680dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		free_pipes(chip, pipe);
681dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		chip->substream[pipe->index] = NULL;
682dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		pipe->index = -1;
683dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
684dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	spin_unlock_irq(&chip->lock);
685dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
686dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	DE_HWP(("pcm_hw_freed\n"));
687dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	snd_pcm_lib_free_pages(substream);
688dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
689dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
690dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
691dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
692dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
693dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int pcm_prepare(struct snd_pcm_substream *substream)
694dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
695dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip = snd_pcm_substream_chip(substream);
696dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct snd_pcm_runtime *runtime = substream->runtime;
697dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct audioformat format;
698dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int pipe_index = ((struct audiopipe *)runtime->private_data)->index;
699dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
700dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	DE_HWP(("Prepare rate=%d format=%d channels=%d\n",
701dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		runtime->rate, runtime->format, runtime->channels));
702dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	format.interleave = runtime->channels;
703dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	format.data_are_bigendian = 0;
704dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	format.mono_to_stereo = 0;
705dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	switch (runtime->format) {
706dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	case SNDRV_PCM_FORMAT_U8:
707dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		format.bits_per_sample = 8;
708dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		break;
709dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	case SNDRV_PCM_FORMAT_S16_LE:
710dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		format.bits_per_sample = 16;
711dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		break;
712dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	case SNDRV_PCM_FORMAT_S24_3LE:
713dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		format.bits_per_sample = 24;
714dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		break;
715dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	case SNDRV_PCM_FORMAT_S32_BE:
716dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		format.data_are_bigendian = 1;
717dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	case SNDRV_PCM_FORMAT_S32_LE:
718dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		format.bits_per_sample = 32;
719dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		break;
720dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	default:
721dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		DE_HWP(("Prepare error: unsupported format %d\n",
722dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			runtime->format));
723dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return -EINVAL;
724dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
725dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
726da3cec35dd3c31d8706db4bf379372ce70d92118Takashi Iwai	if (snd_BUG_ON(pipe_index >= px_num(chip)))
727da3cec35dd3c31d8706db4bf379372ce70d92118Takashi Iwai		return -EINVAL;
728da3cec35dd3c31d8706db4bf379372ce70d92118Takashi Iwai	if (snd_BUG_ON(!is_pipe_allocated(chip, pipe_index)))
729da3cec35dd3c31d8706db4bf379372ce70d92118Takashi Iwai		return -EINVAL;
730dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	set_audio_format(chip, pipe_index, &format);
731dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
732dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
733dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
734dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
735dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
736dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int pcm_trigger(struct snd_pcm_substream *substream, int cmd)
737dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
738dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip = snd_pcm_substream_chip(substream);
739dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct snd_pcm_runtime *runtime = substream->runtime;
740dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct audiopipe *pipe = runtime->private_data;
741dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int i, err;
742dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	u32 channelmask = 0;
743dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct snd_pcm_substream *s;
744dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
745ef991b95aa1351a5782cfaccb9aefba76ca8b990Takashi Iwai	snd_pcm_group_for_each_entry(s, substream) {
746dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		for (i = 0; i < DSP_MAXPIPES; i++) {
747dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			if (s == chip->substream[i]) {
748dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				channelmask |= 1 << i;
749dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				snd_pcm_trigger_done(s, substream);
750dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			}
751dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		}
752dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
753dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
754dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	spin_lock(&chip->lock);
755dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	switch (cmd) {
75647b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	case SNDRV_PCM_TRIGGER_RESUME:
75747b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		DE_ACT(("pcm_trigger resume\n"));
758dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	case SNDRV_PCM_TRIGGER_START:
759dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
760dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		DE_ACT(("pcm_trigger start\n"));
761dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		for (i = 0; i < DSP_MAXPIPES; i++) {
762dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			if (channelmask & (1 << i)) {
763dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				pipe = chip->substream[i]->runtime->private_data;
764dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				switch (pipe->state) {
765dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				case PIPE_STATE_STOPPED:
766dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini					chip->last_period[i] = 0;
767dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini					pipe->last_counter = 0;
768dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini					pipe->position = 0;
769dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini					*pipe->dma_counter = 0;
770dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				case PIPE_STATE_PAUSED:
771dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini					pipe->state = PIPE_STATE_STARTED;
772dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini					break;
773dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				case PIPE_STATE_STARTED:
774dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini					break;
775dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				}
776dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			}
777dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		}
778dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		err = start_transport(chip, channelmask,
779dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				      chip->pipe_cyclic_mask);
780dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		break;
78147b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	case SNDRV_PCM_TRIGGER_SUSPEND:
78247b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		DE_ACT(("pcm_trigger suspend\n"));
783dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	case SNDRV_PCM_TRIGGER_STOP:
784dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		DE_ACT(("pcm_trigger stop\n"));
785dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		for (i = 0; i < DSP_MAXPIPES; i++) {
786dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			if (channelmask & (1 << i)) {
787dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				pipe = chip->substream[i]->runtime->private_data;
788dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				pipe->state = PIPE_STATE_STOPPED;
789dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			}
790dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		}
791dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		err = stop_transport(chip, channelmask);
792dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		break;
793dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
794dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		DE_ACT(("pcm_trigger pause\n"));
795dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		for (i = 0; i < DSP_MAXPIPES; i++) {
796dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			if (channelmask & (1 << i)) {
797dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				pipe = chip->substream[i]->runtime->private_data;
798dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				pipe->state = PIPE_STATE_PAUSED;
799dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			}
800dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		}
801dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		err = pause_transport(chip, channelmask);
802dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		break;
803dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	default:
804dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		err = -EINVAL;
805dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
806dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	spin_unlock(&chip->lock);
807dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return err;
808dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
809dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
810dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
811dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
812dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic snd_pcm_uframes_t pcm_pointer(struct snd_pcm_substream *substream)
813dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
814dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct snd_pcm_runtime *runtime = substream->runtime;
815dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct audiopipe *pipe = runtime->private_data;
816dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	size_t cnt, bufsize, pos;
817dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
818dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	cnt = le32_to_cpu(*pipe->dma_counter);
819dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	pipe->position += cnt - pipe->last_counter;
820dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	pipe->last_counter = cnt;
821dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	bufsize = substream->runtime->buffer_size;
822dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	pos = bytes_to_frames(substream->runtime, pipe->position);
823dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
824dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	while (pos >= bufsize) {
825dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		pipe->position -= frames_to_bytes(substream->runtime, bufsize);
826dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		pos -= bufsize;
827dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
828dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return pos;
829dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
830dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
831dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
832dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
833dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/* pcm *_ops structures */
834dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic struct snd_pcm_ops analog_playback_ops = {
835dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.open = pcm_analog_out_open,
836dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.close = pcm_close,
837dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.ioctl = snd_pcm_lib_ioctl,
838dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.hw_params = pcm_analog_out_hw_params,
839dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.hw_free = pcm_hw_free,
840dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.prepare = pcm_prepare,
841dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.trigger = pcm_trigger,
842dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.pointer = pcm_pointer,
843dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.page = snd_pcm_sgbuf_ops_page,
844dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini};
845dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic struct snd_pcm_ops analog_capture_ops = {
846dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.open = pcm_analog_in_open,
847dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.close = pcm_close,
848dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.ioctl = snd_pcm_lib_ioctl,
849dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.hw_params = pcm_analog_in_hw_params,
850dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.hw_free = pcm_hw_free,
851dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.prepare = pcm_prepare,
852dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.trigger = pcm_trigger,
853dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.pointer = pcm_pointer,
854dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.page = snd_pcm_sgbuf_ops_page,
855dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini};
856dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_DIGITAL_IO
857dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifndef ECHOCARD_HAS_VMIXER
858dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic struct snd_pcm_ops digital_playback_ops = {
859dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.open = pcm_digital_out_open,
860dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.close = pcm_close,
861dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.ioctl = snd_pcm_lib_ioctl,
862dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.hw_params = pcm_digital_out_hw_params,
863dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.hw_free = pcm_hw_free,
864dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.prepare = pcm_prepare,
865dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.trigger = pcm_trigger,
866dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.pointer = pcm_pointer,
867dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.page = snd_pcm_sgbuf_ops_page,
868dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini};
869dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif /* !ECHOCARD_HAS_VMIXER */
870dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic struct snd_pcm_ops digital_capture_ops = {
871dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.open = pcm_digital_in_open,
872dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.close = pcm_close,
873dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.ioctl = snd_pcm_lib_ioctl,
874dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.hw_params = pcm_digital_in_hw_params,
875dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.hw_free = pcm_hw_free,
876dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.prepare = pcm_prepare,
877dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.trigger = pcm_trigger,
878dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.pointer = pcm_pointer,
879dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.page = snd_pcm_sgbuf_ops_page,
880dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini};
881dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif /* ECHOCARD_HAS_DIGITAL_IO */
882dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
883dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
884dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
885dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/* Preallocate memory only for the first substream because it's the most
886dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini * used one
887dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini */
888dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_preallocate_pages(struct snd_pcm *pcm, struct device *dev)
889dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
890dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct snd_pcm_substream *ss;
891dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int stream, err;
892dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
893dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	for (stream = 0; stream < 2; stream++)
894dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		for (ss = pcm->streams[stream].substream; ss; ss = ss->next) {
895dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			err = snd_pcm_lib_preallocate_pages(ss, SNDRV_DMA_TYPE_DEV_SG,
896dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini							    dev,
897dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini							    ss->number ? 0 : 128<<10,
898dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini							    256<<10);
899dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			if (err < 0)
900dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				return err;
901dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		}
902dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
903dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
904dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
905dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
906dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
907dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/*<--snd_echo_probe() */
908dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int __devinit snd_echo_new_pcm(struct echoaudio *chip)
909dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
910dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct snd_pcm *pcm;
911dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int err;
912dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
913dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_VMIXER
914dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* This card has a Vmixer, that is there is no direct mapping from PCM
915dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	streams to physical outputs. The user can mix the streams as he wishes
916dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	via control interface and it's possible to send any stream to any
917dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	output, thus it makes no sense to keep analog and digital outputs
918dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	separated */
919dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
920dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* PCM#0 Virtual outputs and analog inputs */
921dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_pcm_new(chip->card, "PCM", 0, num_pipes_out(chip),
922dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				num_analog_busses_in(chip), &pcm)) < 0)
923dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return err;
924dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	pcm->private_data = chip;
925dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip->analog_pcm = pcm;
926dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	strcpy(pcm->name, chip->card->shortname);
927dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &analog_playback_ops);
928dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &analog_capture_ops);
929dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_echo_preallocate_pages(pcm, snd_dma_pci_data(chip->pci))) < 0)
930dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return err;
931dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	DE_INIT(("Analog PCM ok\n"));
932dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
933dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_DIGITAL_IO
934dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* PCM#1 Digital inputs, no outputs */
935dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_pcm_new(chip->card, "Digital PCM", 1, 0,
936dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			       num_digital_busses_in(chip), &pcm)) < 0)
937dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return err;
938dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	pcm->private_data = chip;
939dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip->digital_pcm = pcm;
940dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	strcpy(pcm->name, chip->card->shortname);
941dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &digital_capture_ops);
942dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_echo_preallocate_pages(pcm, snd_dma_pci_data(chip->pci))) < 0)
943dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return err;
944dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	DE_INIT(("Digital PCM ok\n"));
945dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif /* ECHOCARD_HAS_DIGITAL_IO */
946dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
947dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#else /* ECHOCARD_HAS_VMIXER */
948dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
949dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* The card can manage substreams formed by analog and digital channels
950dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	at the same time, but I prefer to keep analog and digital channels
951dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	separated, because that mixed thing is confusing and useless. So we
952dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	register two PCM devices: */
953dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
954dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* PCM#0 Analog i/o */
955dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_pcm_new(chip->card, "Analog PCM", 0,
956dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			       num_analog_busses_out(chip),
957dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			       num_analog_busses_in(chip), &pcm)) < 0)
958dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return err;
959dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	pcm->private_data = chip;
960dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip->analog_pcm = pcm;
961dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	strcpy(pcm->name, chip->card->shortname);
962dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &analog_playback_ops);
963dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &analog_capture_ops);
964dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_echo_preallocate_pages(pcm, snd_dma_pci_data(chip->pci))) < 0)
965dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return err;
966dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	DE_INIT(("Analog PCM ok\n"));
967dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
968dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_DIGITAL_IO
969dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* PCM#1 Digital i/o */
970dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_pcm_new(chip->card, "Digital PCM", 1,
971dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			       num_digital_busses_out(chip),
972dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			       num_digital_busses_in(chip), &pcm)) < 0)
973dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return err;
974dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	pcm->private_data = chip;
975dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip->digital_pcm = pcm;
976dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	strcpy(pcm->name, chip->card->shortname);
977dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &digital_playback_ops);
978dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &digital_capture_ops);
979dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_echo_preallocate_pages(pcm, snd_dma_pci_data(chip->pci))) < 0)
980dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return err;
981dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	DE_INIT(("Digital PCM ok\n"));
982dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif /* ECHOCARD_HAS_DIGITAL_IO */
983dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
984dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif /* ECHOCARD_HAS_VMIXER */
985dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
986dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
987dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
988dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
989dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
990dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
991dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
992dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/******************************************************************************
993dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	Control interface
994dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini******************************************************************************/
995dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
996392bf2f1ba03b690f0ee71a185d4a5720a82bb25Giuliano Pochini#if !defined(ECHOCARD_HAS_VMIXER) || defined(ECHOCARD_HAS_LINE_OUT_GAIN)
9979f5d790d1b0af8e3705df12fd5d49a1df2a45c47Giuliano Pochini
998dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/******************* PCM output volume *******************/
999dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_output_gain_info(struct snd_kcontrol *kcontrol,
1000dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				     struct snd_ctl_elem_info *uinfo)
1001dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1002dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1003dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1004dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1005dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1006dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->count = num_busses_out(chip);
1007dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->value.integer.min = ECHOGAIN_MINOUT;
1008dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->value.integer.max = ECHOGAIN_MAXOUT;
1009dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
1010dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1011dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1012dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_output_gain_get(struct snd_kcontrol *kcontrol,
1013dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				    struct snd_ctl_elem_value *ucontrol)
1014dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1015dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1016dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int c;
1017dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1018dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1019dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	for (c = 0; c < num_busses_out(chip); c++)
1020dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		ucontrol->value.integer.value[c] = chip->output_gain[c];
1021dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
1022dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1023dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1024dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_output_gain_put(struct snd_kcontrol *kcontrol,
1025dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				    struct snd_ctl_elem_value *ucontrol)
1026dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1027dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1028dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int c, changed, gain;
1029dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1030dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	changed = 0;
1031dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1032dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	spin_lock_irq(&chip->lock);
1033dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	for (c = 0; c < num_busses_out(chip); c++) {
1034dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		gain = ucontrol->value.integer.value[c];
1035dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		/* Ignore out of range values */
1036dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		if (gain < ECHOGAIN_MINOUT || gain > ECHOGAIN_MAXOUT)
1037dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			continue;
1038dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		if (chip->output_gain[c] != gain) {
1039dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			set_output_gain(chip, c, gain);
1040dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			changed = 1;
1041dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		}
1042dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
1043dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (changed)
1044dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		update_output_line_level(chip);
1045dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	spin_unlock_irq(&chip->lock);
1046dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return changed;
1047dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1048dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1049392bf2f1ba03b690f0ee71a185d4a5720a82bb25Giuliano Pochini#ifdef ECHOCARD_HAS_LINE_OUT_GAIN
1050392bf2f1ba03b690f0ee71a185d4a5720a82bb25Giuliano Pochini/* On the Mia this one controls the line-out volume */
1051392bf2f1ba03b690f0ee71a185d4a5720a82bb25Giuliano Pochinistatic struct snd_kcontrol_new snd_echo_line_output_gain __devinitdata = {
1052392bf2f1ba03b690f0ee71a185d4a5720a82bb25Giuliano Pochini	.name = "Line Playback Volume",
1053392bf2f1ba03b690f0ee71a185d4a5720a82bb25Giuliano Pochini	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1054392bf2f1ba03b690f0ee71a185d4a5720a82bb25Giuliano Pochini	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
1055392bf2f1ba03b690f0ee71a185d4a5720a82bb25Giuliano Pochini		  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
1056392bf2f1ba03b690f0ee71a185d4a5720a82bb25Giuliano Pochini	.info = snd_echo_output_gain_info,
1057392bf2f1ba03b690f0ee71a185d4a5720a82bb25Giuliano Pochini	.get = snd_echo_output_gain_get,
1058392bf2f1ba03b690f0ee71a185d4a5720a82bb25Giuliano Pochini	.put = snd_echo_output_gain_put,
1059392bf2f1ba03b690f0ee71a185d4a5720a82bb25Giuliano Pochini	.tlv = {.p = db_scale_output_gain},
1060392bf2f1ba03b690f0ee71a185d4a5720a82bb25Giuliano Pochini};
1061392bf2f1ba03b690f0ee71a185d4a5720a82bb25Giuliano Pochini#else
1062dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic struct snd_kcontrol_new snd_echo_pcm_output_gain __devinitdata = {
1063dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.name = "PCM Playback Volume",
1064dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1065048b945077bdc7e8dff5d5810ff2a0ced3590ca9Giuliano Pochini	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
1066dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.info = snd_echo_output_gain_info,
1067dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.get = snd_echo_output_gain_get,
1068dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.put = snd_echo_output_gain_put,
1069048b945077bdc7e8dff5d5810ff2a0ced3590ca9Giuliano Pochini	.tlv = {.p = db_scale_output_gain},
1070dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini};
1071dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif
1072dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1073392bf2f1ba03b690f0ee71a185d4a5720a82bb25Giuliano Pochini#endif /* !ECHOCARD_HAS_VMIXER || ECHOCARD_HAS_LINE_OUT_GAIN */
1074392bf2f1ba03b690f0ee71a185d4a5720a82bb25Giuliano Pochini
1075dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1076dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1077dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_INPUT_GAIN
1078dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1079dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/******************* Analog input volume *******************/
1080dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_input_gain_info(struct snd_kcontrol *kcontrol,
1081dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				    struct snd_ctl_elem_info *uinfo)
1082dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1083dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1084dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1085dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1086dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1087dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->count = num_analog_busses_in(chip);
1088dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->value.integer.min = ECHOGAIN_MININP;
1089dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->value.integer.max = ECHOGAIN_MAXINP;
1090dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
1091dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1092dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1093dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_input_gain_get(struct snd_kcontrol *kcontrol,
1094dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				   struct snd_ctl_elem_value *ucontrol)
1095dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1096dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1097dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int c;
1098dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1099dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1100dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	for (c = 0; c < num_analog_busses_in(chip); c++)
1101dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		ucontrol->value.integer.value[c] = chip->input_gain[c];
1102dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
1103dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1104dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1105dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_input_gain_put(struct snd_kcontrol *kcontrol,
1106dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				   struct snd_ctl_elem_value *ucontrol)
1107dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1108dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1109dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int c, gain, changed;
1110dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1111dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	changed = 0;
1112dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1113dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	spin_lock_irq(&chip->lock);
1114dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	for (c = 0; c < num_analog_busses_in(chip); c++) {
1115dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		gain = ucontrol->value.integer.value[c];
1116dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		/* Ignore out of range values */
1117dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		if (gain < ECHOGAIN_MININP || gain > ECHOGAIN_MAXINP)
1118dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			continue;
1119dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		if (chip->input_gain[c] != gain) {
1120dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			set_input_gain(chip, c, gain);
1121dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			changed = 1;
1122dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		}
1123dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
1124dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (changed)
1125dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		update_input_line_level(chip);
1126dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	spin_unlock_irq(&chip->lock);
1127dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return changed;
1128dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1129dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
11300cb29ea0d449d7c0ecc9649a08ab63476389701dTakashi Iwaistatic const DECLARE_TLV_DB_SCALE(db_scale_input_gain, -2500, 50, 0);
1131048b945077bdc7e8dff5d5810ff2a0ced3590ca9Giuliano Pochini
1132dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic struct snd_kcontrol_new snd_echo_line_input_gain __devinitdata = {
1133dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.name = "Line Capture Volume",
1134dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1135048b945077bdc7e8dff5d5810ff2a0ced3590ca9Giuliano Pochini	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
1136dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.info = snd_echo_input_gain_info,
1137dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.get = snd_echo_input_gain_get,
1138dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.put = snd_echo_input_gain_put,
1139048b945077bdc7e8dff5d5810ff2a0ced3590ca9Giuliano Pochini	.tlv = {.p = db_scale_input_gain},
1140dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini};
1141dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1142dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif /* ECHOCARD_HAS_INPUT_GAIN */
1143dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1144dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1145dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1146dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL
1147dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1148dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/************ Analog output nominal level (+4dBu / -10dBV) ***************/
1149dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_output_nominal_info (struct snd_kcontrol *kcontrol,
1150dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini					 struct snd_ctl_elem_info *uinfo)
1151dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1152dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1153dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1154dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1155dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1156dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->count = num_analog_busses_out(chip);
1157dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->value.integer.min = 0;
1158dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->value.integer.max = 1;
1159dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
1160dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1161dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1162dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_output_nominal_get(struct snd_kcontrol *kcontrol,
1163dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       struct snd_ctl_elem_value *ucontrol)
1164dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1165dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1166dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int c;
1167dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1168dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1169dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	for (c = 0; c < num_analog_busses_out(chip); c++)
1170dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		ucontrol->value.integer.value[c] = chip->nominal_level[c];
1171dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
1172dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1173dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1174dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_output_nominal_put(struct snd_kcontrol *kcontrol,
1175dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       struct snd_ctl_elem_value *ucontrol)
1176dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1177dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1178dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int c, changed;
1179dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1180dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	changed = 0;
1181dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1182dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	spin_lock_irq(&chip->lock);
1183dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	for (c = 0; c < num_analog_busses_out(chip); c++) {
1184dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		if (chip->nominal_level[c] != ucontrol->value.integer.value[c]) {
1185dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			set_nominal_level(chip, c,
1186dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini					  ucontrol->value.integer.value[c]);
1187dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			changed = 1;
1188dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		}
1189dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
1190dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (changed)
1191dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		update_output_line_level(chip);
1192dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	spin_unlock_irq(&chip->lock);
1193dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return changed;
1194dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1195dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1196dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic struct snd_kcontrol_new snd_echo_output_nominal_level __devinitdata = {
1197dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.name = "Line Playback Switch (-10dBV)",
1198dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1199dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.info = snd_echo_output_nominal_info,
1200dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.get = snd_echo_output_nominal_get,
1201dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.put = snd_echo_output_nominal_put,
1202dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini};
1203dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1204dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif /* ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL */
1205dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1206dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1207dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1208dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_INPUT_NOMINAL_LEVEL
1209dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1210dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/*************** Analog input nominal level (+4dBu / -10dBV) ***************/
1211dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_input_nominal_info(struct snd_kcontrol *kcontrol,
1212dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       struct snd_ctl_elem_info *uinfo)
1213dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1214dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1215dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1216dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1217dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1218dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->count = num_analog_busses_in(chip);
1219dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->value.integer.min = 0;
1220dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->value.integer.max = 1;
1221dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
1222dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1223dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1224dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_input_nominal_get(struct snd_kcontrol *kcontrol,
1225dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				      struct snd_ctl_elem_value *ucontrol)
1226dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1227dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1228dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int c;
1229dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1230dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1231dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	for (c = 0; c < num_analog_busses_in(chip); c++)
1232dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		ucontrol->value.integer.value[c] =
1233dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			chip->nominal_level[bx_analog_in(chip) + c];
1234dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
1235dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1236dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1237dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_input_nominal_put(struct snd_kcontrol *kcontrol,
1238dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				      struct snd_ctl_elem_value *ucontrol)
1239dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1240dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1241dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int c, changed;
1242dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1243dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	changed = 0;
1244dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1245dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	spin_lock_irq(&chip->lock);
1246dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	for (c = 0; c < num_analog_busses_in(chip); c++) {
1247dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		if (chip->nominal_level[bx_analog_in(chip) + c] !=
1248dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		    ucontrol->value.integer.value[c]) {
1249dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			set_nominal_level(chip, bx_analog_in(chip) + c,
1250dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini					  ucontrol->value.integer.value[c]);
1251dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			changed = 1;
1252dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		}
1253dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
1254dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (changed)
1255dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		update_output_line_level(chip);	/* "Output" is not a mistake
1256dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini						 * here.
1257dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini						 */
1258dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	spin_unlock_irq(&chip->lock);
1259dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return changed;
1260dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1261dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1262dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic struct snd_kcontrol_new snd_echo_intput_nominal_level __devinitdata = {
1263dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.name = "Line Capture Switch (-10dBV)",
1264dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1265dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.info = snd_echo_input_nominal_info,
1266dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.get = snd_echo_input_nominal_get,
1267dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.put = snd_echo_input_nominal_put,
1268dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini};
1269dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1270dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif /* ECHOCARD_HAS_INPUT_NOMINAL_LEVEL */
1271dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1272dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1273dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1274dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_MONITOR
1275dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1276dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/******************* Monitor mixer *******************/
1277dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_mixer_info(struct snd_kcontrol *kcontrol,
1278dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			       struct snd_ctl_elem_info *uinfo)
1279dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1280dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1281dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1282dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1283dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1284dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->count = 1;
1285dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->value.integer.min = ECHOGAIN_MINOUT;
1286dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->value.integer.max = ECHOGAIN_MAXOUT;
1287dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->dimen.d[0] = num_busses_out(chip);
1288dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->dimen.d[1] = num_busses_in(chip);
1289dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
1290dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1291dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1292dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_mixer_get(struct snd_kcontrol *kcontrol,
1293dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			      struct snd_ctl_elem_value *ucontrol)
1294dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1295dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1296dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1297dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1298dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	ucontrol->value.integer.value[0] =
1299dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		chip->monitor_gain[ucontrol->id.index / num_busses_in(chip)]
1300dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			[ucontrol->id.index % num_busses_in(chip)];
1301dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
1302dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1303dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1304dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_mixer_put(struct snd_kcontrol *kcontrol,
1305dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			      struct snd_ctl_elem_value *ucontrol)
1306dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1307dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1308dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int changed,  gain;
1309dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	short out, in;
1310dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1311dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	changed = 0;
1312dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1313dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	out = ucontrol->id.index / num_busses_in(chip);
1314dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	in = ucontrol->id.index % num_busses_in(chip);
1315dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	gain = ucontrol->value.integer.value[0];
1316dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (gain < ECHOGAIN_MINOUT || gain > ECHOGAIN_MAXOUT)
1317dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return -EINVAL;
1318dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (chip->monitor_gain[out][in] != gain) {
1319dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		spin_lock_irq(&chip->lock);
1320dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		set_monitor_gain(chip, out, in, gain);
1321dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		update_output_line_level(chip);
1322dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		spin_unlock_irq(&chip->lock);
1323dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		changed = 1;
1324dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
1325dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return changed;
1326dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1327dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1328dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic struct snd_kcontrol_new snd_echo_monitor_mixer __devinitdata = {
1329dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.name = "Monitor Mixer Volume",
1330dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1331048b945077bdc7e8dff5d5810ff2a0ced3590ca9Giuliano Pochini	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
1332dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.info = snd_echo_mixer_info,
1333dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.get = snd_echo_mixer_get,
1334dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.put = snd_echo_mixer_put,
1335048b945077bdc7e8dff5d5810ff2a0ced3590ca9Giuliano Pochini	.tlv = {.p = db_scale_output_gain},
1336dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini};
1337dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1338dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif /* ECHOCARD_HAS_MONITOR */
1339dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1340dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1341dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1342dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_VMIXER
1343dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1344dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/******************* Vmixer *******************/
1345dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_vmixer_info(struct snd_kcontrol *kcontrol,
1346dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				struct snd_ctl_elem_info *uinfo)
1347dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1348dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1349dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1350dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1351dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1352dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->count = 1;
1353dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->value.integer.min = ECHOGAIN_MINOUT;
1354dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->value.integer.max = ECHOGAIN_MAXOUT;
1355dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->dimen.d[0] = num_busses_out(chip);
1356dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->dimen.d[1] = num_pipes_out(chip);
1357dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
1358dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1359dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1360dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_vmixer_get(struct snd_kcontrol *kcontrol,
1361dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			       struct snd_ctl_elem_value *ucontrol)
1362dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1363dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1364dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1365dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1366dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	ucontrol->value.integer.value[0] =
1367dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		chip->vmixer_gain[ucontrol->id.index / num_pipes_out(chip)]
1368dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			[ucontrol->id.index % num_pipes_out(chip)];
1369dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
1370dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1371dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1372dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_vmixer_put(struct snd_kcontrol *kcontrol,
1373dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			       struct snd_ctl_elem_value *ucontrol)
1374dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1375dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1376dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int gain, changed;
1377dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	short vch, out;
1378dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1379dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	changed = 0;
1380dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1381dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	out = ucontrol->id.index / num_pipes_out(chip);
1382dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	vch = ucontrol->id.index % num_pipes_out(chip);
1383dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	gain = ucontrol->value.integer.value[0];
1384dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (gain < ECHOGAIN_MINOUT || gain > ECHOGAIN_MAXOUT)
1385dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return -EINVAL;
1386dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (chip->vmixer_gain[out][vch] != ucontrol->value.integer.value[0]) {
1387dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		spin_lock_irq(&chip->lock);
1388dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		set_vmixer_gain(chip, out, vch, ucontrol->value.integer.value[0]);
1389dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		update_vmixer_level(chip);
1390dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		spin_unlock_irq(&chip->lock);
1391dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		changed = 1;
1392dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
1393dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return changed;
1394dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1395dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1396dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic struct snd_kcontrol_new snd_echo_vmixer __devinitdata = {
1397dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.name = "VMixer Volume",
1398dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1399048b945077bdc7e8dff5d5810ff2a0ced3590ca9Giuliano Pochini	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
1400dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.info = snd_echo_vmixer_info,
1401dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.get = snd_echo_vmixer_get,
1402dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.put = snd_echo_vmixer_put,
1403048b945077bdc7e8dff5d5810ff2a0ced3590ca9Giuliano Pochini	.tlv = {.p = db_scale_output_gain},
1404dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini};
1405dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1406dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif /* ECHOCARD_HAS_VMIXER */
1407dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1408dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1409dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1410dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_DIGITAL_MODE_SWITCH
1411dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1412dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/******************* Digital mode switch *******************/
1413dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_digital_mode_info(struct snd_kcontrol *kcontrol,
1414dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				      struct snd_ctl_elem_info *uinfo)
1415dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1416dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	static char *names[4] = {
1417dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		"S/PDIF Coaxial", "S/PDIF Optical", "ADAT Optical",
1418dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		"S/PDIF Cdrom"
1419dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	};
1420dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1421dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1422dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1423dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1424dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->value.enumerated.items = chip->num_digital_modes;
1425dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->count = 1;
1426dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (uinfo->value.enumerated.item >= chip->num_digital_modes)
1427dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		uinfo->value.enumerated.item = chip->num_digital_modes - 1;
1428dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	strcpy(uinfo->value.enumerated.name, names[
1429dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			chip->digital_mode_list[uinfo->value.enumerated.item]]);
1430dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
1431dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1432dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1433dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_digital_mode_get(struct snd_kcontrol *kcontrol,
1434dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				     struct snd_ctl_elem_value *ucontrol)
1435dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1436dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1437dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int i, mode;
1438dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1439dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1440dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	mode = chip->digital_mode;
1441dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	for (i = chip->num_digital_modes - 1; i >= 0; i--)
1442dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		if (mode == chip->digital_mode_list[i]) {
1443dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			ucontrol->value.enumerated.item[0] = i;
1444dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			break;
1445dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		}
1446dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
1447dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1448dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1449dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_digital_mode_put(struct snd_kcontrol *kcontrol,
1450dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				     struct snd_ctl_elem_value *ucontrol)
1451dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1452dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1453dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int changed;
1454dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	unsigned short emode, dmode;
1455dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1456dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	changed = 0;
1457dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1458dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1459dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	emode = ucontrol->value.enumerated.item[0];
1460dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (emode >= chip->num_digital_modes)
1461dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return -EINVAL;
1462dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	dmode = chip->digital_mode_list[emode];
1463dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1464dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (dmode != chip->digital_mode) {
1465dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		/* mode_mutex is required to make this operation atomic wrt
1466dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		pcm_digital_*_open() and set_input_clock() functions. */
1467befceea90b17792cb03cc4e22f3329c89621bba3Takashi Iwai		mutex_lock(&chip->mode_mutex);
1468dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1469dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		/* Do not allow the user to change the digital mode when a pcm
1470dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		device is open because it also changes the number of channels
1471dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		and the allowed sample rates */
1472dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		if (atomic_read(&chip->opencount)) {
1473dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			changed = -EAGAIN;
1474dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		} else {
1475dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			changed = set_digital_mode(chip, dmode);
1476dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			/* If we had to change the clock source, report it */
1477dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			if (changed > 0 && chip->clock_src_ctl) {
1478dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				snd_ctl_notify(chip->card,
1479dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini					       SNDRV_CTL_EVENT_MASK_VALUE,
1480dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini					       &chip->clock_src_ctl->id);
1481dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				DE_ACT(("SDM() =%d\n", changed));
1482dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			}
1483dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			if (changed >= 0)
1484dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				changed = 1;	/* No errors */
1485dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		}
1486befceea90b17792cb03cc4e22f3329c89621bba3Takashi Iwai		mutex_unlock(&chip->mode_mutex);
1487dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
1488dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return changed;
1489dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1490dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1491dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic struct snd_kcontrol_new snd_echo_digital_mode_switch __devinitdata = {
1492dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.name = "Digital mode Switch",
1493dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.iface = SNDRV_CTL_ELEM_IFACE_CARD,
1494dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.info = snd_echo_digital_mode_info,
1495dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.get = snd_echo_digital_mode_get,
1496dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.put = snd_echo_digital_mode_put,
1497dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini};
1498dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1499dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif /* ECHOCARD_HAS_DIGITAL_MODE_SWITCH */
1500dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1501dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1502dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1503dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_DIGITAL_IO
1504dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1505dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/******************* S/PDIF mode switch *******************/
1506dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_spdif_mode_info(struct snd_kcontrol *kcontrol,
1507dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				    struct snd_ctl_elem_info *uinfo)
1508dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1509dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	static char *names[2] = {"Consumer", "Professional"};
1510dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1511dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1512dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->value.enumerated.items = 2;
1513dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->count = 1;
1514dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (uinfo->value.enumerated.item)
1515dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		uinfo->value.enumerated.item = 1;
1516dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	strcpy(uinfo->value.enumerated.name,
1517dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	       names[uinfo->value.enumerated.item]);
1518dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
1519dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1520dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1521dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_spdif_mode_get(struct snd_kcontrol *kcontrol,
1522dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				   struct snd_ctl_elem_value *ucontrol)
1523dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1524dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1525dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1526dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1527dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	ucontrol->value.enumerated.item[0] = !!chip->professional_spdif;
1528dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
1529dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1530dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1531dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_spdif_mode_put(struct snd_kcontrol *kcontrol,
1532dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				   struct snd_ctl_elem_value *ucontrol)
1533dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1534dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1535dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int mode;
1536dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1537dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1538dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	mode = !!ucontrol->value.enumerated.item[0];
1539dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (mode != chip->professional_spdif) {
1540dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		spin_lock_irq(&chip->lock);
1541dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		set_professional_spdif(chip, mode);
1542dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		spin_unlock_irq(&chip->lock);
1543dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return 1;
1544dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
1545dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
1546dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1547dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1548dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic struct snd_kcontrol_new snd_echo_spdif_mode_switch __devinitdata = {
1549dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.name = "S/PDIF mode Switch",
1550dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.iface = SNDRV_CTL_ELEM_IFACE_CARD,
1551dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.info = snd_echo_spdif_mode_info,
1552dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.get = snd_echo_spdif_mode_get,
1553dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.put = snd_echo_spdif_mode_put,
1554dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini};
1555dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1556dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif /* ECHOCARD_HAS_DIGITAL_IO */
1557dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1558dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1559dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1560dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_EXTERNAL_CLOCK
1561dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1562dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/******************* Select input clock source *******************/
1563dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_clock_source_info(struct snd_kcontrol *kcontrol,
1564dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				      struct snd_ctl_elem_info *uinfo)
1565dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1566dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	static char *names[8] = {
1567dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		"Internal", "Word", "Super", "S/PDIF", "ADAT", "ESync",
1568dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		"ESync96", "MTC"
1569dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	};
1570dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1571dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1572dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1573dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1574dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->value.enumerated.items = chip->num_clock_sources;
1575dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->count = 1;
1576dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (uinfo->value.enumerated.item >= chip->num_clock_sources)
1577dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		uinfo->value.enumerated.item = chip->num_clock_sources - 1;
1578dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	strcpy(uinfo->value.enumerated.name, names[
1579dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			chip->clock_source_list[uinfo->value.enumerated.item]]);
1580dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
1581dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1582dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1583dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_clock_source_get(struct snd_kcontrol *kcontrol,
1584dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				     struct snd_ctl_elem_value *ucontrol)
1585dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1586dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1587dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int i, clock;
1588dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1589dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1590dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	clock = chip->input_clock;
1591dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1592dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	for (i = 0; i < chip->num_clock_sources; i++)
1593dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		if (clock == chip->clock_source_list[i])
1594dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			ucontrol->value.enumerated.item[0] = i;
1595dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1596dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
1597dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1598dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1599dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_clock_source_put(struct snd_kcontrol *kcontrol,
1600dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				     struct snd_ctl_elem_value *ucontrol)
1601dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1602dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1603dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int changed;
1604dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	unsigned int eclock, dclock;
1605dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1606dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	changed = 0;
1607dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1608dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	eclock = ucontrol->value.enumerated.item[0];
1609dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (eclock >= chip->input_clock_types)
1610dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return -EINVAL;
1611dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	dclock = chip->clock_source_list[eclock];
1612dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (chip->input_clock != dclock) {
1613befceea90b17792cb03cc4e22f3329c89621bba3Takashi Iwai		mutex_lock(&chip->mode_mutex);
1614dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		spin_lock_irq(&chip->lock);
1615dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		if ((changed = set_input_clock(chip, dclock)) == 0)
1616dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			changed = 1;	/* no errors */
1617dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		spin_unlock_irq(&chip->lock);
1618befceea90b17792cb03cc4e22f3329c89621bba3Takashi Iwai		mutex_unlock(&chip->mode_mutex);
1619dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
1620dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1621dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (changed < 0)
1622dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		DE_ACT(("seticlk val%d err 0x%x\n", dclock, changed));
1623dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1624dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return changed;
1625dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1626dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1627dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic struct snd_kcontrol_new snd_echo_clock_source_switch __devinitdata = {
1628dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.name = "Sample Clock Source",
1629dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.iface = SNDRV_CTL_ELEM_IFACE_PCM,
1630dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.info = snd_echo_clock_source_info,
1631dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.get = snd_echo_clock_source_get,
1632dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.put = snd_echo_clock_source_put,
1633dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini};
1634dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1635dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif /* ECHOCARD_HAS_EXTERNAL_CLOCK */
1636dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1637dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1638dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1639dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_PHANTOM_POWER
1640dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1641dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/******************* Phantom power switch *******************/
1642a5ce88909d3007caa7b65996a8f6784350beb2a6Takashi Iwai#define snd_echo_phantom_power_info	snd_ctl_boolean_mono_info
1643dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1644dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_phantom_power_get(struct snd_kcontrol *kcontrol,
1645dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				      struct snd_ctl_elem_value *ucontrol)
1646dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1647dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip = snd_kcontrol_chip(kcontrol);
1648dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1649dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	ucontrol->value.integer.value[0] = chip->phantom_power;
1650dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
1651dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1652dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1653dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_phantom_power_put(struct snd_kcontrol *kcontrol,
1654dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				      struct snd_ctl_elem_value *ucontrol)
1655dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1656dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip = snd_kcontrol_chip(kcontrol);
1657dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int power, changed = 0;
1658dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1659dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	power = !!ucontrol->value.integer.value[0];
1660dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (chip->phantom_power != power) {
1661dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		spin_lock_irq(&chip->lock);
1662dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		changed = set_phantom_power(chip, power);
1663dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		spin_unlock_irq(&chip->lock);
1664dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		if (changed == 0)
1665dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			changed = 1;	/* no errors */
1666dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
1667dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return changed;
1668dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1669dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1670dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic struct snd_kcontrol_new snd_echo_phantom_power_switch __devinitdata = {
1671dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.name = "Phantom power Switch",
1672dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.iface = SNDRV_CTL_ELEM_IFACE_CARD,
1673dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.info = snd_echo_phantom_power_info,
1674dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.get = snd_echo_phantom_power_get,
1675dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.put = snd_echo_phantom_power_put,
1676dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini};
1677dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1678dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif /* ECHOCARD_HAS_PHANTOM_POWER */
1679dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1680dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1681dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1682dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE
1683dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1684dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/******************* Digital input automute switch *******************/
1685a5ce88909d3007caa7b65996a8f6784350beb2a6Takashi Iwai#define snd_echo_automute_info		snd_ctl_boolean_mono_info
1686dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1687dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_automute_get(struct snd_kcontrol *kcontrol,
1688dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				 struct snd_ctl_elem_value *ucontrol)
1689dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1690dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip = snd_kcontrol_chip(kcontrol);
1691dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1692dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	ucontrol->value.integer.value[0] = chip->digital_in_automute;
1693dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
1694dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1695dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1696dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_automute_put(struct snd_kcontrol *kcontrol,
1697dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				 struct snd_ctl_elem_value *ucontrol)
1698dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1699dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip = snd_kcontrol_chip(kcontrol);
1700dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int automute, changed = 0;
1701dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1702dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	automute = !!ucontrol->value.integer.value[0];
1703dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (chip->digital_in_automute != automute) {
1704dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		spin_lock_irq(&chip->lock);
1705dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		changed = set_input_auto_mute(chip, automute);
1706dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		spin_unlock_irq(&chip->lock);
1707dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		if (changed == 0)
1708dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			changed = 1;	/* no errors */
1709dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
1710dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return changed;
1711dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1712dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1713dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic struct snd_kcontrol_new snd_echo_automute_switch __devinitdata = {
1714dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.name = "Digital Capture Switch (automute)",
1715dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.iface = SNDRV_CTL_ELEM_IFACE_CARD,
1716dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.info = snd_echo_automute_info,
1717dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.get = snd_echo_automute_get,
1718dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.put = snd_echo_automute_put,
1719dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini};
1720dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1721dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif /* ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE */
1722dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1723dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1724dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1725dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/******************* VU-meters switch *******************/
1726a5ce88909d3007caa7b65996a8f6784350beb2a6Takashi Iwai#define snd_echo_vumeters_switch_info		snd_ctl_boolean_mono_info
1727dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1728dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_vumeters_switch_put(struct snd_kcontrol *kcontrol,
1729dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini					struct snd_ctl_elem_value *ucontrol)
1730dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1731dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1732dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1733dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1734dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	spin_lock_irq(&chip->lock);
1735dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	set_meters_on(chip, ucontrol->value.integer.value[0]);
1736dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	spin_unlock_irq(&chip->lock);
1737dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 1;
1738dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1739dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1740dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic struct snd_kcontrol_new snd_echo_vumeters_switch __devinitdata = {
1741dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.name = "VU-meters Switch",
1742dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.iface = SNDRV_CTL_ELEM_IFACE_CARD,
1743dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.access = SNDRV_CTL_ELEM_ACCESS_WRITE,
1744dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.info = snd_echo_vumeters_switch_info,
1745dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.put = snd_echo_vumeters_switch_put,
1746dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini};
1747dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1748dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1749dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1750dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/***** Read VU-meters (input, output, analog and digital together) *****/
1751dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_vumeters_info(struct snd_kcontrol *kcontrol,
1752dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				  struct snd_ctl_elem_info *uinfo)
1753dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1754dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1755dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1756dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1757dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1758dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->count = 96;
1759dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->value.integer.min = ECHOGAIN_MINOUT;
1760dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->value.integer.max = 0;
1761dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_VMIXER
1762dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->dimen.d[0] = 3;	/* Out, In, Virt */
1763dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#else
1764dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->dimen.d[0] = 2;	/* Out, In */
1765dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif
1766dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->dimen.d[1] = 16;	/* 16 channels */
1767dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->dimen.d[2] = 2;	/* 0=level, 1=peak */
1768dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
1769dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1770dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1771dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_vumeters_get(struct snd_kcontrol *kcontrol,
1772dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				 struct snd_ctl_elem_value *ucontrol)
1773dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1774dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1775dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1776dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1777dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	get_audio_meters(chip, ucontrol->value.integer.value);
1778dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
1779dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1780dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1781dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic struct snd_kcontrol_new snd_echo_vumeters __devinitdata = {
1782dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.name = "VU-meters",
1783dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1784048b945077bdc7e8dff5d5810ff2a0ced3590ca9Giuliano Pochini	.access = SNDRV_CTL_ELEM_ACCESS_READ |
1785048b945077bdc7e8dff5d5810ff2a0ced3590ca9Giuliano Pochini		  SNDRV_CTL_ELEM_ACCESS_VOLATILE |
1786048b945077bdc7e8dff5d5810ff2a0ced3590ca9Giuliano Pochini		  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
1787dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.info = snd_echo_vumeters_info,
1788dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.get = snd_echo_vumeters_get,
1789048b945077bdc7e8dff5d5810ff2a0ced3590ca9Giuliano Pochini	.tlv = {.p = db_scale_output_gain},
1790dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini};
1791dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1792dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1793dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1794dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/*** Channels info - it exports informations about the number of channels ***/
1795dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_channels_info_info(struct snd_kcontrol *kcontrol,
1796dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				       struct snd_ctl_elem_info *uinfo)
1797dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1798dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1799dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1800dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1801dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1802dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->count = 6;
1803dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->value.integer.min = 0;
1804dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	uinfo->value.integer.max = 1 << ECHO_CLOCK_NUMBER;
1805dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
1806dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1807dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1808dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_channels_info_get(struct snd_kcontrol *kcontrol,
1809dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				      struct snd_ctl_elem_value *ucontrol)
1810dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1811dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1812dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int detected, clocks, bit, src;
1813dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1814dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = snd_kcontrol_chip(kcontrol);
1815dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	ucontrol->value.integer.value[0] = num_busses_in(chip);
1816dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	ucontrol->value.integer.value[1] = num_analog_busses_in(chip);
1817dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	ucontrol->value.integer.value[2] = num_busses_out(chip);
1818dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	ucontrol->value.integer.value[3] = num_analog_busses_out(chip);
1819dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	ucontrol->value.integer.value[4] = num_pipes_out(chip);
1820dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1821dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* Compute the bitmask of the currently valid input clocks */
1822dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	detected = detect_input_clocks(chip);
1823dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	clocks = 0;
1824dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	src = chip->num_clock_sources - 1;
1825dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	for (bit = ECHO_CLOCK_NUMBER - 1; bit >= 0; bit--)
1826dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		if (detected & (1 << bit))
1827dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			for (; src >= 0; src--)
1828dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				if (bit == chip->clock_source_list[src]) {
1829dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini					clocks |= 1 << src;
1830dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini					break;
1831dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				}
1832dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	ucontrol->value.integer.value[5] = clocks;
1833dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1834dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
1835dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1836dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1837dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic struct snd_kcontrol_new snd_echo_channels_info __devinitdata = {
1838dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.name = "Channels info",
1839dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.iface = SNDRV_CTL_ELEM_IFACE_HWDEP,
1840dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1841dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.info = snd_echo_channels_info_info,
1842dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.get = snd_echo_channels_info_get,
1843dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini};
1844dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1845dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1846dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1847dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1848dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/******************************************************************************
1849dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	IRQ Handler
1850dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini******************************************************************************/
1851dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
18527d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t snd_echo_interrupt(int irq, void *dev_id)
1853dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1854dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip = dev_id;
1855dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct snd_pcm_substream *substream;
1856dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int period, ss, st;
1857dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1858dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	spin_lock(&chip->lock);
1859dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	st = service_irq(chip);
1860dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (st < 0) {
1861dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		spin_unlock(&chip->lock);
1862dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return IRQ_NONE;
1863dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
1864dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* The hardware doesn't tell us which substream caused the irq,
1865dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	thus we have to check all running substreams. */
1866dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	for (ss = 0; ss < DSP_MAXPIPES; ss++) {
1867b721e68bdc5b39c51bf6a1469f8d3663fbe03243Giuliano Pochini		substream = chip->substream[ss];
1868b721e68bdc5b39c51bf6a1469f8d3663fbe03243Giuliano Pochini		if (substream && ((struct audiopipe *)substream->runtime->
1869b721e68bdc5b39c51bf6a1469f8d3663fbe03243Giuliano Pochini				private_data)->state == PIPE_STATE_STARTED) {
1870dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			period = pcm_pointer(substream) /
1871dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				substream->runtime->period_size;
1872dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			if (period != chip->last_period[ss]) {
1873dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				chip->last_period[ss] = period;
1874dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				spin_unlock(&chip->lock);
1875dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				snd_pcm_period_elapsed(substream);
1876dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				spin_lock(&chip->lock);
1877dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			}
1878dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		}
1879dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
1880dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	spin_unlock(&chip->lock);
1881dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1882dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_MIDI
1883dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (st > 0 && chip->midi_in) {
1884dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		snd_rawmidi_receive(chip->midi_in, chip->midi_buffer, st);
1885dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		DE_MID(("rawmidi_iread=%d\n", st));
1886dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
1887dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif
1888dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return IRQ_HANDLED;
1889dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1890dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1891dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1892dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1893dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1894dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/******************************************************************************
1895dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	Module construction / destruction
1896dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini******************************************************************************/
1897dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1898dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_free(struct echoaudio *chip)
1899dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1900dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	DE_INIT(("Stop DSP...\n"));
1901ebf029da38829ede6b53ac8a5ad45b149064ea16Takashi Iwai	if (chip->comm_page)
1902dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		rest_in_peace(chip);
1903dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	DE_INIT(("Stopped.\n"));
1904dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1905dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (chip->irq >= 0)
1906437a5a4606c12ab904793a7cad5b2062fc76c04eTakashi Iwai		free_irq(chip->irq, chip);
1907dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1908ebf029da38829ede6b53ac8a5ad45b149064ea16Takashi Iwai	if (chip->comm_page)
1909ebf029da38829ede6b53ac8a5ad45b149064ea16Takashi Iwai		snd_dma_free_pages(&chip->commpage_dma_buf);
1910ebf029da38829ede6b53ac8a5ad45b149064ea16Takashi Iwai
1911dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (chip->dsp_registers)
1912dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		iounmap(chip->dsp_registers);
1913dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
19148caf7aa26e0797e5706043f94c491acd1a08636aTakashi Iwai	if (chip->iores)
19158caf7aa26e0797e5706043f94c491acd1a08636aTakashi Iwai		release_and_free_resource(chip->iores);
19168caf7aa26e0797e5706043f94c491acd1a08636aTakashi Iwai
1917dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	DE_INIT(("MMIO freed.\n"));
1918dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1919dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	pci_disable_device(chip->pci);
1920dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1921dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* release chip data */
19224f8ada444cc7a7ea70cdc81f098b34c5f1f2df41Giuliano Pochini	free_firmware_cache(chip);
1923dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	kfree(chip);
1924dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	DE_INIT(("Chip freed.\n"));
1925dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
1926dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1927dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1928dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1929dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1930dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int snd_echo_dev_free(struct snd_device *device)
1931dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1932dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip = device->device_data;
1933dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1934dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	DE_INIT(("snd_echo_dev_free()...\n"));
1935dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return snd_echo_free(chip);
1936dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
1937dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1938dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1939dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1940dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/* <--snd_echo_probe() */
1941dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic __devinit int snd_echo_create(struct snd_card *card,
1942dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				     struct pci_dev *pci,
1943dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				     struct echoaudio **rchip)
1944dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
1945dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
1946dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int err;
1947dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	size_t sz;
1948dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	static struct snd_device_ops ops = {
1949dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		.dev_free = snd_echo_dev_free,
1950dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	};
1951dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1952dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	*rchip = NULL;
1953dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1954dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	pci_write_config_byte(pci, PCI_LATENCY_TIMER, 0xC0);
1955dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1956dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = pci_enable_device(pci)) < 0)
1957dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return err;
1958dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	pci_set_master(pci);
1959dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
196047b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	/* Allocate chip if needed */
196147b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	if (!*rchip) {
196247b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		chip = kzalloc(sizeof(*chip), GFP_KERNEL);
196347b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		if (!chip) {
196447b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini			pci_disable_device(pci);
196547b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini			return -ENOMEM;
196647b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		}
196747b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		DE_INIT(("chip=%p\n", chip));
196847b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		spin_lock_init(&chip->lock);
196947b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		chip->card = card;
197047b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		chip->pci = pci;
197147b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		chip->irq = -1;
197247b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		atomic_set(&chip->opencount, 0);
197347b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		mutex_init(&chip->mode_mutex);
197447b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		chip->can_set_rate = 1;
197547b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	} else {
197647b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		/* If this was called from the resume function, chip is
197747b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		 * already allocated and it contains current card settings.
197847b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		 */
197947b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		chip = *rchip;
1980dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
1981dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1982dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* PCI resource allocation */
1983dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip->dsp_registers_phys = pci_resource_start(pci, 0);
1984dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	sz = pci_resource_len(pci, 0);
1985dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (sz > PAGE_SIZE)
1986dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		sz = PAGE_SIZE;		/* We map only the required part */
1987dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1988dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((chip->iores = request_mem_region(chip->dsp_registers_phys, sz,
1989dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini					      ECHOCARD_NAME)) == NULL) {
1990dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		snd_echo_free(chip);
1991dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		snd_printk(KERN_ERR "cannot get memory region\n");
1992dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return -EBUSY;
1993dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
1994dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip->dsp_registers = (volatile u32 __iomem *)
1995dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		ioremap_nocache(chip->dsp_registers_phys, sz);
1996dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
1997437a5a4606c12ab904793a7cad5b2062fc76c04eTakashi Iwai	if (request_irq(pci->irq, snd_echo_interrupt, IRQF_SHARED,
1998437a5a4606c12ab904793a7cad5b2062fc76c04eTakashi Iwai			ECHOCARD_NAME, chip)) {
1999dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		snd_echo_free(chip);
2000dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		snd_printk(KERN_ERR "cannot grab irq\n");
2001dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return -EBUSY;
2002dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
2003dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip->irq = pci->irq;
2004dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	DE_INIT(("pci=%p irq=%d subdev=%04x Init hardware...\n",
2005dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		 chip->pci, chip->irq, chip->pci->subsystem_device));
2006dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2007dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* Create the DSP comm page - this is the area of memory used for most
2008dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	of the communication with the DSP, which accesses it via bus mastering */
2009dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
2010dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				sizeof(struct comm_page),
2011dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				&chip->commpage_dma_buf) < 0) {
2012dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		snd_echo_free(chip);
2013dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		snd_printk(KERN_ERR "cannot allocate the comm page\n");
2014dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return -ENOMEM;
2015dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
2016dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip->comm_page_phys = chip->commpage_dma_buf.addr;
2017dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip->comm_page = (struct comm_page *)chip->commpage_dma_buf.area;
2018dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2019dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	err = init_hw(chip, chip->pci->device, chip->pci->subsystem_device);
202047b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	if (err >= 0)
202147b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		err = set_mixer_defaults(chip);
202247b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	if (err < 0) {
2023dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		DE_INIT(("init_hw err=%d\n", err));
2024dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		snd_echo_free(chip);
2025dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return err;
2026dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
2027dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	DE_INIT(("Card init OK\n"));
2028dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2029dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
2030dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		snd_echo_free(chip);
2031dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return err;
2032dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
2033dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	*rchip = chip;
2034dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* Init done ! */
2035dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
2036dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
2037dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2038dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2039dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2040dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/* constructor */
2041dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int __devinit snd_echo_probe(struct pci_dev *pci,
2042dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini				    const struct pci_device_id *pci_id)
2043dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
2044dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	static int dev;
2045dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct snd_card *card;
2046dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
2047dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	char *dsp;
2048dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	int i, err;
2049dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2050dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (dev >= SNDRV_CARDS)
2051dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return -ENODEV;
2052dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (!enable[dev]) {
2053dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		dev++;
2054dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return -ENOENT;
2055dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
2056dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2057dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	DE_INIT(("Echoaudio driver starting...\n"));
2058dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	i = 0;
2059e58de7baf7de11f01a675cbbf6ecc8a2758b9ca5Takashi Iwai	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
2060e58de7baf7de11f01a675cbbf6ecc8a2758b9ca5Takashi Iwai	if (err < 0)
2061e58de7baf7de11f01a675cbbf6ecc8a2758b9ca5Takashi Iwai		return err;
2062dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2063c187c041c6552339e4d8883a1a00c3c489354ecaTakashi Iwai	snd_card_set_dev(card, &pci->dev);
2064c187c041c6552339e4d8883a1a00c3c489354ecaTakashi Iwai
206547b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	chip = NULL;	/* Tells snd_echo_create to allocate chip */
2066dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_echo_create(card, pci, &chip)) < 0) {
2067dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		snd_card_free(card);
2068dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return err;
2069dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
2070dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2071dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	strcpy(card->driver, "Echo_" ECHOCARD_NAME);
2072dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	strcpy(card->shortname, chip->card_name);
2073dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2074dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	dsp = "56301";
2075dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (pci_id->device == 0x3410)
2076dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		dsp = "56361";
2077dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2078dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	sprintf(card->longname, "%s rev.%d (DSP%s) at 0x%lx irq %i",
2079dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		card->shortname, pci_id->subdevice & 0x000f, dsp,
2080dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		chip->dsp_registers_phys, chip->irq);
2081dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2082dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_echo_new_pcm(chip)) < 0) {
2083dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		snd_printk(KERN_ERR "new pcm error %d\n", err);
2084dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		snd_card_free(card);
2085dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		return err;
2086dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
2087dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2088dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_MIDI
2089dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (chip->has_midi) {	/* Some Mia's do not have midi */
2090dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		if ((err = snd_echo_midi_create(card, chip)) < 0) {
2091dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			snd_printk(KERN_ERR "new midi error %d\n", err);
2092dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			snd_card_free(card);
2093dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			return err;
2094dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		}
2095dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
2096dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif
2097dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2098dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_VMIXER
2099dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	snd_echo_vmixer.count = num_pipes_out(chip) * num_busses_out(chip);
2100dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vmixer, chip))) < 0)
2101dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		goto ctl_error;
2102392bf2f1ba03b690f0ee71a185d4a5720a82bb25Giuliano Pochini#ifdef ECHOCARD_HAS_LINE_OUT_GAIN
2103392bf2f1ba03b690f0ee71a185d4a5720a82bb25Giuliano Pochini	err = snd_ctl_add(chip->card,
2104392bf2f1ba03b690f0ee71a185d4a5720a82bb25Giuliano Pochini			  snd_ctl_new1(&snd_echo_line_output_gain, chip));
2105392bf2f1ba03b690f0ee71a185d4a5720a82bb25Giuliano Pochini	if (err < 0)
2106dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		goto ctl_error;
2107dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif
2108392bf2f1ba03b690f0ee71a185d4a5720a82bb25Giuliano Pochini#else /* ECHOCARD_HAS_VMIXER */
2109392bf2f1ba03b690f0ee71a185d4a5720a82bb25Giuliano Pochini	err = snd_ctl_add(chip->card,
2110392bf2f1ba03b690f0ee71a185d4a5720a82bb25Giuliano Pochini			  snd_ctl_new1(&snd_echo_pcm_output_gain, chip));
2111392bf2f1ba03b690f0ee71a185d4a5720a82bb25Giuliano Pochini	if (err < 0)
2112392bf2f1ba03b690f0ee71a185d4a5720a82bb25Giuliano Pochini		goto ctl_error;
2113392bf2f1ba03b690f0ee71a185d4a5720a82bb25Giuliano Pochini#endif /* ECHOCARD_HAS_VMIXER */
2114dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2115dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_INPUT_GAIN
2116dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_line_input_gain, chip))) < 0)
2117dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		goto ctl_error;
2118dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif
2119dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2120dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_INPUT_NOMINAL_LEVEL
2121dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (!chip->hasnt_input_nominal_level)
2122dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_intput_nominal_level, chip))) < 0)
2123dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			goto ctl_error;
2124dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif
2125dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2126dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL
2127dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_output_nominal_level, chip))) < 0)
2128dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		goto ctl_error;
2129dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif
2130dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2131dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vumeters_switch, chip))) < 0)
2132dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		goto ctl_error;
2133dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2134dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vumeters, chip))) < 0)
2135dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		goto ctl_error;
2136dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2137dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_MONITOR
2138dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	snd_echo_monitor_mixer.count = num_busses_in(chip) * num_busses_out(chip);
2139dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_monitor_mixer, chip))) < 0)
2140dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		goto ctl_error;
2141dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif
2142dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2143dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE
2144dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_automute_switch, chip))) < 0)
2145dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		goto ctl_error;
2146dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif
2147dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2148dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_channels_info, chip))) < 0)
2149dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		goto ctl_error;
2150dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2151dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_DIGITAL_MODE_SWITCH
2152dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* Creates a list of available digital modes */
2153dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip->num_digital_modes = 0;
2154dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	for (i = 0; i < 6; i++)
2155dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		if (chip->digital_modes & (1 << i))
2156dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			chip->digital_mode_list[chip->num_digital_modes++] = i;
2157dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2158dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_digital_mode_switch, chip))) < 0)
2159dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		goto ctl_error;
2160dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif /* ECHOCARD_HAS_DIGITAL_MODE_SWITCH */
2161dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2162dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_EXTERNAL_CLOCK
2163dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	/* Creates a list of available clock sources */
2164dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip->num_clock_sources = 0;
2165dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	for (i = 0; i < 10; i++)
2166dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		if (chip->input_clock_types & (1 << i))
2167dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			chip->clock_source_list[chip->num_clock_sources++] = i;
2168dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2169dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (chip->num_clock_sources > 1) {
2170dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		chip->clock_src_ctl = snd_ctl_new1(&snd_echo_clock_source_switch, chip);
2171dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		if ((err = snd_ctl_add(chip->card, chip->clock_src_ctl)) < 0)
2172dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			goto ctl_error;
2173dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	}
2174dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif /* ECHOCARD_HAS_EXTERNAL_CLOCK */
2175dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2176dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_DIGITAL_IO
2177dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_spdif_mode_switch, chip))) < 0)
2178dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		goto ctl_error;
2179dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif
2180dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2181dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#ifdef ECHOCARD_HAS_PHANTOM_POWER
2182dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (chip->has_phantom_power)
2183dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_phantom_power_switch, chip))) < 0)
2184dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini			goto ctl_error;
2185dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini#endif
2186dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2187a0fd4345f928d72a56e27b23e4cd28c94bf36be5Julia Lawall	err = snd_card_register(card);
2188a0fd4345f928d72a56e27b23e4cd28c94bf36be5Julia Lawall	if (err < 0)
2189dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		goto ctl_error;
2190dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	snd_printk(KERN_INFO "Card registered: %s\n", card->longname);
2191dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2192dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	pci_set_drvdata(pci, chip);
2193dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	dev++;
2194dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return 0;
2195dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2196dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinictl_error:
2197dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	snd_printk(KERN_ERR "new control error %d\n", err);
2198dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	snd_card_free(card);
2199dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return err;
2200dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
2201dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2202dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2203dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
220447b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini#if defined(CONFIG_PM)
220547b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini
220647b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochinistatic int snd_echo_suspend(struct pci_dev *pci, pm_message_t state)
220747b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini{
220847b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	struct echoaudio *chip = pci_get_drvdata(pci);
220947b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini
221047b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	DE_INIT(("suspend start\n"));
221147b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	snd_pcm_suspend_all(chip->analog_pcm);
221247b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	snd_pcm_suspend_all(chip->digital_pcm);
221347b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini
221447b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini#ifdef ECHOCARD_HAS_MIDI
221547b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	/* This call can sleep */
221647b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	if (chip->midi_out)
221747b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		snd_echo_midi_output_trigger(chip->midi_out, 0);
221847b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini#endif
221947b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	spin_lock_irq(&chip->lock);
222047b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	if (wait_handshake(chip)) {
222147b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		spin_unlock_irq(&chip->lock);
222247b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		return -EIO;
222347b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	}
222447b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	clear_handshake(chip);
222547b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	if (send_vector(chip, DSP_VC_GO_COMATOSE) < 0) {
222647b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		spin_unlock_irq(&chip->lock);
222747b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		return -EIO;
222847b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	}
222947b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	spin_unlock_irq(&chip->lock);
223047b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini
223147b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	chip->dsp_code = NULL;
223247b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	free_irq(chip->irq, chip);
223347b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	chip->irq = -1;
223447b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	pci_save_state(pci);
223547b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	pci_disable_device(pci);
223647b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini
223747b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	DE_INIT(("suspend done\n"));
223847b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	return 0;
223947b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini}
224047b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini
224147b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini
224247b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini
224347b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochinistatic int snd_echo_resume(struct pci_dev *pci)
224447b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini{
224547b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	struct echoaudio *chip = pci_get_drvdata(pci);
224647b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	struct comm_page *commpage, *commpage_bak;
224747b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	u32 pipe_alloc_mask;
224847b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	int err;
224947b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini
225047b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	DE_INIT(("resume start\n"));
225147b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	pci_restore_state(pci);
225247b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	commpage_bak = kmalloc(sizeof(struct echoaudio), GFP_KERNEL);
22530b6d092c8eeeb43893503afd2f6c1c67ceafc863Kulikov Vasiliy	if (commpage_bak == NULL)
22540b6d092c8eeeb43893503afd2f6c1c67ceafc863Kulikov Vasiliy		return -ENOMEM;
225547b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	commpage = chip->comm_page;
225647b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	memcpy(commpage_bak, commpage, sizeof(struct comm_page));
225747b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini
225847b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	err = init_hw(chip, chip->pci->device, chip->pci->subsystem_device);
225947b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	if (err < 0) {
226047b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		kfree(commpage_bak);
226147b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		DE_INIT(("resume init_hw err=%d\n", err));
226247b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		snd_echo_free(chip);
226347b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		return err;
226447b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	}
226547b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	DE_INIT(("resume init OK\n"));
226647b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini
226747b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	/* Temporarily set chip->pipe_alloc_mask=0 otherwise
226847b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	 * restore_dsp_settings() fails.
226947b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	 */
227047b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	pipe_alloc_mask = chip->pipe_alloc_mask;
227147b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	chip->pipe_alloc_mask = 0;
227247b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	err = restore_dsp_rettings(chip);
227347b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	chip->pipe_alloc_mask = pipe_alloc_mask;
227447b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	if (err < 0) {
227547b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		kfree(commpage_bak);
227647b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		return err;
227747b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	}
227847b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	DE_INIT(("resume restore OK\n"));
227947b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini
228047b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	memcpy(&commpage->audio_format, &commpage_bak->audio_format,
228147b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		sizeof(commpage->audio_format));
228247b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	memcpy(&commpage->sglist_addr, &commpage_bak->sglist_addr,
228347b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		sizeof(commpage->sglist_addr));
228447b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	memcpy(&commpage->midi_output, &commpage_bak->midi_output,
228547b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		sizeof(commpage->midi_output));
228647b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	kfree(commpage_bak);
228747b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini
228847b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	if (request_irq(pci->irq, snd_echo_interrupt, IRQF_SHARED,
228947b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini			ECHOCARD_NAME, chip)) {
229047b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		snd_echo_free(chip);
229147b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		snd_printk(KERN_ERR "cannot grab irq\n");
229247b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		return -EBUSY;
229347b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	}
229447b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	chip->irq = pci->irq;
229547b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	DE_INIT(("resume irq=%d\n", chip->irq));
229647b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini
229747b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini#ifdef ECHOCARD_HAS_MIDI
229847b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	if (chip->midi_input_enabled)
229947b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		enable_midi_input(chip, TRUE);
230047b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	if (chip->midi_out)
230147b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini		snd_echo_midi_output_trigger(chip->midi_out, 1);
230247b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini#endif
230347b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini
230447b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	DE_INIT(("resume done\n"));
230547b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	return 0;
230647b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini}
230747b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini
230847b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini#endif /* CONFIG_PM */
230947b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini
231047b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini
231147b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini
2312dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic void __devexit snd_echo_remove(struct pci_dev *pci)
2313dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
2314dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	struct echoaudio *chip;
2315dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2316dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	chip = pci_get_drvdata(pci);
2317dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	if (chip)
2318dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini		snd_card_free(chip->card);
2319dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	pci_set_drvdata(pci, NULL);
2320dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
2321dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2322dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2323dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2324dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/******************************************************************************
2325dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	Everything starts and ends here
2326dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini******************************************************************************/
2327dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2328dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/* pci_driver definition */
2329dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic struct pci_driver driver = {
2330dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.name = "Echoaudio " ECHOCARD_NAME,
2331dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.id_table = snd_echo_ids,
2332dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.probe = snd_echo_probe,
2333dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	.remove = __devexit_p(snd_echo_remove),
233447b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini#ifdef CONFIG_PM
233547b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	.suspend = snd_echo_suspend,
233647b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini	.resume = snd_echo_resume,
233747b5d028fdce8f809bf22852ac900338fb90e8aaGiuliano Pochini#endif /* CONFIG_PM */
2338dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini};
2339dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2340dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2341dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2342dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/* initialization of the module */
2343dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic int __init alsa_card_echo_init(void)
2344dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
2345dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	return pci_register_driver(&driver);
2346dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
2347dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2348dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2349dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2350dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini/* clean up the module */
2351dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinistatic void __exit alsa_card_echo_exit(void)
2352dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini{
2353dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini	pci_unregister_driver(&driver);
2354dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini}
2355dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2356dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochini
2357dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinimodule_init(alsa_card_echo_init)
2358dd7b254d8dd3a9528f423ac3bf875e6f0c8da561Giuliano Pochinimodule_exit(alsa_card_echo_exit)
2359