emumixer.c 30.9 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
/*
 *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>,
 *                   Takashi Iwai <tiwai@suse.de>
 *                   Creative Labs, Inc.
 *  Routines for control of EMU10K1 chips / mixer routines
 *  Multichannel PCM support Copyright (c) Lee Revell <rlrevell@joe-job.com>
 *
 *  BUGS:
 *    --
 *
 *  TODO:
 *    --
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 */

#include <sound/driver.h>
#include <linux/time.h>
#include <linux/init.h>
#include <sound/core.h>
#include <sound/emu10k1.h>

#define AC97_ID_STAC9758	0x83847658

38
static int snd_emu10k1_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
L
Linus Torvalds 已提交
39 40 41 42 43 44
{
	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
	uinfo->count = 1;
	return 0;
}

45 46
static int snd_emu10k1_spdif_get(struct snd_kcontrol *kcontrol,
                                 struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
47
{
48
	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
49 50 51 52 53 54 55 56 57 58 59 60
	unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
	unsigned long flags;

	spin_lock_irqsave(&emu->reg_lock, flags);
	ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff;
	ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff;
	ucontrol->value.iec958.status[2] = (emu->spdif_bits[idx] >> 16) & 0xff;
	ucontrol->value.iec958.status[3] = (emu->spdif_bits[idx] >> 24) & 0xff;
	spin_unlock_irqrestore(&emu->reg_lock, flags);
	return 0;
}

61 62
static int snd_emu10k1_spdif_get_mask(struct snd_kcontrol *kcontrol,
				      struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
63 64 65 66 67 68 69 70
{
	ucontrol->value.iec958.status[0] = 0xff;
	ucontrol->value.iec958.status[1] = 0xff;
	ucontrol->value.iec958.status[2] = 0xff;
	ucontrol->value.iec958.status[3] = 0xff;
	return 0;
}

T
Takashi Iwai 已提交
71
#if 0
72
static int snd_audigy_spdif_output_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
L
Linus Torvalds 已提交
73 74 75 76 77 78 79 80 81 82 83 84
{
	static char *texts[] = {"44100", "48000", "96000"};

	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
	uinfo->count = 1;
	uinfo->value.enumerated.items = 3;
	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
	return 0;
}

85 86
static int snd_audigy_spdif_output_rate_get(struct snd_kcontrol *kcontrol,
                                 struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
87
{
88
	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
	unsigned int tmp;
	unsigned long flags;
	

	spin_lock_irqsave(&emu->reg_lock, flags);
	tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
	switch (tmp & A_SPDIF_RATE_MASK) {
	case A_SPDIF_44100:
		ucontrol->value.enumerated.item[0] = 0;
		break;
	case A_SPDIF_48000:
		ucontrol->value.enumerated.item[0] = 1;
		break;
	case A_SPDIF_96000:
		ucontrol->value.enumerated.item[0] = 2;
		break;
	default:
		ucontrol->value.enumerated.item[0] = 1;
	}
	spin_unlock_irqrestore(&emu->reg_lock, flags);
	return 0;
}

112 113
static int snd_audigy_spdif_output_rate_put(struct snd_kcontrol *kcontrol,
                                 struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
114
{
115
	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
	int change;
	unsigned int reg, val, tmp;
	unsigned long flags;

	switch(ucontrol->value.enumerated.item[0]) {
	case 0:
		val = A_SPDIF_44100;
		break;
	case 1:
		val = A_SPDIF_48000;
		break;
	case 2:
		val = A_SPDIF_96000;
		break;
	default:
		val = A_SPDIF_48000;
		break;
	}

	
	spin_lock_irqsave(&emu->reg_lock, flags);
	reg = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
	tmp = reg & ~A_SPDIF_RATE_MASK;
	tmp |= val;
	if ((change = (tmp != reg)))
		snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp);
	spin_unlock_irqrestore(&emu->reg_lock, flags);
	return change;
}

146
static struct snd_kcontrol_new snd_audigy_spdif_output_rate =
L
Linus Torvalds 已提交
147 148 149 150 151 152 153 154 155
{
	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE,
	.iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
	.name =         "Audigy SPDIF Output Sample Rate",
	.count =	1,
	.info =         snd_audigy_spdif_output_rate_info,
	.get =          snd_audigy_spdif_output_rate_get,
	.put =          snd_audigy_spdif_output_rate_put
};
T
Takashi Iwai 已提交
156
#endif
L
Linus Torvalds 已提交
157

158 159
static int snd_emu10k1_spdif_put(struct snd_kcontrol *kcontrol,
                                 struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
160
{
161
	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
	unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
	int change;
	unsigned int val;
	unsigned long flags;

	val = (ucontrol->value.iec958.status[0] << 0) |
	      (ucontrol->value.iec958.status[1] << 8) |
	      (ucontrol->value.iec958.status[2] << 16) |
	      (ucontrol->value.iec958.status[3] << 24);
	spin_lock_irqsave(&emu->reg_lock, flags);
	change = val != emu->spdif_bits[idx];
	if (change) {
		snd_emu10k1_ptr_write(emu, SPCS0 + idx, 0, val);
		emu->spdif_bits[idx] = val;
	}
	spin_unlock_irqrestore(&emu->reg_lock, flags);
	return change;
}

181
static struct snd_kcontrol_new snd_emu10k1_spdif_mask_control =
L
Linus Torvalds 已提交
182 183
{
	.access =	SNDRV_CTL_ELEM_ACCESS_READ,
184
	.iface =        SNDRV_CTL_ELEM_IFACE_PCM,
L
Linus Torvalds 已提交
185 186 187 188 189 190
	.name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
	.count =	4,
	.info =         snd_emu10k1_spdif_info,
	.get =          snd_emu10k1_spdif_get_mask
};

191
static struct snd_kcontrol_new snd_emu10k1_spdif_control =
L
Linus Torvalds 已提交
192
{
193
	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
L
Linus Torvalds 已提交
194 195 196 197 198 199 200 201
	.name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
	.count =	4,
	.info =         snd_emu10k1_spdif_info,
	.get =          snd_emu10k1_spdif_get,
	.put =          snd_emu10k1_spdif_put
};


202
static void update_emu10k1_fxrt(struct snd_emu10k1 *emu, int voice, unsigned char *route)
L
Linus Torvalds 已提交
203 204 205 206 207 208 209 210 211 212 213 214
{
	if (emu->audigy) {
		snd_emu10k1_ptr_write(emu, A_FXRT1, voice,
				      snd_emu10k1_compose_audigy_fxrt1(route));
		snd_emu10k1_ptr_write(emu, A_FXRT2, voice,
				      snd_emu10k1_compose_audigy_fxrt2(route));
	} else {
		snd_emu10k1_ptr_write(emu, FXRT, voice,
				      snd_emu10k1_compose_send_routing(route));
	}
}

215
static void update_emu10k1_send_volume(struct snd_emu10k1 *emu, int voice, unsigned char *volume)
L
Linus Torvalds 已提交
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
{
	snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_A, voice, volume[0]);
	snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_B, voice, volume[1]);
	snd_emu10k1_ptr_write(emu, PSST_FXSENDAMOUNT_C, voice, volume[2]);
	snd_emu10k1_ptr_write(emu, DSL_FXSENDAMOUNT_D, voice, volume[3]);
	if (emu->audigy) {
		unsigned int val = ((unsigned int)volume[4] << 24) |
			((unsigned int)volume[5] << 16) |
			((unsigned int)volume[6] << 8) |
			(unsigned int)volume[7];
		snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, voice, val);
	}
}

/* PCM stream controls */

232
static int snd_emu10k1_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
L
Linus Torvalds 已提交
233
{
234
	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
235 236 237 238 239 240 241
	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
	uinfo->count = emu->audigy ? 3*8 : 3*4;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
	return 0;
}

242 243
static int snd_emu10k1_send_routing_get(struct snd_kcontrol *kcontrol,
                                        struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
244 245
{
	unsigned long flags;
246 247 248
	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
	struct snd_emu10k1_pcm_mixer *mix =
		&emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
L
Linus Torvalds 已提交
249 250 251 252 253 254 255 256 257 258 259 260 261
	int voice, idx;
	int num_efx = emu->audigy ? 8 : 4;
	int mask = emu->audigy ? 0x3f : 0x0f;

	spin_lock_irqsave(&emu->reg_lock, flags);
	for (voice = 0; voice < 3; voice++)
		for (idx = 0; idx < num_efx; idx++)
			ucontrol->value.integer.value[(voice * num_efx) + idx] = 
				mix->send_routing[voice][idx] & mask;
	spin_unlock_irqrestore(&emu->reg_lock, flags);
	return 0;
}

262 263
static int snd_emu10k1_send_routing_put(struct snd_kcontrol *kcontrol,
                                        struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
264 265
{
	unsigned long flags;
266 267 268
	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
	struct snd_emu10k1_pcm_mixer *mix =
		&emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
L
Linus Torvalds 已提交
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
	int change = 0, voice, idx, val;
	int num_efx = emu->audigy ? 8 : 4;
	int mask = emu->audigy ? 0x3f : 0x0f;

	spin_lock_irqsave(&emu->reg_lock, flags);
	for (voice = 0; voice < 3; voice++)
		for (idx = 0; idx < num_efx; idx++) {
			val = ucontrol->value.integer.value[(voice * num_efx) + idx] & mask;
			if (mix->send_routing[voice][idx] != val) {
				mix->send_routing[voice][idx] = val;
				change = 1;
			}
		}	
	if (change && mix->epcm) {
		if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
			update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
					    &mix->send_routing[1][0]);
			update_emu10k1_fxrt(emu, mix->epcm->voices[1]->number,
					    &mix->send_routing[2][0]);
		} else if (mix->epcm->voices[0]) {
			update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
					    &mix->send_routing[0][0]);
		}
	}
	spin_unlock_irqrestore(&emu->reg_lock, flags);
	return change;
}

