[ARM] Support register switch in nommu mode
[linux-2.6/verdex.git] / sound / pci / pcxhr / pcxhr_mixer.c
blob760e733ac25e314641e0240a52abfedef359b34d
1 #define __NO_VERSION__
2 /*
3 * Driver for Digigram pcxhr compatible soundcards
5 * mixer callbacks
7 * Copyright (c) 2004 by Digigram <alsa@digigram.com>
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.
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.
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
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"
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 ) */
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 ) */
45 static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip, int is_capture, int channel)
47 int err, vol;
48 struct pcxhr_rmh rmh;
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 */
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;
70 return 0;
74 * analog level control
76 static int pcxhr_analog_vol_info(struct snd_kcontrol *kcontrol,
77 struct snd_ctl_elem_info *uinfo)
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 */
88 return 0;
91 static int pcxhr_analog_vol_get(struct snd_kcontrol *kcontrol,
92 struct snd_ctl_elem_value *ucontrol)
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];
103 up(&chip->mgr->mixer_mutex);
104 return 0;
107 static int pcxhr_analog_vol_put(struct snd_kcontrol *kcontrol,
108 struct snd_ctl_elem_value *ucontrol)
110 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
111 int changed = 0;
112 int is_capture, i;
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);
126 up(&chip->mgr->mixer_mutex);
127 return changed;
130 static 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,
138 /* shared */
139 static int pcxhr_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
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;
148 static int pcxhr_audio_sw_get(struct snd_kcontrol *kcontrol,
149 struct snd_ctl_elem_value *ucontrol)
151 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
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;
160 static int pcxhr_audio_sw_put(struct snd_kcontrol *kcontrol,
161 struct snd_ctl_elem_value *ucontrol)
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 */
173 up(&chip->mgr->mixer_mutex);
174 return changed;
177 static 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
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 */
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
197 static int pcxhr_update_playback_stream_level(struct snd_pcxhr* chip, int idx)
199 int err;
200 struct pcxhr_rmh rmh;
201 struct pcxhr_pipe *pipe = &chip->playback_pipe;
202 int left, right;
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;
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;
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;
230 return 0;
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
240 static int pcxhr_update_audio_pipe_level(struct snd_pcxhr* chip, int capture, int channel)
242 int err;
243 struct pcxhr_rmh rmh;
244 struct pcxhr_pipe *pipe;
246 if (capture)
247 pipe = &chip->capture_pipe[0];
248 else
249 pipe = &chip->playback_pipe;
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
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)
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;
270 rmh.cmd_len = 3;
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;
278 return 0;
282 /* shared */
283 static int pcxhr_digital_vol_info(struct snd_kcontrol *kcontrol,
284 struct snd_ctl_elem_info *uinfo)
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;
294 static int pcxhr_pcm_vol_get(struct snd_kcontrol *kcontrol,
295 struct snd_ctl_elem_value *ucontrol)
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;
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;
313 static int pcxhr_pcm_vol_put(struct snd_kcontrol *kcontrol,
314 struct snd_ctl_elem_value *ucontrol)
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;
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);
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;
342 static struct snd_kcontrol_new snd_pcxhr_pcm_vol =
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,
353 static int pcxhr_pcm_sw_get(struct snd_kcontrol *kcontrol,
354 struct snd_ctl_elem_value *ucontrol)
356 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
357 int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
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;
366 static int pcxhr_pcm_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
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;
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;
381 if (changed)
382 pcxhr_update_playback_stream_level(chip, idx);
383 up(&chip->mgr->mixer_mutex);
384 return changed;
387 static 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
398 * monitoring level control
401 static int pcxhr_monitor_vol_get(struct snd_kcontrol *kcontrol,
402 struct snd_ctl_elem_value *ucontrol)
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;
412 static int pcxhr_monitor_vol_put(struct snd_kcontrol *kcontrol,
413 struct snd_ctl_elem_value *ucontrol)
415 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
416 int changed = 0;
417 int i;
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;
429 up(&chip->mgr->mixer_mutex);
430 return changed;
433 static 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,
442 * monitoring switch control
445 static int pcxhr_monitor_sw_get(struct snd_kcontrol *kcontrol,
446 struct snd_ctl_elem_value *ucontrol)
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;
456 static int pcxhr_monitor_sw_put(struct snd_kcontrol *kcontrol,
457 struct snd_ctl_elem_value *ucontrol)
459 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
460 int changed = 0;
461 int i;
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 */
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);
477 up(&chip->mgr->mixer_mutex);
478 return (changed != 0);
481 static 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
492 * audio source select
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
500 static int pcxhr_set_audio_source(struct snd_pcxhr* chip)
502 struct pcxhr_rmh rmh;
503 unsigned int mask, reg;
504 unsigned int codec;
505 int err, use_src, changed;
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;
514 reg = 0; /* audio source from analog plug */
515 use_src = 0; /* do not activate codec SRC */
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;
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;
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;
545 static int pcxhr_audio_src_info(struct snd_kcontrol *kcontrol,
546 struct snd_ctl_elem_info *uinfo)
548 static char *texts[3] = {"Analog", "Digital", "Digi+SRC"};
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;
560 static int pcxhr_audio_src_get(struct snd_kcontrol *kcontrol,
561 struct snd_ctl_elem_value *ucontrol)
563 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
564 ucontrol->value.enumerated.item[0] = chip->audio_capture_source;
565 return 0;
568 static int pcxhr_audio_src_put(struct snd_kcontrol *kcontrol,
569 struct snd_ctl_elem_value *ucontrol)
571 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
572 int ret = 0;
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;
580 up(&chip->mgr->mixer_mutex);
581 return ret;
584 static 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,
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 * };
606 static int pcxhr_clock_type_info(struct snd_kcontrol *kcontrol,
607 struct snd_ctl_elem_info *uinfo)
609 static char *texts[7] = {
610 "Internal", "WordClock", "AES Sync", "AES 1", "AES 2", "AES 3", "AES 4"
612 struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
613 int clock_items = 3 + mgr->capture_chips;
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;
625 static int pcxhr_clock_type_get(struct snd_kcontrol *kcontrol,
626 struct snd_ctl_elem_value *ucontrol)
628 struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
629 ucontrol->value.enumerated.item[0] = mgr->use_clock_type;
630 return 0;
633 static int pcxhr_clock_type_put(struct snd_kcontrol *kcontrol,
634 struct snd_ctl_elem_value *ucontrol)
636 struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
637 int rate, ret = 0;
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;
652 up(&mgr->setup_mutex);
653 ret = 1; /* return 1 even if the set was not done. ok ? */
655 up(&mgr->mixer_mutex);
656 return ret;
659 static 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,
668 * clock rate control
669 * specific control that scans the sample rates on the external plugs
671 static int pcxhr_clock_rate_info(struct snd_kcontrol *kcontrol,
672 struct snd_ctl_elem_info *uinfo)
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;
682 static int pcxhr_clock_rate_get(struct snd_kcontrol *kcontrol,
683 struct snd_ctl_elem_value *ucontrol)
685 struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
686 int i, err, rate;
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;
697 ucontrol->value.integer.value[i] = rate;
699 up(&mgr->mixer_mutex);
700 return 0;
703 static 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,
712 * IEC958 status bits
714 static int pcxhr_iec958_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
716 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
717 uinfo->count = 1;
718 return 0;
721 static int pcxhr_iec958_capture_byte(struct snd_pcxhr *chip, int aes_idx, unsigned char* aes_bits)
723 int i, err;
724 unsigned char temp;
725 struct pcxhr_rmh rmh;
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;
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;
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;
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;
762 static int pcxhr_iec958_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
764 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
765 unsigned char aes_bits;
766 int i, err;
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;
777 ucontrol->value.iec958.status[i] = aes_bits;
779 up(&chip->mgr->mixer_mutex);
780 return 0;
783 static int pcxhr_iec958_mask_get(struct snd_kcontrol *kcontrol,
784 struct snd_ctl_elem_value *ucontrol)
786 int i;
787 for (i = 0; i < 5; i++)
788 ucontrol->value.iec958.status[i] = 0xff;
789 return 0;
792 static int pcxhr_iec958_update_byte(struct snd_pcxhr *chip, int aes_idx, unsigned char aes_bits)
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;
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;
817 old_bits >>= 1;
818 new_bits >>= 1;
820 chip->aes_bits[aes_idx] = aes_bits;
821 return 0;
824 static int pcxhr_iec958_put(struct snd_kcontrol *kcontrol,
825 struct snd_ctl_elem_value *ucontrol)
827 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
828 int i, changed = 0;
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;
838 up(&chip->mgr->mixer_mutex);
839 return changed;
842 static 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
849 static 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 */
858 static 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
865 static 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 */
874 static void pcxhr_init_audio_levels(struct snd_pcxhr *chip)
876 int i;
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;
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 */
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 */
910 return;
914 int pcxhr_create_mixer(struct pcxhr_mgr *mgr)
916 struct snd_pcxhr *chip;
917 int err, i;
919 init_MUTEX(&mgr->mixer_mutex); /* can be in another place */
921 for (i = 0; i < mgr->num_cards; i++) {
922 struct snd_kcontrol_new temp;
923 chip = mgr->chip[i];
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;
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;
945 if ((err = snd_ctl_add(chip->card,
946 snd_ctl_new1(&pcxhr_control_pcm_switch,
947 chip))) < 0)
948 return err;
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;
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;
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;
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;
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;
1015 /* init values for the mixer data */
1016 pcxhr_init_audio_levels(chip);
1019 return 0;