blob: 4d8654575e18258dde0b2f17ee3d751128f1a2df [file] [log] [blame]
Markus Bollingere12229b2005-12-06 13:55:26 +01001#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>
Ingo Molnar62932df2006-01-16 16:34:20 +010028#include <linux/mutex.h>
Markus Bollingere12229b2005-12-06 13:55:26 +010029#include <sound/core.h>
30#include "pcxhr.h"
31#include "pcxhr_hwdep.h"
32#include "pcxhr_core.h"
33#include <sound/control.h>
Takashi Iwaic6ff77f2006-08-23 19:53:02 +020034#include <sound/tlv.h>
Markus Bollingere12229b2005-12-06 13:55:26 +010035#include <sound/asoundef.h>
36#include "pcxhr_mixer.h"
37
38
39#define PCXHR_ANALOG_CAPTURE_LEVEL_MIN 0 /* -96.0 dB */
40#define PCXHR_ANALOG_CAPTURE_LEVEL_MAX 255 /* +31.5 dB */
41#define PCXHR_ANALOG_CAPTURE_ZERO_LEVEL 224 /* +16.0 dB ( +31.5 dB - fix level +15.5 dB ) */
42
43#define PCXHR_ANALOG_PLAYBACK_LEVEL_MIN 0 /* -128.0 dB */
44#define PCXHR_ANALOG_PLAYBACK_LEVEL_MAX 128 /* 0.0 dB */
45#define PCXHR_ANALOG_PLAYBACK_ZERO_LEVEL 104 /* -24.0 dB ( 0.0 dB - fix level +24.0 dB ) */
46
Takashi Iwaie6382cf2007-10-10 10:06:46 +020047static const DECLARE_TLV_DB_SCALE(db_scale_analog_capture, -9600, 50, 3150);
48static const DECLARE_TLV_DB_SCALE(db_scale_analog_playback, -10400, 100, 2400);
Takashi Iwaic6ff77f2006-08-23 19:53:02 +020049
Markus Bollingere12229b2005-12-06 13:55:26 +010050static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip, int is_capture, int channel)
51{
52 int err, vol;
53 struct pcxhr_rmh rmh;
54
55 pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
56 if (is_capture) {
57 rmh.cmd[0] |= IO_NUM_REG_IN_ANA_LEVEL;
58 rmh.cmd[2] = chip->analog_capture_volume[channel];
59 } else {
60 rmh.cmd[0] |= IO_NUM_REG_OUT_ANA_LEVEL;
61 if (chip->analog_playback_active[channel])
62 vol = chip->analog_playback_volume[channel];
63 else
64 vol = PCXHR_ANALOG_PLAYBACK_LEVEL_MIN;
65 rmh.cmd[2] = PCXHR_ANALOG_PLAYBACK_LEVEL_MAX - vol; /* playback analog levels are inversed */
66 }
67 rmh.cmd[1] = 1 << ((2 * chip->chip_idx) + channel); /* audio mask */
68 rmh.cmd_len = 3;
69 err = pcxhr_send_msg(chip->mgr, &rmh);
70 if (err < 0) {
71 snd_printk(KERN_DEBUG "error update_analog_audio_level card(%d) "
72 "is_capture(%d) err(%x)\n", chip->chip_idx, is_capture, err);
73 return -EINVAL;
74 }
75 return 0;
76}
77
78/*
79 * analog level control
80 */
81static int pcxhr_analog_vol_info(struct snd_kcontrol *kcontrol,
82 struct snd_ctl_elem_info *uinfo)
83{
84 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
85 uinfo->count = 2;
86 if (kcontrol->private_value == 0) { /* playback */
87 uinfo->value.integer.min = PCXHR_ANALOG_PLAYBACK_LEVEL_MIN; /* -128 dB */
88 uinfo->value.integer.max = PCXHR_ANALOG_PLAYBACK_LEVEL_MAX; /* 0 dB */
89 } else { /* capture */
90 uinfo->value.integer.min = PCXHR_ANALOG_CAPTURE_LEVEL_MIN; /* -96 dB */
91 uinfo->value.integer.max = PCXHR_ANALOG_CAPTURE_LEVEL_MAX; /* 31.5 dB */
92 }
93 return 0;
94}
95
96static int pcxhr_analog_vol_get(struct snd_kcontrol *kcontrol,
97 struct snd_ctl_elem_value *ucontrol)
98{
99 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
Ingo Molnar62932df2006-01-16 16:34:20 +0100100 mutex_lock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100101 if (kcontrol->private_value == 0) { /* playback */
102 ucontrol->value.integer.value[0] = chip->analog_playback_volume[0];
103 ucontrol->value.integer.value[1] = chip->analog_playback_volume[1];
104 } else { /* capture */
105 ucontrol->value.integer.value[0] = chip->analog_capture_volume[0];
106 ucontrol->value.integer.value[1] = chip->analog_capture_volume[1];
107 }
Ingo Molnar62932df2006-01-16 16:34:20 +0100108 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100109 return 0;
110}
111
112static int pcxhr_analog_vol_put(struct snd_kcontrol *kcontrol,
113 struct snd_ctl_elem_value *ucontrol)
114{
115 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
116 int changed = 0;
117 int is_capture, i;
118
Ingo Molnar62932df2006-01-16 16:34:20 +0100119 mutex_lock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100120 is_capture = (kcontrol->private_value != 0);
121 for (i = 0; i < 2; i++) {
122 int new_volume = ucontrol->value.integer.value[i];
Takashi Iwai4e98d6a2007-11-15 15:58:13 +0100123 int *stored_volume = is_capture ?
124 &chip->analog_capture_volume[i] :
Markus Bollingere12229b2005-12-06 13:55:26 +0100125 &chip->analog_playback_volume[i];
Takashi Iwai4e98d6a2007-11-15 15:58:13 +0100126 if (is_capture) {
127 if (new_volume < PCXHR_ANALOG_CAPTURE_LEVEL_MIN ||
128 new_volume > PCXHR_ANALOG_CAPTURE_LEVEL_MAX)
129 continue;
130 } else {
131 if (new_volume < PCXHR_ANALOG_PLAYBACK_LEVEL_MIN ||
132 new_volume > PCXHR_ANALOG_PLAYBACK_LEVEL_MAX)
133 continue;
134 }
Markus Bollingere12229b2005-12-06 13:55:26 +0100135 if (*stored_volume != new_volume) {
136 *stored_volume = new_volume;
137 changed = 1;
138 pcxhr_update_analog_audio_level(chip, is_capture, i);
139 }
140 }
Ingo Molnar62932df2006-01-16 16:34:20 +0100141 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100142 return changed;
143}
144
145static struct snd_kcontrol_new pcxhr_control_analog_level = {
146 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
Takashi Iwaic6ff77f2006-08-23 19:53:02 +0200147 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
148 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
Markus Bollingere12229b2005-12-06 13:55:26 +0100149 /* name will be filled later */
150 .info = pcxhr_analog_vol_info,
151 .get = pcxhr_analog_vol_get,
152 .put = pcxhr_analog_vol_put,
Takashi Iwaic6ff77f2006-08-23 19:53:02 +0200153 /* tlv will be filled later */
Markus Bollingere12229b2005-12-06 13:55:26 +0100154};
155
156/* shared */
Takashi Iwaia5ce8892007-07-23 15:42:26 +0200157#define pcxhr_sw_info snd_ctl_boolean_stereo_info
Markus Bollingere12229b2005-12-06 13:55:26 +0100158
159static int pcxhr_audio_sw_get(struct snd_kcontrol *kcontrol,
160 struct snd_ctl_elem_value *ucontrol)
161{
162 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
163
Ingo Molnar62932df2006-01-16 16:34:20 +0100164 mutex_lock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100165 ucontrol->value.integer.value[0] = chip->analog_playback_active[0];
166 ucontrol->value.integer.value[1] = chip->analog_playback_active[1];
Ingo Molnar62932df2006-01-16 16:34:20 +0100167 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100168 return 0;
169}
170
171static int pcxhr_audio_sw_put(struct snd_kcontrol *kcontrol,
172 struct snd_ctl_elem_value *ucontrol)
173{
174 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
175 int i, changed = 0;
Ingo Molnar62932df2006-01-16 16:34:20 +0100176 mutex_lock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100177 for(i = 0; i < 2; i++) {
Takashi Iwai4e98d6a2007-11-15 15:58:13 +0100178 if (chip->analog_playback_active[i] !=
179 ucontrol->value.integer.value[i]) {
180 chip->analog_playback_active[i] =
181 !!ucontrol->value.integer.value[i];
Markus Bollingere12229b2005-12-06 13:55:26 +0100182 changed = 1;
Takashi Iwai4e98d6a2007-11-15 15:58:13 +0100183 /* update playback levels */
184 pcxhr_update_analog_audio_level(chip, 0, i);
Markus Bollingere12229b2005-12-06 13:55:26 +0100185 }
186 }
Ingo Molnar62932df2006-01-16 16:34:20 +0100187 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100188 return changed;
189}
190
191static struct snd_kcontrol_new pcxhr_control_output_switch = {
192 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
193 .name = "Master Playback Switch",
194 .info = pcxhr_sw_info, /* shared */
195 .get = pcxhr_audio_sw_get,
196 .put = pcxhr_audio_sw_put
197};
198
199
200#define PCXHR_DIGITAL_LEVEL_MIN 0x000 /* -110 dB */
201#define PCXHR_DIGITAL_LEVEL_MAX 0x1ff /* +18 dB */
202#define PCXHR_DIGITAL_ZERO_LEVEL 0x1b7 /* 0 dB */
203
Takashi Iwaie6382cf2007-10-10 10:06:46 +0200204static const DECLARE_TLV_DB_SCALE(db_scale_digital, -10975, 25, 1800);
Markus Bollingere12229b2005-12-06 13:55:26 +0100205
206#define MORE_THAN_ONE_STREAM_LEVEL 0x000001
207#define VALID_STREAM_PAN_LEVEL_MASK 0x800000
208#define VALID_STREAM_LEVEL_MASK 0x400000
209#define VALID_STREAM_LEVEL_1_MASK 0x200000
210#define VALID_STREAM_LEVEL_2_MASK 0x100000
211
212static int pcxhr_update_playback_stream_level(struct snd_pcxhr* chip, int idx)
213{
214 int err;
215 struct pcxhr_rmh rmh;
216 struct pcxhr_pipe *pipe = &chip->playback_pipe;
217 int left, right;
218
219 if (chip->digital_playback_active[idx][0])
220 left = chip->digital_playback_volume[idx][0];
221 else
222 left = PCXHR_DIGITAL_LEVEL_MIN;
223 if (chip->digital_playback_active[idx][1])
224 right = chip->digital_playback_volume[idx][1];
225 else
226 right = PCXHR_DIGITAL_LEVEL_MIN;
227
228 pcxhr_init_rmh(&rmh, CMD_STREAM_OUT_LEVEL_ADJUST);
229 /* add pipe and stream mask */
230 pcxhr_set_pipe_cmd_params(&rmh, 0, pipe->first_audio, 0, 1<<idx);
231 /* volume left->left / right->right panoramic level */
232 rmh.cmd[0] |= MORE_THAN_ONE_STREAM_LEVEL;
233 rmh.cmd[2] = VALID_STREAM_PAN_LEVEL_MASK | VALID_STREAM_LEVEL_1_MASK;
234 rmh.cmd[2] |= (left << 10);
235 rmh.cmd[3] = VALID_STREAM_PAN_LEVEL_MASK | VALID_STREAM_LEVEL_2_MASK;
236 rmh.cmd[3] |= right;
237 rmh.cmd_len = 4;
238
239 err = pcxhr_send_msg(chip->mgr, &rmh);
240 if (err < 0) {
241 snd_printk(KERN_DEBUG "error update_playback_stream_level "
242 "card(%d) err(%x)\n", chip->chip_idx, err);
243 return -EINVAL;
244 }
245 return 0;
246}
247
248#define AUDIO_IO_HAS_MUTE_LEVEL 0x400000
249#define AUDIO_IO_HAS_MUTE_MONITOR_1 0x200000
250#define VALID_AUDIO_IO_DIGITAL_LEVEL 0x000001
251#define VALID_AUDIO_IO_MONITOR_LEVEL 0x000002
252#define VALID_AUDIO_IO_MUTE_LEVEL 0x000004
253#define VALID_AUDIO_IO_MUTE_MONITOR_1 0x000008
254
255static int pcxhr_update_audio_pipe_level(struct snd_pcxhr* chip, int capture, int channel)
256{
257 int err;
258 struct pcxhr_rmh rmh;
259 struct pcxhr_pipe *pipe;
260
261 if (capture)
262 pipe = &chip->capture_pipe[0];
263 else
264 pipe = &chip->playback_pipe;
265
266 pcxhr_init_rmh(&rmh, CMD_AUDIO_LEVEL_ADJUST);
267 /* add channel mask */
268 pcxhr_set_pipe_cmd_params(&rmh, capture, 0, 0, 1 << (channel + pipe->first_audio));
269 /* TODO : if mask (3 << pipe->first_audio) is used, left and right channel
270 * will be programmed to the same params
271 */
272 if (capture) {
273 rmh.cmd[0] |= VALID_AUDIO_IO_DIGITAL_LEVEL;
274 /* VALID_AUDIO_IO_MUTE_LEVEL not yet handled (capture pipe level) */
275 rmh.cmd[2] = chip->digital_capture_volume[channel];
276 } else {
277 rmh.cmd[0] |= VALID_AUDIO_IO_MONITOR_LEVEL | VALID_AUDIO_IO_MUTE_MONITOR_1;
278 /* VALID_AUDIO_IO_DIGITAL_LEVEL and VALID_AUDIO_IO_MUTE_LEVEL not yet
279 * handled (playback pipe level)
280 */
281 rmh.cmd[2] = chip->monitoring_volume[channel] << 10;
282 if (chip->monitoring_active[channel] == 0)
283 rmh.cmd[2] |= AUDIO_IO_HAS_MUTE_MONITOR_1;
284 }
285 rmh.cmd_len = 3;
286
287 err = pcxhr_send_msg(chip->mgr, &rmh);
288 if(err<0) {
289 snd_printk(KERN_DEBUG "error update_audio_level card(%d) err(%x)\n",
290 chip->chip_idx, err);
291 return -EINVAL;
292 }
293 return 0;
294}
295
296
297/* shared */
298static int pcxhr_digital_vol_info(struct snd_kcontrol *kcontrol,
299 struct snd_ctl_elem_info *uinfo)
300{
301 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
302 uinfo->count = 2;
303 uinfo->value.integer.min = PCXHR_DIGITAL_LEVEL_MIN; /* -109.5 dB */
304 uinfo->value.integer.max = PCXHR_DIGITAL_LEVEL_MAX; /* 18.0 dB */
305 return 0;
306}
307
308
309static int pcxhr_pcm_vol_get(struct snd_kcontrol *kcontrol,
310 struct snd_ctl_elem_value *ucontrol)
311{
312 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
313 int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
314 int *stored_volume;
315 int is_capture = kcontrol->private_value;
316
Ingo Molnar62932df2006-01-16 16:34:20 +0100317 mutex_lock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100318 if (is_capture)
319 stored_volume = chip->digital_capture_volume; /* digital capture */
320 else
321 stored_volume = chip->digital_playback_volume[idx]; /* digital playback */
322 ucontrol->value.integer.value[0] = stored_volume[0];
323 ucontrol->value.integer.value[1] = stored_volume[1];
Ingo Molnar62932df2006-01-16 16:34:20 +0100324 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100325 return 0;
326}
327
328static int pcxhr_pcm_vol_put(struct snd_kcontrol *kcontrol,
329 struct snd_ctl_elem_value *ucontrol)
330{
331 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
332 int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
333 int changed = 0;
334 int is_capture = kcontrol->private_value;
335 int *stored_volume;
336 int i;
337
Ingo Molnar62932df2006-01-16 16:34:20 +0100338 mutex_lock(&chip->mgr->mixer_mutex);
Takashi Iwai4e98d6a2007-11-15 15:58:13 +0100339 if (is_capture) /* digital capture */
340 stored_volume = chip->digital_capture_volume;
341 else /* digital playback */
342 stored_volume = chip->digital_playback_volume[idx];
Markus Bollingere12229b2005-12-06 13:55:26 +0100343 for (i = 0; i < 2; i++) {
Takashi Iwai4e98d6a2007-11-15 15:58:13 +0100344 int vol = ucontrol->value.integer.value[i];
345 if (vol < PCXHR_DIGITAL_LEVEL_MIN ||
346 vol > PCXHR_DIGITAL_LEVEL_MAX)
347 continue;
348 if (stored_volume[i] != vol) {
349 stored_volume[i] = vol;
Markus Bollingere12229b2005-12-06 13:55:26 +0100350 changed = 1;
351 if (is_capture) /* update capture volume */
352 pcxhr_update_audio_pipe_level(chip, 1, i);
353 }
354 }
Takashi Iwai4e98d6a2007-11-15 15:58:13 +0100355 if (!is_capture && changed) /* update playback volume */
356 pcxhr_update_playback_stream_level(chip, idx);
Ingo Molnar62932df2006-01-16 16:34:20 +0100357 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100358 return changed;
359}
360
361static struct snd_kcontrol_new snd_pcxhr_pcm_vol =
362{
363 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
Takashi Iwaic6ff77f2006-08-23 19:53:02 +0200364 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
365 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
Markus Bollingere12229b2005-12-06 13:55:26 +0100366 /* name will be filled later */
367 /* count will be filled later */
368 .info = pcxhr_digital_vol_info, /* shared */
369 .get = pcxhr_pcm_vol_get,
370 .put = pcxhr_pcm_vol_put,
Takashi Iwaic6ff77f2006-08-23 19:53:02 +0200371 .tlv = { .p = db_scale_digital },
Markus Bollingere12229b2005-12-06 13:55:26 +0100372};
373
374
375static int pcxhr_pcm_sw_get(struct snd_kcontrol *kcontrol,
376 struct snd_ctl_elem_value *ucontrol)
377{
378 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
379 int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
380
Ingo Molnar62932df2006-01-16 16:34:20 +0100381 mutex_lock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100382 ucontrol->value.integer.value[0] = chip->digital_playback_active[idx][0];
383 ucontrol->value.integer.value[1] = chip->digital_playback_active[idx][1];
Ingo Molnar62932df2006-01-16 16:34:20 +0100384 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100385 return 0;
386}
387
388static int pcxhr_pcm_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
389{
390 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
391 int changed = 0;
392 int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
393 int i, j;
394
Ingo Molnar62932df2006-01-16 16:34:20 +0100395 mutex_lock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100396 j = idx;
397 for (i = 0; i < 2; i++) {
Takashi Iwai4e98d6a2007-11-15 15:58:13 +0100398 if (chip->digital_playback_active[j][i] !=
399 ucontrol->value.integer.value[i]) {
400 chip->digital_playback_active[j][i] =
401 !!ucontrol->value.integer.value[i];
Markus Bollingere12229b2005-12-06 13:55:26 +0100402 changed = 1;
403 }
404 }
405 if (changed)
406 pcxhr_update_playback_stream_level(chip, idx);
Ingo Molnar62932df2006-01-16 16:34:20 +0100407 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100408 return changed;
409}
410
411static struct snd_kcontrol_new pcxhr_control_pcm_switch = {
412 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
413 .name = "PCM Playback Switch",
414 .count = PCXHR_PLAYBACK_STREAMS,
415 .info = pcxhr_sw_info, /* shared */
416 .get = pcxhr_pcm_sw_get,
417 .put = pcxhr_pcm_sw_put
418};
419
420
421/*
422 * monitoring level control
423 */
424
425static int pcxhr_monitor_vol_get(struct snd_kcontrol *kcontrol,
426 struct snd_ctl_elem_value *ucontrol)
427{
428 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
Ingo Molnar62932df2006-01-16 16:34:20 +0100429 mutex_lock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100430 ucontrol->value.integer.value[0] = chip->monitoring_volume[0];
431 ucontrol->value.integer.value[1] = chip->monitoring_volume[1];
Ingo Molnar62932df2006-01-16 16:34:20 +0100432 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100433 return 0;
434}
435
436static int pcxhr_monitor_vol_put(struct snd_kcontrol *kcontrol,
437 struct snd_ctl_elem_value *ucontrol)
438{
439 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
440 int changed = 0;
441 int i;
442
Ingo Molnar62932df2006-01-16 16:34:20 +0100443 mutex_lock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100444 for (i = 0; i < 2; i++) {
Takashi Iwai4e98d6a2007-11-15 15:58:13 +0100445 if (chip->monitoring_volume[i] !=
446 ucontrol->value.integer.value[i]) {
447 chip->monitoring_volume[i] =
448 !!ucontrol->value.integer.value[i];
449 if(chip->monitoring_active[i])
Markus Bollingere12229b2005-12-06 13:55:26 +0100450 /* update monitoring volume and mute */
Takashi Iwai4e98d6a2007-11-15 15:58:13 +0100451 /* do only when monitoring is unmuted */
Markus Bollingere12229b2005-12-06 13:55:26 +0100452 pcxhr_update_audio_pipe_level(chip, 0, i);
453 changed = 1;
454 }
455 }
Ingo Molnar62932df2006-01-16 16:34:20 +0100456 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100457 return changed;
458}
459
460static struct snd_kcontrol_new pcxhr_control_monitor_vol = {
461 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
Takashi Iwaic6ff77f2006-08-23 19:53:02 +0200462 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
463 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
Markus Bollingere12229b2005-12-06 13:55:26 +0100464 .name = "Monitoring Volume",
465 .info = pcxhr_digital_vol_info, /* shared */
466 .get = pcxhr_monitor_vol_get,
467 .put = pcxhr_monitor_vol_put,
Takashi Iwaic6ff77f2006-08-23 19:53:02 +0200468 .tlv = { .p = db_scale_digital },
Markus Bollingere12229b2005-12-06 13:55:26 +0100469};
470
471/*
472 * monitoring switch control
473 */
474
475static int pcxhr_monitor_sw_get(struct snd_kcontrol *kcontrol,
476 struct snd_ctl_elem_value *ucontrol)
477{
478 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
Ingo Molnar62932df2006-01-16 16:34:20 +0100479 mutex_lock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100480 ucontrol->value.integer.value[0] = chip->monitoring_active[0];
481 ucontrol->value.integer.value[1] = chip->monitoring_active[1];
Ingo Molnar62932df2006-01-16 16:34:20 +0100482 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100483 return 0;
484}
485
486static int pcxhr_monitor_sw_put(struct snd_kcontrol *kcontrol,
487 struct snd_ctl_elem_value *ucontrol)
488{
489 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
490 int changed = 0;
491 int i;
492
Ingo Molnar62932df2006-01-16 16:34:20 +0100493 mutex_lock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100494 for (i = 0; i < 2; i++) {
Takashi Iwai4e98d6a2007-11-15 15:58:13 +0100495 if (chip->monitoring_active[i] !=
496 ucontrol->value.integer.value[i]) {
497 chip->monitoring_active[i] =
498 !!ucontrol->value.integer.value[i];
Markus Bollingere12229b2005-12-06 13:55:26 +0100499 changed |= (1<<i); /* mask 0x01 and 0x02 */
500 }
501 }
Takashi Iwai4e98d6a2007-11-15 15:58:13 +0100502 if (changed & 0x01)
Markus Bollingere12229b2005-12-06 13:55:26 +0100503 /* update left monitoring volume and mute */
504 pcxhr_update_audio_pipe_level(chip, 0, 0);
Takashi Iwai4e98d6a2007-11-15 15:58:13 +0100505 if (changed & 0x02)
Markus Bollingere12229b2005-12-06 13:55:26 +0100506 /* update right monitoring volume and mute */
507 pcxhr_update_audio_pipe_level(chip, 0, 1);
508
Ingo Molnar62932df2006-01-16 16:34:20 +0100509 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100510 return (changed != 0);
511}
512
513static struct snd_kcontrol_new pcxhr_control_monitor_sw = {
514 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
515 .name = "Monitoring Switch",
516 .info = pcxhr_sw_info, /* shared */
517 .get = pcxhr_monitor_sw_get,
518 .put = pcxhr_monitor_sw_put
519};
520
521
522
523/*
524 * audio source select
525 */
526#define PCXHR_SOURCE_AUDIO01_UER 0x000100
527#define PCXHR_SOURCE_AUDIO01_SYNC 0x000200
528#define PCXHR_SOURCE_AUDIO23_UER 0x000400
529#define PCXHR_SOURCE_AUDIO45_UER 0x001000
530#define PCXHR_SOURCE_AUDIO67_UER 0x040000
531
532static int pcxhr_set_audio_source(struct snd_pcxhr* chip)
533{
534 struct pcxhr_rmh rmh;
535 unsigned int mask, reg;
536 unsigned int codec;
537 int err, use_src, changed;
538
539 switch (chip->chip_idx) {
540 case 0 : mask = PCXHR_SOURCE_AUDIO01_UER; codec = CS8420_01_CS; break;
541 case 1 : mask = PCXHR_SOURCE_AUDIO23_UER; codec = CS8420_23_CS; break;
542 case 2 : mask = PCXHR_SOURCE_AUDIO45_UER; codec = CS8420_45_CS; break;
543 case 3 : mask = PCXHR_SOURCE_AUDIO67_UER; codec = CS8420_67_CS; break;
544 default: return -EINVAL;
545 }
546 reg = 0; /* audio source from analog plug */
547 use_src = 0; /* do not activate codec SRC */
548
549 if (chip->audio_capture_source != 0) {
550 reg = mask; /* audio source from digital plug */
551 if (chip->audio_capture_source == 2)
552 use_src = 1;
553 }
554 /* set the input source */
555 pcxhr_write_io_num_reg_cont(chip->mgr, mask, reg, &changed);
556 /* resync them (otherwise channel inversion possible) */
557 if (changed) {
558 pcxhr_init_rmh(&rmh, CMD_RESYNC_AUDIO_INPUTS);
559 rmh.cmd[0] |= (1 << chip->chip_idx);
560 err = pcxhr_send_msg(chip->mgr, &rmh);
561 if (err)
562 return err;
563 }
564 pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); /* set codec SRC on off */
565 rmh.cmd_len = 3;
566 rmh.cmd[0] |= IO_NUM_UER_CHIP_REG;
567 rmh.cmd[1] = codec;
568 rmh.cmd[2] = (CS8420_DATA_FLOW_CTL & CHIP_SIG_AND_MAP_SPI) | (use_src ? 0x41 : 0x54);
569 err = pcxhr_send_msg(chip->mgr, &rmh);
570 if(err)
571 return err;
572 rmh.cmd[2] = (CS8420_CLOCK_SRC_CTL & CHIP_SIG_AND_MAP_SPI) | (use_src ? 0x41 : 0x49);
573 err = pcxhr_send_msg(chip->mgr, &rmh);
574 return err;
575}
576
577static int pcxhr_audio_src_info(struct snd_kcontrol *kcontrol,
578 struct snd_ctl_elem_info *uinfo)
579{
580 static char *texts[3] = {"Analog", "Digital", "Digi+SRC"};
581
582 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
583 uinfo->count = 1;
584 uinfo->value.enumerated.items = 3;
585 if (uinfo->value.enumerated.item > 2)
586 uinfo->value.enumerated.item = 2;
587 strcpy(uinfo->value.enumerated.name,
588 texts[uinfo->value.enumerated.item]);
589 return 0;
590}
591
592static int pcxhr_audio_src_get(struct snd_kcontrol *kcontrol,
593 struct snd_ctl_elem_value *ucontrol)
594{
595 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
596 ucontrol->value.enumerated.item[0] = chip->audio_capture_source;
597 return 0;
598}
599
600static int pcxhr_audio_src_put(struct snd_kcontrol *kcontrol,
601 struct snd_ctl_elem_value *ucontrol)
602{
603 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
604 int ret = 0;
605
Takashi Iwai4e98d6a2007-11-15 15:58:13 +0100606 if (ucontrol->value.enumerated.item[0] >= 3)
607 return -EINVAL;
Ingo Molnar62932df2006-01-16 16:34:20 +0100608 mutex_lock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100609 if (chip->audio_capture_source != ucontrol->value.enumerated.item[0]) {
610 chip->audio_capture_source = ucontrol->value.enumerated.item[0];
611 pcxhr_set_audio_source(chip);
612 ret = 1;
613 }
Ingo Molnar62932df2006-01-16 16:34:20 +0100614 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100615 return ret;
616}
617
618static struct snd_kcontrol_new pcxhr_control_audio_src = {
619 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
620 .name = "Capture Source",
621 .info = pcxhr_audio_src_info,
622 .get = pcxhr_audio_src_get,
623 .put = pcxhr_audio_src_put,
624};
625
626
627/*
628 * clock type selection
629 * enum pcxhr_clock_type {
630 * PCXHR_CLOCK_TYPE_INTERNAL = 0,
631 * PCXHR_CLOCK_TYPE_WORD_CLOCK,
632 * PCXHR_CLOCK_TYPE_AES_SYNC,
633 * PCXHR_CLOCK_TYPE_AES_1,
634 * PCXHR_CLOCK_TYPE_AES_2,
635 * PCXHR_CLOCK_TYPE_AES_3,
636 * PCXHR_CLOCK_TYPE_AES_4,
637 * };
638 */
639
640static int pcxhr_clock_type_info(struct snd_kcontrol *kcontrol,
641 struct snd_ctl_elem_info *uinfo)
642{
643 static char *texts[7] = {
644 "Internal", "WordClock", "AES Sync", "AES 1", "AES 2", "AES 3", "AES 4"
645 };
646 struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
647 int clock_items = 3 + mgr->capture_chips;
648
649 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
650 uinfo->count = 1;
651 uinfo->value.enumerated.items = clock_items;
652 if (uinfo->value.enumerated.item >= clock_items)
653 uinfo->value.enumerated.item = clock_items-1;
654 strcpy(uinfo->value.enumerated.name,
655 texts[uinfo->value.enumerated.item]);
656 return 0;
657}
658
659static int pcxhr_clock_type_get(struct snd_kcontrol *kcontrol,
660 struct snd_ctl_elem_value *ucontrol)
661{
662 struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
663 ucontrol->value.enumerated.item[0] = mgr->use_clock_type;
664 return 0;
665}
666
667static int pcxhr_clock_type_put(struct snd_kcontrol *kcontrol,
668 struct snd_ctl_elem_value *ucontrol)
669{
670 struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
Takashi Iwai4e98d6a2007-11-15 15:58:13 +0100671 unsigned int clock_items = 3 + mgr->capture_chips;
Markus Bollingere12229b2005-12-06 13:55:26 +0100672 int rate, ret = 0;
673
Takashi Iwai4e98d6a2007-11-15 15:58:13 +0100674 if (ucontrol->value.enumerated.item[0] >= clock_items)
675 return -EINVAL;
Ingo Molnar62932df2006-01-16 16:34:20 +0100676 mutex_lock(&mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100677 if (mgr->use_clock_type != ucontrol->value.enumerated.item[0]) {
Ingo Molnar62932df2006-01-16 16:34:20 +0100678 mutex_lock(&mgr->setup_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100679 mgr->use_clock_type = ucontrol->value.enumerated.item[0];
680 if (mgr->use_clock_type)
681 pcxhr_get_external_clock(mgr, mgr->use_clock_type, &rate);
682 else
683 rate = mgr->sample_rate;
684 if (rate) {
685 pcxhr_set_clock(mgr, rate);
686 if (mgr->sample_rate)
687 mgr->sample_rate = rate;
688 }
Ingo Molnar62932df2006-01-16 16:34:20 +0100689 mutex_unlock(&mgr->setup_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100690 ret = 1; /* return 1 even if the set was not done. ok ? */
691 }
Ingo Molnar62932df2006-01-16 16:34:20 +0100692 mutex_unlock(&mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100693 return ret;
694}
695
696static struct snd_kcontrol_new pcxhr_control_clock_type = {
697 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
698 .name = "Clock Mode",
699 .info = pcxhr_clock_type_info,
700 .get = pcxhr_clock_type_get,
701 .put = pcxhr_clock_type_put,
702};
703
704/*
705 * clock rate control
706 * specific control that scans the sample rates on the external plugs
707 */
708static int pcxhr_clock_rate_info(struct snd_kcontrol *kcontrol,
709 struct snd_ctl_elem_info *uinfo)
710{
711 struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
712 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
713 uinfo->count = 3 + mgr->capture_chips;
714 uinfo->value.integer.min = 0; /* clock not present */
715 uinfo->value.integer.max = 192000; /* max sample rate 192 kHz */
716 return 0;
717}
718
719static int pcxhr_clock_rate_get(struct snd_kcontrol *kcontrol,
720 struct snd_ctl_elem_value *ucontrol)
721{
722 struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
723 int i, err, rate;
724
Ingo Molnar62932df2006-01-16 16:34:20 +0100725 mutex_lock(&mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100726 for(i = 0; i < 3 + mgr->capture_chips; i++) {
727 if (i == PCXHR_CLOCK_TYPE_INTERNAL)
728 rate = mgr->sample_rate_real;
729 else {
730 err = pcxhr_get_external_clock(mgr, i, &rate);
731 if (err)
732 break;
733 }
734 ucontrol->value.integer.value[i] = rate;
735 }
Ingo Molnar62932df2006-01-16 16:34:20 +0100736 mutex_unlock(&mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100737 return 0;
738}
739
740static struct snd_kcontrol_new pcxhr_control_clock_rate = {
741 .access = SNDRV_CTL_ELEM_ACCESS_READ,
742 .iface = SNDRV_CTL_ELEM_IFACE_CARD,
743 .name = "Clock Rates",
744 .info = pcxhr_clock_rate_info,
745 .get = pcxhr_clock_rate_get,
746};
747
748/*
749 * IEC958 status bits
750 */
751static int pcxhr_iec958_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
752{
753 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
754 uinfo->count = 1;
755 return 0;
756}
757
758static int pcxhr_iec958_capture_byte(struct snd_pcxhr *chip, int aes_idx, unsigned char* aes_bits)
759{
760 int i, err;
761 unsigned char temp;
762 struct pcxhr_rmh rmh;
763
764 pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ);
765 rmh.cmd[0] |= IO_NUM_UER_CHIP_REG;
766 switch (chip->chip_idx) {
767 case 0: rmh.cmd[1] = CS8420_01_CS; break; /* use CS8416_01_CS for AES SYNC plug */
768 case 1: rmh.cmd[1] = CS8420_23_CS; break;
769 case 2: rmh.cmd[1] = CS8420_45_CS; break;
770 case 3: rmh.cmd[1] = CS8420_67_CS; break;
771 default: return -EINVAL;
772 }
773 switch (aes_idx) {
774 case 0: rmh.cmd[2] = CS8420_CSB0; break; /* use CS8416_CSBx for AES SYNC plug */
775 case 1: rmh.cmd[2] = CS8420_CSB1; break;
776 case 2: rmh.cmd[2] = CS8420_CSB2; break;
777 case 3: rmh.cmd[2] = CS8420_CSB3; break;
778 case 4: rmh.cmd[2] = CS8420_CSB4; break;
779 default: return -EINVAL;
780 }
781 rmh.cmd[1] &= 0x0fffff; /* size and code the chip id for the fpga */
782 rmh.cmd[2] &= CHIP_SIG_AND_MAP_SPI; /* chip signature + map for spi read */
783 rmh.cmd_len = 3;
784 err = pcxhr_send_msg(chip->mgr, &rmh);
785 if (err)
786 return err;
787 temp = 0;
788 for (i = 0; i < 8; i++) {
789 /* attention : reversed bit order (not with CS8416_01_CS) */
790 temp <<= 1;
791 if (rmh.stat[1] & (1 << i))
792 temp |= 1;
793 }
794 snd_printdd("read iec958 AES %d byte %d = 0x%x\n", chip->chip_idx, aes_idx, temp);
795 *aes_bits = temp;
796 return 0;
797}
798
799static int pcxhr_iec958_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
800{
801 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
802 unsigned char aes_bits;
803 int i, err;
804
Ingo Molnar62932df2006-01-16 16:34:20 +0100805 mutex_lock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100806 for(i = 0; i < 5; i++) {
807 if (kcontrol->private_value == 0) /* playback */
808 aes_bits = chip->aes_bits[i];
809 else { /* capture */
810 err = pcxhr_iec958_capture_byte(chip, i, &aes_bits);
811 if (err)
812 break;
813 }
814 ucontrol->value.iec958.status[i] = aes_bits;
815 }
Ingo Molnar62932df2006-01-16 16:34:20 +0100816 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100817 return 0;
818}
819
820static int pcxhr_iec958_mask_get(struct snd_kcontrol *kcontrol,
821 struct snd_ctl_elem_value *ucontrol)
822{
823 int i;
824 for (i = 0; i < 5; i++)
825 ucontrol->value.iec958.status[i] = 0xff;
826 return 0;
827}
828
829static int pcxhr_iec958_update_byte(struct snd_pcxhr *chip, int aes_idx, unsigned char aes_bits)
830{
831 int i, err, cmd;
832 unsigned char new_bits = aes_bits;
833 unsigned char old_bits = chip->aes_bits[aes_idx];
834 struct pcxhr_rmh rmh;
835
836 for (i = 0; i < 8; i++) {
837 if ((old_bits & 0x01) != (new_bits & 0x01)) {
838 cmd = chip->chip_idx & 0x03; /* chip index 0..3 */
839 if(chip->chip_idx > 3)
840 /* new bit used if chip_idx>3 (PCX1222HR) */
841 cmd |= 1 << 22;
842 cmd |= ((aes_idx << 3) + i) << 2; /* add bit offset */
843 cmd |= (new_bits & 0x01) << 23; /* add bit value */
844 pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
845 rmh.cmd[0] |= IO_NUM_REG_CUER;
846 rmh.cmd[1] = cmd;
847 rmh.cmd_len = 2;
848 snd_printdd("write iec958 AES %d byte %d bit %d (cmd %x)\n",
849 chip->chip_idx, aes_idx, i, cmd);
850 err = pcxhr_send_msg(chip->mgr, &rmh);
851 if (err)
852 return err;
853 }
854 old_bits >>= 1;
855 new_bits >>= 1;
856 }
857 chip->aes_bits[aes_idx] = aes_bits;
858 return 0;
859}
860
861static int pcxhr_iec958_put(struct snd_kcontrol *kcontrol,
862 struct snd_ctl_elem_value *ucontrol)
863{
864 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
865 int i, changed = 0;
866
867 /* playback */
Ingo Molnar62932df2006-01-16 16:34:20 +0100868 mutex_lock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100869 for (i = 0; i < 5; i++) {
870 if (ucontrol->value.iec958.status[i] != chip->aes_bits[i]) {
871 pcxhr_iec958_update_byte(chip, i, ucontrol->value.iec958.status[i]);
872 changed = 1;
873 }
874 }
Ingo Molnar62932df2006-01-16 16:34:20 +0100875 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100876 return changed;
877}
878
879static struct snd_kcontrol_new pcxhr_control_playback_iec958_mask = {
880 .access = SNDRV_CTL_ELEM_ACCESS_READ,
881 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
882 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
883 .info = pcxhr_iec958_info,
884 .get = pcxhr_iec958_mask_get
885};
886static struct snd_kcontrol_new pcxhr_control_playback_iec958 = {
887 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
888 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
889 .info = pcxhr_iec958_info,
890 .get = pcxhr_iec958_get,
891 .put = pcxhr_iec958_put,
892 .private_value = 0 /* playback */
893};
894
895static struct snd_kcontrol_new pcxhr_control_capture_iec958_mask = {
896 .access = SNDRV_CTL_ELEM_ACCESS_READ,
897 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
898 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK),
899 .info = pcxhr_iec958_info,
900 .get = pcxhr_iec958_mask_get
901};
902static struct snd_kcontrol_new pcxhr_control_capture_iec958 = {
903 .access = SNDRV_CTL_ELEM_ACCESS_READ,
904 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
905 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
906 .info = pcxhr_iec958_info,
907 .get = pcxhr_iec958_get,
908 .private_value = 1 /* capture */
909};
910
911static void pcxhr_init_audio_levels(struct snd_pcxhr *chip)
912{
913 int i;
914
915 for (i = 0; i < 2; i++) {
916 if (chip->nb_streams_play) {
917 int j;
918 /* at boot time the digital volumes are unmuted 0dB */
919 for (j = 0; j < PCXHR_PLAYBACK_STREAMS; j++) {
920 chip->digital_playback_active[j][i] = 1;
921 chip->digital_playback_volume[j][i] = PCXHR_DIGITAL_ZERO_LEVEL;
922 }
923 /* after boot, only two bits are set on the uer interface */
924 chip->aes_bits[0] = IEC958_AES0_PROFESSIONAL | IEC958_AES0_PRO_FS_48000;
925/* only for test purpose, remove later */
926#ifdef CONFIG_SND_DEBUG
927 /* analog volumes for playback (is LEVEL_MIN after boot) */
928 chip->analog_playback_active[i] = 1;
929 chip->analog_playback_volume[i] = PCXHR_ANALOG_PLAYBACK_ZERO_LEVEL;
930 pcxhr_update_analog_audio_level(chip, 0, i);
931#endif
932/* test end */
933 }
934 if (chip->nb_streams_capt) {
935 /* at boot time the digital volumes are unmuted 0dB */
936 chip->digital_capture_volume[i] = PCXHR_DIGITAL_ZERO_LEVEL;
937/* only for test purpose, remove later */
938#ifdef CONFIG_SND_DEBUG
939 /* analog volumes for playback (is LEVEL_MIN after boot) */
940 chip->analog_capture_volume[i] = PCXHR_ANALOG_CAPTURE_ZERO_LEVEL;
941 pcxhr_update_analog_audio_level(chip, 1, i);
942#endif
943/* test end */
944 }
945 }
946
947 return;
948}
949
950
951int pcxhr_create_mixer(struct pcxhr_mgr *mgr)
952{
953 struct snd_pcxhr *chip;
954 int err, i;
955
Ingo Molnar62932df2006-01-16 16:34:20 +0100956 mutex_init(&mgr->mixer_mutex); /* can be in another place */
Markus Bollingere12229b2005-12-06 13:55:26 +0100957
958 for (i = 0; i < mgr->num_cards; i++) {
959 struct snd_kcontrol_new temp;
960 chip = mgr->chip[i];
961
962 if (chip->nb_streams_play) {
963 /* analog output level control */
964 temp = pcxhr_control_analog_level;
965 temp.name = "Master Playback Volume";
966 temp.private_value = 0; /* playback */
Takashi Iwaic6ff77f2006-08-23 19:53:02 +0200967 temp.tlv.p = db_scale_analog_playback;
Markus Bollingere12229b2005-12-06 13:55:26 +0100968 if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
969 return err;
970 /* output mute controls */
971 if ((err = snd_ctl_add(chip->card,
972 snd_ctl_new1(&pcxhr_control_output_switch,
973 chip))) < 0)
974 return err;
975
976 temp = snd_pcxhr_pcm_vol;
977 temp.name = "PCM Playback Volume";
978 temp.count = PCXHR_PLAYBACK_STREAMS;
979 temp.private_value = 0; /* playback */
980 if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
981 return err;
982
983 if ((err = snd_ctl_add(chip->card,
984 snd_ctl_new1(&pcxhr_control_pcm_switch,
985 chip))) < 0)
986 return err;
987
988 /* IEC958 controls */
989 if ((err = snd_ctl_add(chip->card,
990 snd_ctl_new1(&pcxhr_control_playback_iec958_mask,
991 chip))) < 0)
992 return err;
993 if ((err = snd_ctl_add(chip->card,
994 snd_ctl_new1(&pcxhr_control_playback_iec958,
995 chip))) < 0)
996 return err;
997 }
998 if (chip->nb_streams_capt) {
999 /* analog input level control only on first two chips !*/
1000 temp = pcxhr_control_analog_level;
1001 temp.name = "Master Capture Volume";
1002 temp.private_value = 1; /* capture */
Takashi Iwaic6ff77f2006-08-23 19:53:02 +02001003 temp.tlv.p = db_scale_analog_capture;
Markus Bollingere12229b2005-12-06 13:55:26 +01001004 if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
1005 return err;
1006
1007 temp = snd_pcxhr_pcm_vol;
1008 temp.name = "PCM Capture Volume";
1009 temp.count = 1;
1010 temp.private_value = 1; /* capture */
1011 if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
1012 return err;
1013 /* Audio source */
1014 if ((err = snd_ctl_add(chip->card,
1015 snd_ctl_new1(&pcxhr_control_audio_src,
1016 chip))) < 0)
1017 return err;
1018 /* IEC958 controls */
1019 if ((err = snd_ctl_add(chip->card,
1020 snd_ctl_new1(&pcxhr_control_capture_iec958_mask,
1021 chip))) < 0)
1022 return err;
1023 if ((err = snd_ctl_add(chip->card,
1024 snd_ctl_new1(&pcxhr_control_capture_iec958,
1025 chip))) < 0)
1026 return err;
1027 }
1028 /* monitoring only if playback and capture device available */
1029 if (chip->nb_streams_capt > 0 && chip->nb_streams_play > 0) {
1030 /* monitoring */
1031 if ((err = snd_ctl_add(chip->card,
1032 snd_ctl_new1(&pcxhr_control_monitor_vol,
1033 chip))) < 0)
1034 return err;
1035 if ((err = snd_ctl_add(chip->card,
1036 snd_ctl_new1(&pcxhr_control_monitor_sw,
1037 chip))) < 0)
1038 return err;
1039 }
1040
1041 if (i == 0) {
1042 /* clock mode only one control per pcxhr */
1043 if ((err = snd_ctl_add(chip->card,
1044 snd_ctl_new1(&pcxhr_control_clock_type,
1045 mgr))) < 0)
1046 return err;
1047 /* non standard control used to scan the external clock presence/frequencies */
1048 if ((err = snd_ctl_add(chip->card,
1049 snd_ctl_new1(&pcxhr_control_clock_rate,
1050 mgr))) < 0)
1051 return err;
1052 }
1053
1054 /* init values for the mixer data */
1055 pcxhr_init_audio_levels(chip);
1056 }
1057
1058 return 0;
1059}