297
static struct snd_kcontrol_new snd_emu10k1_send_routing_control =
L
Linus Torvalds 已提交
298 299
{
	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
300
	.iface =        SNDRV_CTL_ELEM_IFACE_PCM,
L
Linus Torvalds 已提交
301 302 303 304 305 306 307
	.name =         "EMU10K1 PCM Send Routing",
	.count =	32,
	.info =         snd_emu10k1_send_routing_info,
	.get =          snd_emu10k1_send_routing_get,
	.put =          snd_emu10k1_send_routing_put
};

308
static int snd_emu10k1_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
L
Linus Torvalds 已提交
309
{
310
	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
311 312 313 314 315 316 317
	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
	uinfo->count = emu->audigy ? 3*8 : 3*4;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max = 255;
	return 0;
}

318 319
static int snd_emu10k1_send_volume_get(struct snd_kcontrol *kcontrol,
                                       struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
320 321
{
	unsigned long flags;
322 323 324
	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
	struct snd_emu10k1_pcm_mixer *mix =
		&emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
L
Linus Torvalds 已提交
325 326 327 328 329 330 331 332 333 334
	int idx;
	int num_efx = emu->audigy ? 8 : 4;

	spin_lock_irqsave(&emu->reg_lock, flags);
	for (idx = 0; idx < 3*num_efx; idx++)
		ucontrol->value.integer.value[idx] = mix->send_volume[idx/num_efx][idx%num_efx];
	spin_unlock_irqrestore(&emu->reg_lock, flags);
	return 0;
}

335 336
static int snd_emu10k1_send_volume_put(struct snd_kcontrol *kcontrol,
                                       struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
337 338
{
	unsigned long flags;
339 340 341
	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
	struct snd_emu10k1_pcm_mixer *mix =
		&emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
L
Linus Torvalds 已提交
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
	int change = 0, idx, val;
	int num_efx = emu->audigy ? 8 : 4;

	spin_lock_irqsave(&emu->reg_lock, flags);
	for (idx = 0; idx < 3*num_efx; idx++) {
		val = ucontrol->value.integer.value[idx] & 255;
		if (mix->send_volume[idx/num_efx][idx%num_efx] != val) {
			mix->send_volume[idx/num_efx][idx%num_efx] = val;
			change = 1;
		}
	}
	if (change && mix->epcm) {
		if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
			update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
						   &mix->send_volume[1][0]);
			update_emu10k1_send_volume(emu, mix->epcm->voices[1]->number,
						   &mix->send_volume[2][0]);
		} else if (mix->epcm->voices[0]) {
			update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
						   &mix->send_volume[0][0]);
		}
	}
	spin_unlock_irqrestore(&emu->reg_lock, flags);
	return change;
}

