source: GPL/alsa-kernel/pci/emu10k1/emumixer.c@ 1

Last change on this file since 1 was 1, checked in by vladest, 20 years ago

initial import

File size: 32.8 KB
Line 
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>,
3 * Takashi Iwai <tiwai@suse.de>
4 * Creative Labs, Inc.
5 * Routines for control of EMU10K1 chips / mixer routines
6 * Multichannel PCM support Copyright (c) Lee Revell <rlrevell@joe-job.com>
7 *
8 * BUGS:
9 * --
10 *
11 * TODO:
12 * --
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 *
28 */
29
30#define __NO_VERSION__
31#include <sound/driver.h>
32#include <linux/time.h>
33#include <sound/core.h>
34#include <sound/emu10k1.h>
35
36#define AC97_ID_STAC9758 0x83847658
37
38static int snd_emu10k1_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
39{
40 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
41 uinfo->count = 1;
42 return 0;
43}
44
45static int snd_emu10k1_spdif_get(snd_kcontrol_t * kcontrol,
46 snd_ctl_elem_value_t * ucontrol)
47{
48 emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
49 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
50 unsigned long flags;
51
52 spin_lock_irqsave(&emu->reg_lock, flags);
53 ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff;
54 ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff;
55 ucontrol->value.iec958.status[2] = (emu->spdif_bits[idx] >> 16) & 0xff;
56 ucontrol->value.iec958.status[3] = (emu->spdif_bits[idx] >> 24) & 0xff;
57 spin_unlock_irqrestore(&emu->reg_lock, flags);
58 return 0;
59}
60
61static int snd_emu10k1_spdif_get_mask(snd_kcontrol_t * kcontrol,
62 snd_ctl_elem_value_t * ucontrol)
63{
64 ucontrol->value.iec958.status[0] = 0xff;
65 ucontrol->value.iec958.status[1] = 0xff;
66 ucontrol->value.iec958.status[2] = 0xff;
67 ucontrol->value.iec958.status[3] = 0xff;
68 return 0;
69}
70
71static int snd_audigy_spdif_output_rate_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
72{
73 static char *texts[] = {"44100", "48000", "96000"};
74
75 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
76 uinfo->count = 1;
77 uinfo->value.enumerated.items = 3;
78 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
79 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
80 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
81 return 0;
82}
83
84static int snd_audigy_spdif_output_rate_get(snd_kcontrol_t * kcontrol,
85 snd_ctl_elem_value_t * ucontrol)
86{
87 emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
88 unsigned int tmp;
89 unsigned long flags;
90
91
92 spin_lock_irqsave(&emu->reg_lock, flags);
93 tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
94 switch (tmp & A_SPDIF_RATE_MASK) {
95 case A_SPDIF_44100:
96 ucontrol->value.enumerated.item[0] = 0;
97 break;
98 case A_SPDIF_48000:
99 ucontrol->value.enumerated.item[0] = 1;
100 break;
101 case A_SPDIF_96000:
102 ucontrol->value.enumerated.item[0] = 2;
103 break;
104 default:
105 ucontrol->value.enumerated.item[0] = 1;
106 }
107 spin_unlock_irqrestore(&emu->reg_lock, flags);
108 return 0;
109}
110
111static int snd_audigy_spdif_output_rate_put(snd_kcontrol_t * kcontrol,
112 snd_ctl_elem_value_t * ucontrol)
113{
114 emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
115 int change;
116 unsigned int reg, val, tmp;
117 unsigned long flags;
118
119 switch(ucontrol->value.enumerated.item[0]) {
120 case 0:
121 val = A_SPDIF_44100;
122 break;
123 case 1:
124 val = A_SPDIF_48000;
125 break;
126 case 2:
127 val = A_SPDIF_96000;
128 break;
129 default:
130 val = A_SPDIF_48000;
131 break;
132 }
133
134
135 spin_lock_irqsave(&emu->reg_lock, flags);
136 reg = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
137 tmp = reg & ~A_SPDIF_RATE_MASK;
138 tmp |= val;
139 if ((change = (tmp != reg)))
140 snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp);
141 spin_unlock_irqrestore(&emu->reg_lock, flags);
142 return change;
143}
144
145static snd_kcontrol_new_t snd_audigy_spdif_output_rate =
146{
147 SNDRV_CTL_ELEM_IFACE_MIXER,0,0,
148 "Audigy SPDIF Output Sample Rate", 0,
149 SNDRV_CTL_ELEM_ACCESS_READWRITE,
150 1,
151 snd_audigy_spdif_output_rate_info,
152 snd_audigy_spdif_output_rate_get,
153 snd_audigy_spdif_output_rate_put, 0
154};
155
156static int snd_emu10k1_spdif_put(snd_kcontrol_t * kcontrol,
157 snd_ctl_elem_value_t * ucontrol)
158{
159 emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
160 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
161 int change;
162 unsigned int val;
163 unsigned long flags;
164
165 val = (ucontrol->value.iec958.status[0] << 0) |
166 (ucontrol->value.iec958.status[1] << 8) |
167 (ucontrol->value.iec958.status[2] << 16) |
168 (ucontrol->value.iec958.status[3] << 24);
169 spin_lock_irqsave(&emu->reg_lock, flags);
170 change = val != emu->spdif_bits[idx];
171 if (change) {
172 snd_emu10k1_ptr_write(emu, SPCS0 + idx, 0, val);
173 emu->spdif_bits[idx] = val;
174 }
175 spin_unlock_irqrestore(&emu->reg_lock, flags);
176 return change;
177}
178
179static snd_kcontrol_new_t snd_emu10k1_spdif_mask_control =
180{
181 SNDRV_CTL_ELEM_IFACE_PCM,0,0,
182 SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
183 0,SNDRV_CTL_ELEM_ACCESS_READ,4,
184 snd_emu10k1_spdif_info,
185 snd_emu10k1_spdif_get_mask,0,0
186};
187
188static snd_kcontrol_new_t snd_emu10k1_spdif_control =
189{
190 SNDRV_CTL_ELEM_IFACE_PCM,0,0,
191 SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),0,0,4,
192 snd_emu10k1_spdif_info,
193 snd_emu10k1_spdif_get,
194 snd_emu10k1_spdif_put,0
195};
196
197static void update_emu10k1_fxrt(emu10k1_t *emu, int voice, unsigned char *route)
198{
199 if (emu->audigy) {
200 snd_emu10k1_ptr_write(emu, A_FXRT1, voice,
201 snd_emu10k1_compose_audigy_fxrt1(route));
202 snd_emu10k1_ptr_write(emu, A_FXRT2, voice,
203 snd_emu10k1_compose_audigy_fxrt2(route));
204 } else {
205 snd_emu10k1_ptr_write(emu, FXRT, voice,
206 snd_emu10k1_compose_send_routing(route));
207 }
208}
209
210static void update_emu10k1_send_volume(emu10k1_t *emu, int voice, unsigned char *volume)
211{
212 snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_A, voice, volume[0]);
213 snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_B, voice, volume[1]);
214 snd_emu10k1_ptr_write(emu, PSST_FXSENDAMOUNT_C, voice, volume[2]);
215 snd_emu10k1_ptr_write(emu, DSL_FXSENDAMOUNT_D, voice, volume[3]);
216 if (emu->audigy) {
217 unsigned int val = ((unsigned int)volume[4] << 24) |
218 ((unsigned int)volume[5] << 16) |
219 ((unsigned int)volume[6] << 8) |
220 (unsigned int)volume[7];
221 snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, voice, val);
222 }
223}
224
225/* PCM stream controls */
226
227static int snd_emu10k1_send_routing_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
228{
229 emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
230 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
231 uinfo->count = emu->audigy ? 3*8 : 3*4;
232 uinfo->value.integer.min = 0;
233 uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
234 return 0;
235}
236
237static int snd_emu10k1_send_routing_get(snd_kcontrol_t * kcontrol,
238 snd_ctl_elem_value_t * ucontrol)
239{
240 unsigned long flags;
241 emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
242 emu10k1_pcm_mixer_t *mix = &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
243 int voice, idx;
244 int num_efx = emu->audigy ? 8 : 4;
245 int mask = emu->audigy ? 0x3f : 0x0f;
246
247 spin_lock_irqsave(&emu->reg_lock, flags);
248 for (voice = 0; voice < 3; voice++)
249 for (idx = 0; idx < num_efx; idx++)
250 ucontrol->value.integer.value[(voice * num_efx) + idx] =
251 mix->send_routing[voice][idx] & mask;
252 spin_unlock_irqrestore(&emu->reg_lock, flags);
253 return 0;
254}
255
256static int snd_emu10k1_send_routing_put(snd_kcontrol_t * kcontrol,
257 snd_ctl_elem_value_t * ucontrol)
258{
259 unsigned long flags;
260 emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
261 emu10k1_pcm_mixer_t *mix = &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
262 int change = 0, voice, idx, val;
263 int num_efx = emu->audigy ? 8 : 4;
264 int mask = emu->audigy ? 0x3f : 0x0f;
265
266 spin_lock_irqsave(&emu->reg_lock, flags);
267 for (voice = 0; voice < 3; voice++)
268 for (idx = 0; idx < num_efx; idx++) {
269 val = ucontrol->value.integer.value[(voice * num_efx) + idx] & mask;
270 if (mix->send_routing[voice][idx] != val) {
271 mix->send_routing[voice][idx] = val;
272 change = 1;
273 }
274 }
275 if (change && mix->epcm) {
276 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
277 update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
278 &mix->send_routing[1][0]);
279 update_emu10k1_fxrt(emu, mix->epcm->voices[1]->number,
280 &mix->send_routing[2][0]);
281 } else if (mix->epcm->voices[0]) {
282 update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
283 &mix->send_routing[0][0]);
284 }
285 }
286 spin_unlock_irqrestore(&emu->reg_lock, flags);
287 return change;
288}
289
290static snd_kcontrol_new_t snd_emu10k1_send_routing_control =
291{
292 SNDRV_CTL_ELEM_IFACE_PCM,0,0,
293 "EMU10K1 PCM Send Routing",0,
294 SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,32,
295 snd_emu10k1_send_routing_info,
296 snd_emu10k1_send_routing_get,
297 snd_emu10k1_send_routing_put,0
298};
299
300static int snd_emu10k1_send_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
301{
302 emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
303 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
304 uinfo->count = emu->audigy ? 3*8 : 3*4;
305 uinfo->value.integer.min = 0;
306 uinfo->value.integer.max = 255;
307 return 0;
308}
309
310static int snd_emu10k1_send_volume_get(snd_kcontrol_t * kcontrol,
311 snd_ctl_elem_value_t * ucontrol)
312{
313 unsigned long flags;
314 emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
315 emu10k1_pcm_mixer_t *mix = &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
316 int idx;
317 int num_efx = emu->audigy ? 8 : 4;
318
319 spin_lock_irqsave(&emu->reg_lock, flags);
320 for (idx = 0; idx < 3*num_efx; idx++)
321 ucontrol->value.integer.value[idx] = mix->send_volume[idx/num_efx][idx%num_efx];
322 spin_unlock_irqrestore(&emu->reg_lock, flags);
323 return 0;
324}
325
326static int snd_emu10k1_send_volume_put(snd_kcontrol_t * kcontrol,
327 snd_ctl_elem_value_t * ucontrol)
328{
329 unsigned long flags;
330 emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
331 emu10k1_pcm_mixer_t *mix = &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
332 int change = 0, idx, val;
333 int num_efx = emu->audigy ? 8 : 4;
334
335 spin_lock_irqsave(&emu->reg_lock, flags);
336 for (idx = 0; idx < 3*num_efx; idx++) {
337 val = ucontrol->value.integer.value[idx] & 255;
338 if (mix->send_volume[idx/num_efx][idx%num_efx] != val) {
339 mix->send_volume[idx/num_efx][idx%num_efx] = val;
340 change = 1;
341 }
342 }
343 if (change && mix->epcm) {
344 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
345 update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
346 &mix->send_volume[1][0]);
347 update_emu10k1_send_volume(emu, mix->epcm->voices[1]->number,
348 &mix->send_volume[2][0]);
349 } else if (mix->epcm->voices[0]) {
350 update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
351 &mix->send_volume[0][0]);
352 }
353 }
354 spin_unlock_irqrestore(&emu->reg_lock, flags);
355 return change;
356}
357
358static snd_kcontrol_new_t snd_emu10k1_send_volume_control =
359{
360 SNDRV_CTL_ELEM_IFACE_PCM,0,0,
361 "EMU10K1 PCM Send Volume",0,
362 SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,32,
363 snd_emu10k1_send_volume_info,
364 snd_emu10k1_send_volume_get,
365 snd_emu10k1_send_volume_put,0
366};
367
368static int snd_emu10k1_attn_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
369{
370 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
371 uinfo->count = 3;
372 uinfo->value.integer.min = 0;
373 uinfo->value.integer.max = 0xffff;
374 return 0;
375}
376
377static int snd_emu10k1_attn_get(snd_kcontrol_t * kcontrol,
378 snd_ctl_elem_value_t * ucontrol)
379{
380 emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
381 emu10k1_pcm_mixer_t *mix = &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
382 unsigned long flags;
383 int idx;
384
385 spin_lock_irqsave(&emu->reg_lock, flags);
386 for (idx = 0; idx < 3; idx++)
387 ucontrol->value.integer.value[idx] = mix->attn[idx];
388 spin_unlock_irqrestore(&emu->reg_lock, flags);
389 return 0;
390}
391
392static int snd_emu10k1_attn_put(snd_kcontrol_t * kcontrol,
393 snd_ctl_elem_value_t * ucontrol)
394{
395 unsigned long flags;
396 emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
397 emu10k1_pcm_mixer_t *mix = &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
398 int change = 0, idx, val;
399
400 spin_lock_irqsave(&emu->reg_lock, flags);
401 for (idx = 0; idx < 3; idx++) {
402 val = ucontrol->value.integer.value[idx] & 0xffff;
403 if (mix->attn[idx] != val) {
404 mix->attn[idx] = val;
405 change = 1;
406 }
407 }
408 if (change && mix->epcm) {
409 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
410 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[1]);
411 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[1]->number, mix->attn[2]);
412 } else if (mix->epcm->voices[0]) {
413 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[0]);
414 }
415 }
416 spin_unlock_irqrestore(&emu->reg_lock, flags);
417 return change;
418}
419
420static snd_kcontrol_new_t snd_emu10k1_attn_control =
421{
422 SNDRV_CTL_ELEM_IFACE_PCM,0,0,
423 "EMU10K1 PCM Volume",0,
424 SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,32,
425 snd_emu10k1_attn_info,
426 snd_emu10k1_attn_get,
427 snd_emu10k1_attn_put,0
428};
429
430/* Mutichannel PCM stream controls */
431
432static int snd_emu10k1_efx_send_routing_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
433{
434 emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
435 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
436 uinfo->count = emu->audigy ? 8 : 4;
437 uinfo->value.integer.min = 0;
438 uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
439 return 0;
440}
441
442static int snd_emu10k1_efx_send_routing_get(snd_kcontrol_t * kcontrol,
443 snd_ctl_elem_value_t * ucontrol)
444{
445 unsigned long flags;
446 emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
447 emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
448 int idx;
449 int num_efx = emu->audigy ? 8 : 4;
450 int mask = emu->audigy ? 0x3f : 0x0f;
451
452 spin_lock_irqsave(&emu->reg_lock, flags);
453 for (idx = 0; idx < num_efx; idx++)
454 ucontrol->value.integer.value[idx] =
455 mix->send_routing[0][idx] & mask;
456 spin_unlock_irqrestore(&emu->reg_lock, flags);
457 return 0;
458}
459
460static int snd_emu10k1_efx_send_routing_put(snd_kcontrol_t * kcontrol,
461 snd_ctl_elem_value_t * ucontrol)
462{
463 unsigned long flags;
464 emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
465 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
466 emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[ch];
467 int change = 0, idx, val;
468 int num_efx = emu->audigy ? 8 : 4;
469 int mask = emu->audigy ? 0x3f : 0x0f;
470
471 spin_lock_irqsave(&emu->reg_lock, flags);
472 for (idx = 0; idx < num_efx; idx++) {
473 val = ucontrol->value.integer.value[idx] & mask;
474 if (mix->send_routing[0][idx] != val) {
475 mix->send_routing[0][idx] = val;
476 change = 1;
477 }
478 }
479 if (change && mix->epcm) {
480 if (mix->epcm->voices[ch]) {
481 update_emu10k1_fxrt(emu, mix->epcm->voices[ch]->number,
482 &mix->send_routing[0][0]);
483 }
484 }
485 spin_unlock_irqrestore(&emu->reg_lock, flags);
486 return change;
487}
488
489static snd_kcontrol_new_t snd_emu10k1_efx_send_routing_control =
490{
491 SNDRV_CTL_ELEM_IFACE_PCM,0,0,
492 "Multichannel PCM Send Routing",0,
493 SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
494 16,
495 snd_emu10k1_efx_send_routing_info,
496 snd_emu10k1_efx_send_routing_get,
497 snd_emu10k1_efx_send_routing_put,0
498};
499
500static int snd_emu10k1_efx_send_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
501{
502 emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
503 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
504 uinfo->count = emu->audigy ? 8 : 4;
505 uinfo->value.integer.min = 0;
506 uinfo->value.integer.max = 255;
507 return 0;
508}
509
510static int snd_emu10k1_efx_send_volume_get(snd_kcontrol_t * kcontrol,
511 snd_ctl_elem_value_t * ucontrol)
512{
513 unsigned long flags;
514 emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
515 emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
516 int idx;
517 int num_efx = emu->audigy ? 8 : 4;
518
519 spin_lock_irqsave(&emu->reg_lock, flags);
520 for (idx = 0; idx < num_efx; idx++)
521 ucontrol->value.integer.value[idx] = mix->send_volume[0][idx];
522 spin_unlock_irqrestore(&emu->reg_lock, flags);
523 return 0;
524}
525
526static int snd_emu10k1_efx_send_volume_put(snd_kcontrol_t * kcontrol,
527 snd_ctl_elem_value_t * ucontrol)
528{
529 unsigned long flags;
530 emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
531 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
532 emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[ch];
533 int change = 0, idx, val;
534 int num_efx = emu->audigy ? 8 : 4;
535
536 spin_lock_irqsave(&emu->reg_lock, flags);
537 for (idx = 0; idx < num_efx; idx++) {
538 val = ucontrol->value.integer.value[idx] & 255;
539 if (mix->send_volume[0][idx] != val) {
540 mix->send_volume[0][idx] = val;
541 change = 1;
542 }
543 }
544 if (change && mix->epcm) {
545 if (mix->epcm->voices[ch]) {
546 update_emu10k1_send_volume(emu, mix->epcm->voices[ch]->number,
547 &mix->send_volume[0][0]);
548 }
549 }
550 spin_unlock_irqrestore(&emu->reg_lock, flags);
551 return change;
552}
553
554
555static snd_kcontrol_new_t snd_emu10k1_efx_send_volume_control =
556{
557 SNDRV_CTL_ELEM_IFACE_PCM,0,0,
558 "Multichannel PCM Send Volume",0,
559 SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
560 16,
561 snd_emu10k1_efx_send_volume_info,
562 snd_emu10k1_efx_send_volume_get,
563 snd_emu10k1_efx_send_volume_put,0
564};
565
566static int snd_emu10k1_efx_attn_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
567{
568 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
569 uinfo->count = 1;
570 uinfo->value.integer.min = 0;
571 uinfo->value.integer.max = 0xffff;
572 return 0;
573}
574
575static int snd_emu10k1_efx_attn_get(snd_kcontrol_t * kcontrol,
576 snd_ctl_elem_value_t * ucontrol)
577{
578 emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
579 emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
580 unsigned long flags;
581
582 spin_lock_irqsave(&emu->reg_lock, flags);
583 ucontrol->value.integer.value[0] = mix->attn[0];
584 spin_unlock_irqrestore(&emu->reg_lock, flags);
585 return 0;
586}
587
588static int snd_emu10k1_efx_attn_put(snd_kcontrol_t * kcontrol,
589 snd_ctl_elem_value_t * ucontrol)
590{
591 unsigned long flags;
592 emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
593 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
594 emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[ch];
595 int change = 0, val;
596
597 spin_lock_irqsave(&emu->reg_lock, flags);
598 val = ucontrol->value.integer.value[0] & 0xffff;
599 if (mix->attn[0] != val) {
600 mix->attn[0] = val;
601 change = 1;
602 }
603 if (change && mix->epcm) {
604 if (mix->epcm->voices[ch]) {
605 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[ch]->number, mix->attn[0]);
606 }
607 }
608 spin_unlock_irqrestore(&emu->reg_lock, flags);
609 return change;
610}
611
612static snd_kcontrol_new_t snd_emu10k1_efx_attn_control =
613{
614 SNDRV_CTL_ELEM_IFACE_PCM,0,0,
615 "Multichannel PCM Volume",0,
616 SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
617 16,
618 snd_emu10k1_efx_attn_info,
619 snd_emu10k1_efx_attn_get,
620 snd_emu10k1_efx_attn_put,0
621};
622
623static int snd_emu10k1_shared_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
624{
625 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
626 uinfo->count = 1;
627 uinfo->value.integer.min = 0;
628 uinfo->value.integer.max = 1;
629 return 0;
630}
631
632static int snd_emu10k1_shared_spdif_get(snd_kcontrol_t * kcontrol,
633 snd_ctl_elem_value_t * ucontrol)
634{
635 emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
636
637 if (emu->audigy)
638 ucontrol->value.integer.value[0] = inl(emu->port + A_IOCFG) & A_IOCFG_GPOUT0 ? 1 : 0;
639 else
640 ucontrol->value.integer.value[0] = inl(emu->port + HCFG) & HCFG_GPOUT0 ? 1 : 0;
641 return 0;
642}
643
644static int snd_emu10k1_shared_spdif_put(snd_kcontrol_t * kcontrol,
645 snd_ctl_elem_value_t * ucontrol)
646{
647 unsigned long flags;
648 emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
649 unsigned int reg, val;
650 int change = 0;
651
652 spin_lock_irqsave(&emu->reg_lock, flags);
653 if (emu->audigy) {
654 reg = inl(emu->port + A_IOCFG);
655 val = ucontrol->value.integer.value[0] ? A_IOCFG_GPOUT0 : 0;
656 change = (reg & A_IOCFG_GPOUT0) != val;
657 if (change) {
658 reg &= ~A_IOCFG_GPOUT0;
659 reg |= val;
660 outl(reg | val, emu->port + A_IOCFG);
661 }
662 }
663 reg = inl(emu->port + HCFG);
664 val = ucontrol->value.integer.value[0] ? HCFG_GPOUT0 : 0;
665 change |= (reg & HCFG_GPOUT0) != val;
666 if (change) {
667 reg &= ~HCFG_GPOUT0;
668 reg |= val;
669 outl(reg | val, emu->port + HCFG);
670 }
671 spin_unlock_irqrestore(&emu->reg_lock, flags);
672 return change;
673}
674
675static snd_kcontrol_new_t snd_emu10k1_shared_spdif __devinitdata =
676{
677 SNDRV_CTL_ELEM_IFACE_MIXER,0,0,
678 "SB Live Analog/Digital Output Jack",0,0,0,
679 snd_emu10k1_shared_spdif_info,
680 snd_emu10k1_shared_spdif_get,
681 snd_emu10k1_shared_spdif_put,0
682};
683
684static snd_kcontrol_new_t snd_audigy_shared_spdif __devinitdata =
685{
686 SNDRV_CTL_ELEM_IFACE_MIXER,0,0,
687 "Audigy Analog/Digital Output Jack",0,0,0,
688 snd_emu10k1_shared_spdif_info,
689 snd_emu10k1_shared_spdif_get,
690 snd_emu10k1_shared_spdif_put,0
691};
692
693/*
694 */
695static void snd_emu10k1_mixer_free_ac97(ac97_t *ac97)
696{
697 emu10k1_t *emu = ac97->private_data;
698 emu->ac97 = NULL;
699}
700
701/*
702 */
703static int remove_ctl(snd_card_t *card, const char *name)
704{
705 snd_ctl_elem_id_t id;
706 memset(&id, 0, sizeof(id));
707 strcpy(id.name, name);
708 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
709 return snd_ctl_remove_id(card, &id);
710}
711
712static snd_kcontrol_t *ctl_find(snd_card_t *card, const char *name)
713{
714 snd_ctl_elem_id_t sid;
715 memset(&sid, 0, sizeof(sid));
716 strcpy(sid.name, name);
717 sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
718 return snd_ctl_find_id(card, &sid);
719}
720
721static int rename_ctl(snd_card_t *card, const char *src, const char *dst)
722{
723 snd_kcontrol_t *kctl = ctl_find(card, src);
724 if (kctl) {
725 strcpy(kctl->id.name, dst);
726 return 0;
727 }
728 return -ENOENT;
729}
730
731int __devinit snd_emu10k1_mixer(emu10k1_t *emu,
732 int pcm_device, int multi_device)
733{
734 int err, pcm;
735 snd_kcontrol_t *kctl;
736 snd_card_t *card = emu->card;
737 char **c;
738 static char *emu10k1_remove_ctls[] = {
739 /* no AC97 mono, surround, center/lfe */
740 "Master Mono Playback Switch",
741 "Master Mono Playback Volume",
742 "PCM Out Path & Mute",
743 "Mono Output Select",
744 "Surround Playback Switch",
745 "Surround Playback Volume",
746 "Center Playback Switch",
747 "Center Playback Volume",
748 "LFE Playback Switch",
749 "LFE Playback Volume",
750 NULL
751 };
752 static char *emu10k1_rename_ctls[] = {
753 "Surround Digital Playback Volume", "Surround Playback Volume",
754 "Center Digital Playback Volume", "Center Playback Volume",
755 "LFE Digital Playback Volume", "LFE Playback Volume",
756 NULL
757 };
758 static char *audigy_remove_ctls[] = {
759 /* Master/PCM controls on ac97 of Audigy has no effect */
760 "PCM Playback Switch",
761 "PCM Playback Volume",
762 "Master Mono Playback Switch",
763 "Master Mono Playback Volume",
764 "Master Playback Switch",
765 "Master Playback Volume",
766 "PCM Out Path & Mute",
767 "Mono Output Select",
768 /* remove unused AC97 capture controls */
769 "Capture Source",
770 "Capture Switch",
771 "Capture Volume",
772 "Mic Select",
773 "Video Playback Switch",
774 "Video Playback Volume",
775 "Mic Playback Switch",
776 "Mic Playback Volume",
777 NULL
778 };
779 static char *audigy_rename_ctls[] = {
780 /* use conventional names */
781 "Wave Playback Volume", "PCM Playback Volume",
782 /* "Wave Capture Volume", "PCM Capture Volume", */
783 "Wave Master Playback Volume", "Master Playback Volume",
784 "AMic Playback Volume", "Mic Playback Volume",
785 NULL
786 };
787
788 if (emu->card_capabilities->ac97_chip) {
789 ac97_bus_t *pbus;
790 ac97_template_t ac97;
791 static ac97_bus_ops_t ops = {
792 0,snd_emu10k1_ac97_write,
793 snd_emu10k1_ac97_read,0,0
794 };
795
796 if ((err = snd_ac97_bus(emu->card, 0, &ops, NULL, &pbus)) < 0)
797 return err;
798
799 pbus->no_vra = 1; /* we don't need VRA */
800 memset(&ac97, 0, sizeof(ac97));
801 ac97.private_data = emu;
802 ac97.private_free = snd_emu10k1_mixer_free_ac97;
803 ac97.scaps = AC97_SCAP_NO_SPDIF;
804 if ((err = snd_ac97_mixer(pbus, &ac97, &emu->ac97)) < 0) {
805 if (emu->card_capabilities->ac97_chip == 1)
806 return err;
807 snd_printd(KERN_INFO "emu10k1: AC97 is optional on this board\n");
808 snd_printd(KERN_INFO" Proceeding without ac97 mixers...\n");
809 snd_device_free(emu->card, pbus);
810 goto no_ac97; /* FIXME: get rid of ugly gotos.. */
811 }
812 if (emu->audigy) {
813 /* set master volume to 0 dB */
814 snd_ac97_write(emu->ac97, AC97_MASTER, 0x0000);
815 /* set capture source to mic */
816 snd_ac97_write(emu->ac97, AC97_REC_SEL, 0x0000);
817 c = audigy_remove_ctls;
818 } else {
819 if (emu->ac97->id == AC97_ID_STAC9758) {
820 emu->rear_ac97 = 1;
821 snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE|AC97SLOT_REAR_LEFT|AC97SLOT_REAR_RIGHT);
822 }
823 /* remove unused AC97 controls */
824 snd_ac97_write(emu->ac97, AC97_SURROUND_MASTER, 0x0202);
825 snd_ac97_write(emu->ac97, AC97_CENTER_LFE_MASTER, 0x0202);
826 c = emu10k1_remove_ctls;
827 }
828 for (; *c; c++)
829 remove_ctl(card, *c);
830 } else {
831 no_ac97:
832 if (emu->card_capabilities->ecard)
833 strcpy(emu->card->mixername, "EMU APS");
834 else if (emu->audigy)
835 strcpy(emu->card->mixername, "SB Audigy");
836 else
837 strcpy(emu->card->mixername, "Emu10k1");
838 }
839
840 if (emu->audigy)
841 c = audigy_rename_ctls;
842 else
843 c = emu10k1_rename_ctls;
844 for (; *c; c += 2)
845 rename_ctl(card, c[0], c[1]);
846
847 if ((kctl = emu->ctl_send_routing = snd_ctl_new1(&snd_emu10k1_send_routing_control, emu)) == NULL)
848 return -ENOMEM;
849 kctl->id.device = pcm_device;
850 if ((err = snd_ctl_add(card, kctl)))
851 return err;
852 if ((kctl = emu->ctl_send_volume = snd_ctl_new1(&snd_emu10k1_send_volume_control, emu)) == NULL)
853 return -ENOMEM;
854 kctl->id.device = pcm_device;
855 if ((err = snd_ctl_add(card, kctl)))
856 return err;
857 if ((kctl = emu->ctl_attn = snd_ctl_new1(&snd_emu10k1_attn_control, emu)) == NULL)
858 return -ENOMEM;
859 kctl->id.device = pcm_device;
860 if ((err = snd_ctl_add(card, kctl)))
861 return err;
862
863 if ((kctl = emu->ctl_efx_send_routing = snd_ctl_new1(&snd_emu10k1_efx_send_routing_control, emu)) == NULL)
864 return -ENOMEM;
865 kctl->id.device = multi_device;
866 if ((err = snd_ctl_add(card, kctl)))
867 return err;
868
869 if ((kctl = emu->ctl_efx_send_volume = snd_ctl_new1(&snd_emu10k1_efx_send_volume_control, emu)) == NULL)
870 return -ENOMEM;
871 kctl->id.device = multi_device;
872 if ((err = snd_ctl_add(card, kctl)))
873 return err;
874
875 if ((kctl = emu->ctl_efx_attn = snd_ctl_new1(&snd_emu10k1_efx_attn_control, emu)) == NULL)
876 return -ENOMEM;
877 kctl->id.device = multi_device;
878 if ((err = snd_ctl_add(card, kctl)))
879 return err;
880
881 /* initialize the routing and volume table for each pcm playback stream */
882 for (pcm = 0; pcm < 32; pcm++) {
883 emu10k1_pcm_mixer_t *mix;
884 int v;
885
886 mix = &emu->pcm_mixer[pcm];
887 mix->epcm = NULL;
888
889 for (v = 0; v < 4; v++)
890 mix->send_routing[0][v] =
891 mix->send_routing[1][v] =
892 mix->send_routing[2][v] = v;
893
894 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
895 mix->send_volume[0][0] = mix->send_volume[0][1] =
896 mix->send_volume[1][0] = mix->send_volume[2][1] = 255;
897
898 mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff;
899 }
900
901 /* initialize the routing and volume table for the multichannel playback stream */
902 for (pcm = 0; pcm < NUM_EFX_PLAYBACK; pcm++) {
903 emu10k1_pcm_mixer_t *mix;
904 int v;
905
906 mix = &emu->efx_pcm_mixer[pcm];
907 mix->epcm = NULL;
908
909 mix->send_routing[0][0] = pcm;
910 mix->send_routing[0][1] = (pcm == 0) ? 1 : 0;
911 for (v = 0; v < 2; v++)
912 mix->send_routing[0][2+v] = 13+v;
913 if (emu->audigy)
914 for (v = 0; v < 4; v++)
915 mix->send_routing[0][4+v] = 60+v;
916
917 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
918 mix->send_volume[0][0] = 255;
919
920 mix->attn[0] = 0xffff;
921 }
922
923 if (! emu->card_capabilities->ecard) { /* FIXME: APS has these controls? */
924 /* sb live! and audigy */
925 if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL)
926 return -ENOMEM;
927 if (!emu->audigy)
928 kctl->id.device = emu->pcm_efx->device;
929 if ((err = snd_ctl_add(card, kctl)))
930 return err;
931 if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu)) == NULL)
932 return -ENOMEM;
933 if (!emu->audigy)
934 kctl->id.device = emu->pcm_efx->device;
935 if ((err = snd_ctl_add(card, kctl)))
936 return err;
937 }
938
939 if (emu->audigy) {
940 if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL)
941 return -ENOMEM;
942 if ((err = snd_ctl_add(card, kctl)))
943 return err;
944#if 0
945 if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL)
946 return -ENOMEM;
947 if ((err = snd_ctl_add(card, kctl)))
948 return err;
949#endif
950 } else if (! emu->card_capabilities->ecard) {
951 /* sb live! */
952 if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL)
953 return -ENOMEM;
954 if ((err = snd_ctl_add(card, kctl)))
955 return err;
956 }
957 if (emu->card_capabilities->ca0151_chip) { /* P16V */
958 if ((err = snd_p16v_mixer(emu)))
959 return err;
960 }
961 return 0;
962}
Note: See TracBrowser for help on using the repository browser.