| 1 | // SPDX-License-Identifier: GPL-2.0-or-later
|
|---|
| 2 | /*
|
|---|
| 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
|
|---|
| 4 | * Lee Revell <rlrevell@joe-job.com>
|
|---|
| 5 | * James Courtier-Dutton <James@superbug.co.uk>
|
|---|
| 6 | * Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
|
|---|
| 7 | * Creative Labs, Inc.
|
|---|
| 8 | *
|
|---|
| 9 | * Routines for control of EMU10K1 chips / PCM routines
|
|---|
| 10 | */
|
|---|
| 11 |
|
|---|
| 12 | #include <linux/pci.h>
|
|---|
| 13 | #include <linux/delay.h>
|
|---|
| 14 | #include <linux/slab.h>
|
|---|
| 15 | #include <linux/time.h>
|
|---|
| 16 | #include <linux/init.h>
|
|---|
| 17 | #include <sound/core.h>
|
|---|
| 18 | #include <sound/emu10k1.h>
|
|---|
| 19 |
|
|---|
| 20 | static void snd_emu10k1_pcm_interrupt(struct snd_emu10k1 *emu,
|
|---|
| 21 | struct snd_emu10k1_voice *voice)
|
|---|
| 22 | {
|
|---|
| 23 | struct snd_emu10k1_pcm *epcm;
|
|---|
| 24 |
|
|---|
| 25 | epcm = voice->epcm;
|
|---|
| 26 | if (!epcm)
|
|---|
| 27 | return;
|
|---|
| 28 | if (epcm->substream == NULL)
|
|---|
| 29 | return;
|
|---|
| 30 | #if 0
|
|---|
| 31 | dev_dbg(emu->card->dev,
|
|---|
| 32 | "IRQ: position = 0x%x, period = 0x%x, size = 0x%x\n",
|
|---|
| 33 | epcm->substream->runtime->hw->pointer(emu, epcm->substream),
|
|---|
| 34 | snd_pcm_lib_period_bytes(epcm->substream),
|
|---|
| 35 | snd_pcm_lib_buffer_bytes(epcm->substream));
|
|---|
| 36 | #endif
|
|---|
| 37 | snd_pcm_period_elapsed(epcm->substream);
|
|---|
| 38 | }
|
|---|
| 39 |
|
|---|
| 40 | static void snd_emu10k1_pcm_ac97adc_interrupt(struct snd_emu10k1 *emu,
|
|---|
| 41 | unsigned int status)
|
|---|
| 42 | {
|
|---|
| 43 | #if 0
|
|---|
| 44 | if (status & IPR_ADCBUFHALFFULL) {
|
|---|
| 45 | if (emu->pcm_capture_substream->runtime->mode == SNDRV_PCM_MODE_FRAME)
|
|---|
| 46 | return;
|
|---|
| 47 | }
|
|---|
| 48 | #endif
|
|---|
| 49 | snd_pcm_period_elapsed(emu->pcm_capture_substream);
|
|---|
| 50 | }
|
|---|
| 51 |
|
|---|
| 52 | static void snd_emu10k1_pcm_ac97mic_interrupt(struct snd_emu10k1 *emu,
|
|---|
| 53 | unsigned int status)
|
|---|
| 54 | {
|
|---|
| 55 | #if 0
|
|---|
| 56 | if (status & IPR_MICBUFHALFFULL) {
|
|---|
| 57 | if (emu->pcm_capture_mic_substream->runtime->mode == SNDRV_PCM_MODE_FRAME)
|
|---|
| 58 | return;
|
|---|
| 59 | }
|
|---|
| 60 | #endif
|
|---|
| 61 | snd_pcm_period_elapsed(emu->pcm_capture_mic_substream);
|
|---|
| 62 | }
|
|---|
| 63 |
|
|---|
| 64 | static void snd_emu10k1_pcm_efx_interrupt(struct snd_emu10k1 *emu,
|
|---|
| 65 | unsigned int status)
|
|---|
| 66 | {
|
|---|
| 67 | #if 0
|
|---|
| 68 | if (status & IPR_EFXBUFHALFFULL) {
|
|---|
| 69 | if (emu->pcm_capture_efx_substream->runtime->mode == SNDRV_PCM_MODE_FRAME)
|
|---|
| 70 | return;
|
|---|
| 71 | }
|
|---|
| 72 | #endif
|
|---|
| 73 | snd_pcm_period_elapsed(emu->pcm_capture_efx_substream);
|
|---|
| 74 | }
|
|---|
| 75 |
|
|---|
| 76 | static void snd_emu10k1_pcm_free_voices(struct snd_emu10k1_pcm *epcm)
|
|---|
| 77 | {
|
|---|
| 78 | for (unsigned i = 0; i < ARRAY_SIZE(epcm->voices); i++) {
|
|---|
| 79 | if (epcm->voices[i]) {
|
|---|
| 80 | snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]);
|
|---|
| 81 | epcm->voices[i] = NULL;
|
|---|
| 82 | }
|
|---|
| 83 | }
|
|---|
| 84 | }
|
|---|
| 85 |
|
|---|
| 86 | static int snd_emu10k1_pcm_channel_alloc(struct snd_emu10k1_pcm *epcm,
|
|---|
| 87 | int type, int count, int channels)
|
|---|
| 88 | {
|
|---|
| 89 | int err;
|
|---|
| 90 |
|
|---|
| 91 | snd_emu10k1_pcm_free_voices(epcm);
|
|---|
| 92 |
|
|---|
| 93 | err = snd_emu10k1_voice_alloc(epcm->emu,
|
|---|
| 94 | type, count, channels,
|
|---|
| 95 | epcm, &epcm->voices[0]);
|
|---|
| 96 | if (err < 0)
|
|---|
| 97 | return err;
|
|---|
| 98 |
|
|---|
| 99 | if (epcm->extra == NULL) {
|
|---|
| 100 | // The hardware supports only (half-)loop interrupts, so to support an
|
|---|
| 101 | // arbitrary number of periods per buffer, we use an extra voice with a
|
|---|
| 102 | // period-sized loop as the interrupt source. Additionally, the interrupt
|
|---|
| 103 | // timing of the hardware is "suboptimal" and needs some compensation.
|
|---|
| 104 | err = snd_emu10k1_voice_alloc(epcm->emu,
|
|---|
| 105 | type + 1, 1, 1,
|
|---|
| 106 | epcm, &epcm->extra);
|
|---|
| 107 | if (err < 0) {
|
|---|
| 108 | /*
|
|---|
| 109 | dev_dbg(emu->card->dev, "pcm_channel_alloc: "
|
|---|
| 110 | "failed extra: voices=%d, frame=%d\n",
|
|---|
| 111 | voices, frame);
|
|---|
| 112 | */
|
|---|
| 113 | snd_emu10k1_pcm_free_voices(epcm);
|
|---|
| 114 | return err;
|
|---|
| 115 | }
|
|---|
| 116 | epcm->extra->interrupt = snd_emu10k1_pcm_interrupt;
|
|---|
| 117 | }
|
|---|
| 118 |
|
|---|
| 119 | return 0;
|
|---|
| 120 | }
|
|---|
| 121 |
|
|---|
| 122 | // Primes 2-7 and 2^n multiples thereof, up to 16.
|
|---|
| 123 | static const unsigned int efx_capture_channels[] = {
|
|---|
| 124 | 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16
|
|---|
| 125 | };
|
|---|
| 126 |
|
|---|
| 127 | static const struct snd_pcm_hw_constraint_list hw_constraints_efx_capture_channels = {
|
|---|
| 128 | .count = ARRAY_SIZE(efx_capture_channels),
|
|---|
| 129 | .list = efx_capture_channels,
|
|---|
| 130 | .mask = 0
|
|---|
| 131 | };
|
|---|
| 132 |
|
|---|
| 133 | static const unsigned int capture_buffer_sizes[31] = {
|
|---|
| 134 | 384, 448, 512, 640,
|
|---|
| 135 | 384*2, 448*2, 512*2, 640*2,
|
|---|
| 136 | 384*4, 448*4, 512*4, 640*4,
|
|---|
| 137 | 384*8, 448*8, 512*8, 640*8,
|
|---|
| 138 | 384*16, 448*16, 512*16, 640*16,
|
|---|
| 139 | 384*32, 448*32, 512*32, 640*32,
|
|---|
| 140 | 384*64, 448*64, 512*64, 640*64,
|
|---|
| 141 | 384*128,448*128,512*128
|
|---|
| 142 | };
|
|---|
| 143 |
|
|---|
| 144 | static const struct snd_pcm_hw_constraint_list hw_constraints_capture_buffer_sizes = {
|
|---|
| 145 | .count = 31,
|
|---|
| 146 | .list = capture_buffer_sizes,
|
|---|
| 147 | .mask = 0
|
|---|
| 148 | };
|
|---|
| 149 |
|
|---|
| 150 | static unsigned int snd_emu10k1_capture_rate_reg(unsigned int rate)
|
|---|
| 151 | {
|
|---|
| 152 | switch (rate) {
|
|---|
| 153 | case 8000: return ADCCR_SAMPLERATE_8;
|
|---|
| 154 | case 11025: return ADCCR_SAMPLERATE_11;
|
|---|
| 155 | case 16000: return ADCCR_SAMPLERATE_16;
|
|---|
| 156 | case 22050: return ADCCR_SAMPLERATE_22;
|
|---|
| 157 | case 24000: return ADCCR_SAMPLERATE_24;
|
|---|
| 158 | case 32000: return ADCCR_SAMPLERATE_32;
|
|---|
| 159 | case 44100: return ADCCR_SAMPLERATE_44;
|
|---|
| 160 | case 48000: return ADCCR_SAMPLERATE_48;
|
|---|
| 161 | default:
|
|---|
| 162 | snd_BUG();
|
|---|
| 163 | return ADCCR_SAMPLERATE_8;
|
|---|
| 164 | }
|
|---|
| 165 | }
|
|---|
| 166 |
|
|---|
| 167 | static unsigned int snd_emu10k1_audigy_capture_rate_reg(unsigned int rate)
|
|---|
| 168 | {
|
|---|
| 169 | switch (rate) {
|
|---|
| 170 | case 8000: return A_ADCCR_SAMPLERATE_8;
|
|---|
| 171 | case 11025: return A_ADCCR_SAMPLERATE_11;
|
|---|
| 172 | case 12000: return A_ADCCR_SAMPLERATE_12;
|
|---|
| 173 | case 16000: return ADCCR_SAMPLERATE_16;
|
|---|
| 174 | case 22050: return ADCCR_SAMPLERATE_22;
|
|---|
| 175 | case 24000: return ADCCR_SAMPLERATE_24;
|
|---|
| 176 | case 32000: return ADCCR_SAMPLERATE_32;
|
|---|
| 177 | case 44100: return ADCCR_SAMPLERATE_44;
|
|---|
| 178 | case 48000: return ADCCR_SAMPLERATE_48;
|
|---|
| 179 | default:
|
|---|
| 180 | snd_BUG();
|
|---|
| 181 | return A_ADCCR_SAMPLERATE_8;
|
|---|
| 182 | }
|
|---|
| 183 | }
|
|---|
| 184 |
|
|---|
| 185 | static void snd_emu10k1_constrain_capture_rates(struct snd_emu10k1 *emu,
|
|---|
| 186 | struct snd_pcm_runtime *runtime)
|
|---|
| 187 | {
|
|---|
| 188 | if (emu->card_capabilities->emu_model &&
|
|---|
| 189 | emu->emu1010.word_clock == 44100) {
|
|---|
| 190 | runtime->hw.rates = SNDRV_PCM_RATE_11025 | \
|
|---|
| 191 | SNDRV_PCM_RATE_22050 | \
|
|---|
| 192 | SNDRV_PCM_RATE_44100;
|
|---|
| 193 | runtime->hw.rate_min = 11025;
|
|---|
| 194 | runtime->hw.rate_max = 44100;
|
|---|
| 195 | } else if (emu->audigy) {
|
|---|
| 196 | runtime->hw.rates = SNDRV_PCM_RATE_8000_48000 |
|
|---|
| 197 | SNDRV_PCM_RATE_12000 |
|
|---|
| 198 | SNDRV_PCM_RATE_24000;
|
|---|
| 199 | }
|
|---|
| 200 | }
|
|---|
| 201 |
|
|---|
| 202 | static void snd_emu1010_constrain_efx_rate(struct snd_emu10k1 *emu,
|
|---|
| 203 | struct snd_pcm_runtime *runtime)
|
|---|
| 204 | {
|
|---|
| 205 | int rate;
|
|---|
| 206 |
|
|---|
| 207 | rate = emu->emu1010.word_clock;
|
|---|
| 208 | runtime->hw.rate_min = runtime->hw.rate_max = rate;
|
|---|
| 209 | runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate);
|
|---|
| 210 | }
|
|---|
| 211 |
|
|---|
| 212 | static unsigned int emu10k1_calc_pitch_target(unsigned int rate)
|
|---|
| 213 | {
|
|---|
| 214 | unsigned int pitch_target;
|
|---|
| 215 |
|
|---|
| 216 | pitch_target = (rate << 8) / 375;
|
|---|
| 217 | pitch_target = (pitch_target >> 1) + (pitch_target & 1);
|
|---|
| 218 | return pitch_target;
|
|---|
| 219 | }
|
|---|
| 220 |
|
|---|
| 221 | #define PITCH_48000 0x00004000
|
|---|
| 222 | #define PITCH_96000 0x00008000
|
|---|
| 223 | #define PITCH_85000 0x00007155
|
|---|
| 224 | #define PITCH_80726 0x00006ba2
|
|---|
| 225 | #define PITCH_67882 0x00005a82
|
|---|
| 226 | #define PITCH_57081 0x00004c1c
|
|---|
| 227 |
|
|---|
| 228 | static unsigned int emu10k1_select_interprom(unsigned int pitch_target)
|
|---|
| 229 | {
|
|---|
| 230 | if (pitch_target == PITCH_48000)
|
|---|
| 231 | return CCCA_INTERPROM_0;
|
|---|
| 232 | else if (pitch_target < PITCH_48000)
|
|---|
| 233 | return CCCA_INTERPROM_1;
|
|---|
| 234 | else if (pitch_target >= PITCH_96000)
|
|---|
| 235 | return CCCA_INTERPROM_0;
|
|---|
| 236 | else if (pitch_target >= PITCH_85000)
|
|---|
| 237 | return CCCA_INTERPROM_6;
|
|---|
| 238 | else if (pitch_target >= PITCH_80726)
|
|---|
| 239 | return CCCA_INTERPROM_5;
|
|---|
| 240 | else if (pitch_target >= PITCH_67882)
|
|---|
| 241 | return CCCA_INTERPROM_4;
|
|---|
| 242 | else if (pitch_target >= PITCH_57081)
|
|---|
| 243 | return CCCA_INTERPROM_3;
|
|---|
| 244 | else
|
|---|
| 245 | return CCCA_INTERPROM_2;
|
|---|
| 246 | }
|
|---|
| 247 |
|
|---|
| 248 | static u16 emu10k1_send_target_from_amount(u8 amount)
|
|---|
| 249 | {
|
|---|
| 250 | static const u8 shifts[8] = { 4, 4, 5, 6, 7, 8, 9, 10 };
|
|---|
| 251 | static const u16 offsets[8] = { 0, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000 };
|
|---|
| 252 | u8 exp;
|
|---|
| 253 |
|
|---|
| 254 | if (amount == 0xff)
|
|---|
| 255 | return 0xffff;
|
|---|
| 256 | exp = amount >> 5;
|
|---|
| 257 | return ((amount & 0x1f) << shifts[exp]) + offsets[exp];
|
|---|
| 258 | }
|
|---|
| 259 |
|
|---|
| 260 | static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
|
|---|
| 261 | struct snd_emu10k1_voice *evoice,
|
|---|
| 262 | bool w_16, bool stereo,
|
|---|
| 263 | unsigned int start_addr,
|
|---|
| 264 | unsigned int end_addr,
|
|---|
| 265 | const unsigned char *send_routing,
|
|---|
| 266 | const unsigned char *send_amount)
|
|---|
| 267 | {
|
|---|
| 268 | unsigned int silent_page;
|
|---|
| 269 | int voice;
|
|---|
| 270 |
|
|---|
| 271 | voice = evoice->number;
|
|---|
| 272 |
|
|---|
| 273 | silent_page = ((unsigned int)emu->silent_page.addr << emu->address_mode) |
|
|---|
| 274 | (emu->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
|
|---|
| 275 | snd_emu10k1_ptr_write_multiple(emu, voice,
|
|---|
| 276 | // Not really necessary for the slave, but it doesn't hurt
|
|---|
| 277 | CPF, stereo ? CPF_STEREO_MASK : 0,
|
|---|
| 278 | // Assumption that PT is already 0 so no harm overwriting
|
|---|
| 279 | PTRX, (send_amount[0] << 8) | send_amount[1],
|
|---|
| 280 | // Stereo slaves don't need to have the addresses set, but it doesn't hurt
|
|---|
| 281 | DSL, end_addr | (send_amount[3] << 24),
|
|---|
| 282 | PSST, start_addr | (send_amount[2] << 24),
|
|---|
| 283 | CCCA, emu10k1_select_interprom(evoice->epcm->pitch_target) |
|
|---|
| 284 | (w_16 ? 0 : CCCA_8BITSELECT),
|
|---|
| 285 | // Clear filter delay memory
|
|---|
| 286 | Z1, 0,
|
|---|
| 287 | Z2, 0,
|
|---|
| 288 | // Invalidate maps
|
|---|
| 289 | MAPA, silent_page,
|
|---|
| 290 | MAPB, silent_page,
|
|---|
| 291 | // Disable filter (in conjunction with CCCA_RESONANCE == 0)
|
|---|
| 292 | VTFT, VTFT_FILTERTARGET_MASK,
|
|---|
| 293 | CVCF, CVCF_CURRENTFILTER_MASK,
|
|---|
| 294 | REGLIST_END);
|
|---|
| 295 | // Setup routing
|
|---|
| 296 | if (emu->audigy) {
|
|---|
| 297 | snd_emu10k1_ptr_write_multiple(emu, voice,
|
|---|
| 298 | A_FXRT1, snd_emu10k1_compose_audigy_fxrt1(send_routing),
|
|---|
| 299 | A_FXRT2, snd_emu10k1_compose_audigy_fxrt2(send_routing),
|
|---|
| 300 | A_SENDAMOUNTS, snd_emu10k1_compose_audigy_sendamounts(send_amount),
|
|---|
| 301 | REGLIST_END);
|
|---|
| 302 | for (int i = 0; i < 4; i++) {
|
|---|
| 303 | u32 aml = emu10k1_send_target_from_amount(send_amount[2 * i]);
|
|---|
| 304 | u32 amh = emu10k1_send_target_from_amount(send_amount[2 * i + 1]);
|
|---|
| 305 | snd_emu10k1_ptr_write(emu, A_CSBA + i, voice, (amh << 16) | aml);
|
|---|
| 306 | }
|
|---|
| 307 | } else {
|
|---|
| 308 | snd_emu10k1_ptr_write(emu, FXRT, voice,
|
|---|
| 309 | snd_emu10k1_compose_send_routing(send_routing));
|
|---|
| 310 | }
|
|---|
| 311 |
|
|---|
| 312 | emu->voices[voice].dirty = 1;
|
|---|
| 313 | }
|
|---|
| 314 |
|
|---|
| 315 | static void snd_emu10k1_pcm_init_voices(struct snd_emu10k1 *emu,
|
|---|
| 316 | struct snd_emu10k1_voice *evoice,
|
|---|
| 317 | bool w_16, bool stereo,
|
|---|
| 318 | unsigned int start_addr,
|
|---|
| 319 | unsigned int end_addr,
|
|---|
| 320 | struct snd_emu10k1_pcm_mixer *mix)
|
|---|
| 321 | {
|
|---|
| 322 | spin_lock_irq(&emu->reg_lock);
|
|---|
| 323 | snd_emu10k1_pcm_init_voice(emu, evoice, w_16, stereo,
|
|---|
| 324 | start_addr, end_addr,
|
|---|
| 325 | &mix->send_routing[stereo][0],
|
|---|
| 326 | &mix->send_volume[stereo][0]);
|
|---|
| 327 | if (stereo)
|
|---|
| 328 | snd_emu10k1_pcm_init_voice(emu, evoice + 1, w_16, true,
|
|---|
| 329 | start_addr, end_addr,
|
|---|
| 330 | &mix->send_routing[2][0],
|
|---|
| 331 | &mix->send_volume[2][0]);
|
|---|
| 332 | spin_unlock_irq(&emu->reg_lock);
|
|---|
| 333 | }
|
|---|
| 334 |
|
|---|
| 335 | static void snd_emu10k1_pcm_init_extra_voice(struct snd_emu10k1 *emu,
|
|---|
| 336 | struct snd_emu10k1_voice *evoice,
|
|---|
| 337 | bool w_16,
|
|---|
| 338 | unsigned int start_addr,
|
|---|
| 339 | unsigned int end_addr)
|
|---|
| 340 | {
|
|---|
| 341 | static const unsigned char send_routing[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
|
|---|
| 342 | static const unsigned char send_amount[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
|---|
| 343 |
|
|---|
| 344 | snd_emu10k1_pcm_init_voice(emu, evoice, w_16, false,
|
|---|
| 345 | start_addr, end_addr,
|
|---|
| 346 | send_routing, send_amount);
|
|---|
| 347 | }
|
|---|
| 348 |
|
|---|
| 349 | static int snd_emu10k1_playback_hw_params(struct snd_pcm_substream *substream,
|
|---|
| 350 | struct snd_pcm_hw_params *hw_params)
|
|---|
| 351 | {
|
|---|
| 352 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
|
|---|
| 353 | struct snd_pcm_runtime *runtime = substream->runtime;
|
|---|
| 354 | struct snd_emu10k1_pcm *epcm = runtime->private_data;
|
|---|
| 355 | size_t alloc_size;
|
|---|
| 356 | int type, channels, count;
|
|---|
| 357 | int err;
|
|---|
| 358 |
|
|---|
| 359 | if (epcm->type == PLAYBACK_EMUVOICE) {
|
|---|
| 360 | type = EMU10K1_PCM;
|
|---|
| 361 | channels = 1;
|
|---|
| 362 | count = params_channels(hw_params);
|
|---|
| 363 | } else {
|
|---|
| 364 | type = EMU10K1_EFX;
|
|---|
| 365 | channels = params_channels(hw_params);
|
|---|
| 366 | count = 1;
|
|---|
| 367 | }
|
|---|
| 368 | err = snd_emu10k1_pcm_channel_alloc(epcm, type, count, channels);
|
|---|
| 369 | if (err < 0)
|
|---|
| 370 | return err;
|
|---|
| 371 |
|
|---|
| 372 | alloc_size = params_buffer_bytes(hw_params);
|
|---|
| 373 | if (emu->iommu_workaround)
|
|---|
| 374 | alloc_size += EMUPAGESIZE;
|
|---|
| 375 | err = snd_pcm_lib_malloc_pages(substream, alloc_size);
|
|---|
| 376 | if (err < 0)
|
|---|
| 377 | return err;
|
|---|
| 378 | if (emu->iommu_workaround && runtime->dma_bytes >= EMUPAGESIZE)
|
|---|
| 379 | runtime->dma_bytes -= EMUPAGESIZE;
|
|---|
| 380 | if (err > 0) { /* change */
|
|---|
| 381 | int mapped;
|
|---|
| 382 | if (epcm->memblk != NULL)
|
|---|
| 383 | snd_emu10k1_free_pages(emu, epcm->memblk);
|
|---|
| 384 | epcm->memblk = snd_emu10k1_alloc_pages(emu, substream);
|
|---|
| 385 | epcm->start_addr = 0;
|
|---|
| 386 | if (! epcm->memblk)
|
|---|
| 387 | return -ENOMEM;
|
|---|
| 388 | mapped = ((struct snd_emu10k1_memblk *)epcm->memblk)->mapped_page;
|
|---|
| 389 | if (mapped < 0)
|
|---|
| 390 | return -ENOMEM;
|
|---|
| 391 | epcm->start_addr = mapped << PAGE_SHIFT;
|
|---|
| 392 | }
|
|---|
| 393 | return 0;
|
|---|
| 394 | }
|
|---|
| 395 |
|
|---|
| 396 | static int snd_emu10k1_playback_hw_free(struct snd_pcm_substream *substream)
|
|---|
| 397 | {
|
|---|
| 398 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
|
|---|
| 399 | struct snd_pcm_runtime *runtime = substream->runtime;
|
|---|
| 400 | struct snd_emu10k1_pcm *epcm;
|
|---|
| 401 |
|
|---|
| 402 | if (runtime->private_data == NULL)
|
|---|
| 403 | return 0;
|
|---|
| 404 | epcm = runtime->private_data;
|
|---|
| 405 | if (epcm->extra) {
|
|---|
| 406 | snd_emu10k1_voice_free(epcm->emu, epcm->extra);
|
|---|
| 407 | epcm->extra = NULL;
|
|---|
| 408 | }
|
|---|
| 409 | snd_emu10k1_pcm_free_voices(epcm);
|
|---|
| 410 | if (epcm->memblk) {
|
|---|
| 411 | snd_emu10k1_free_pages(emu, epcm->memblk);
|
|---|
| 412 | epcm->memblk = NULL;
|
|---|
| 413 | epcm->start_addr = 0;
|
|---|
| 414 | }
|
|---|
| 415 | snd_pcm_lib_free_pages(substream);
|
|---|
| 416 | return 0;
|
|---|
| 417 | }
|
|---|
| 418 |
|
|---|
| 419 | static int snd_emu10k1_playback_prepare(struct snd_pcm_substream *substream)
|
|---|
| 420 | {
|
|---|
| 421 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
|
|---|
| 422 | struct snd_pcm_runtime *runtime = substream->runtime;
|
|---|
| 423 | struct snd_emu10k1_pcm *epcm = runtime->private_data;
|
|---|
| 424 | bool w_16 = snd_pcm_format_width(runtime->format) == 16;
|
|---|
| 425 | bool stereo = runtime->channels == 2;
|
|---|
| 426 | unsigned int start_addr, end_addr;
|
|---|
| 427 | unsigned int rate;
|
|---|
| 428 |
|
|---|
| 429 | rate = runtime->rate;
|
|---|
| 430 | if (emu->card_capabilities->emu_model &&
|
|---|
| 431 | emu->emu1010.word_clock == 44100)
|
|---|
| 432 | rate = rate * 480 / 441;
|
|---|
| 433 | epcm->pitch_target = emu10k1_calc_pitch_target(rate);
|
|---|
| 434 |
|
|---|
| 435 | start_addr = epcm->start_addr >> w_16;
|
|---|
| 436 | end_addr = start_addr + runtime->period_size;
|
|---|
| 437 | snd_emu10k1_pcm_init_extra_voice(emu, epcm->extra, w_16,
|
|---|
| 438 | start_addr, end_addr);
|
|---|
| 439 | start_addr >>= stereo;
|
|---|
| 440 | epcm->ccca_start_addr = start_addr;
|
|---|
| 441 | end_addr = start_addr + runtime->buffer_size;
|
|---|
| 442 | snd_emu10k1_pcm_init_voices(emu, epcm->voices[0], w_16, stereo,
|
|---|
| 443 | start_addr, end_addr,
|
|---|
| 444 | &emu->pcm_mixer[substream->number]);
|
|---|
| 445 |
|
|---|
| 446 | return 0;
|
|---|
| 447 | }
|
|---|
| 448 |
|
|---|
| 449 | static int snd_emu10k1_efx_playback_prepare(struct snd_pcm_substream *substream)
|
|---|
| 450 | {
|
|---|
| 451 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
|
|---|
| 452 | struct snd_pcm_runtime *runtime = substream->runtime;
|
|---|
| 453 | struct snd_emu10k1_pcm *epcm = runtime->private_data;
|
|---|
| 454 | unsigned int start_addr;
|
|---|
| 455 | unsigned int extra_size, channel_size;
|
|---|
| 456 | unsigned int i;
|
|---|
| 457 |
|
|---|
| 458 | epcm->pitch_target = PITCH_48000;
|
|---|
| 459 |
|
|---|
| 460 | start_addr = epcm->start_addr >> 1; // 16-bit voices
|
|---|
| 461 |
|
|---|
| 462 | extra_size = runtime->period_size;
|
|---|
| 463 | channel_size = runtime->buffer_size;
|
|---|
| 464 |
|
|---|
| 465 | snd_emu10k1_pcm_init_extra_voice(emu, epcm->extra, true,
|
|---|
| 466 | start_addr, start_addr + extra_size);
|
|---|
| 467 |
|
|---|
| 468 | epcm->ccca_start_addr = start_addr;
|
|---|
| 469 | for (i = 0; i < runtime->channels; i++) {
|
|---|
| 470 | snd_emu10k1_pcm_init_voices(emu, epcm->voices[i], true, false,
|
|---|
| 471 | start_addr, start_addr + channel_size,
|
|---|
| 472 | &emu->efx_pcm_mixer[i]);
|
|---|
| 473 | start_addr += channel_size;
|
|---|
| 474 | }
|
|---|
| 475 |
|
|---|
| 476 | return 0;
|
|---|
| 477 | }
|
|---|
| 478 |
|
|---|
| 479 | static const struct snd_pcm_hardware snd_emu10k1_efx_playback =
|
|---|
| 480 | {
|
|---|
| 481 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_NONINTERLEAVED |
|
|---|
| 482 | SNDRV_PCM_INFO_BLOCK_TRANSFER |
|
|---|
| 483 | SNDRV_PCM_INFO_RESUME |
|
|---|
| 484 | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE),
|
|---|
| 485 | .formats = SNDRV_PCM_FMTBIT_S16_LE,
|
|---|
| 486 | .rates = SNDRV_PCM_RATE_48000,
|
|---|
| 487 | .rate_min = 48000,
|
|---|
| 488 | .rate_max = 48000,
|
|---|
| 489 | .channels_min = 1,
|
|---|
| 490 | .channels_max = NUM_EFX_PLAYBACK,
|
|---|
| 491 | .buffer_bytes_max = (128*1024),
|
|---|
| 492 | .period_bytes_max = (128*1024),
|
|---|
| 493 | .periods_min = 2,
|
|---|
| 494 | .periods_max = 1024,
|
|---|
| 495 | .fifo_size = 0,
|
|---|
| 496 | };
|
|---|
| 497 |
|
|---|
| 498 | static int snd_emu10k1_capture_prepare(struct snd_pcm_substream *substream)
|
|---|
| 499 | {
|
|---|
| 500 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
|
|---|
| 501 | struct snd_pcm_runtime *runtime = substream->runtime;
|
|---|
| 502 | struct snd_emu10k1_pcm *epcm = runtime->private_data;
|
|---|
| 503 | int idx;
|
|---|
| 504 |
|
|---|
| 505 | /* zeroing the buffer size will stop capture */
|
|---|
| 506 | snd_emu10k1_ptr_write(emu, epcm->capture_bs_reg, 0, 0);
|
|---|
| 507 | switch (epcm->type) {
|
|---|
| 508 | case CAPTURE_AC97ADC:
|
|---|
| 509 | snd_emu10k1_ptr_write(emu, ADCCR, 0, 0);
|
|---|
| 510 | break;
|
|---|
| 511 | case CAPTURE_EFX:
|
|---|
| 512 | if (emu->card_capabilities->emu_model) {
|
|---|
| 513 | // The upper 32 16-bit capture voices, two for each of the 16 32-bit channels.
|
|---|
| 514 | // The lower voices are occupied by A_EXTOUT_*_CAP*.
|
|---|
| 515 | epcm->capture_cr_val = 0;
|
|---|
| 516 | epcm->capture_cr_val2 = 0xffffffff >> (32 - runtime->channels * 2);
|
|---|
| 517 | }
|
|---|
| 518 | if (emu->audigy) {
|
|---|
| 519 | snd_emu10k1_ptr_write_multiple(emu, 0,
|
|---|
| 520 | A_FXWC1, 0,
|
|---|
| 521 | A_FXWC2, 0,
|
|---|
| 522 | REGLIST_END);
|
|---|
| 523 | } else
|
|---|
| 524 | snd_emu10k1_ptr_write(emu, FXWC, 0, 0);
|
|---|
| 525 | break;
|
|---|
| 526 | default:
|
|---|
| 527 | break;
|
|---|
| 528 | }
|
|---|
| 529 | snd_emu10k1_ptr_write(emu, epcm->capture_ba_reg, 0, runtime->dma_addr);
|
|---|
| 530 | epcm->capture_bufsize = snd_pcm_lib_buffer_bytes(substream);
|
|---|
| 531 | epcm->capture_bs_val = 0;
|
|---|
| 532 | for (idx = 0; idx < 31; idx++) {
|
|---|
| 533 | if (capture_buffer_sizes[idx] == epcm->capture_bufsize) {
|
|---|
| 534 | epcm->capture_bs_val = idx + 1;
|
|---|
| 535 | break;
|
|---|
| 536 | }
|
|---|
| 537 | }
|
|---|
| 538 | if (epcm->capture_bs_val == 0) {
|
|---|
| 539 | snd_BUG();
|
|---|
| 540 | epcm->capture_bs_val++;
|
|---|
| 541 | }
|
|---|
| 542 | if (epcm->type == CAPTURE_AC97ADC) {
|
|---|
| 543 | unsigned rate = runtime->rate;
|
|---|
| 544 | if (!(runtime->hw.rates & SNDRV_PCM_RATE_48000))
|
|---|
| 545 | rate = rate * 480 / 441;
|
|---|
| 546 |
|
|---|
| 547 | epcm->capture_cr_val = emu->audigy ? A_ADCCR_LCHANENABLE : ADCCR_LCHANENABLE;
|
|---|
| 548 | if (runtime->channels > 1)
|
|---|
| 549 | epcm->capture_cr_val |= emu->audigy ? A_ADCCR_RCHANENABLE : ADCCR_RCHANENABLE;
|
|---|
| 550 | epcm->capture_cr_val |= emu->audigy ?
|
|---|
| 551 | snd_emu10k1_audigy_capture_rate_reg(rate) :
|
|---|
| 552 | snd_emu10k1_capture_rate_reg(rate);
|
|---|
| 553 | }
|
|---|
| 554 | return 0;
|
|---|
| 555 | }
|
|---|
| 556 |
|
|---|
| 557 | static void snd_emu10k1_playback_fill_cache(struct snd_emu10k1 *emu,
|
|---|
| 558 | unsigned voice,
|
|---|
| 559 | u32 sample, bool stereo)
|
|---|
| 560 | {
|
|---|
| 561 | u32 ccr;
|
|---|
| 562 |
|
|---|
| 563 | // We assume that the cache is resting at this point (i.e.,
|
|---|
| 564 | // CCR_CACHEINVALIDSIZE is very small).
|
|---|
| 565 |
|
|---|
| 566 | // Clear leading frames. For simplicitly, this does too much,
|
|---|
| 567 | // except for 16-bit stereo. And the interpolator will actually
|
|---|
| 568 | // access them at all only when we're pitch-shifting.
|
|---|
| 569 | for (int i = 0; i < 3; i++)
|
|---|
| 570 | snd_emu10k1_ptr_write(emu, CD0 + i, voice, sample);
|
|---|
| 571 |
|
|---|
| 572 | // Fill cache
|
|---|
| 573 | ccr = (64 - 3) << REG_SHIFT(CCR_CACHEINVALIDSIZE);
|
|---|
| 574 | if (stereo) {
|
|---|
| 575 | // The engine goes haywire if CCR_READADDRESS is out of sync
|
|---|
| 576 | snd_emu10k1_ptr_write(emu, CCR, voice + 1, ccr);
|
|---|
| 577 | }
|
|---|
| 578 | snd_emu10k1_ptr_write(emu, CCR, voice, ccr);
|
|---|
| 579 | }
|
|---|
| 580 |
|
|---|
| 581 | static void snd_emu10k1_playback_prepare_voices(struct snd_emu10k1 *emu,
|
|---|
| 582 | struct snd_emu10k1_pcm *epcm,
|
|---|
| 583 | bool w_16, bool stereo,
|
|---|
| 584 | int channels)
|
|---|
| 585 | {
|
|---|
| 586 | struct snd_pcm_substream *substream = epcm->substream;
|
|---|
| 587 | struct snd_pcm_runtime *runtime = substream->runtime;
|
|---|
| 588 | unsigned eloop_start = epcm->start_addr >> w_16;
|
|---|
| 589 | unsigned loop_start = eloop_start >> stereo;
|
|---|
| 590 | unsigned eloop_size = runtime->period_size;
|
|---|
| 591 | unsigned loop_size = runtime->buffer_size;
|
|---|
| 592 | u32 sample = w_16 ? 0 : 0x80808080;
|
|---|
| 593 |
|
|---|
| 594 | // To make the playback actually start at the 1st frame,
|
|---|
| 595 | // we need to compensate for two circumstances:
|
|---|
| 596 | // - The actual position is delayed by the cache size (64 frames)
|
|---|
| 597 | // - The interpolator is centered around the 4th frame
|
|---|
| 598 | loop_start += (epcm->resume_pos + 64 - 3) % loop_size;
|
|---|
| 599 | for (int i = 0; i < channels; i++) {
|
|---|
| 600 | unsigned voice = epcm->voices[i]->number;
|
|---|
| 601 | snd_emu10k1_ptr_write(emu, CCCA_CURRADDR, voice, loop_start);
|
|---|
| 602 | loop_start += loop_size;
|
|---|
| 603 | snd_emu10k1_playback_fill_cache(emu, voice, sample, stereo);
|
|---|
| 604 | }
|
|---|
| 605 |
|
|---|
| 606 | // The interrupt is triggered when CCCA_CURRADDR (CA) wraps around,
|
|---|
| 607 | // which is ahead of the actual playback position, so the interrupt
|
|---|
| 608 | // source needs to be delayed.
|
|---|
| 609 | //
|
|---|
| 610 | // In principle, this wouldn't need to be the cache's entire size - in
|
|---|
| 611 | // practice, CCR_CACHEINVALIDSIZE (CIS) > `fetch threshold` has never
|
|---|
| 612 | // been observed, and assuming 40 _bytes_ should be safe.
|
|---|
| 613 | //
|
|---|
| 614 | // The cache fills are somewhat random, which makes it impossible to
|
|---|
| 615 | // align them with the interrupts. This makes a non-delayed interrupt
|
|---|
| 616 | // source not practical, as the interrupt handler would have to wait
|
|---|
| 617 | // for (CA - CIS) >= period_boundary for every channel in the stream.
|
|---|
| 618 | //
|
|---|
| 619 | // This is why all other (open) drivers for these chips use timer-based
|
|---|
| 620 | // interrupts.
|
|---|
| 621 | //
|
|---|
| 622 | eloop_start += (epcm->resume_pos + eloop_size - 3) % eloop_size;
|
|---|
| 623 | snd_emu10k1_ptr_write(emu, CCCA_CURRADDR, epcm->extra->number, eloop_start);
|
|---|
| 624 |
|
|---|
| 625 | // It takes a moment until the cache fills complete,
|
|---|
| 626 | // but the unmuting takes long enough for that.
|
|---|
| 627 | }
|
|---|
| 628 |
|
|---|
| 629 | static void snd_emu10k1_playback_commit_volume(struct snd_emu10k1 *emu,
|
|---|
| 630 | struct snd_emu10k1_voice *evoice,
|
|---|
| 631 | unsigned int vattn)
|
|---|
| 632 | {
|
|---|
| 633 | snd_emu10k1_ptr_write_multiple(emu, evoice->number,
|
|---|
| 634 | VTFT, vattn | VTFT_FILTERTARGET_MASK,
|
|---|
| 635 | CVCF, vattn | CVCF_CURRENTFILTER_MASK,
|
|---|
| 636 | REGLIST_END);
|
|---|
| 637 | }
|
|---|
| 638 |
|
|---|
| 639 | static void snd_emu10k1_playback_unmute_voice(struct snd_emu10k1 *emu,
|
|---|
| 640 | struct snd_emu10k1_voice *evoice,
|
|---|
| 641 | bool stereo, bool master,
|
|---|
| 642 | struct snd_emu10k1_pcm_mixer *mix)
|
|---|
| 643 | {
|
|---|
| 644 | unsigned int vattn;
|
|---|
| 645 | unsigned int tmp;
|
|---|
| 646 |
|
|---|
| 647 | tmp = stereo ? (master ? 1 : 2) : 0;
|
|---|
| 648 | vattn = mix->attn[tmp] << 16;
|
|---|
| 649 | snd_emu10k1_playback_commit_volume(emu, evoice, vattn);
|
|---|
| 650 | }
|
|---|
| 651 |
|
|---|
| 652 | static void snd_emu10k1_playback_unmute_voices(struct snd_emu10k1 *emu,
|
|---|
| 653 | struct snd_emu10k1_voice *evoice,
|
|---|
| 654 | bool stereo,
|
|---|
| 655 | struct snd_emu10k1_pcm_mixer *mix)
|
|---|
| 656 | {
|
|---|
| 657 | snd_emu10k1_playback_unmute_voice(emu, evoice, stereo, true, mix);
|
|---|
| 658 | if (stereo)
|
|---|
| 659 | snd_emu10k1_playback_unmute_voice(emu, evoice + 1, true, false, mix);
|
|---|
| 660 | }
|
|---|
| 661 |
|
|---|
| 662 | static void snd_emu10k1_playback_mute_voice(struct snd_emu10k1 *emu,
|
|---|
| 663 | struct snd_emu10k1_voice *evoice)
|
|---|
| 664 | {
|
|---|
| 665 | snd_emu10k1_playback_commit_volume(emu, evoice, 0);
|
|---|
| 666 | }
|
|---|
| 667 |
|
|---|
| 668 | static void snd_emu10k1_playback_mute_voices(struct snd_emu10k1 *emu,
|
|---|
| 669 | struct snd_emu10k1_voice *evoice,
|
|---|
| 670 | bool stereo)
|
|---|
| 671 | {
|
|---|
| 672 | snd_emu10k1_playback_mute_voice(emu, evoice);
|
|---|
| 673 | if (stereo)
|
|---|
| 674 | snd_emu10k1_playback_mute_voice(emu, evoice + 1);
|
|---|
| 675 | }
|
|---|
| 676 |
|
|---|
| 677 | static void snd_emu10k1_playback_commit_pitch(struct snd_emu10k1 *emu,
|
|---|
| 678 | u32 voice, u32 pitch_target)
|
|---|
| 679 | {
|
|---|
| 680 | u32 ptrx = snd_emu10k1_ptr_read(emu, PTRX, voice);
|
|---|
| 681 | u32 cpf = snd_emu10k1_ptr_read(emu, CPF, voice);
|
|---|
| 682 | snd_emu10k1_ptr_write_multiple(emu, voice,
|
|---|
| 683 | PTRX, (ptrx & ~PTRX_PITCHTARGET_MASK) | pitch_target,
|
|---|
| 684 | CPF, (cpf & ~(CPF_CURRENTPITCH_MASK | CPF_FRACADDRESS_MASK)) | pitch_target,
|
|---|
| 685 | REGLIST_END);
|
|---|
| 686 | }
|
|---|
| 687 |
|
|---|
| 688 | static void snd_emu10k1_playback_trigger_voice(struct snd_emu10k1 *emu,
|
|---|
| 689 | struct snd_emu10k1_voice *evoice)
|
|---|
| 690 | {
|
|---|
| 691 | unsigned int voice;
|
|---|
| 692 |
|
|---|
| 693 | voice = evoice->number;
|
|---|
| 694 | snd_emu10k1_playback_commit_pitch(emu, voice, evoice->epcm->pitch_target << 16);
|
|---|
| 695 | }
|
|---|
| 696 |
|
|---|
| 697 | static void snd_emu10k1_playback_stop_voice(struct snd_emu10k1 *emu,
|
|---|
| 698 | struct snd_emu10k1_voice *evoice)
|
|---|
| 699 | {
|
|---|
| 700 | unsigned int voice;
|
|---|
| 701 |
|
|---|
| 702 | voice = evoice->number;
|
|---|
| 703 | snd_emu10k1_playback_commit_pitch(emu, voice, 0);
|
|---|
| 704 | }
|
|---|
| 705 |
|
|---|
| 706 | static void snd_emu10k1_playback_set_running(struct snd_emu10k1 *emu,
|
|---|
| 707 | struct snd_emu10k1_pcm *epcm)
|
|---|
| 708 | {
|
|---|
| 709 | epcm->running = 1;
|
|---|
| 710 | snd_emu10k1_voice_intr_enable(emu, epcm->extra->number);
|
|---|
| 711 | }
|
|---|
| 712 |
|
|---|
| 713 | static void snd_emu10k1_playback_set_stopped(struct snd_emu10k1 *emu,
|
|---|
| 714 | struct snd_emu10k1_pcm *epcm)
|
|---|
| 715 | {
|
|---|
| 716 | snd_emu10k1_voice_intr_disable(emu, epcm->extra->number);
|
|---|
| 717 | epcm->running = 0;
|
|---|
| 718 | }
|
|---|
| 719 |
|
|---|
| 720 | static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream,
|
|---|
| 721 | int cmd)
|
|---|
| 722 | {
|
|---|
| 723 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
|
|---|
| 724 | struct snd_pcm_runtime *runtime = substream->runtime;
|
|---|
| 725 | struct snd_emu10k1_pcm *epcm = runtime->private_data;
|
|---|
| 726 | struct snd_emu10k1_pcm_mixer *mix;
|
|---|
| 727 | bool w_16 = snd_pcm_format_width(runtime->format) == 16;
|
|---|
| 728 | bool stereo = runtime->channels == 2;
|
|---|
| 729 | int result = 0;
|
|---|
| 730 |
|
|---|
| 731 | /*
|
|---|
| 732 | dev_dbg(emu->card->dev,
|
|---|
| 733 | "trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n",
|
|---|
| 734 | (int)emu, cmd, substream->ops->pointer(substream))
|
|---|
| 735 | */
|
|---|
| 736 | spin_lock(&emu->reg_lock);
|
|---|
| 737 | switch (cmd) {
|
|---|
| 738 | case SNDRV_PCM_TRIGGER_START:
|
|---|
| 739 | snd_emu10k1_playback_prepare_voices(emu, epcm, w_16, stereo, 1);
|
|---|
| 740 | fallthrough;
|
|---|
| 741 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
|---|
| 742 | case SNDRV_PCM_TRIGGER_RESUME:
|
|---|
| 743 | mix = &emu->pcm_mixer[substream->number];
|
|---|
| 744 | snd_emu10k1_playback_unmute_voices(emu, epcm->voices[0], stereo, mix);
|
|---|
| 745 | snd_emu10k1_playback_set_running(emu, epcm);
|
|---|
| 746 | snd_emu10k1_playback_trigger_voice(emu, epcm->voices[0]);
|
|---|
| 747 | snd_emu10k1_playback_trigger_voice(emu, epcm->extra);
|
|---|
| 748 | break;
|
|---|
| 749 | case SNDRV_PCM_TRIGGER_STOP:
|
|---|
| 750 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
|---|
| 751 | case SNDRV_PCM_TRIGGER_SUSPEND:
|
|---|
| 752 | snd_emu10k1_playback_stop_voice(emu, epcm->voices[0]);
|
|---|
| 753 | snd_emu10k1_playback_stop_voice(emu, epcm->extra);
|
|---|
| 754 | snd_emu10k1_playback_set_stopped(emu, epcm);
|
|---|
| 755 | snd_emu10k1_playback_mute_voices(emu, epcm->voices[0], stereo);
|
|---|
| 756 | break;
|
|---|
| 757 | default:
|
|---|
| 758 | result = -EINVAL;
|
|---|
| 759 | break;
|
|---|
| 760 | }
|
|---|
| 761 | spin_unlock(&emu->reg_lock);
|
|---|
| 762 | return result;
|
|---|
| 763 | }
|
|---|
| 764 |
|
|---|
| 765 | static int snd_emu10k1_capture_trigger(struct snd_pcm_substream *substream,
|
|---|
| 766 | int cmd)
|
|---|
| 767 | {
|
|---|
| 768 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
|
|---|
| 769 | struct snd_pcm_runtime *runtime = substream->runtime;
|
|---|
| 770 | struct snd_emu10k1_pcm *epcm = runtime->private_data;
|
|---|
| 771 | int result = 0;
|
|---|
| 772 |
|
|---|
| 773 | spin_lock(&emu->reg_lock);
|
|---|
| 774 | switch (cmd) {
|
|---|
| 775 | case SNDRV_PCM_TRIGGER_START:
|
|---|
| 776 | case SNDRV_PCM_TRIGGER_RESUME:
|
|---|
| 777 | /* hmm this should cause full and half full interrupt to be raised? */
|
|---|
| 778 | outl(epcm->capture_ipr, emu->port + IPR);
|
|---|
| 779 | snd_emu10k1_intr_enable(emu, epcm->capture_inte);
|
|---|
| 780 | /*
|
|---|
| 781 | dev_dbg(emu->card->dev, "adccr = 0x%x, adcbs = 0x%x\n",
|
|---|
| 782 | epcm->adccr, epcm->adcbs);
|
|---|
| 783 | */
|
|---|
| 784 | switch (epcm->type) {
|
|---|
| 785 | case CAPTURE_AC97ADC:
|
|---|
| 786 | snd_emu10k1_ptr_write(emu, ADCCR, 0, epcm->capture_cr_val);
|
|---|
| 787 | break;
|
|---|
| 788 | case CAPTURE_EFX:
|
|---|
| 789 | if (emu->audigy) {
|
|---|
| 790 | snd_emu10k1_ptr_write_multiple(emu, 0,
|
|---|
| 791 | A_FXWC1, epcm->capture_cr_val,
|
|---|
| 792 | A_FXWC2, epcm->capture_cr_val2,
|
|---|
| 793 | REGLIST_END);
|
|---|
| 794 | dev_dbg(emu->card->dev,
|
|---|
| 795 | "cr_val=0x%x, cr_val2=0x%x\n",
|
|---|
| 796 | epcm->capture_cr_val,
|
|---|
| 797 | epcm->capture_cr_val2);
|
|---|
| 798 | } else
|
|---|
| 799 | snd_emu10k1_ptr_write(emu, FXWC, 0, epcm->capture_cr_val);
|
|---|
| 800 | break;
|
|---|
| 801 | default:
|
|---|
| 802 | break;
|
|---|
| 803 | }
|
|---|
| 804 | snd_emu10k1_ptr_write(emu, epcm->capture_bs_reg, 0, epcm->capture_bs_val);
|
|---|
| 805 | epcm->running = 1;
|
|---|
| 806 | epcm->first_ptr = 1;
|
|---|
| 807 | break;
|
|---|
| 808 | case SNDRV_PCM_TRIGGER_STOP:
|
|---|
| 809 | case SNDRV_PCM_TRIGGER_SUSPEND:
|
|---|
| 810 | epcm->running = 0;
|
|---|
| 811 | snd_emu10k1_intr_disable(emu, epcm->capture_inte);
|
|---|
| 812 | outl(epcm->capture_ipr, emu->port + IPR);
|
|---|
| 813 | snd_emu10k1_ptr_write(emu, epcm->capture_bs_reg, 0, 0);
|
|---|
| 814 | switch (epcm->type) {
|
|---|
| 815 | case CAPTURE_AC97ADC:
|
|---|
| 816 | snd_emu10k1_ptr_write(emu, ADCCR, 0, 0);
|
|---|
| 817 | break;
|
|---|
| 818 | case CAPTURE_EFX:
|
|---|
| 819 | if (emu->audigy) {
|
|---|
| 820 | snd_emu10k1_ptr_write_multiple(emu, 0,
|
|---|
| 821 | A_FXWC1, 0,
|
|---|
| 822 | A_FXWC2, 0,
|
|---|
| 823 | REGLIST_END);
|
|---|
| 824 | } else
|
|---|
| 825 | snd_emu10k1_ptr_write(emu, FXWC, 0, 0);
|
|---|
| 826 | break;
|
|---|
| 827 | default:
|
|---|
| 828 | break;
|
|---|
| 829 | }
|
|---|
| 830 | break;
|
|---|
| 831 | default:
|
|---|
| 832 | result = -EINVAL;
|
|---|
| 833 | }
|
|---|
| 834 | spin_unlock(&emu->reg_lock);
|
|---|
| 835 | return result;
|
|---|
| 836 | }
|
|---|
| 837 |
|
|---|
| 838 | static snd_pcm_uframes_t snd_emu10k1_playback_pointer(struct snd_pcm_substream *substream)
|
|---|
| 839 | {
|
|---|
| 840 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
|
|---|
| 841 | struct snd_pcm_runtime *runtime = substream->runtime;
|
|---|
| 842 | struct snd_emu10k1_pcm *epcm = runtime->private_data;
|
|---|
| 843 | int ptr;
|
|---|
| 844 |
|
|---|
| 845 | if (!epcm->running)
|
|---|
| 846 | return 0;
|
|---|
| 847 |
|
|---|
| 848 | ptr = snd_emu10k1_ptr_read(emu, CCCA, epcm->voices[0]->number) & 0x00ffffff;
|
|---|
| 849 | ptr -= epcm->ccca_start_addr;
|
|---|
| 850 |
|
|---|
| 851 | // This is the size of the whole cache minus the interpolator read-ahead,
|
|---|
| 852 | // which leads us to the actual playback position.
|
|---|
| 853 | //
|
|---|
| 854 | // The cache is constantly kept mostly filled, so in principle we could
|
|---|
| 855 | // return a more advanced position representing how far the hardware has
|
|---|
| 856 | // already read the buffer, and set runtime->delay accordingly. However,
|
|---|
| 857 | // this would be slightly different for every channel (and remarkably slow
|
|---|
| 858 | // to obtain), so only a fixed worst-case value would be practical.
|
|---|
| 859 | //
|
|---|
| 860 | ptr -= 64 - 3;
|
|---|
| 861 | if (ptr < 0)
|
|---|
| 862 | ptr += runtime->buffer_size;
|
|---|
| 863 |
|
|---|
| 864 | /*
|
|---|
| 865 | dev_dbg(emu->card->dev,
|
|---|
| 866 | "ptr = 0x%lx, buffer_size = 0x%lx, period_size = 0x%lx\n",
|
|---|
| 867 | (long)ptr, (long)runtime->buffer_size,
|
|---|
| 868 | (long)runtime->period_size);
|
|---|
| 869 | */
|
|---|
| 870 | return ptr;
|
|---|
| 871 | }
|
|---|
| 872 |
|
|---|
| 873 | static u64 snd_emu10k1_efx_playback_voice_mask(struct snd_emu10k1_pcm *epcm,
|
|---|
| 874 | int channels)
|
|---|
| 875 | {
|
|---|
| 876 | u64 mask = 0;
|
|---|
| 877 |
|
|---|
| 878 | for (int i = 0; i < channels; i++) {
|
|---|
| 879 | int voice = epcm->voices[i]->number;
|
|---|
| 880 | mask |= 1ULL << voice;
|
|---|
| 881 | }
|
|---|
| 882 | return mask;
|
|---|
| 883 | }
|
|---|
| 884 |
|
|---|
| 885 | static void snd_emu10k1_efx_playback_freeze_voices(struct snd_emu10k1 *emu,
|
|---|
| 886 | struct snd_emu10k1_pcm *epcm,
|
|---|
| 887 | int channels)
|
|---|
| 888 | {
|
|---|
| 889 | for (int i = 0; i < channels; i++) {
|
|---|
| 890 | int voice = epcm->voices[i]->number;
|
|---|
| 891 | snd_emu10k1_ptr_write(emu, CPF_STOP, voice, 1);
|
|---|
| 892 | snd_emu10k1_playback_commit_pitch(emu, voice, PITCH_48000 << 16);
|
|---|
| 893 | }
|
|---|
| 894 | }
|
|---|
| 895 |
|
|---|
| 896 | static void snd_emu10k1_efx_playback_unmute_voices(struct snd_emu10k1 *emu,
|
|---|
| 897 | struct snd_emu10k1_pcm *epcm,
|
|---|
| 898 | int channels)
|
|---|
| 899 | {
|
|---|
| 900 | for (int i = 0; i < channels; i++)
|
|---|
| 901 | snd_emu10k1_playback_unmute_voice(emu, epcm->voices[i], false, true,
|
|---|
| 902 | &emu->efx_pcm_mixer[i]);
|
|---|
| 903 | }
|
|---|
| 904 |
|
|---|
| 905 | static void snd_emu10k1_efx_playback_stop_voices(struct snd_emu10k1 *emu,
|
|---|
| 906 | struct snd_emu10k1_pcm *epcm,
|
|---|
| 907 | int channels)
|
|---|
| 908 | {
|
|---|
| 909 | for (int i = 0; i < channels; i++)
|
|---|
| 910 | snd_emu10k1_playback_stop_voice(emu, epcm->voices[i]);
|
|---|
| 911 | snd_emu10k1_playback_set_stopped(emu, epcm);
|
|---|
| 912 |
|
|---|
| 913 | for (int i = 0; i < channels; i++)
|
|---|
| 914 | snd_emu10k1_playback_mute_voice(emu, epcm->voices[i]);
|
|---|
| 915 | }
|
|---|
| 916 |
|
|---|
| 917 | static int snd_emu10k1_efx_playback_trigger(struct snd_pcm_substream *substream,
|
|---|
| 918 | int cmd)
|
|---|
| 919 | {
|
|---|
| 920 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
|
|---|
| 921 | struct snd_pcm_runtime *runtime = substream->runtime;
|
|---|
| 922 | struct snd_emu10k1_pcm *epcm = runtime->private_data;
|
|---|
| 923 | u64 mask;
|
|---|
| 924 | int result = 0;
|
|---|
| 925 |
|
|---|
| 926 | spin_lock(&emu->reg_lock);
|
|---|
| 927 | switch (cmd) {
|
|---|
| 928 | case SNDRV_PCM_TRIGGER_START:
|
|---|
| 929 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
|---|
| 930 | case SNDRV_PCM_TRIGGER_RESUME:
|
|---|
| 931 | mask = snd_emu10k1_efx_playback_voice_mask(
|
|---|
| 932 | epcm, runtime->channels);
|
|---|
| 933 | for (int i = 0; i < 10; i++) {
|
|---|
| 934 | // Note that the freeze is not interruptible, so we make no
|
|---|
| 935 | // effort to reset the bits outside the error handling here.
|
|---|
| 936 | snd_emu10k1_voice_set_loop_stop_multiple(emu, mask);
|
|---|
| 937 | snd_emu10k1_efx_playback_freeze_voices(
|
|---|
| 938 | emu, epcm, runtime->channels);
|
|---|
| 939 | snd_emu10k1_playback_prepare_voices(
|
|---|
| 940 | emu, epcm, true, false, runtime->channels);
|
|---|
| 941 |
|
|---|
| 942 | // It might seem to make more sense to unmute the voices only after
|
|---|
| 943 | // they have been started, to potentially avoid torturing the speakers
|
|---|
| 944 | // if something goes wrong. However, we cannot unmute atomically,
|
|---|
| 945 | // which means that we'd get some mild artifacts in the regular case.
|
|---|
| 946 | snd_emu10k1_efx_playback_unmute_voices(emu, epcm, runtime->channels);
|
|---|
| 947 |
|
|---|
| 948 | snd_emu10k1_playback_set_running(emu, epcm);
|
|---|
| 949 | result = snd_emu10k1_voice_clear_loop_stop_multiple_atomic(emu, mask);
|
|---|
| 950 | if (result == 0) {
|
|---|
| 951 | // The extra voice is allowed to lag a bit
|
|---|
| 952 | snd_emu10k1_playback_trigger_voice(emu, epcm->extra);
|
|---|
| 953 | goto leave;
|
|---|
| 954 | }
|
|---|
| 955 |
|
|---|
| 956 | snd_emu10k1_efx_playback_stop_voices(
|
|---|
| 957 | emu, epcm, runtime->channels);
|
|---|
| 958 |
|
|---|
| 959 | if (result != -EAGAIN)
|
|---|
| 960 | break;
|
|---|
| 961 | // The sync start can legitimately fail due to NMIs, etc.
|
|---|
| 962 | }
|
|---|
| 963 | snd_emu10k1_voice_clear_loop_stop_multiple(emu, mask);
|
|---|
| 964 | break;
|
|---|
| 965 | case SNDRV_PCM_TRIGGER_SUSPEND:
|
|---|
| 966 | case SNDRV_PCM_TRIGGER_STOP:
|
|---|
| 967 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
|---|
| 968 | snd_emu10k1_playback_stop_voice(emu, epcm->extra);
|
|---|
| 969 | snd_emu10k1_efx_playback_stop_voices(
|
|---|
| 970 | emu, epcm, runtime->channels);
|
|---|
| 971 |
|
|---|
| 972 | epcm->resume_pos = snd_emu10k1_playback_pointer(substream);
|
|---|
| 973 | break;
|
|---|
| 974 | default:
|
|---|
| 975 | result = -EINVAL;
|
|---|
| 976 | break;
|
|---|
| 977 | }
|
|---|
| 978 | leave:
|
|---|
| 979 | spin_unlock(&emu->reg_lock);
|
|---|
| 980 | return result;
|
|---|
| 981 | }
|
|---|
| 982 |
|
|---|
| 983 |
|
|---|
| 984 | static snd_pcm_uframes_t snd_emu10k1_capture_pointer(struct snd_pcm_substream *substream)
|
|---|
| 985 | {
|
|---|
| 986 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
|
|---|
| 987 | struct snd_pcm_runtime *runtime = substream->runtime;
|
|---|
| 988 | struct snd_emu10k1_pcm *epcm = runtime->private_data;
|
|---|
| 989 | unsigned int ptr;
|
|---|
| 990 |
|
|---|
| 991 | if (!epcm->running)
|
|---|
| 992 | return 0;
|
|---|
| 993 | if (epcm->first_ptr) {
|
|---|
| 994 | udelay(50); /* hack, it takes awhile until capture is started */
|
|---|
| 995 | epcm->first_ptr = 0;
|
|---|
| 996 | }
|
|---|
| 997 | ptr = snd_emu10k1_ptr_read(emu, epcm->capture_idx_reg, 0) & 0x0000ffff;
|
|---|
| 998 | return bytes_to_frames(runtime, ptr);
|
|---|
| 999 | }
|
|---|
| 1000 |
|
|---|
| 1001 | /*
|
|---|
| 1002 | * Playback support device description
|
|---|
| 1003 | */
|
|---|
| 1004 |
|
|---|
| 1005 | static const struct snd_pcm_hardware snd_emu10k1_playback =
|
|---|
| 1006 | {
|
|---|
| 1007 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
|
|---|
| 1008 | SNDRV_PCM_INFO_BLOCK_TRANSFER |
|
|---|
| 1009 | SNDRV_PCM_INFO_RESUME |
|
|---|
| 1010 | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE),
|
|---|
| 1011 | .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
|
|---|
| 1012 | .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_96000,
|
|---|
| 1013 | .rate_min = 4000,
|
|---|
| 1014 | .rate_max = 96000,
|
|---|
| 1015 | .channels_min = 1,
|
|---|
| 1016 | .channels_max = 2,
|
|---|
| 1017 | .buffer_bytes_max = (128*1024),
|
|---|
| 1018 | .period_bytes_max = (128*1024),
|
|---|
| 1019 | .periods_min = 2,
|
|---|
| 1020 | .periods_max = 1024,
|
|---|
| 1021 | .fifo_size = 0,
|
|---|
| 1022 | };
|
|---|
| 1023 |
|
|---|
| 1024 | /*
|
|---|
| 1025 | * Capture support device description
|
|---|
| 1026 | */
|
|---|
| 1027 |
|
|---|
| 1028 | static const struct snd_pcm_hardware snd_emu10k1_capture =
|
|---|
| 1029 | {
|
|---|
| 1030 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
|
|---|
| 1031 | SNDRV_PCM_INFO_BLOCK_TRANSFER |
|
|---|
| 1032 | SNDRV_PCM_INFO_RESUME |
|
|---|
| 1033 | SNDRV_PCM_INFO_MMAP_VALID),
|
|---|
| 1034 | .formats = SNDRV_PCM_FMTBIT_S16_LE,
|
|---|
| 1035 | .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_24000,
|
|---|
| 1036 | .rate_min = 8000,
|
|---|
| 1037 | .rate_max = 48000,
|
|---|
| 1038 | .channels_min = 1,
|
|---|
| 1039 | .channels_max = 2,
|
|---|
| 1040 | .buffer_bytes_max = (64*1024),
|
|---|
| 1041 | .period_bytes_min = 384,
|
|---|
| 1042 | .period_bytes_max = (64*1024),
|
|---|
| 1043 | .periods_min = 2,
|
|---|
| 1044 | .periods_max = 2,
|
|---|
| 1045 | .fifo_size = 0,
|
|---|
| 1046 | };
|
|---|
| 1047 |
|
|---|
| 1048 | static const struct snd_pcm_hardware snd_emu10k1_capture_efx =
|
|---|
| 1049 | {
|
|---|
| 1050 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
|
|---|
| 1051 | SNDRV_PCM_INFO_BLOCK_TRANSFER |
|
|---|
| 1052 | SNDRV_PCM_INFO_RESUME |
|
|---|
| 1053 | SNDRV_PCM_INFO_MMAP_VALID),
|
|---|
| 1054 | .formats = SNDRV_PCM_FMTBIT_S16_LE,
|
|---|
| 1055 | .rates = SNDRV_PCM_RATE_48000,
|
|---|
| 1056 | .rate_min = 48000,
|
|---|
| 1057 | .rate_max = 48000,
|
|---|
| 1058 | .channels_min = 1,
|
|---|
| 1059 | .channels_max = 16,
|
|---|
| 1060 | .buffer_bytes_max = (64*1024),
|
|---|
| 1061 | .period_bytes_min = 384,
|
|---|
| 1062 | .period_bytes_max = (64*1024),
|
|---|
| 1063 | .periods_min = 2,
|
|---|
| 1064 | .periods_max = 2,
|
|---|
| 1065 | .fifo_size = 0,
|
|---|
| 1066 | };
|
|---|
| 1067 |
|
|---|
| 1068 | /*
|
|---|
| 1069 | *
|
|---|
| 1070 | */
|
|---|
| 1071 |
|
|---|
| 1072 | static void snd_emu10k1_pcm_mixer_notify1(struct snd_emu10k1 *emu, struct snd_kcontrol *kctl, int idx, int activate)
|
|---|
| 1073 | {
|
|---|
| 1074 | struct snd_ctl_elem_id id;
|
|---|
| 1075 |
|
|---|
| 1076 | if (! kctl)
|
|---|
| 1077 | return;
|
|---|
| 1078 | if (activate)
|
|---|
| 1079 | kctl->vd[idx].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
|
|---|
| 1080 | else
|
|---|
| 1081 | kctl->vd[idx].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
|
|---|
| 1082 | snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE |
|
|---|
| 1083 | SNDRV_CTL_EVENT_MASK_INFO,
|
|---|
| 1084 | snd_ctl_build_ioff(&id, kctl, idx));
|
|---|
| 1085 | }
|
|---|
| 1086 |
|
|---|
| 1087 | static void snd_emu10k1_pcm_mixer_notify(struct snd_emu10k1 *emu, int idx, int activate)
|
|---|
| 1088 | {
|
|---|
| 1089 | snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_send_routing, idx, activate);
|
|---|
| 1090 | snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_send_volume, idx, activate);
|
|---|
| 1091 | snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_attn, idx, activate);
|
|---|
| 1092 | }
|
|---|
| 1093 |
|
|---|
| 1094 | static void snd_emu10k1_pcm_efx_mixer_notify(struct snd_emu10k1 *emu, int idx, int activate)
|
|---|
| 1095 | {
|
|---|
| 1096 | snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_efx_send_routing, idx, activate);
|
|---|
| 1097 | snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_efx_send_volume, idx, activate);
|
|---|
| 1098 | snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_efx_attn, idx, activate);
|
|---|
| 1099 | }
|
|---|
| 1100 |
|
|---|
| 1101 | static void snd_emu10k1_pcm_free_substream(struct snd_pcm_runtime *runtime)
|
|---|
| 1102 | {
|
|---|
| 1103 | kfree(runtime->private_data);
|
|---|
| 1104 | }
|
|---|
| 1105 |
|
|---|
| 1106 | static int snd_emu10k1_efx_playback_close(struct snd_pcm_substream *substream)
|
|---|
| 1107 | {
|
|---|
| 1108 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
|
|---|
| 1109 | struct snd_emu10k1_pcm_mixer *mix;
|
|---|
| 1110 | int i;
|
|---|
| 1111 |
|
|---|
| 1112 | for (i = 0; i < NUM_EFX_PLAYBACK; i++) {
|
|---|
| 1113 | mix = &emu->efx_pcm_mixer[i];
|
|---|
| 1114 | mix->epcm = NULL;
|
|---|
| 1115 | snd_emu10k1_pcm_efx_mixer_notify(emu, i, 0);
|
|---|
| 1116 | }
|
|---|
| 1117 | return 0;
|
|---|
| 1118 | }
|
|---|
| 1119 |
|
|---|
| 1120 | static int snd_emu10k1_playback_set_constraints(struct snd_pcm_runtime *runtime)
|
|---|
| 1121 | {
|
|---|
| 1122 | int err;
|
|---|
| 1123 |
|
|---|
| 1124 | // The buffer size must be a multiple of the period size, to avoid a
|
|---|
| 1125 | // mismatch between the extra voice and the regular voices.
|
|---|
| 1126 | err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
|
|---|
| 1127 | if (err < 0)
|
|---|
| 1128 | return err;
|
|---|
| 1129 | // The hardware is typically the cache's size of 64 frames ahead.
|
|---|
| 1130 | // Leave enough time for actually filling up the buffer.
|
|---|
| 1131 | err = snd_pcm_hw_constraint_minmax(
|
|---|
| 1132 | runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 128, UINT_MAX);
|
|---|
| 1133 | return err;
|
|---|
| 1134 | }
|
|---|
| 1135 |
|
|---|
| 1136 | static int snd_emu10k1_efx_playback_open(struct snd_pcm_substream *substream)
|
|---|
| 1137 | {
|
|---|
| 1138 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
|
|---|
| 1139 | struct snd_emu10k1_pcm *epcm;
|
|---|
| 1140 | struct snd_emu10k1_pcm_mixer *mix;
|
|---|
| 1141 | struct snd_pcm_runtime *runtime = substream->runtime;
|
|---|
| 1142 | int i, j, err;
|
|---|
| 1143 |
|
|---|
| 1144 | epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
|
|---|
| 1145 | if (epcm == NULL)
|
|---|
| 1146 | return -ENOMEM;
|
|---|
| 1147 | epcm->emu = emu;
|
|---|
| 1148 | epcm->type = PLAYBACK_EFX;
|
|---|
| 1149 | epcm->substream = substream;
|
|---|
| 1150 |
|
|---|
| 1151 | runtime->private_data = epcm;
|
|---|
| 1152 | runtime->private_free = snd_emu10k1_pcm_free_substream;
|
|---|
| 1153 | runtime->hw = snd_emu10k1_efx_playback;
|
|---|
| 1154 | if (emu->card_capabilities->emu_model)
|
|---|
| 1155 | snd_emu1010_constrain_efx_rate(emu, runtime);
|
|---|
| 1156 | err = snd_emu10k1_playback_set_constraints(runtime);
|
|---|
| 1157 | if (err < 0) {
|
|---|
| 1158 | kfree(epcm);
|
|---|
| 1159 | return err;
|
|---|
| 1160 | }
|
|---|
| 1161 |
|
|---|
| 1162 | for (i = 0; i < NUM_EFX_PLAYBACK; i++) {
|
|---|
| 1163 | mix = &emu->efx_pcm_mixer[i];
|
|---|
| 1164 | for (j = 0; j < 8; j++)
|
|---|
| 1165 | mix->send_routing[0][j] = i + j;
|
|---|
| 1166 | memset(&mix->send_volume, 0, sizeof(mix->send_volume));
|
|---|
| 1167 | mix->send_volume[0][0] = 255;
|
|---|
| 1168 | mix->attn[0] = 0x8000;
|
|---|
| 1169 | mix->epcm = epcm;
|
|---|
| 1170 | snd_emu10k1_pcm_efx_mixer_notify(emu, i, 1);
|
|---|
| 1171 | }
|
|---|
| 1172 | return 0;
|
|---|
| 1173 | }
|
|---|
| 1174 |
|
|---|
| 1175 | static int snd_emu10k1_playback_open(struct snd_pcm_substream *substream)
|
|---|
| 1176 | {
|
|---|
| 1177 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
|
|---|
| 1178 | struct snd_emu10k1_pcm *epcm;
|
|---|
| 1179 | struct snd_emu10k1_pcm_mixer *mix;
|
|---|
| 1180 | struct snd_pcm_runtime *runtime = substream->runtime;
|
|---|
| 1181 | int i, err, sample_rate;
|
|---|
| 1182 |
|
|---|
| 1183 | epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
|
|---|
| 1184 | if (epcm == NULL)
|
|---|
| 1185 | return -ENOMEM;
|
|---|
| 1186 | epcm->emu = emu;
|
|---|
| 1187 | epcm->type = PLAYBACK_EMUVOICE;
|
|---|
| 1188 | epcm->substream = substream;
|
|---|
| 1189 | runtime->private_data = epcm;
|
|---|
| 1190 | runtime->private_free = snd_emu10k1_pcm_free_substream;
|
|---|
| 1191 | runtime->hw = snd_emu10k1_playback;
|
|---|
| 1192 | err = snd_emu10k1_playback_set_constraints(runtime);
|
|---|
| 1193 | if (err < 0) {
|
|---|
| 1194 | kfree(epcm);
|
|---|
| 1195 | return err;
|
|---|
| 1196 | }
|
|---|
| 1197 | if (emu->card_capabilities->emu_model)
|
|---|
| 1198 | sample_rate = emu->emu1010.word_clock;
|
|---|
| 1199 | else
|
|---|
| 1200 | sample_rate = 48000;
|
|---|
| 1201 | err = snd_pcm_hw_rule_noresample(runtime, sample_rate);
|
|---|
| 1202 | if (err < 0) {
|
|---|
| 1203 | kfree(epcm);
|
|---|
| 1204 | return err;
|
|---|
| 1205 | }
|
|---|
| 1206 | mix = &emu->pcm_mixer[substream->number];
|
|---|
| 1207 | for (i = 0; i < 8; i++)
|
|---|
| 1208 | mix->send_routing[0][i] = mix->send_routing[1][i] = mix->send_routing[2][i] = i;
|
|---|
| 1209 | memset(&mix->send_volume, 0, sizeof(mix->send_volume));
|
|---|
| 1210 | mix->send_volume[0][0] = mix->send_volume[0][1] =
|
|---|
| 1211 | mix->send_volume[1][0] = mix->send_volume[2][1] = 255;
|
|---|
| 1212 | mix->attn[0] = mix->attn[1] = mix->attn[2] = 0x8000;
|
|---|
| 1213 | mix->epcm = epcm;
|
|---|
| 1214 | snd_emu10k1_pcm_mixer_notify(emu, substream->number, 1);
|
|---|
| 1215 | return 0;
|
|---|
| 1216 | }
|
|---|
| 1217 |
|
|---|
| 1218 | static int snd_emu10k1_playback_close(struct snd_pcm_substream *substream)
|
|---|
| 1219 | {
|
|---|
| 1220 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
|
|---|
| 1221 | struct snd_emu10k1_pcm_mixer *mix = &emu->pcm_mixer[substream->number];
|
|---|
| 1222 |
|
|---|
| 1223 | mix->epcm = NULL;
|
|---|
| 1224 | snd_emu10k1_pcm_mixer_notify(emu, substream->number, 0);
|
|---|
| 1225 | return 0;
|
|---|
| 1226 | }
|
|---|
| 1227 |
|
|---|
| 1228 | static int snd_emu10k1_capture_open(struct snd_pcm_substream *substream)
|
|---|
| 1229 | {
|
|---|
| 1230 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
|
|---|
| 1231 | struct snd_pcm_runtime *runtime = substream->runtime;
|
|---|
| 1232 | struct snd_emu10k1_pcm *epcm;
|
|---|
| 1233 |
|
|---|
| 1234 | epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
|
|---|
| 1235 | if (epcm == NULL)
|
|---|
| 1236 | return -ENOMEM;
|
|---|
| 1237 | epcm->emu = emu;
|
|---|
| 1238 | epcm->type = CAPTURE_AC97ADC;
|
|---|
| 1239 | epcm->substream = substream;
|
|---|
| 1240 | epcm->capture_ipr = IPR_ADCBUFFULL|IPR_ADCBUFHALFFULL;
|
|---|
| 1241 | epcm->capture_inte = INTE_ADCBUFENABLE;
|
|---|
| 1242 | epcm->capture_ba_reg = ADCBA;
|
|---|
| 1243 | epcm->capture_bs_reg = ADCBS;
|
|---|
| 1244 | epcm->capture_idx_reg = emu->audigy ? A_ADCIDX : ADCIDX;
|
|---|
| 1245 | runtime->private_data = epcm;
|
|---|
| 1246 | runtime->private_free = snd_emu10k1_pcm_free_substream;
|
|---|
| 1247 | runtime->hw = snd_emu10k1_capture;
|
|---|
| 1248 | snd_emu10k1_constrain_capture_rates(emu, runtime);
|
|---|
| 1249 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
|
|---|
| 1250 | &hw_constraints_capture_buffer_sizes);
|
|---|
| 1251 | emu->capture_interrupt = snd_emu10k1_pcm_ac97adc_interrupt;
|
|---|
| 1252 | emu->pcm_capture_substream = substream;
|
|---|
| 1253 | return 0;
|
|---|
| 1254 | }
|
|---|
| 1255 |
|
|---|
| 1256 | static int snd_emu10k1_capture_close(struct snd_pcm_substream *substream)
|
|---|
| 1257 | {
|
|---|
| 1258 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
|
|---|
| 1259 |
|
|---|
| 1260 | emu->capture_interrupt = NULL;
|
|---|
| 1261 | emu->pcm_capture_substream = NULL;
|
|---|
| 1262 | return 0;
|
|---|
| 1263 | }
|
|---|
| 1264 |
|
|---|
| 1265 | static int snd_emu10k1_capture_mic_open(struct snd_pcm_substream *substream)
|
|---|
| 1266 | {
|
|---|
| 1267 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
|
|---|
| 1268 | struct snd_emu10k1_pcm *epcm;
|
|---|
| 1269 | struct snd_pcm_runtime *runtime = substream->runtime;
|
|---|
| 1270 |
|
|---|
| 1271 | epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
|
|---|
| 1272 | if (epcm == NULL)
|
|---|
| 1273 | return -ENOMEM;
|
|---|
| 1274 | epcm->emu = emu;
|
|---|
| 1275 | epcm->type = CAPTURE_AC97MIC;
|
|---|
| 1276 | epcm->substream = substream;
|
|---|
| 1277 | epcm->capture_ipr = IPR_MICBUFFULL|IPR_MICBUFHALFFULL;
|
|---|
| 1278 | epcm->capture_inte = INTE_MICBUFENABLE;
|
|---|
| 1279 | epcm->capture_ba_reg = MICBA;
|
|---|
| 1280 | epcm->capture_bs_reg = MICBS;
|
|---|
| 1281 | epcm->capture_idx_reg = emu->audigy ? A_MICIDX : MICIDX;
|
|---|
| 1282 | substream->runtime->private_data = epcm;
|
|---|
| 1283 | substream->runtime->private_free = snd_emu10k1_pcm_free_substream;
|
|---|
| 1284 | runtime->hw = snd_emu10k1_capture;
|
|---|
| 1285 | runtime->hw.rates = SNDRV_PCM_RATE_8000;
|
|---|
| 1286 | runtime->hw.rate_min = runtime->hw.rate_max = 8000;
|
|---|
| 1287 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
|
|---|
| 1288 | &hw_constraints_capture_buffer_sizes);
|
|---|
| 1289 | emu->capture_mic_interrupt = snd_emu10k1_pcm_ac97mic_interrupt;
|
|---|
| 1290 | emu->pcm_capture_mic_substream = substream;
|
|---|
| 1291 | return 0;
|
|---|
| 1292 | }
|
|---|
| 1293 |
|
|---|
| 1294 | static int snd_emu10k1_capture_mic_close(struct snd_pcm_substream *substream)
|
|---|
| 1295 | {
|
|---|
| 1296 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
|
|---|
| 1297 |
|
|---|
| 1298 | emu->capture_mic_interrupt = NULL;
|
|---|
| 1299 | emu->pcm_capture_mic_substream = NULL;
|
|---|
| 1300 | return 0;
|
|---|
| 1301 | }
|
|---|
| 1302 |
|
|---|
| 1303 | static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream)
|
|---|
| 1304 | {
|
|---|
| 1305 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
|
|---|
| 1306 | struct snd_emu10k1_pcm *epcm;
|
|---|
| 1307 | struct snd_pcm_runtime *runtime = substream->runtime;
|
|---|
| 1308 | int nefx = emu->audigy ? 64 : 32;
|
|---|
| 1309 | int idx, err;
|
|---|
| 1310 |
|
|---|
| 1311 | epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
|
|---|
| 1312 | if (epcm == NULL)
|
|---|
| 1313 | return -ENOMEM;
|
|---|
| 1314 | epcm->emu = emu;
|
|---|
| 1315 | epcm->type = CAPTURE_EFX;
|
|---|
| 1316 | epcm->substream = substream;
|
|---|
| 1317 | epcm->capture_ipr = IPR_EFXBUFFULL|IPR_EFXBUFHALFFULL;
|
|---|
| 1318 | epcm->capture_inte = INTE_EFXBUFENABLE;
|
|---|
| 1319 | epcm->capture_ba_reg = FXBA;
|
|---|
| 1320 | epcm->capture_bs_reg = FXBS;
|
|---|
| 1321 | epcm->capture_idx_reg = FXIDX;
|
|---|
| 1322 | substream->runtime->private_data = epcm;
|
|---|
| 1323 | substream->runtime->private_free = snd_emu10k1_pcm_free_substream;
|
|---|
| 1324 | runtime->hw = snd_emu10k1_capture_efx;
|
|---|
| 1325 | if (emu->card_capabilities->emu_model) {
|
|---|
| 1326 | snd_emu1010_constrain_efx_rate(emu, runtime);
|
|---|
| 1327 | /*
|
|---|
| 1328 | * There are 32 mono channels of 16bits each.
|
|---|
| 1329 | * 24bit Audio uses 2x channels over 16bit,
|
|---|
| 1330 | * 96kHz uses 2x channels over 48kHz,
|
|---|
| 1331 | * 192kHz uses 4x channels over 48kHz.
|
|---|
| 1332 | * So, for 48kHz 24bit, one has 16 channels,
|
|---|
| 1333 | * for 96kHz 24bit, one has 8 channels,
|
|---|
| 1334 | * for 192kHz 24bit, one has 4 channels.
|
|---|
| 1335 | * 1010rev2 and 1616(m) cards have double that,
|
|---|
| 1336 | * but we don't exceed 16 channels anyway.
|
|---|
| 1337 | */
|
|---|
| 1338 | #if 0
|
|---|
| 1339 | /* For 96kHz */
|
|---|
| 1340 | runtime->hw.channels_min = runtime->hw.channels_max = 4;
|
|---|
| 1341 | #endif
|
|---|
| 1342 | #if 0
|
|---|
| 1343 | /* For 192kHz */
|
|---|
| 1344 | runtime->hw.channels_min = runtime->hw.channels_max = 2;
|
|---|
| 1345 | #endif
|
|---|
| 1346 | runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
|
|---|
| 1347 | } else {
|
|---|
| 1348 | spin_lock_irq(&emu->reg_lock);
|
|---|
| 1349 | runtime->hw.channels_min = runtime->hw.channels_max = 0;
|
|---|
| 1350 | for (idx = 0; idx < nefx; idx++) {
|
|---|
| 1351 | if (emu->efx_voices_mask[idx/32] & (1 << (idx%32))) {
|
|---|
| 1352 | runtime->hw.channels_min++;
|
|---|
| 1353 | runtime->hw.channels_max++;
|
|---|
| 1354 | }
|
|---|
| 1355 | }
|
|---|
| 1356 | epcm->capture_cr_val = emu->efx_voices_mask[0];
|
|---|
| 1357 | epcm->capture_cr_val2 = emu->efx_voices_mask[1];
|
|---|
| 1358 | spin_unlock_irq(&emu->reg_lock);
|
|---|
| 1359 | }
|
|---|
| 1360 | err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
|
|---|
| 1361 | &hw_constraints_efx_capture_channels);
|
|---|
| 1362 | if (err < 0) {
|
|---|
| 1363 | kfree(epcm);
|
|---|
| 1364 | return err;
|
|---|
| 1365 | }
|
|---|
| 1366 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
|
|---|
| 1367 | &hw_constraints_capture_buffer_sizes);
|
|---|
| 1368 | emu->capture_efx_interrupt = snd_emu10k1_pcm_efx_interrupt;
|
|---|
| 1369 | emu->pcm_capture_efx_substream = substream;
|
|---|
| 1370 | return 0;
|
|---|
| 1371 | }
|
|---|
| 1372 |
|
|---|
| 1373 | static int snd_emu10k1_capture_efx_close(struct snd_pcm_substream *substream)
|
|---|
| 1374 | {
|
|---|
| 1375 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
|
|---|
| 1376 |
|
|---|
| 1377 | emu->capture_efx_interrupt = NULL;
|
|---|
| 1378 | emu->pcm_capture_efx_substream = NULL;
|
|---|
| 1379 | return 0;
|
|---|
| 1380 | }
|
|---|
| 1381 |
|
|---|
| 1382 | static const struct snd_pcm_ops snd_emu10k1_playback_ops = {
|
|---|
| 1383 | .open = snd_emu10k1_playback_open,
|
|---|
| 1384 | .close = snd_emu10k1_playback_close,
|
|---|
| 1385 | .hw_params = snd_emu10k1_playback_hw_params,
|
|---|
| 1386 | .hw_free = snd_emu10k1_playback_hw_free,
|
|---|
| 1387 | .prepare = snd_emu10k1_playback_prepare,
|
|---|
| 1388 | .trigger = snd_emu10k1_playback_trigger,
|
|---|
| 1389 | .pointer = snd_emu10k1_playback_pointer,
|
|---|
| 1390 | };
|
|---|
| 1391 |
|
|---|
| 1392 | static const struct snd_pcm_ops snd_emu10k1_capture_ops = {
|
|---|
| 1393 | .open = snd_emu10k1_capture_open,
|
|---|
| 1394 | .close = snd_emu10k1_capture_close,
|
|---|
| 1395 | .prepare = snd_emu10k1_capture_prepare,
|
|---|
| 1396 | .trigger = snd_emu10k1_capture_trigger,
|
|---|
| 1397 | .pointer = snd_emu10k1_capture_pointer,
|
|---|
| 1398 | };
|
|---|
| 1399 |
|
|---|
| 1400 | /* EFX playback */
|
|---|
| 1401 | static const struct snd_pcm_ops snd_emu10k1_efx_playback_ops = {
|
|---|
| 1402 | .open = snd_emu10k1_efx_playback_open,
|
|---|
| 1403 | .close = snd_emu10k1_efx_playback_close,
|
|---|
| 1404 | .hw_params = snd_emu10k1_playback_hw_params,
|
|---|
| 1405 | .hw_free = snd_emu10k1_playback_hw_free,
|
|---|
| 1406 | .prepare = snd_emu10k1_efx_playback_prepare,
|
|---|
| 1407 | .trigger = snd_emu10k1_efx_playback_trigger,
|
|---|
| 1408 | .pointer = snd_emu10k1_playback_pointer,
|
|---|
| 1409 | };
|
|---|
| 1410 |
|
|---|
| 1411 | int snd_emu10k1_pcm(struct snd_emu10k1 *emu, int device)
|
|---|
| 1412 | {
|
|---|
| 1413 | struct snd_pcm *pcm;
|
|---|
| 1414 | struct snd_pcm_substream *substream;
|
|---|
| 1415 | int err;
|
|---|
| 1416 |
|
|---|
| 1417 | err = snd_pcm_new(emu->card, "emu10k1", device, 32, 1, &pcm);
|
|---|
| 1418 | if (err < 0)
|
|---|
| 1419 | return err;
|
|---|
| 1420 |
|
|---|
| 1421 | pcm->private_data = emu;
|
|---|
| 1422 |
|
|---|
| 1423 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_playback_ops);
|
|---|
| 1424 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_ops);
|
|---|
| 1425 |
|
|---|
| 1426 | pcm->info_flags = 0;
|
|---|
| 1427 | pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
|
|---|
| 1428 | strcpy(pcm->name, "ADC Capture/Standard PCM Playback");
|
|---|
| 1429 | emu->pcm = pcm;
|
|---|
| 1430 |
|
|---|
| 1431 | /* playback substream can't use managed buffers due to alignment */
|
|---|
| 1432 | for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next)
|
|---|
| 1433 | snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV_SG,
|
|---|
| 1434 | &emu->pci->dev,
|
|---|
| 1435 | 64*1024, 64*1024);
|
|---|
| 1436 |
|
|---|
| 1437 | for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; substream; substream = substream->next)
|
|---|
| 1438 | snd_pcm_set_managed_buffer(substream, SNDRV_DMA_TYPE_DEV,
|
|---|
| 1439 | &emu->pci->dev, 64*1024, 64*1024);
|
|---|
| 1440 |
|
|---|
| 1441 | return 0;
|
|---|
| 1442 | }
|
|---|
| 1443 |
|
|---|
| 1444 | int snd_emu10k1_pcm_multi(struct snd_emu10k1 *emu, int device)
|
|---|
| 1445 | {
|
|---|
| 1446 | struct snd_pcm *pcm;
|
|---|
| 1447 | struct snd_pcm_substream *substream;
|
|---|
| 1448 | int err;
|
|---|
| 1449 |
|
|---|
| 1450 | err = snd_pcm_new(emu->card, "emu10k1", device, 1, 0, &pcm);
|
|---|
| 1451 | if (err < 0)
|
|---|
| 1452 | return err;
|
|---|
| 1453 |
|
|---|
| 1454 | pcm->private_data = emu;
|
|---|
| 1455 |
|
|---|
| 1456 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_efx_playback_ops);
|
|---|
| 1457 |
|
|---|
| 1458 | pcm->info_flags = 0;
|
|---|
| 1459 | pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
|
|---|
| 1460 | strcpy(pcm->name, "Multichannel Playback");
|
|---|
| 1461 | emu->pcm_multi = pcm;
|
|---|
| 1462 |
|
|---|
| 1463 | for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next)
|
|---|
| 1464 | snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV_SG,
|
|---|
| 1465 | &emu->pci->dev,
|
|---|
| 1466 | 64*1024, 64*1024);
|
|---|
| 1467 |
|
|---|
| 1468 | return 0;
|
|---|
| 1469 | }
|
|---|
| 1470 |
|
|---|
| 1471 |
|
|---|
| 1472 | static const struct snd_pcm_ops snd_emu10k1_capture_mic_ops = {
|
|---|
| 1473 | .open = snd_emu10k1_capture_mic_open,
|
|---|
| 1474 | .close = snd_emu10k1_capture_mic_close,
|
|---|
| 1475 | .prepare = snd_emu10k1_capture_prepare,
|
|---|
| 1476 | .trigger = snd_emu10k1_capture_trigger,
|
|---|
| 1477 | .pointer = snd_emu10k1_capture_pointer,
|
|---|
| 1478 | };
|
|---|
| 1479 |
|
|---|
| 1480 | int snd_emu10k1_pcm_mic(struct snd_emu10k1 *emu, int device)
|
|---|
| 1481 | {
|
|---|
| 1482 | struct snd_pcm *pcm;
|
|---|
| 1483 | int err;
|
|---|
| 1484 |
|
|---|
| 1485 | err = snd_pcm_new(emu->card, "emu10k1 mic", device, 0, 1, &pcm);
|
|---|
| 1486 | if (err < 0)
|
|---|
| 1487 | return err;
|
|---|
| 1488 |
|
|---|
| 1489 | pcm->private_data = emu;
|
|---|
| 1490 |
|
|---|
| 1491 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_mic_ops);
|
|---|
| 1492 |
|
|---|
| 1493 | pcm->info_flags = 0;
|
|---|
| 1494 | strcpy(pcm->name, "Mic Capture");
|
|---|
| 1495 | emu->pcm_mic = pcm;
|
|---|
| 1496 |
|
|---|
| 1497 | snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, &emu->pci->dev,
|
|---|
| 1498 | 64*1024, 64*1024);
|
|---|
| 1499 |
|
|---|
| 1500 | return 0;
|
|---|
| 1501 | }
|
|---|
| 1502 |
|
|---|
| 1503 | static int snd_emu10k1_pcm_efx_voices_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
|
|---|
| 1504 | {
|
|---|
| 1505 | struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
|
|---|
| 1506 | int nefx = emu->audigy ? 64 : 32;
|
|---|
| 1507 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
|
|---|
| 1508 | uinfo->count = nefx;
|
|---|
| 1509 | uinfo->value.integer.min = 0;
|
|---|
| 1510 | uinfo->value.integer.max = 1;
|
|---|
| 1511 | return 0;
|
|---|
| 1512 | }
|
|---|
| 1513 |
|
|---|
| 1514 | static int snd_emu10k1_pcm_efx_voices_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
|---|
| 1515 | {
|
|---|
| 1516 | struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
|
|---|
| 1517 | int nefx = emu->audigy ? 64 : 32;
|
|---|
| 1518 | int idx;
|
|---|
| 1519 |
|
|---|
| 1520 | for (idx = 0; idx < nefx; idx++)
|
|---|
| 1521 | ucontrol->value.integer.value[idx] = (emu->efx_voices_mask[idx / 32] & (1 << (idx % 32))) ? 1 : 0;
|
|---|
| 1522 | return 0;
|
|---|
| 1523 | }
|
|---|
| 1524 |
|
|---|
| 1525 | static int snd_emu10k1_pcm_efx_voices_mask_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
|---|
| 1526 | {
|
|---|
| 1527 | struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
|
|---|
| 1528 | unsigned int nval[2], bits;
|
|---|
| 1529 | int nefx = emu->audigy ? 64 : 32;
|
|---|
| 1530 | int change, idx;
|
|---|
| 1531 |
|
|---|
| 1532 | nval[0] = nval[1] = 0;
|
|---|
| 1533 | for (idx = 0, bits = 0; idx < nefx; idx++)
|
|---|
| 1534 | if (ucontrol->value.integer.value[idx]) {
|
|---|
| 1535 | nval[idx / 32] |= 1 << (idx % 32);
|
|---|
| 1536 | bits++;
|
|---|
| 1537 | }
|
|---|
| 1538 |
|
|---|
| 1539 | if (bits == 9 || bits == 11 || bits == 13 || bits == 15 || bits > 16)
|
|---|
| 1540 | return -EINVAL;
|
|---|
| 1541 |
|
|---|
| 1542 | spin_lock_irq(&emu->reg_lock);
|
|---|
| 1543 | change = (nval[0] != emu->efx_voices_mask[0]) ||
|
|---|
| 1544 | (nval[1] != emu->efx_voices_mask[1]);
|
|---|
| 1545 | emu->efx_voices_mask[0] = nval[0];
|
|---|
| 1546 | emu->efx_voices_mask[1] = nval[1];
|
|---|
| 1547 | spin_unlock_irq(&emu->reg_lock);
|
|---|
| 1548 | return change;
|
|---|
| 1549 | }
|
|---|
| 1550 |
|
|---|
| 1551 | static const struct snd_kcontrol_new snd_emu10k1_pcm_efx_voices_mask = {
|
|---|
| 1552 | .iface = SNDRV_CTL_ELEM_IFACE_PCM,
|
|---|
| 1553 | .name = "Captured FX8010 Outputs",
|
|---|
| 1554 | .info = snd_emu10k1_pcm_efx_voices_mask_info,
|
|---|
| 1555 | .get = snd_emu10k1_pcm_efx_voices_mask_get,
|
|---|
| 1556 | .put = snd_emu10k1_pcm_efx_voices_mask_put
|
|---|
| 1557 | };
|
|---|
| 1558 |
|
|---|
| 1559 | static const struct snd_pcm_ops snd_emu10k1_capture_efx_ops = {
|
|---|
| 1560 | .open = snd_emu10k1_capture_efx_open,
|
|---|
| 1561 | .close = snd_emu10k1_capture_efx_close,
|
|---|
| 1562 | .prepare = snd_emu10k1_capture_prepare,
|
|---|
| 1563 | .trigger = snd_emu10k1_capture_trigger,
|
|---|
| 1564 | .pointer = snd_emu10k1_capture_pointer,
|
|---|
| 1565 | };
|
|---|
| 1566 |
|
|---|
| 1567 |
|
|---|
| 1568 | /* EFX playback */
|
|---|
| 1569 |
|
|---|
| 1570 | #define INITIAL_TRAM_SHIFT 14
|
|---|
| 1571 | #define INITIAL_TRAM_POS(size) ((((size) / 2) - INITIAL_TRAM_SHIFT) - 1)
|
|---|
| 1572 |
|
|---|
| 1573 | static void snd_emu10k1_fx8010_playback_irq(struct snd_emu10k1 *emu, void *private_data)
|
|---|
| 1574 | {
|
|---|
| 1575 | struct snd_pcm_substream *substream = private_data;
|
|---|
| 1576 | snd_pcm_period_elapsed(substream);
|
|---|
| 1577 | }
|
|---|
| 1578 |
|
|---|
| 1579 | static void snd_emu10k1_fx8010_playback_tram_poke1(unsigned short *dst_left,
|
|---|
| 1580 | unsigned short *dst_right,
|
|---|
| 1581 | unsigned short *src,
|
|---|
| 1582 | unsigned int count,
|
|---|
| 1583 | unsigned int tram_shift)
|
|---|
| 1584 | {
|
|---|
| 1585 | /*
|
|---|
| 1586 | dev_dbg(emu->card->dev,
|
|---|
| 1587 | "tram_poke1: dst_left = 0x%p, dst_right = 0x%p, "
|
|---|
| 1588 | "src = 0x%p, count = 0x%x\n",
|
|---|
| 1589 | dst_left, dst_right, src, count);
|
|---|
| 1590 | */
|
|---|
| 1591 | if ((tram_shift & 1) == 0) {
|
|---|
| 1592 | while (count--) {
|
|---|
| 1593 | *dst_left-- = *src++;
|
|---|
| 1594 | *dst_right-- = *src++;
|
|---|
| 1595 | }
|
|---|
| 1596 | } else {
|
|---|
| 1597 | while (count--) {
|
|---|
| 1598 | *dst_right-- = *src++;
|
|---|
| 1599 | *dst_left-- = *src++;
|
|---|
| 1600 | }
|
|---|
| 1601 | }
|
|---|
| 1602 | }
|
|---|
| 1603 |
|
|---|
| 1604 | static void fx8010_pb_trans_copy(struct snd_pcm_substream *substream,
|
|---|
| 1605 | struct snd_pcm_indirect *rec, size_t bytes)
|
|---|
| 1606 | {
|
|---|
| 1607 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
|
|---|
| 1608 | struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number];
|
|---|
| 1609 | unsigned int tram_size = pcm->buffer_size;
|
|---|
| 1610 | unsigned short *src = (unsigned short *)(substream->runtime->dma_area + rec->sw_data);
|
|---|
| 1611 | unsigned int frames = bytes >> 2, count;
|
|---|
| 1612 | unsigned int tram_pos = pcm->tram_pos;
|
|---|
| 1613 | unsigned int tram_shift = pcm->tram_shift;
|
|---|
| 1614 |
|
|---|
| 1615 | while (frames > tram_pos) {
|
|---|
| 1616 | count = tram_pos + 1;
|
|---|
| 1617 | snd_emu10k1_fx8010_playback_tram_poke1((unsigned short *)emu->fx8010.etram_pages.area + tram_pos,
|
|---|
| 1618 | (unsigned short *)emu->fx8010.etram_pages.area + tram_pos + tram_size / 2,
|
|---|
| 1619 | src, count, tram_shift);
|
|---|
| 1620 | src += count * 2;
|
|---|
| 1621 | frames -= count;
|
|---|
| 1622 | tram_pos = (tram_size / 2) - 1;
|
|---|
| 1623 | tram_shift++;
|
|---|
| 1624 | }
|
|---|
| 1625 | snd_emu10k1_fx8010_playback_tram_poke1((unsigned short *)emu->fx8010.etram_pages.area + tram_pos,
|
|---|
| 1626 | (unsigned short *)emu->fx8010.etram_pages.area + tram_pos + tram_size / 2,
|
|---|
| 1627 | src, frames, tram_shift);
|
|---|
| 1628 | tram_pos -= frames;
|
|---|
| 1629 | pcm->tram_pos = tram_pos;
|
|---|
| 1630 | pcm->tram_shift = tram_shift;
|
|---|
| 1631 | }
|
|---|
| 1632 |
|
|---|
| 1633 | static int snd_emu10k1_fx8010_playback_transfer(struct snd_pcm_substream *substream)
|
|---|
| 1634 | {
|
|---|
| 1635 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
|
|---|
| 1636 | struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number];
|
|---|
| 1637 |
|
|---|
| 1638 | return snd_pcm_indirect_playback_transfer(substream, &pcm->pcm_rec,
|
|---|
| 1639 | fx8010_pb_trans_copy);
|
|---|
| 1640 | }
|
|---|
| 1641 |
|
|---|
| 1642 | static int snd_emu10k1_fx8010_playback_hw_free(struct snd_pcm_substream *substream)
|
|---|
| 1643 | {
|
|---|
| 1644 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
|
|---|
| 1645 | struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number];
|
|---|
| 1646 | unsigned int i;
|
|---|
| 1647 |
|
|---|
| 1648 | for (i = 0; i < pcm->channels; i++)
|
|---|
| 1649 | snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + 0x80 + pcm->etram[i], 0, 0);
|
|---|
| 1650 | return 0;
|
|---|
| 1651 | }
|
|---|
| 1652 |
|
|---|
| 1653 | static int snd_emu10k1_fx8010_playback_prepare(struct snd_pcm_substream *substream)
|
|---|
| 1654 | {
|
|---|
| 1655 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
|
|---|
| 1656 | struct snd_pcm_runtime *runtime = substream->runtime;
|
|---|
| 1657 | struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number];
|
|---|
| 1658 | unsigned int i;
|
|---|
| 1659 |
|
|---|
| 1660 | /*
|
|---|
| 1661 | dev_dbg(emu->card->dev, "prepare: etram_pages = 0x%p, dma_area = 0x%x, "
|
|---|
| 1662 | "buffer_size = 0x%x (0x%x)\n",
|
|---|
| 1663 | emu->fx8010.etram_pages, runtime->dma_area,
|
|---|
| 1664 | runtime->buffer_size, runtime->buffer_size << 2);
|
|---|
| 1665 | */
|
|---|
| 1666 | memset(&pcm->pcm_rec, 0, sizeof(pcm->pcm_rec));
|
|---|
| 1667 | pcm->pcm_rec.hw_buffer_size = pcm->buffer_size * 2; /* byte size */
|
|---|
| 1668 | pcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
|
|---|
| 1669 | pcm->tram_pos = INITIAL_TRAM_POS(pcm->buffer_size);
|
|---|
| 1670 | pcm->tram_shift = 0;
|
|---|
| 1671 | snd_emu10k1_ptr_write_multiple(emu, 0,
|
|---|
| 1672 | emu->gpr_base + pcm->gpr_running, 0, /* reset */
|
|---|
| 1673 | emu->gpr_base + pcm->gpr_trigger, 0, /* reset */
|
|---|
| 1674 | emu->gpr_base + pcm->gpr_size, runtime->buffer_size,
|
|---|
| 1675 | emu->gpr_base + pcm->gpr_ptr, 0, /* reset ptr number */
|
|---|
| 1676 | emu->gpr_base + pcm->gpr_count, runtime->period_size,
|
|---|
| 1677 | emu->gpr_base + pcm->gpr_tmpcount, runtime->period_size,
|
|---|
| 1678 | REGLIST_END);
|
|---|
| 1679 | for (i = 0; i < pcm->channels; i++)
|
|---|
| 1680 | snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + 0x80 + pcm->etram[i], 0, (TANKMEMADDRREG_READ|TANKMEMADDRREG_ALIGN) + i * (runtime->buffer_size / pcm->channels));
|
|---|
| 1681 | return 0;
|
|---|
| 1682 | }
|
|---|
| 1683 |
|
|---|
| 1684 | static int snd_emu10k1_fx8010_playback_trigger(struct snd_pcm_substream *substream, int cmd)
|
|---|
| 1685 | {
|
|---|
| 1686 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
|
|---|
| 1687 | struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number];
|
|---|
| 1688 | int result = 0;
|
|---|
| 1689 |
|
|---|
| 1690 | spin_lock(&emu->reg_lock);
|
|---|
| 1691 | switch (cmd) {
|
|---|
| 1692 | case SNDRV_PCM_TRIGGER_START:
|
|---|
| 1693 | /* follow thru */
|
|---|
| 1694 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
|---|
| 1695 | case SNDRV_PCM_TRIGGER_RESUME:
|
|---|
| 1696 | #ifdef EMU10K1_SET_AC3_IEC958
|
|---|
| 1697 | {
|
|---|
| 1698 | int i;
|
|---|
| 1699 | for (i = 0; i < 3; i++) {
|
|---|
| 1700 | unsigned int bits;
|
|---|
| 1701 | bits = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
|
|---|
| 1702 | SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS |
|
|---|
| 1703 | 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT | SPCS_NOTAUDIODATA;
|
|---|
| 1704 | snd_emu10k1_ptr_write(emu, SPCS0 + i, 0, bits);
|
|---|
| 1705 | }
|
|---|
| 1706 | }
|
|---|
| 1707 | #endif
|
|---|
| 1708 | result = snd_emu10k1_fx8010_register_irq_handler(emu, snd_emu10k1_fx8010_playback_irq, pcm->gpr_running, substream, &pcm->irq);
|
|---|
| 1709 | if (result < 0)
|
|---|
| 1710 | goto __err;
|
|---|
| 1711 | snd_emu10k1_fx8010_playback_transfer(substream); /* roll the ball */
|
|---|
| 1712 | snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 1);
|
|---|
| 1713 | break;
|
|---|
| 1714 | case SNDRV_PCM_TRIGGER_STOP:
|
|---|
| 1715 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
|---|
| 1716 | case SNDRV_PCM_TRIGGER_SUSPEND:
|
|---|
| 1717 | snd_emu10k1_fx8010_unregister_irq_handler(emu, &pcm->irq);
|
|---|
| 1718 | snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 0);
|
|---|
| 1719 | pcm->tram_pos = INITIAL_TRAM_POS(pcm->buffer_size);
|
|---|
| 1720 | pcm->tram_shift = 0;
|
|---|
| 1721 | break;
|
|---|
| 1722 | default:
|
|---|
| 1723 | result = -EINVAL;
|
|---|
| 1724 | break;
|
|---|
| 1725 | }
|
|---|
| 1726 | __err:
|
|---|
| 1727 | spin_unlock(&emu->reg_lock);
|
|---|
| 1728 | return result;
|
|---|
| 1729 | }
|
|---|
| 1730 |
|
|---|
| 1731 | static snd_pcm_uframes_t snd_emu10k1_fx8010_playback_pointer(struct snd_pcm_substream *substream)
|
|---|
| 1732 | {
|
|---|
| 1733 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
|
|---|
| 1734 | struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number];
|
|---|
| 1735 | size_t ptr; /* byte pointer */
|
|---|
| 1736 |
|
|---|
| 1737 | if (!snd_emu10k1_ptr_read(emu, emu->gpr_base + pcm->gpr_trigger, 0))
|
|---|
| 1738 | return 0;
|
|---|
| 1739 | ptr = snd_emu10k1_ptr_read(emu, emu->gpr_base + pcm->gpr_ptr, 0) << 2;
|
|---|
| 1740 | return snd_pcm_indirect_playback_pointer(substream, &pcm->pcm_rec, ptr);
|
|---|
| 1741 | }
|
|---|
| 1742 |
|
|---|
| 1743 | static const struct snd_pcm_hardware snd_emu10k1_fx8010_playback =
|
|---|
| 1744 | {
|
|---|
| 1745 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
|
|---|
| 1746 | SNDRV_PCM_INFO_RESUME |
|
|---|
| 1747 | /* SNDRV_PCM_INFO_MMAP_VALID | */ SNDRV_PCM_INFO_PAUSE |
|
|---|
| 1748 | SNDRV_PCM_INFO_SYNC_APPLPTR),
|
|---|
| 1749 | .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
|
|---|
| 1750 | .rates = SNDRV_PCM_RATE_48000,
|
|---|
| 1751 | .rate_min = 48000,
|
|---|
| 1752 | .rate_max = 48000,
|
|---|
| 1753 | .channels_min = 1,
|
|---|
| 1754 | .channels_max = 1,
|
|---|
| 1755 | .buffer_bytes_max = (128*1024),
|
|---|
| 1756 | .period_bytes_min = 1024,
|
|---|
| 1757 | .period_bytes_max = (128*1024),
|
|---|
| 1758 | .periods_min = 2,
|
|---|
| 1759 | .periods_max = 1024,
|
|---|
| 1760 | .fifo_size = 0,
|
|---|
| 1761 | };
|
|---|
| 1762 |
|
|---|
| 1763 | static int snd_emu10k1_fx8010_playback_open(struct snd_pcm_substream *substream)
|
|---|
| 1764 | {
|
|---|
| 1765 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
|
|---|
| 1766 | struct snd_pcm_runtime *runtime = substream->runtime;
|
|---|
| 1767 | struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number];
|
|---|
| 1768 |
|
|---|
| 1769 | runtime->hw = snd_emu10k1_fx8010_playback;
|
|---|
| 1770 | runtime->hw.channels_min = runtime->hw.channels_max = pcm->channels;
|
|---|
| 1771 | runtime->hw.period_bytes_max = (pcm->buffer_size * 2) / 2;
|
|---|
| 1772 | spin_lock_irq(&emu->reg_lock);
|
|---|
| 1773 | if (pcm->valid == 0) {
|
|---|
| 1774 | spin_unlock_irq(&emu->reg_lock);
|
|---|
| 1775 | return -ENODEV;
|
|---|
| 1776 | }
|
|---|
| 1777 | pcm->opened = 1;
|
|---|
| 1778 | spin_unlock_irq(&emu->reg_lock);
|
|---|
| 1779 | return 0;
|
|---|
| 1780 | }
|
|---|
| 1781 |
|
|---|
| 1782 | static int snd_emu10k1_fx8010_playback_close(struct snd_pcm_substream *substream)
|
|---|
| 1783 | {
|
|---|
| 1784 | struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
|
|---|
| 1785 | struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number];
|
|---|
| 1786 |
|
|---|
| 1787 | spin_lock_irq(&emu->reg_lock);
|
|---|
| 1788 | pcm->opened = 0;
|
|---|
| 1789 | spin_unlock_irq(&emu->reg_lock);
|
|---|
| 1790 | return 0;
|
|---|
| 1791 | }
|
|---|
| 1792 |
|
|---|
| 1793 | static const struct snd_pcm_ops snd_emu10k1_fx8010_playback_ops = {
|
|---|
| 1794 | .open = snd_emu10k1_fx8010_playback_open,
|
|---|
| 1795 | .close = snd_emu10k1_fx8010_playback_close,
|
|---|
| 1796 | .hw_free = snd_emu10k1_fx8010_playback_hw_free,
|
|---|
| 1797 | .prepare = snd_emu10k1_fx8010_playback_prepare,
|
|---|
| 1798 | .trigger = snd_emu10k1_fx8010_playback_trigger,
|
|---|
| 1799 | .pointer = snd_emu10k1_fx8010_playback_pointer,
|
|---|
| 1800 | .ack = snd_emu10k1_fx8010_playback_transfer,
|
|---|
| 1801 | };
|
|---|
| 1802 |
|
|---|
| 1803 | int snd_emu10k1_pcm_efx(struct snd_emu10k1 *emu, int device)
|
|---|
| 1804 | {
|
|---|
| 1805 | struct snd_pcm *pcm;
|
|---|
| 1806 | struct snd_kcontrol *kctl;
|
|---|
| 1807 | int err;
|
|---|
| 1808 |
|
|---|
| 1809 | err = snd_pcm_new(emu->card, "emu10k1 efx", device, emu->audigy ? 0 : 8, 1, &pcm);
|
|---|
| 1810 | if (err < 0)
|
|---|
| 1811 | return err;
|
|---|
| 1812 |
|
|---|
| 1813 | pcm->private_data = emu;
|
|---|
| 1814 |
|
|---|
| 1815 | if (!emu->audigy)
|
|---|
| 1816 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_fx8010_playback_ops);
|
|---|
| 1817 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_efx_ops);
|
|---|
| 1818 |
|
|---|
| 1819 | pcm->info_flags = 0;
|
|---|
| 1820 | if (emu->audigy)
|
|---|
| 1821 | strcpy(pcm->name, "Multichannel Capture");
|
|---|
| 1822 | else
|
|---|
| 1823 | strcpy(pcm->name, "Multichannel Capture/PT Playback");
|
|---|
| 1824 | emu->pcm_efx = pcm;
|
|---|
| 1825 |
|
|---|
| 1826 | if (!emu->card_capabilities->emu_model) {
|
|---|
| 1827 | // On Sound Blasters, the DSP code copies the EXTINs to FXBUS2.
|
|---|
| 1828 | // The mask determines which of these and the EXTOUTs the multi-
|
|---|
| 1829 | // channel capture actually records (the channel order is fixed).
|
|---|
| 1830 | if (emu->audigy) {
|
|---|
| 1831 | emu->efx_voices_mask[0] = 0;
|
|---|
| 1832 | emu->efx_voices_mask[1] = 0xffff;
|
|---|
| 1833 | } else {
|
|---|
| 1834 | emu->efx_voices_mask[0] = 0xffff0000;
|
|---|
| 1835 | emu->efx_voices_mask[1] = 0;
|
|---|
| 1836 | }
|
|---|
| 1837 | kctl = snd_ctl_new1(&snd_emu10k1_pcm_efx_voices_mask, emu);
|
|---|
| 1838 | if (!kctl)
|
|---|
| 1839 | return -ENOMEM;
|
|---|
| 1840 | kctl->id.device = device;
|
|---|
| 1841 | err = snd_ctl_add(emu->card, kctl);
|
|---|
| 1842 | if (err < 0)
|
|---|
| 1843 | return err;
|
|---|
| 1844 | } else {
|
|---|
| 1845 | // On E-MU cards, the DSP code copies the P16VINs/EMU32INs to
|
|---|
| 1846 | // FXBUS2. These are already selected & routed by the FPGA,
|
|---|
| 1847 | // so there is no need to apply additional masking.
|
|---|
| 1848 | }
|
|---|
| 1849 |
|
|---|
| 1850 | snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, &emu->pci->dev,
|
|---|
| 1851 | 64*1024, 64*1024);
|
|---|
| 1852 |
|
|---|
| 1853 | return 0;
|
|---|
| 1854 | }
|
|---|