368
static struct snd_kcontrol_new snd_emu10k1_send_volume_control =
L
Linus Torvalds 已提交
369 370
{
	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
371
	.iface =        SNDRV_CTL_ELEM_IFACE_PCM,
L
Linus Torvalds 已提交
372 373 374 375 376 377 378
	.name =         "EMU10K1 PCM Send Volume",
	.count =	32,
	.info =         snd_emu10k1_send_volume_info,
	.get =          snd_emu10k1_send_volume_get,
	.put =          snd_emu10k1_send_volume_put
};

379
static int snd_emu10k1_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
L
Linus Torvalds 已提交
380 381 382 383 384 385 386 387
{
	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
	uinfo->count = 3;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max = 0xffff;
	return 0;
}

388 389
static int snd_emu10k1_attn_get(struct snd_kcontrol *kcontrol,
                                struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
390
{
391 392 393
	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
	struct snd_emu10k1_pcm_mixer *mix =
		&emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
L
Linus Torvalds 已提交
394 395 396 397 398 399 400 401 402 403
	unsigned long flags;
	int idx;

	spin_lock_irqsave(&emu->reg_lock, flags);
	for (idx = 0; idx < 3; idx++)
		ucontrol->value.integer.value[idx] = mix->attn[idx];
	spin_unlock_irqrestore(&emu->reg_lock, flags);
	return 0;
}

404 405
static int snd_emu10k1_attn_put(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
406 407
{
	unsigned long flags;
408 409 410
	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
	struct snd_emu10k1_pcm_mixer *mix =
		&emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
L
Linus Torvalds 已提交
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432
	int change = 0, idx, val;

	spin_lock_irqsave(&emu->reg_lock, flags);
	for (idx = 0; idx < 3; idx++) {
		val = ucontrol->value.integer.value[idx] & 0xffff;
		if (mix->attn[idx] != val) {
			mix->attn[idx] = val;
			change = 1;
		}
	}
	if (change && mix->epcm) {
		if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
			snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[1]);
			snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[1]->number, mix->attn[2]);
		} else if (mix->epcm->voices[0]) {
			snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[0]);
		}
	}
	spin_unlock_irqrestore(&emu->reg_lock, flags);
	return change;
}

