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