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