433
static struct snd_kcontrol_new snd_emu10k1_attn_control =
L
Linus Torvalds 已提交
434 435
{
	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
436
	.iface =        SNDRV_CTL_ELEM_IFACE_PCM,
L
Linus Torvalds 已提交
437 438 439 440 441 442 443 444 445
	.name =         "EMU10K1 PCM Volume",
	.count =	32,
	.info =         snd_emu10k1_attn_info,
	.get =          snd_emu10k1_attn_get,
	.put =          snd_emu10k1_attn_put
};

/* Mutichannel PCM stream controls */

446
static int snd_emu10k1_efx_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
L
Linus Torvalds 已提交
447
{
448
	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
449 450 451 452 453 454 455
	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
	uinfo->count = emu->audigy ? 8 : 4;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
	return 0;
}

456 457
static int snd_emu10k1_efx_send_routing_get(struct snd_kcontrol *kcontrol,
                                        struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
458 459
{
	unsigned long flags;
460 461 462
	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
	struct snd_emu10k1_pcm_mixer *mix =
		&emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
L
Linus Torvalds 已提交
463 464 465 466 467 468 469 470 471 472 473 474
	int idx;
	int num_efx = emu->audigy ? 8 : 4;
	int mask = emu->audigy ? 0x3f : 0x0f;

	spin_lock_irqsave(&emu->reg_lock, flags);
	for (idx = 0; idx < num_efx; idx++)
		ucontrol->value.integer.value[idx] = 
			mix->send_routing[0][idx] & mask;
	spin_unlock_irqrestore(&emu->reg_lock, flags);
	return 0;
}

475 476
static int snd_emu10k1_efx_send_routing_put(struct snd_kcontrol *kcontrol,
                                        struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
477 478
{
	unsigned long flags;
479
	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
480
	int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
481
	struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
L
Linus Torvalds 已提交
482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504
	int change = 0, idx, val;
	int num_efx = emu->audigy ? 8 : 4;
	int mask = emu->audigy ? 0x3f : 0x0f;

	spin_lock_irqsave(&emu->reg_lock, flags);
	for (idx = 0; idx < num_efx; idx++) {
		val = ucontrol->value.integer.value[idx] & mask;
		if (mix->send_routing[0][idx] != val) {
			mix->send_routing[0][idx] = val;
			change = 1;
		}
	}	

	if (change && mix->epcm) {
		if (mix->epcm->voices[ch]) {
			update_emu10k1_fxrt(emu, mix->epcm->voices[ch]->number,
					&mix->send_routing[0][0]);
		}
	}
	spin_unlock_irqrestore(&emu->reg_lock, flags);
	return change;
}

505
static struct snd_kcontrol_new snd_emu10k1_efx_send_routing_control =
L
Linus Torvalds 已提交
506 507 508 509 510 511 512 513 514 515
{
	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
	.iface =        SNDRV_CTL_ELEM_IFACE_PCM,
	.name =         "Multichannel PCM Send Routing",
	.count =	16,
	.info =         snd_emu10k1_efx_send_routing_info,
	.get =          snd_emu10k1_efx_send_routing_get,
	.put =          snd_emu10k1_efx_send_routing_put
};

516
static int snd_emu10k1_efx_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
L
Linus Torvalds 已提交
517
{
518
	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
519 520 521 522 523 524 525
	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
	uinfo->count = emu->audigy ? 8 : 4;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max = 255;
	return 0;
}

526 527
static int snd_emu10k1_efx_send_volume_get(struct snd_kcontrol *kcontrol,
                                       struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
528 529
{
	unsigned long flags;
530 531 532
	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
	struct snd_emu10k1_pcm_mixer *mix =
		&emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
L
Linus Torvalds 已提交
533 534 535 536 537 538 539 540 541 542
	int idx;
	int num_efx = emu->audigy ? 8 : 4;

	spin_lock_irqsave(&emu->reg_lock, flags);
	for (idx = 0; idx < num_efx; idx++)
		ucontrol->value.integer.value[idx] = mix->send_volume[0][idx];
	spin_unlock_irqrestore(&emu->reg_lock, flags);
	return 0;
}

543 544
static int snd_emu10k1_efx_send_volume_put(struct snd_kcontrol *kcontrol,
                                       struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
545 546
{
	unsigned long flags;
547
	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
548
	int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
549
	struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
L
Linus Torvalds 已提交
550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571
	int change = 0, idx, val;
	int num_efx = emu->audigy ? 8 : 4;

	spin_lock_irqsave(&emu->reg_lock, flags);
	for (idx = 0; idx < num_efx; idx++) {
		val = ucontrol->value.integer.value[idx] & 255;
		if (mix->send_volume[0][idx] != val) {
			mix->send_volume[0][idx] = val;
			change = 1;
		}
	}
	if (change && mix->epcm) {
		if (mix->epcm->voices[ch]) {
			update_emu10k1_send_volume(emu, mix->epcm->voices[ch]->number,
						   &mix->send_volume[0][0]);
		}
	}
	spin_unlock_irqrestore(&emu->reg_lock, flags);
	return change;
}


572
static struct snd_kcontrol_new snd_emu10k1_efx_send_volume_control =
L
Linus Torvalds 已提交
573 574 575 576 577 578 579 580 581 582
{
	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
	.iface =        SNDRV_CTL_ELEM_IFACE_PCM,
	.name =         "Multichannel PCM Send Volume",
	.count =	16,
	.info =         snd_emu10k1_efx_send_volume_info,
	.get =          snd_emu10k1_efx_send_volume_get,
	.put =          snd_emu10k1_efx_send_volume_put
};

583
static int snd_emu10k1_efx_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
L
Linus Torvalds 已提交
584 585 586 587 588 589 590 591
{
	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
	uinfo->count = 1;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max = 0xffff;
	return 0;
}

592 593
static int snd_emu10k1_efx_attn_get(struct snd_kcontrol *kcontrol,
                                struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
594
{
595 596 597
	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
	struct snd_emu10k1_pcm_mixer *mix =
		&emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
L
Linus Torvalds 已提交
598 599 600 601 602 603 604 605
	unsigned long flags;

	spin_lock_irqsave(&emu->reg_lock, flags);
	ucontrol->value.integer.value[0] = mix->attn[0];
	spin_unlock_irqrestore(&emu->reg_lock, flags);
	return 0;
}

606 607
static int snd_emu10k1_efx_attn_put(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
608 609
{
	unsigned long flags;
610
	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
611
	int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
612
	struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
L
Linus Torvalds 已提交
613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629
	int change = 0, val;

	spin_lock_irqsave(&emu->reg_lock, flags);
	val = ucontrol->value.integer.value[0] & 0xffff;
	if (mix->attn[0] != val) {
		mix->attn[0] = val;
		change = 1;
	}
	if (change && mix->epcm) {
		if (mix->epcm->voices[ch]) {
			snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[ch]->number, mix->attn[0]);
		}
	}
	spin_unlock_irqrestore(&emu->reg_lock, flags);
	return change;
}

630
static struct snd_kcontrol_new snd_emu10k1_efx_attn_control =
L
Linus Torvalds 已提交
631 632 633 634 635 636 637 638 639 640
{
	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
	.iface =        SNDRV_CTL_ELEM_IFACE_PCM,
	.name =         "Multichannel PCM Volume",
	.count =	16,
	.info =         snd_emu10k1_efx_attn_info,
	.get =          snd_emu10k1_efx_attn_get,
	.put =          snd_emu10k1_efx_attn_put
};

641
static int snd_emu10k1_shared_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
L
Linus Torvalds 已提交
642 643 644 645 646 647 648 649
{
	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
	uinfo->count = 1;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max = 1;
	return 0;
}

650 651
static int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol,
					struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
652
{
653
	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
654 655 656 657 658 659 660 661

	if (emu->audigy)
		ucontrol->value.integer.value[0] = inl(emu->port + A_IOCFG) & A_IOCFG_GPOUT0 ? 1 : 0;
	else
		ucontrol->value.integer.value[0] = inl(emu->port + HCFG) & HCFG_GPOUT0 ? 1 : 0;
	return 0;
}

662 663
static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol,
					struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
664 665
{
	unsigned long flags;
666
	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692
	unsigned int reg, val;
	int change = 0;

	spin_lock_irqsave(&emu->reg_lock, flags);
	if (emu->audigy) {
		reg = inl(emu->port + A_IOCFG);
		val = ucontrol->value.integer.value[0] ? A_IOCFG_GPOUT0 : 0;
		change = (reg & A_IOCFG_GPOUT0) != val;
		if (change) {
			reg &= ~A_IOCFG_GPOUT0;
			reg |= val;
			outl(reg | val, emu->port + A_IOCFG);
		}
	}
	reg = inl(emu->port + HCFG);
	val = ucontrol->value.integer.value[0] ? HCFG_GPOUT0 : 0;
	change |= (reg & HCFG_GPOUT0) != val;
	if (change) {
		reg &= ~HCFG_GPOUT0;
		reg |= val;
		outl(reg | val, emu->port + HCFG);
	}
	spin_unlock_irqrestore(&emu->reg_lock, flags);
	return change;
}

693
static struct snd_kcontrol_new snd_emu10k1_shared_spdif __devinitdata =
L
Linus Torvalds 已提交
694 695 696 697 698 699 700 701
{
	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
	.name =		"SB Live Analog/Digital Output Jack",
	.info =		snd_emu10k1_shared_spdif_info,
	.get =		snd_emu10k1_shared_spdif_get,
	.put =		snd_emu10k1_shared_spdif_put
};

702
static struct snd_kcontrol_new snd_audigy_shared_spdif __devinitdata =
L
Linus Torvalds 已提交
703 704 705 706 707 708 709 710 711 712
{
	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
	.name =		"Audigy Analog/Digital Output Jack",
	.info =		snd_emu10k1_shared_spdif_info,
	.get =		snd_emu10k1_shared_spdif_get,
	.put =		snd_emu10k1_shared_spdif_put
};

/*
 */
713
static void snd_emu10k1_mixer_free_ac97(struct snd_ac97 *ac97)
L
Linus Torvalds 已提交
714
{
715
	struct snd_emu10k1 *emu = ac97->private_data;
L
Linus Torvalds 已提交
716 717 718 719 720
	emu->ac97 = NULL;
}

/*
 */
721
static int remove_ctl(struct snd_card *card, const char *name)
L
Linus Torvalds 已提交
722
{
723
	struct snd_ctl_elem_id id;
L
Linus Torvalds 已提交
724 725 726 727 728 729
	memset(&id, 0, sizeof(id));
	strcpy(id.name, name);
	id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
	return snd_ctl_remove_id(card, &id);
}

730
static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name)
L
Linus Torvalds 已提交
731
{
732
	struct snd_ctl_elem_id sid;
L
Linus Torvalds 已提交
733 734 735 736 737 738
	memset(&sid, 0, sizeof(sid));
	strcpy(sid.name, name);
	sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
	return snd_ctl_find_id(card, &sid);
}

739
static int rename_ctl(struct snd_card *card, const char *src, const char *dst)
L
Linus Torvalds 已提交
740
{
741
	struct snd_kcontrol *kctl = ctl_find(card, src);
L
Linus Torvalds 已提交
742 743 744 745 746 747 748
	if (kctl) {
		strcpy(kctl->id.name, dst);
		return 0;
	}
	return -ENOENT;
}

749
int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
750
				int pcm_device, int multi_device)
L
Linus Torvalds 已提交
751 752
{
	int err, pcm;
753 754
	struct snd_kcontrol *kctl;
	struct snd_card *card = emu->card;
L
Linus Torvalds 已提交
755 756 757 758 759 760 761
	char **c;
	static char *emu10k1_remove_ctls[] = {
		/* no AC97 mono, surround, center/lfe */
		"Master Mono Playback Switch",
		"Master Mono Playback Volume",
		"PCM Out Path & Mute",
		"Mono Output Select",
762 763
		"Front Playback Switch",
		"Front Playback Volume",
L
Linus Torvalds 已提交
764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807
		"Surround Playback Switch",
		"Surround Playback Volume",
		"Center Playback Switch",
		"Center Playback Volume",
		"LFE Playback Switch",
		"LFE Playback Volume",
		NULL
	};
	static char *emu10k1_rename_ctls[] = {
		"Surround Digital Playback Volume", "Surround Playback Volume",
		"Center Digital Playback Volume", "Center Playback Volume",
		"LFE Digital Playback Volume", "LFE Playback Volume",
		NULL
	};
	static char *audigy_remove_ctls[] = {
		/* Master/PCM controls on ac97 of Audigy has no effect */
		"PCM Playback Switch",
		"PCM Playback Volume",
		"Master Mono Playback Switch",
		"Master Mono Playback Volume",
		"Master Playback Switch",
		"Master Playback Volume",
		"PCM Out Path & Mute",
		"Mono Output Select",
		/* remove unused AC97 capture controls */
		"Capture Source",
		"Capture Switch",
		"Capture Volume",
		"Mic Select",
		"Video Playback Switch",
		"Video Playback Volume",
		"Mic Playback Switch",
		"Mic Playback Volume",
		NULL
	};
	static char *audigy_rename_ctls[] = {
		/* use conventional names */
		"Wave Playback Volume", "PCM Playback Volume",
		/* "Wave Capture Volume", "PCM Capture Volume", */
		"Wave Master Playback Volume", "Master Playback Volume",
		"AMic Playback Volume", "Mic Playback Volume",
		NULL
	};

L
Lee Revell 已提交
808
	if (emu->card_capabilities->ac97_chip) {
809 810 811
		struct snd_ac97_bus *pbus;
		struct snd_ac97_template ac97;
		static struct snd_ac97_bus_ops ops = {
L
Linus Torvalds 已提交
812 813 814 815
			.write = snd_emu10k1_ac97_write,
			.read = snd_emu10k1_ac97_read,
		};

816 817
		if ((err = snd_ac97_bus(emu->card, 0, &ops, NULL, &pbus)) < 0)
			return err;
L
Linus Torvalds 已提交
818 819 820 821 822 823
		pbus->no_vra = 1; /* we don't need VRA */
		
		memset(&ac97, 0, sizeof(ac97));
		ac97.private_data = emu;
		ac97.private_free = snd_emu10k1_mixer_free_ac97;
		ac97.scaps = AC97_SCAP_NO_SPDIF;
824 825 826 827 828 829 830 831
		if ((err = snd_ac97_mixer(pbus, &ac97, &emu->ac97)) < 0) {
			if (emu->card_capabilities->ac97_chip == 1)
				return err;
			snd_printd(KERN_INFO "emu10k1: AC97 is optional on this board\n");
			snd_printd(KERN_INFO"          Proceeding without ac97 mixers...\n");
			snd_device_free(emu->card, pbus);
			goto no_ac97; /* FIXME: get rid of ugly gotos.. */
		}
L
Linus Torvalds 已提交
832 833
		if (emu->audigy) {
			/* set master volume to 0 dB */
834
			snd_ac97_write_cache(emu->ac97, AC97_MASTER, 0x0000);
L
Linus Torvalds 已提交
835
			/* set capture source to mic */
836
			snd_ac97_write_cache(emu->ac97, AC97_REC_SEL, 0x0000);
L
Linus Torvalds 已提交
837 838 839 840 841 842 843 844 845 846 847 848
			c = audigy_remove_ctls;
		} else {
			/*
			 * Credits for cards based on STAC9758:
			 *   James Courtier-Dutton <James@superbug.demon.co.uk>
			 *   Voluspa <voluspa@comhem.se>
			 */
			if (emu->ac97->id == AC97_ID_STAC9758) {
				emu->rear_ac97 = 1;
				snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE|AC97SLOT_REAR_LEFT|AC97SLOT_REAR_RIGHT);
			}
			/* remove unused AC97 controls */
849 850
			snd_ac97_write_cache(emu->ac97, AC97_SURROUND_MASTER, 0x0202);
			snd_ac97_write_cache(emu->ac97, AC97_CENTER_LFE_MASTER, 0x0202);
L
Linus Torvalds 已提交
851 852 853 854 855
			c = emu10k1_remove_ctls;
		}
		for (; *c; c++)
			remove_ctl(card, *c);
	} else {
856
	no_ac97:
L
Lee Revell 已提交
857
		if (emu->card_capabilities->ecard)
L
Linus Torvalds 已提交
858 859 860 861 862 863 864 865 866 867 868 869 870
			strcpy(emu->card->mixername, "EMU APS");
		else if (emu->audigy)
			strcpy(emu->card->mixername, "SB Audigy");
		else
			strcpy(emu->card->mixername, "Emu10k1");
	}

	if (emu->audigy)
		c = audigy_rename_ctls;
	else
		c = emu10k1_rename_ctls;
	for (; *c; c += 2)
		rename_ctl(card, c[0], c[1]);
871 872 873 874 875 876 877 878 879 880 881
	if (emu->card_capabilities->subsystem == 0x20071102) {  /* Audigy 4 Pro */
		rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume");
		rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume");
		rename_ctl(card, "Aux2 Capture Volume", "Line3 Capture Volume");
		rename_ctl(card, "Mic Capture Volume", "Unknown1 Capture Volume");
		remove_ctl(card, "Headphone Playback Switch");
		remove_ctl(card, "Headphone Playback Volume");
		remove_ctl(card, "3D Control - Center");
		remove_ctl(card, "3D Control - Depth");
		remove_ctl(card, "3D Control - Switch");
	}
L
Linus Torvalds 已提交
882 883
	if ((kctl = emu->ctl_send_routing = snd_ctl_new1(&snd_emu10k1_send_routing_control, emu)) == NULL)
		return -ENOMEM;
884
	kctl->id.device = pcm_device;
L
Linus Torvalds 已提交
885 886 887 888
	if ((err = snd_ctl_add(card, kctl)))
		return err;
	if ((kctl = emu->ctl_send_volume = snd_ctl_new1(&snd_emu10k1_send_volume_control, emu)) == NULL)
		return -ENOMEM;
889
	kctl->id.device = pcm_device;
L
Linus Torvalds 已提交
890 891 892 893
	if ((err = snd_ctl_add(card, kctl)))
		return err;
	if ((kctl = emu->ctl_attn = snd_ctl_new1(&snd_emu10k1_attn_control, emu)) == NULL)
		return -ENOMEM;
894
	kctl->id.device = pcm_device;
L
Linus Torvalds 已提交
895 896 897 898 899
	if ((err = snd_ctl_add(card, kctl)))
		return err;

	if ((kctl = emu->ctl_efx_send_routing = snd_ctl_new1(&snd_emu10k1_efx_send_routing_control, emu)) == NULL)
		return -ENOMEM;
900
	kctl->id.device = multi_device;
L
Linus Torvalds 已提交
901 902 903 904 905
	if ((err = snd_ctl_add(card, kctl)))
		return err;
	
	if ((kctl = emu->ctl_efx_send_volume = snd_ctl_new1(&snd_emu10k1_efx_send_volume_control, emu)) == NULL)
		return -ENOMEM;
906
	kctl->id.device = multi_device;
L
Linus Torvalds 已提交
907 908 909 910 911
	if ((err = snd_ctl_add(card, kctl)))
		return err;
	
	if ((kctl = emu->ctl_efx_attn = snd_ctl_new1(&snd_emu10k1_efx_attn_control, emu)) == NULL)
		return -ENOMEM;
912
	kctl->id.device = multi_device;
L
Linus Torvalds 已提交
913 914 915 916 917
	if ((err = snd_ctl_add(card, kctl)))
		return err;

	/* initialize the routing and volume table for each pcm playback stream */
	for (pcm = 0; pcm < 32; pcm++) {
918
		struct snd_emu10k1_pcm_mixer *mix;
L
Linus Torvalds 已提交
919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937
		int v;
		
		mix = &emu->pcm_mixer[pcm];
		mix->epcm = NULL;

		for (v = 0; v < 4; v++)
			mix->send_routing[0][v] = 
				mix->send_routing[1][v] = 
				mix->send_routing[2][v] = v;
		
		memset(&mix->send_volume, 0, sizeof(mix->send_volume));
		mix->send_volume[0][0] = mix->send_volume[0][1] =
		mix->send_volume[1][0] = mix->send_volume[2][1] = 255;
		
		mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff;
	}
	
	/* initialize the routing and volume table for the multichannel playback stream */
	for (pcm = 0; pcm < NUM_EFX_PLAYBACK; pcm++) {
938
		struct snd_emu10k1_pcm_mixer *mix;
L
Linus Torvalds 已提交
939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957
		int v;
		
		mix = &emu->efx_pcm_mixer[pcm];
		mix->epcm = NULL;

		mix->send_routing[0][0] = pcm;
		mix->send_routing[0][1] = (pcm == 0) ? 1 : 0;
		for (v = 0; v < 2; v++)
			mix->send_routing[0][2+v] = 13+v;
		if (emu->audigy)
			for (v = 0; v < 4; v++)
				mix->send_routing[0][4+v] = 60+v;
		
		memset(&mix->send_volume, 0, sizeof(mix->send_volume));
		mix->send_volume[0][0]  = 255;
		
		mix->attn[0] = 0xffff;
	}
	
L
Lee Revell 已提交
958
	if (! emu->card_capabilities->ecard) { /* FIXME: APS has these controls? */
L
Linus Torvalds 已提交
959 960 961
		/* sb live! and audigy */
		if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL)
			return -ENOMEM;
962 963
		if (!emu->audigy)
			kctl->id.device = emu->pcm_efx->device;
L
Linus Torvalds 已提交
964 965 966 967
		if ((err = snd_ctl_add(card, kctl)))
			return err;
		if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu)) == NULL)
			return -ENOMEM;
