aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/pcxhr/pcxhr_mixer.c
diff options
context:
space:
mode:
authorMarkus Bollinger <bollinger@digigram.com>2005-12-06 07:55:26 -0500
committerJaroslav Kysela <perex@suse.cz>2006-01-03 06:30:26 -0500
commite12229b4d2b7863b1baaeca759aa87703bf9fdf8 (patch)
tree64e43c92fd1f675c29cb6002557ef04156713cbf /sound/pci/pcxhr/pcxhr_mixer.c
parent46a1736d7c07687e7456f72b238a68034fd5a624 (diff)
[ALSA] Add PCXHR driver
Modules: Documentation,PCI drivers,Digigram PCXHR driver Add Digigram PCXHR driver. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/pcxhr/pcxhr_mixer.c')
-rw-r--r--sound/pci/pcxhr/pcxhr_mixer.c1020
1 files changed, 1020 insertions, 0 deletions
diff --git a/sound/pci/pcxhr/pcxhr_mixer.c b/sound/pci/pcxhr/pcxhr_mixer.c
new file mode 100644
index 000000000000..760e733ac25e
--- /dev/null
+++ b/sound/pci/pcxhr/pcxhr_mixer.c
@@ -0,0 +1,1020 @@
1#define __NO_VERSION__
2/*
3 * Driver for Digigram pcxhr compatible soundcards
4 *
5 * mixer callbacks
6 *
7 * Copyright (c) 2004 by Digigram <alsa@digigram.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24#include <sound/driver.h>
25#include <linux/time.h>
26#include <linux/interrupt.h>
27#include <linux/init.h>
28#include <sound/core.h>
29#include "pcxhr.h"
30#include "pcxhr_hwdep.h"
31#include "pcxhr_core.h"
32#include <sound/control.h>
33#include <sound/asoundef.h>
34#include "pcxhr_mixer.h"
35
36
37#define PCXHR_ANALOG_CAPTURE_LEVEL_MIN 0 /* -96.0 dB */
38#define PCXHR_ANALOG_CAPTURE_LEVEL_MAX 255 /* +31.5 dB */
39#define PCXHR_ANALOG_CAPTURE_ZERO_LEVEL 224 /* +16.0 dB ( +31.5 dB - fix level +15.5 dB ) */
40
41#define PCXHR_ANALOG_PLAYBACK_LEVEL_MIN 0 /* -128.0 dB */
42#define PCXHR_ANALOG_PLAYBACK_LEVEL_MAX 128 /* 0.0 dB */
43#define PCXHR_ANALOG_PLAYBACK_ZERO_LEVEL 104 /* -24.0 dB ( 0.0 dB - fix level +24.0 dB ) */
44
45static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip, int is_capture, int channel)
46{
47 int err, vol;
48 struct pcxhr_rmh rmh;
49
50 pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
51 if (is_capture) {
52 rmh.cmd[0] |= IO_NUM_REG_IN_ANA_LEVEL;
53 rmh.cmd[2] = chip->analog_capture_volume[channel];
54 } else {
55 rmh.cmd[0] |= IO_NUM_REG_OUT_ANA_LEVEL;
56 if (chip->analog_playback_active[channel])
57 vol = chip->analog_playback_volume[channel];
58 else
59 vol = PCXHR_ANALOG_PLAYBACK_LEVEL_MIN;
60 rmh.cmd[2] = PCXHR_ANALOG_PLAYBACK_LEVEL_MAX - vol; /* playback analog levels are inversed */
61 }
62 rmh.cmd[1] = 1 << ((2 * chip->chip_idx) + channel); /* audio mask */
63 rmh.cmd_len = 3;
64 err = pcxhr_send_msg(chip->mgr, &rmh);
65 if (err < 0) {
66 snd_printk(KERN_DEBUG "error update_analog_audio_level card(%d) "
67 "is_capture(%d) err(%x)\n", chip->chip_idx, is_capture, err);
68 return -EINVAL;
69 }
70 return 0;
71}
72
73/*
74 * analog level control
75 */
76static int pcxhr_analog_vol_info(struct snd_kcontrol *kcontrol,
77 struct snd_ctl_elem_info *uinfo)
78{
79 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
80 uinfo->count = 2;
81 if (kcontrol->private_value == 0) { /* playback */
82 uinfo->value.integer.min = PCXHR_ANALOG_PLAYBACK_LEVEL_MIN; /* -128 dB */
83 uinfo->value.integer.max = PCXHR_ANALOG_PLAYBACK_LEVEL_MAX; /* 0 dB */
84 } else { /* capture */
85 uinfo->value.integer.min = PCXHR_ANALOG_CAPTURE_LEVEL_MIN; /* -96 dB */
86 uinfo->value.integer.max = PCXHR_ANALOG_CAPTURE_LEVEL_MAX; /* 31.5 dB */
87 }
88 return 0;
89}
90
91static int pcxhr_analog_vol_get(struct snd_kcontrol *kcontrol,
92 struct snd_ctl_elem_value *ucontrol)
93{
94 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
95 down(&chip->mgr->mixer_mutex);
96 if (kcontrol->private_value == 0) { /* playback */
97 ucontrol->value.integer.value[0] = chip->analog_playback_volume[0];
98 ucontrol->value.integer.value[1] = chip->analog_playback_volume[1];
99 } else { /* capture */
100 ucontrol->value.integer.value[0] = chip->analog_capture_volume[0];
101 ucontrol->value.integer.value[1] = chip->analog_capture_volume[1];
102 }
103 up(&chip->mgr->mixer_mutex);
104 return 0;
105}
106
107static int pcxhr_analog_vol_put(struct snd_kcontrol *kcontrol,
108 struct snd_ctl_elem_value *ucontrol)
109{
110 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
111 int changed = 0;
112 int is_capture, i;
113
114 down(&chip->mgr->mixer_mutex);
115 is_capture = (kcontrol->private_value != 0);
116 for (i = 0; i < 2; i++) {
117 int new_volume = ucontrol->value.integer.value[i];
118 int* stored_volume = is_capture ? &chip->analog_capture_volume[i] :
119 &chip->analog_playback_volume[i];
120 if (*stored_volume != new_volume) {
121 *stored_volume = new_volume;
122 changed = 1;
123 pcxhr_update_analog_audio_level(chip, is_capture, i);
124 }
125 }
126 up(&chip->mgr->mixer_mutex);
127 return changed;
128}
129
130static struct snd_kcontrol_new pcxhr_control_analog_level = {
131 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
132 /* name will be filled later */
133 .info = pcxhr_analog_vol_info,
134 .get = pcxhr_analog_vol_get,
135 .put = pcxhr_analog_vol_put,
136};
137
138/* shared */
139static int pcxhr_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
140{
141 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
142 uinfo->count = 2;
143 uinfo->value.integer.min = 0;
144 uinfo->value.integer.max = 1;
145 return 0;
146}
147
148static int pcxhr_audio_sw_get(struct snd_kcontrol *kcontrol,
149 struct snd_ctl_elem_value *ucontrol)
150{
151 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
152
153 down(&chip->mgr->mixer_mutex);
154 ucontrol->value.integer.value[0] = chip->analog_playback_active[0];
155 ucontrol->value.integer.value[1] = chip->analog_playback_active[1];
156 up(&chip->mgr->mixer_mutex);
157 return 0;
158}
159
160static int pcxhr_audio_sw_put(struct snd_kcontrol *kcontrol,
161 struct snd_ctl_elem_value *ucontrol)
162{
163 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
164 int i, changed = 0;
165 down(&chip->mgr->mixer_mutex);
166 for(i = 0; i < 2; i++) {
167 if (chip->analog_playback_active[i] != ucontrol->value.integer.value[i]) {
168 chip->analog_playback_active[i] = ucontrol->value.integer.value[i];
169 changed = 1;
170 pcxhr_update_analog_audio_level(chip, 0, i); /* update playback levels */
171 }
172 }
173 up(&chip->mgr->mixer_mutex);
174 return changed;
175}
176
177static struct snd_kcontrol_new pcxhr_control_output_switch = {
178 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
179 .name = "Master Playback Switch",
180 .info = pcxhr_sw_info, /* shared */
181 .get = pcxhr_audio_sw_get,
182 .put = pcxhr_audio_sw_put
183};
184
185
186#define PCXHR_DIGITAL_LEVEL_MIN 0x000 /* -110 dB */
187#define PCXHR_DIGITAL_LEVEL_MAX 0x1ff /* +18 dB */
188#define PCXHR_DIGITAL_ZERO_LEVEL 0x1b7 /* 0 dB */
189
190
191#define MORE_THAN_ONE_STREAM_LEVEL 0x000001
192#define VALID_STREAM_PAN_LEVEL_MASK 0x800000
193#define VALID_STREAM_LEVEL_MASK 0x400000
194#define VALID_STREAM_LEVEL_1_MASK 0x200000
195#define VALID_STREAM_LEVEL_2_MASK 0x100000
196
197static int pcxhr_update_playback_stream_level(struct snd_pcxhr* chip, int idx)
198{
199 int err;
200 struct pcxhr_rmh rmh;
201 struct pcxhr_pipe *pipe = &chip->playback_pipe;
202 int left, right;
203
204 if (chip->digital_playback_active[idx][0])
205 left = chip->digital_playback_volume[idx][0];
206 else
207 left = PCXHR_DIGITAL_LEVEL_MIN;
208 if (chip->digital_playback_active[idx][1])
209 right = chip->digital_playback_volume[idx][1];
210 else
211 right = PCXHR_DIGITAL_LEVEL_MIN;
212
213 pcxhr_init_rmh(&rmh, CMD_STREAM_OUT_LEVEL_ADJUST);
214 /* add pipe and stream mask */
215 pcxhr_set_pipe_cmd_params(&rmh, 0, pipe->first_audio, 0, 1<<idx);
216 /* volume left->left / right->right panoramic level */
217 rmh.cmd[0] |= MORE_THAN_ONE_STREAM_LEVEL;
218 rmh.cmd[2] = VALID_STREAM_PAN_LEVEL_MASK | VALID_STREAM_LEVEL_1_MASK;
219 rmh.cmd[2] |= (left << 10);
220 rmh.cmd[3] = VALID_STREAM_PAN_LEVEL_MASK | VALID_STREAM_LEVEL_2_MASK;
221 rmh.cmd[3] |= right;
222 rmh.cmd_len = 4;
223
224 err = pcxhr_send_msg(chip->mgr, &rmh);
225 if (err < 0) {
226 snd_printk(KERN_DEBUG "error update_playback_stream_level "
227 "card(%d) err(%x)\n", chip->chip_idx, err);
228 return -EINVAL;
229 }
230 return 0;
231}
232
233#define AUDIO_IO_HAS_MUTE_LEVEL 0x400000
234#define AUDIO_IO_HAS_MUTE_MONITOR_1 0x200000
235#define VALID_AUDIO_IO_DIGITAL_LEVEL 0x000001
236#define VALID_AUDIO_IO_MONITOR_LEVEL 0x000002
237#define VALID_AUDIO_IO_MUTE_LEVEL 0x000004
238#define VALID_AUDIO_IO_MUTE_MONITOR_1 0x000008
239
240static int pcxhr_update_audio_pipe_level(struct snd_pcxhr* chip, int capture, int channel)
241{
242 int err;
243 struct pcxhr_rmh rmh;
244 struct pcxhr_pipe *pipe;
245
246 if (capture)
247 pipe = &chip->capture_pipe[0];
248 else
249 pipe = &chip->playback_pipe;
250
251 pcxhr_init_rmh(&rmh, CMD_AUDIO_LEVEL_ADJUST);
252 /* add channel mask */
253 pcxhr_set_pipe_cmd_params(&rmh, capture, 0, 0, 1 << (channel + pipe->first_audio));
254 /* TODO : if mask (3 << pipe->first_audio) is used, left and right channel
255 * will be programmed to the same params
256 */
257 if (capture) {
258 rmh.cmd[0] |= VALID_AUDIO_IO_DIGITAL_LEVEL;
259 /* VALID_AUDIO_IO_MUTE_LEVEL not yet handled (capture pipe level) */
260 rmh.cmd[2] = chip->digital_capture_volume[channel];
261 } else {
262 rmh.cmd[0] |= VALID_AUDIO_IO_MONITOR_LEVEL | VALID_AUDIO_IO_MUTE_MONITOR_1;
263 /* VALID_AUDIO_IO_DIGITAL_LEVEL and VALID_AUDIO_IO_MUTE_LEVEL not yet
264 * handled (playback pipe level)
265 */
266 rmh.cmd[2] = chip->monitoring_volume[channel] << 10;
267 if (chip->monitoring_active[channel] == 0)
268 rmh.cmd[2] |= AUDIO_IO_HAS_MUTE_MONITOR_1;
269 }
270 rmh.cmd_len = 3;
271
272 err = pcxhr_send_msg(chip->mgr, &rmh);
273 if(err<0) {
274 snd_printk(KERN_DEBUG "error update_audio_level card(%d) err(%x)\n",
275 chip->chip_idx, err);
276 return -EINVAL;
277 }
278 return 0;
279}
280
281
282/* shared */
283static int pcxhr_digital_vol_info(struct snd_kcontrol *kcontrol,
284 struct snd_ctl_elem_info *uinfo)
285{
286 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
287 uinfo->count = 2;
288 uinfo->value.integer.min = PCXHR_DIGITAL_LEVEL_MIN; /* -109.5 dB */
289 uinfo->value.integer.max = PCXHR_DIGITAL_LEVEL_MAX; /* 18.0 dB */
290 return 0;
291}
292
293
294static int pcxhr_pcm_vol_get(struct snd_kcontrol *kcontrol,
295 struct snd_ctl_elem_value *ucontrol)
296{
297 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
298 int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
299 int *stored_volume;
300 int is_capture = kcontrol->private_value;
301
302 down(&chip->mgr->mixer_mutex);
303 if (is_capture)
304 stored_volume = chip->digital_capture_volume; /* digital capture */
305 else
306 stored_volume = chip->digital_playback_volume[idx]; /* digital playback */
307 ucontrol->value.integer.value[0] = stored_volume[0];
308 ucontrol->value.integer.value[1] = stored_volume[1];
309 up(&chip->mgr->mixer_mutex);
310 return 0;
311}
312
313static int pcxhr_pcm_vol_put(struct snd_kcontrol *kcontrol,
314 struct snd_ctl_elem_value *ucontrol)
315{
316 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
317 int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
318 int changed = 0;
319 int is_capture = kcontrol->private_value;
320 int *stored_volume;
321 int i;
322
323 down(&chip->mgr->mixer_mutex);
324 if (is_capture)
325 stored_volume = chip->digital_capture_volume; /* digital capture */
326 else
327 stored_volume = chip->digital_playback_volume[idx]; /* digital playback */
328 for (i = 0; i < 2; i++) {
329 if (stored_volume[i] != ucontrol->value.integer.value[i]) {
330 stored_volume[i] = ucontrol->value.integer.value[i];
331 changed = 1;
332 if (is_capture) /* update capture volume */
333 pcxhr_update_audio_pipe_level(chip, 1, i);
334 }
335 }
336 if (! is_capture && changed)
337 pcxhr_update_playback_stream_level(chip, idx); /* update playback volume */
338 up(&chip->mgr->mixer_mutex);
339 return changed;
340}
341
342static struct snd_kcontrol_new snd_pcxhr_pcm_vol =
343{
344 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
345 /* name will be filled later */
346 /* count will be filled later */
347 .info = pcxhr_digital_vol_info, /* shared */
348 .get = pcxhr_pcm_vol_get,
349 .put = pcxhr_pcm_vol_put,
350};
351
352
353static int pcxhr_pcm_sw_get(struct snd_kcontrol *kcontrol,
354 struct snd_ctl_elem_value *ucontrol)
355{
356 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
357 int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
358
359 down(&chip->mgr->mixer_mutex);
360 ucontrol->value.integer.value[0] = chip->digital_playback_active[idx][0];
361 ucontrol->value.integer.value[1] = chip->digital_playback_active[idx][1];
362 up(&chip->mgr->mixer_mutex);
363 return 0;
364}
365
366static int pcxhr_pcm_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
367{
368 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
369 int changed = 0;
370 int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
371 int i, j;
372
373 down(&chip->mgr->mixer_mutex);
374 j = idx;
375 for (i = 0; i < 2; i++) {
376 if (chip->digital_playback_active[j][i] != ucontrol->value.integer.value[i]) {
377 chip->digital_playback_active[j][i] = ucontrol->value.integer.value[i];
378 changed = 1;
379 }
380 }
381 if (changed)
382 pcxhr_update_playback_stream_level(chip, idx);
383 up(&chip->mgr->mixer_mutex);
384 return changed;
385}
386
387static struct snd_kcontrol_new pcxhr_control_pcm_switch = {
388 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
389 .name = "PCM Playback Switch",
390 .count = PCXHR_PLAYBACK_STREAMS,
391 .info = pcxhr_sw_info, /* shared */
392 .get = pcxhr_pcm_sw_get,
393 .put = pcxhr_pcm_sw_put
394};
395
396
397/*
398 * monitoring level control
399 */
400
401static int pcxhr_monitor_vol_get(struct snd_kcontrol *kcontrol,
402 struct snd_ctl_elem_value *ucontrol)
403{
404 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
405 down(&chip->mgr->mixer_mutex);
406 ucontrol->value.integer.value[0] = chip->monitoring_volume[0];
407 ucontrol->value.integer.value[1] = chip->monitoring_volume[1];
408 up(&chip->mgr->mixer_mutex);
409 return 0;
410}
411
412static int pcxhr_monitor_vol_put(struct snd_kcontrol *kcontrol,
413 struct snd_ctl_elem_value *ucontrol)
414{
415 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
416 int changed = 0;
417 int i;
418
419 down(&chip->mgr->mixer_mutex);
420 for (i = 0; i < 2; i++) {
421 if (chip->monitoring_volume[i] != ucontrol->value.integer.value[i]) {
422 chip->monitoring_volume[i] = ucontrol->value.integer.value[i];
423 if(chip->monitoring_active[i]) /* do only when monitoring is unmuted */
424 /* update monitoring volume and mute */
425 pcxhr_update_audio_pipe_level(chip, 0, i);
426 changed = 1;
427 }
428 }
429 up(&chip->mgr->mixer_mutex);
430 return changed;
431}
432
433static struct snd_kcontrol_new pcxhr_control_monitor_vol = {
434 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
435 .name = "Monitoring Volume",
436 .info = pcxhr_digital_vol_info, /* shared */
437 .get = pcxhr_monitor_vol_get,
438 .put = pcxhr_monitor_vol_put,
439};
440
441/*
442 * monitoring switch control
443 */
444
445static int pcxhr_monitor_sw_get(struct snd_kcontrol *kcontrol,
446 struct snd_ctl_elem_value *ucontrol)
447{
448 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
449 down(&chip->mgr->mixer_mutex);
450 ucontrol->value.integer.value[0] = chip->monitoring_active[0];
451 ucontrol->value.integer.value[1] = chip->monitoring_active[1];
452 up(&chip->mgr->mixer_mutex);
453 return 0;
454}
455
456static int pcxhr_monitor_sw_put(struct snd_kcontrol *kcontrol,
457 struct snd_ctl_elem_value *ucontrol)
458{
459 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
460 int changed = 0;
461 int i;
462
463 down(&chip->mgr->mixer_mutex);
464 for (i = 0; i < 2; i++) {
465 if (chip->monitoring_active[i] != ucontrol->value.integer.value[i]) {
466 chip->monitoring_active[i] = ucontrol->value.integer.value[i];
467 changed |= (1<<i); /* mask 0x01 and 0x02 */
468 }
469 }
470 if(changed & 0x01)
471 /* update left monitoring volume and mute */
472 pcxhr_update_audio_pipe_level(chip, 0, 0);
473 if(changed & 0x02)
474 /* update right monitoring volume and mute */
475 pcxhr_update_audio_pipe_level(chip, 0, 1);
476
477 up(&chip->mgr->mixer_mutex);
478 return (changed != 0);
479}
480
481static struct snd_kcontrol_new pcxhr_control_monitor_sw = {
482 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
483 .name = "Monitoring Switch",
484 .info = pcxhr_sw_info, /* shared */
485 .get = pcxhr_monitor_sw_get,
486 .put = pcxhr_monitor_sw_put
487};
488
489
490
491/*
492 * audio source select
493 */
494#define PCXHR_SOURCE_AUDIO01_UER 0x000100
495#define PCXHR_SOURCE_AUDIO01_SYNC 0x000200
496#define PCXHR_SOURCE_AUDIO23_UER 0x000400
497#define PCXHR_SOURCE_AUDIO45_UER 0x001000
498#define PCXHR_SOURCE_AUDIO67_UER 0x040000
499
500static int pcxhr_set_audio_source(struct snd_pcxhr* chip)
501{
502 struct pcxhr_rmh rmh;
503 unsigned int mask, reg;
504 unsigned int codec;
505 int err, use_src, changed;
506
507 switch (chip->chip_idx) {
508 case 0 : mask = PCXHR_SOURCE_AUDIO01_UER; codec = CS8420_01_CS; break;
509 case 1 : mask = PCXHR_SOURCE_AUDIO23_UER; codec = CS8420_23_CS; break;
510 case 2 : mask = PCXHR_SOURCE_AUDIO45_UER; codec = CS8420_45_CS; break;
511 case 3 : mask = PCXHR_SOURCE_AUDIO67_UER; codec = CS8420_67_CS; break;
512 default: return -EINVAL;
513 }
514 reg = 0; /* audio source from analog plug */
515 use_src = 0; /* do not activate codec SRC */
516
517 if (chip->audio_capture_source != 0) {
518 reg = mask; /* audio source from digital plug */
519 if (chip->audio_capture_source == 2)
520 use_src = 1;
521 }
522 /* set the input source */
523 pcxhr_write_io_num_reg_cont(chip->mgr, mask, reg, &changed);
524 /* resync them (otherwise channel inversion possible) */
525 if (changed) {
526 pcxhr_init_rmh(&rmh, CMD_RESYNC_AUDIO_INPUTS);
527 rmh.cmd[0] |= (1 << chip->chip_idx);
528 err = pcxhr_send_msg(chip->mgr, &rmh);
529 if (err)
530 return err;
531 }
532 pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); /* set codec SRC on off */
533 rmh.cmd_len = 3;
534 rmh.cmd[0] |= IO_NUM_UER_CHIP_REG;
535 rmh.cmd[1] = codec;
536 rmh.cmd[2] = (CS8420_DATA_FLOW_CTL & CHIP_SIG_AND_MAP_SPI) | (use_src ? 0x41 : 0x54);
537 err = pcxhr_send_msg(chip->mgr, &rmh);
538 if(err)
539 return err;
540 rmh.cmd[2] = (CS8420_CLOCK_SRC_CTL & CHIP_SIG_AND_MAP_SPI) | (use_src ? 0x41 : 0x49);
541 err = pcxhr_send_msg(chip->mgr, &rmh);
542 return err;
543}
544
545static int pcxhr_audio_src_info(struct snd_kcontrol *kcontrol,
546 struct snd_ctl_elem_info *uinfo)
547{
548 static char *texts[3] = {"Analog", "Digital", "Digi+SRC"};
549
550 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
551 uinfo->count = 1;
552 uinfo->value.enumerated.items = 3;
553 if (uinfo->value.enumerated.item > 2)
554 uinfo->value.enumerated.item = 2;
555 strcpy(uinfo->value.enumerated.name,
556 texts[uinfo->value.enumerated.item]);
557 return 0;
558}
559
560static int pcxhr_audio_src_get(struct snd_kcontrol *kcontrol,
561 struct snd_ctl_elem_value *ucontrol)
562{
563 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
564 ucontrol->value.enumerated.item[0] = chip->audio_capture_source;
565 return 0;
566}
567
568static int pcxhr_audio_src_put(struct snd_kcontrol *kcontrol,
569 struct snd_ctl_elem_value *ucontrol)
570{
571 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
572 int ret = 0;
573
574 down(&chip->mgr->mixer_mutex);
575 if (chip->audio_capture_source != ucontrol->value.enumerated.item[0]) {
576 chip->audio_capture_source = ucontrol->value.enumerated.item[0];
577 pcxhr_set_audio_source(chip);
578 ret = 1;
579 }
580 up(&chip->mgr->mixer_mutex);
581 return ret;
582}
583
584static struct snd_kcontrol_new pcxhr_control_audio_src = {
585 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
586 .name = "Capture Source",
587 .info = pcxhr_audio_src_info,
588 .get = pcxhr_audio_src_get,
589 .put = pcxhr_audio_src_put,
590};
591
592
593/*
594 * clock type selection
595 * enum pcxhr_clock_type {
596 * PCXHR_CLOCK_TYPE_INTERNAL = 0,
597 * PCXHR_CLOCK_TYPE_WORD_CLOCK,
598 * PCXHR_CLOCK_TYPE_AES_SYNC,
599 * PCXHR_CLOCK_TYPE_AES_1,
600 * PCXHR_CLOCK_TYPE_AES_2,
601 * PCXHR_CLOCK_TYPE_AES_3,
602 * PCXHR_CLOCK_TYPE_AES_4,
603 * };
604 */
605
606static int pcxhr_clock_type_info(struct snd_kcontrol *kcontrol,
607 struct snd_ctl_elem_info *uinfo)
608{
609 static char *texts[7] = {
610 "Internal", "WordClock", "AES Sync", "AES 1", "AES 2", "AES 3", "AES 4"
611 };
612 struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
613 int clock_items = 3 + mgr->capture_chips;
614
615 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
616 uinfo->count = 1;
617 uinfo->value.enumerated.items = clock_items;
618 if (uinfo->value.enumerated.item >= clock_items)
619 uinfo->value.enumerated.item = clock_items-1;
620 strcpy(uinfo->value.enumerated.name,
621 texts[uinfo->value.enumerated.item]);
622 return 0;
623}
624
625static int pcxhr_clock_type_get(struct snd_kcontrol *kcontrol,
626 struct snd_ctl_elem_value *ucontrol)
627{
628 struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
629 ucontrol->value.enumerated.item[0] = mgr->use_clock_type;
630 return 0;
631}
632
633static int pcxhr_clock_type_put(struct snd_kcontrol *kcontrol,
634 struct snd_ctl_elem_value *ucontrol)
635{
636 struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
637 int rate, ret = 0;
638
639 down(&mgr->mixer_mutex);
640 if (mgr->use_clock_type != ucontrol->value.enumerated.item[0]) {
641 down(&mgr->setup_mutex);
642 mgr->use_clock_type = ucontrol->value.enumerated.item[0];
643 if (mgr->use_clock_type)
644 pcxhr_get_external_clock(mgr, mgr->use_clock_type, &rate);
645 else
646 rate = mgr->sample_rate;
647 if (rate) {
648 pcxhr_set_clock(mgr, rate);
649 if (mgr->sample_rate)
650 mgr->sample_rate = rate;
651 }
652 up(&mgr->setup_mutex);
653 ret = 1; /* return 1 even if the set was not done. ok ? */
654 }
655 up(&mgr->mixer_mutex);
656 return ret;
657}
658
659static struct snd_kcontrol_new pcxhr_control_clock_type = {
660 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
661 .name = "Clock Mode",
662 .info = pcxhr_clock_type_info,
663 .get = pcxhr_clock_type_get,
664 .put = pcxhr_clock_type_put,
665};
666
667/*
668 * clock rate control
669 * specific control that scans the sample rates on the external plugs
670 */
671static int pcxhr_clock_rate_info(struct snd_kcontrol *kcontrol,
672 struct snd_ctl_elem_info *uinfo)
673{
674 struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
675 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
676 uinfo->count = 3 + mgr->capture_chips;
677 uinfo->value.integer.min = 0; /* clock not present */
678 uinfo->value.integer.max = 192000; /* max sample rate 192 kHz */
679 return 0;
680}
681
682static int pcxhr_clock_rate_get(struct snd_kcontrol *kcontrol,
683 struct snd_ctl_elem_value *ucontrol)
684{
685 struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
686 int i, err, rate;
687
688 down(&mgr->mixer_mutex);
689 for(i = 0; i < 3 + mgr->capture_chips; i++) {
690 if (i == PCXHR_CLOCK_TYPE_INTERNAL)
691 rate = mgr->sample_rate_real;
692 else {
693 err = pcxhr_get_external_clock(mgr, i, &rate);
694 if (err)
695 break;
696 }
697 ucontrol->value.integer.value[i] = rate;
698 }
699 up(&mgr->mixer_mutex);
700 return 0;
701}
702
703static struct snd_kcontrol_new pcxhr_control_clock_rate = {
704 .access = SNDRV_CTL_ELEM_ACCESS_READ,
705 .iface = SNDRV_CTL_ELEM_IFACE_CARD,
706 .name = "Clock Rates",
707 .info = pcxhr_clock_rate_info,
708 .get = pcxhr_clock_rate_get,
709};
710
711/*
712 * IEC958 status bits
713 */
714static int pcxhr_iec958_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
715{
716 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
717 uinfo->count = 1;
718 return 0;
719}
720
721static int pcxhr_iec958_capture_byte(struct snd_pcxhr *chip, int aes_idx, unsigned char* aes_bits)
722{
723 int i, err;
724 unsigned char temp;
725 struct pcxhr_rmh rmh;
726
727 pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ);
728 rmh.cmd[0] |= IO_NUM_UER_CHIP_REG;
729 switch (chip->chip_idx) {
730 case 0: rmh.cmd[1] = CS8420_01_CS; break; /* use CS8416_01_CS for AES SYNC plug */
731 case 1: rmh.cmd[1] = CS8420_23_CS; break;
732 case 2: rmh.cmd[1] = CS8420_45_CS; break;
733 case 3: rmh.cmd[1] = CS8420_67_CS; break;
734 default: return -EINVAL;
735 }
736 switch (aes_idx) {
737 case 0: rmh.cmd[2] = CS8420_CSB0; break; /* use CS8416_CSBx for AES SYNC plug */
738 case 1: rmh.cmd[2] = CS8420_CSB1; break;
739 case 2: rmh.cmd[2] = CS8420_CSB2; break;
740 case 3: rmh.cmd[2] = CS8420_CSB3; break;
741 case 4: rmh.cmd[2] = CS8420_CSB4; break;
742 default: return -EINVAL;
743 }
744 rmh.cmd[1] &= 0x0fffff; /* size and code the chip id for the fpga */
745 rmh.cmd[2] &= CHIP_SIG_AND_MAP_SPI; /* chip signature + map for spi read */
746 rmh.cmd_len = 3;
747 err = pcxhr_send_msg(chip->mgr, &rmh);
748 if (err)
749 return err;
750 temp = 0;
751 for (i = 0; i < 8; i++) {
752 /* attention : reversed bit order (not with CS8416_01_CS) */
753 temp <<= 1;
754 if (rmh.stat[1] & (1 << i))
755 temp |= 1;
756 }
757 snd_printdd("read iec958 AES %d byte %d = 0x%x\n", chip->chip_idx, aes_idx, temp);
758 *aes_bits = temp;
759 return 0;
760}
761
762static int pcxhr_iec958_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
763{
764 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
765 unsigned char aes_bits;
766 int i, err;
767
768 down(&chip->mgr->mixer_mutex);
769 for(i = 0; i < 5; i++) {
770 if (kcontrol->private_value == 0) /* playback */
771 aes_bits = chip->aes_bits[i];
772 else { /* capture */
773 err = pcxhr_iec958_capture_byte(chip, i, &aes_bits);
774 if (err)
775 break;
776 }
777 ucontrol->value.iec958.status[i] = aes_bits;
778 }
779 up(&chip->mgr->mixer_mutex);
780 return 0;
781}
782
783static int pcxhr_iec958_mask_get(struct snd_kcontrol *kcontrol,
784 struct snd_ctl_elem_value *ucontrol)
785{
786 int i;
787 for (i = 0; i < 5; i++)
788 ucontrol->value.iec958.status[i] = 0xff;
789 return 0;
790}
791
792static int pcxhr_iec958_update_byte(struct snd_pcxhr *chip, int aes_idx, unsigned char aes_bits)
793{
794 int i, err, cmd;
795 unsigned char new_bits = aes_bits;
796 unsigned char old_bits = chip->aes_bits[aes_idx];
797 struct pcxhr_rmh rmh;
798
799 for (i = 0; i < 8; i++) {
800 if ((old_bits & 0x01) != (new_bits & 0x01)) {
801 cmd = chip->chip_idx & 0x03; /* chip index 0..3 */
802 if(chip->chip_idx > 3)
803 /* new bit used if chip_idx>3 (PCX1222HR) */
804 cmd |= 1 << 22;
805 cmd |= ((aes_idx << 3) + i) << 2; /* add bit offset */
806 cmd |= (new_bits & 0x01) << 23; /* add bit value */
807 pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
808 rmh.cmd[0] |= IO_NUM_REG_CUER;
809 rmh.cmd[1] = cmd;
810 rmh.cmd_len = 2;
811 snd_printdd("write iec958 AES %d byte %d bit %d (cmd %x)\n",
812 chip->chip_idx, aes_idx, i, cmd);
813 err = pcxhr_send_msg(chip->mgr, &rmh);
814 if (err)
815 return err;
816 }
817 old_bits >>= 1;
818 new_bits >>= 1;
819 }
820 chip->aes_bits[aes_idx] = aes_bits;
821 return 0;
822}
823
824static int pcxhr_iec958_put(struct snd_kcontrol *kcontrol,
825 struct snd_ctl_elem_value *ucontrol)
826{
827 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
828 int i, changed = 0;
829
830 /* playback */
831 down(&chip->mgr->mixer_mutex);
832 for (i = 0; i < 5; i++) {
833 if (ucontrol->value.iec958.status[i] != chip->aes_bits[i]) {
834 pcxhr_iec958_update_byte(chip, i, ucontrol->value.iec958.status[i]);
835 changed = 1;
836 }
837 }
838 up(&chip->mgr->mixer_mutex);
839 return changed;
840}
841
842static struct snd_kcontrol_new pcxhr_control_playback_iec958_mask = {
843 .access = SNDRV_CTL_ELEM_ACCESS_READ,
844 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
845 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
846 .info = pcxhr_iec958_info,
847 .get = pcxhr_iec958_mask_get
848};
849static struct snd_kcontrol_new pcxhr_control_playback_iec958 = {
850 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
851 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
852 .info = pcxhr_iec958_info,
853 .get = pcxhr_iec958_get,
854 .put = pcxhr_iec958_put,
855 .private_value = 0 /* playback */
856};
857
858static struct snd_kcontrol_new pcxhr_control_capture_iec958_mask = {
859 .access = SNDRV_CTL_ELEM_ACCESS_READ,
860 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
861 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK),
862 .info = pcxhr_iec958_info,
863 .get = pcxhr_iec958_mask_get
864};
865static struct snd_kcontrol_new pcxhr_control_capture_iec958 = {
866 .access = SNDRV_CTL_ELEM_ACCESS_READ,
867 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
868 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
869 .info = pcxhr_iec958_info,
870 .get = pcxhr_iec958_get,
871 .private_value = 1 /* capture */
872};
873
874static void pcxhr_init_audio_levels(struct snd_pcxhr *chip)
875{
876 int i;
877
878 for (i = 0; i < 2; i++) {
879 if (chip->nb_streams_play) {
880 int j;
881 /* at boot time the digital volumes are unmuted 0dB */
882 for (j = 0; j < PCXHR_PLAYBACK_STREAMS; j++) {
883 chip->digital_playback_active[j][i] = 1;
884 chip->digital_playback_volume[j][i] = PCXHR_DIGITAL_ZERO_LEVEL;
885 }
886 /* after boot, only two bits are set on the uer interface */
887 chip->aes_bits[0] = IEC958_AES0_PROFESSIONAL | IEC958_AES0_PRO_FS_48000;
888/* only for test purpose, remove later */
889#ifdef CONFIG_SND_DEBUG
890 /* analog volumes for playback (is LEVEL_MIN after boot) */
891 chip->analog_playback_active[i] = 1;
892 chip->analog_playback_volume[i] = PCXHR_ANALOG_PLAYBACK_ZERO_LEVEL;
893 pcxhr_update_analog_audio_level(chip, 0, i);
894#endif
895/* test end */
896 }
897 if (chip->nb_streams_capt) {
898 /* at boot time the digital volumes are unmuted 0dB */
899 chip->digital_capture_volume[i] = PCXHR_DIGITAL_ZERO_LEVEL;
900/* only for test purpose, remove later */
901#ifdef CONFIG_SND_DEBUG
902 /* analog volumes for playback (is LEVEL_MIN after boot) */
903 chip->analog_capture_volume[i] = PCXHR_ANALOG_CAPTURE_ZERO_LEVEL;
904 pcxhr_update_analog_audio_level(chip, 1, i);
905#endif
906/* test end */
907 }
908 }
909
910 return;
911}
912
913
914int pcxhr_create_mixer(struct pcxhr_mgr *mgr)
915{
916 struct snd_pcxhr *chip;
917 int err, i;
918
919 init_MUTEX(&mgr->mixer_mutex); /* can be in another place */
920
921 for (i = 0; i < mgr->num_cards; i++) {
922 struct snd_kcontrol_new temp;
923 chip = mgr->chip[i];
924
925 if (chip->nb_streams_play) {
926 /* analog output level control */
927 temp = pcxhr_control_analog_level;
928 temp.name = "Master Playback Volume";
929 temp.private_value = 0; /* playback */
930 if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
931 return err;
932 /* output mute controls */
933 if ((err = snd_ctl_add(chip->card,
934 snd_ctl_new1(&pcxhr_control_output_switch,
935 chip))) < 0)
936 return err;
937
938 temp = snd_pcxhr_pcm_vol;
939 temp.name = "PCM Playback Volume";
940 temp.count = PCXHR_PLAYBACK_STREAMS;
941 temp.private_value = 0; /* playback */
942 if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
943 return err;
944
945 if ((err = snd_ctl_add(chip->card,
946 snd_ctl_new1(&pcxhr_control_pcm_switch,
947 chip))) < 0)
948 return err;
949
950 /* IEC958 controls */
951 if ((err = snd_ctl_add(chip->card,
952 snd_ctl_new1(&pcxhr_control_playback_iec958_mask,
953 chip))) < 0)
954 return err;
955 if ((err = snd_ctl_add(chip->card,
956 snd_ctl_new1(&pcxhr_control_playback_iec958,
957 chip))) < 0)
958 return err;
959 }
960 if (chip->nb_streams_capt) {
961 /* analog input level control only on first two chips !*/
962 temp = pcxhr_control_analog_level;
963 temp.name = "Master Capture Volume";
964 temp.private_value = 1; /* capture */
965 if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
966 return err;
967
968 temp = snd_pcxhr_pcm_vol;
969 temp.name = "PCM Capture Volume";
970 temp.count = 1;
971 temp.private_value = 1; /* capture */
972 if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
973 return err;
974 /* Audio source */
975 if ((err = snd_ctl_add(chip->card,
976 snd_ctl_new1(&pcxhr_control_audio_src,
977 chip))) < 0)
978 return err;
979 /* IEC958 controls */
980 if ((err = snd_ctl_add(chip->card,
981 snd_ctl_new1(&pcxhr_control_capture_iec958_mask,
982 chip))) < 0)
983 return err;
984 if ((err = snd_ctl_add(chip->card,
985 snd_ctl_new1(&pcxhr_control_capture_iec958,
986 chip))) < 0)
987 return err;
988 }
989 /* monitoring only if playback and capture device available */
990 if (chip->nb_streams_capt > 0 && chip->nb_streams_play > 0) {
991 /* monitoring */
992 if ((err = snd_ctl_add(chip->card,
993 snd_ctl_new1(&pcxhr_control_monitor_vol,
994 chip))) < 0)
995 return err;
996 if ((err = snd_ctl_add(chip->card,
997 snd_ctl_new1(&pcxhr_control_monitor_sw,
998 chip))) < 0)
999 return err;
1000 }
1001
1002 if (i == 0) {
1003 /* clock mode only one control per pcxhr */
1004 if ((err = snd_ctl_add(chip->card,
1005 snd_ctl_new1(&pcxhr_control_clock_type,
1006 mgr))) < 0)
1007 return err;
1008 /* non standard control used to scan the external clock presence/frequencies */
1009 if ((err = snd_ctl_add(chip->card,
1010 snd_ctl_new1(&pcxhr_control_clock_rate,
1011 mgr))) < 0)
1012 return err;
1013 }
1014
1015 /* init values for the mixer data */
1016 pcxhr_init_audio_levels(chip);
1017 }
1018
1019 return 0;
1020}