968 969
		if (!emu->audigy)
			kctl->id.device = emu->pcm_efx->device;
L
Linus Torvalds 已提交
970 971 972 973
		if ((err = snd_ctl_add(card, kctl)))
			return err;
	}

974 975 976
	if ( emu->card_capabilities->emu1212m) {
		;  /* Disable the snd_audigy_spdif_shared_spdif */
	} else if (emu->audigy) {
L
Linus Torvalds 已提交
977 978 979 980
		if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL)
			return -ENOMEM;
		if ((err = snd_ctl_add(card, kctl)))
			return err;
981
#if 0
L
Linus Torvalds 已提交
982 983 984 985
		if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL)
			return -ENOMEM;
		if ((err = snd_ctl_add(card, kctl)))
			return err;
986
#endif
L
Lee Revell 已提交
987
	} else if (! emu->card_capabilities->ecard) {
L
Linus Torvalds 已提交
988 989 990 991 992 993
		/* sb live! */
		if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL)
			return -ENOMEM;
		if ((err = snd_ctl_add(card, kctl)))
			return err;
	}
L
Lee Revell 已提交
994
	if (emu->card_capabilities->ca0151_chip) { /* P16V */
L
Linus Torvalds 已提交
995 996 997 998 999 1000
		if ((err = snd_p16v_mixer(emu)))
			return err;
	}
		
	return 0;
}