blob: 5f8d42633b040b92a88b173df5ad4222d2bdcd43 [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];
123 int* stored_volume = is_capture ? &chip->analog_capture_volume[i] :
124 &chip->analog_playback_volume[i];
125 if (*stored_volume != new_volume) {
126 *stored_volume = new_volume;
127 changed = 1;
128 pcxhr_update_analog_audio_level(chip, is_capture, i);
129 }
130 }
Ingo Molnar62932df2006-01-16 16:34:20 +0100131 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100132 return changed;
133}
134
135static struct snd_kcontrol_new pcxhr_control_analog_level = {
136 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
Takashi Iwaic6ff77f2006-08-23 19:53:02 +0200137 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
138 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
Markus Bollingere12229b2005-12-06 13:55:26 +0100139 /* name will be filled later */
140 .info = pcxhr_analog_vol_info,
141 .get = pcxhr_analog_vol_get,
142 .put = pcxhr_analog_vol_put,
Takashi Iwaic6ff77f2006-08-23 19:53:02 +0200143 /* tlv will be filled later */
Markus Bollingere12229b2005-12-06 13:55:26 +0100144};
145
146/* shared */
Takashi Iwaia5ce8892007-07-23 15:42:26 +0200147#define pcxhr_sw_info snd_ctl_boolean_stereo_info
Markus Bollingere12229b2005-12-06 13:55:26 +0100148
149static int pcxhr_audio_sw_get(struct snd_kcontrol *kcontrol,
150 struct snd_ctl_elem_value *ucontrol)
151{
152 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
153
Ingo Molnar62932df2006-01-16 16:34:20 +0100154 mutex_lock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100155 ucontrol->value.integer.value[0] = chip->analog_playback_active[0];
156 ucontrol->value.integer.value[1] = chip->analog_playback_active[1];
Ingo Molnar62932df2006-01-16 16:34:20 +0100157 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100158 return 0;
159}
160
161static int pcxhr_audio_sw_put(struct snd_kcontrol *kcontrol,
162 struct snd_ctl_elem_value *ucontrol)
163{
164 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
165 int i, changed = 0;
Ingo Molnar62932df2006-01-16 16:34:20 +0100166 mutex_lock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100167 for(i = 0; i < 2; i++) {
168 if (chip->analog_playback_active[i] != ucontrol->value.integer.value[i]) {
169 chip->analog_playback_active[i] = ucontrol->value.integer.value[i];
170 changed = 1;
171 pcxhr_update_analog_audio_level(chip, 0, i); /* update playback levels */
172 }
173 }
Ingo Molnar62932df2006-01-16 16:34:20 +0100174 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100175 return changed;
176}
177
178static struct snd_kcontrol_new pcxhr_control_output_switch = {
179 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
180 .name = "Master Playback Switch",
181 .info = pcxhr_sw_info, /* shared */
182 .get = pcxhr_audio_sw_get,
183 .put = pcxhr_audio_sw_put
184};
185
186
187#define PCXHR_DIGITAL_LEVEL_MIN 0x000 /* -110 dB */
188#define PCXHR_DIGITAL_LEVEL_MAX 0x1ff /* +18 dB */
189#define PCXHR_DIGITAL_ZERO_LEVEL 0x1b7 /* 0 dB */
190
Takashi Iwaie6382cf2007-10-10 10:06:46 +0200191static const DECLARE_TLV_DB_SCALE(db_scale_digital, -10975, 25, 1800);
Markus Bollingere12229b2005-12-06 13:55:26 +0100192
193#define MORE_THAN_ONE_STREAM_LEVEL 0x000001
194#define VALID_STREAM_PAN_LEVEL_MASK 0x800000
195#define VALID_STREAM_LEVEL_MASK 0x400000
196#define VALID_STREAM_LEVEL_1_MASK 0x200000
197#define VALID_STREAM_LEVEL_2_MASK 0x100000
198
199static int pcxhr_update_playback_stream_level(struct snd_pcxhr* chip, int idx)
200{
201 int err;
202 struct pcxhr_rmh rmh;
203 struct pcxhr_pipe *pipe = &chip->playback_pipe;
204 int left, right;
205
206 if (chip->digital_playback_active[idx][0])
207 left = chip->digital_playback_volume[idx][0];
208 else
209 left = PCXHR_DIGITAL_LEVEL_MIN;
210 if (chip->digital_playback_active[idx][1])
211 right = chip->digital_playback_volume[idx][1];
212 else
213 right = PCXHR_DIGITAL_LEVEL_MIN;
214
215 pcxhr_init_rmh(&rmh, CMD_STREAM_OUT_LEVEL_ADJUST);
216 /* add pipe and stream mask */
217 pcxhr_set_pipe_cmd_params(&rmh, 0, pipe->first_audio, 0, 1<<idx);
218 /* volume left->left / right->right panoramic level */
219 rmh.cmd[0] |= MORE_THAN_ONE_STREAM_LEVEL;
220 rmh.cmd[2] = VALID_STREAM_PAN_LEVEL_MASK | VALID_STREAM_LEVEL_1_MASK;
221 rmh.cmd[2] |= (left << 10);
222 rmh.cmd[3] = VALID_STREAM_PAN_LEVEL_MASK | VALID_STREAM_LEVEL_2_MASK;
223 rmh.cmd[3] |= right;
224 rmh.cmd_len = 4;
225
226 err = pcxhr_send_msg(chip->mgr, &rmh);
227 if (err < 0) {
228 snd_printk(KERN_DEBUG "error update_playback_stream_level "
229 "card(%d) err(%x)\n", chip->chip_idx, err);
230 return -EINVAL;
231 }
232 return 0;
233}
234
235#define AUDIO_IO_HAS_MUTE_LEVEL 0x400000
236#define AUDIO_IO_HAS_MUTE_MONITOR_1 0x200000
237#define VALID_AUDIO_IO_DIGITAL_LEVEL 0x000001
238#define VALID_AUDIO_IO_MONITOR_LEVEL 0x000002
239#define VALID_AUDIO_IO_MUTE_LEVEL 0x000004
240#define VALID_AUDIO_IO_MUTE_MONITOR_1 0x000008
241
242static int pcxhr_update_audio_pipe_level(struct snd_pcxhr* chip, int capture, int channel)
243{
244 int err;
245 struct pcxhr_rmh rmh;
246 struct pcxhr_pipe *pipe;
247
248 if (capture)
249 pipe = &chip->capture_pipe[0];
250 else
251 pipe = &chip->playback_pipe;
252
253 pcxhr_init_rmh(&rmh, CMD_AUDIO_LEVEL_ADJUST);
254 /* add channel mask */
255 pcxhr_set_pipe_cmd_params(&rmh, capture, 0, 0, 1 << (channel + pipe->first_audio));
256 /* TODO : if mask (3 << pipe->first_audio) is used, left and right channel
257 * will be programmed to the same params
258 */
259 if (capture) {
260 rmh.cmd[0] |= VALID_AUDIO_IO_DIGITAL_LEVEL;
261 /* VALID_AUDIO_IO_MUTE_LEVEL not yet handled (capture pipe level) */
262 rmh.cmd[2] = chip->digital_capture_volume[channel];
263 } else {
264 rmh.cmd[0] |= VALID_AUDIO_IO_MONITOR_LEVEL | VALID_AUDIO_IO_MUTE_MONITOR_1;
265 /* VALID_AUDIO_IO_DIGITAL_LEVEL and VALID_AUDIO_IO_MUTE_LEVEL not yet
266 * handled (playback pipe level)
267 */
268 rmh.cmd[2] = chip->monitoring_volume[channel] << 10;
269 if (chip->monitoring_active[channel] == 0)
270 rmh.cmd[2] |= AUDIO_IO_HAS_MUTE_MONITOR_1;
271 }
272 rmh.cmd_len = 3;
273
274 err = pcxhr_send_msg(chip->mgr, &rmh);
275 if(err<0) {
276 snd_printk(KERN_DEBUG "error update_audio_level card(%d) err(%x)\n",
277 chip->chip_idx, err);
278 return -EINVAL;
279 }
280 return 0;
281}
282
283
284/* shared */
285static int pcxhr_digital_vol_info(struct snd_kcontrol *kcontrol,
286 struct snd_ctl_elem_info *uinfo)
287{
288 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
289 uinfo->count = 2;
290 uinfo->value.integer.min = PCXHR_DIGITAL_LEVEL_MIN; /* -109.5 dB */
291 uinfo->value.integer.max = PCXHR_DIGITAL_LEVEL_MAX; /* 18.0 dB */
292 return 0;
293}
294
295
296static int pcxhr_pcm_vol_get(struct snd_kcontrol *kcontrol,
297 struct snd_ctl_elem_value *ucontrol)
298{
299 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
300 int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
301 int *stored_volume;
302 int is_capture = kcontrol->private_value;
303
Ingo Molnar62932df2006-01-16 16:34:20 +0100304 mutex_lock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100305 if (is_capture)
306 stored_volume = chip->digital_capture_volume; /* digital capture */
307 else
308 stored_volume = chip->digital_playback_volume[idx]; /* digital playback */
309 ucontrol->value.integer.value[0] = stored_volume[0];
310 ucontrol->value.integer.value[1] = stored_volume[1];
Ingo Molnar62932df2006-01-16 16:34:20 +0100311 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100312 return 0;
313}
314
315static int pcxhr_pcm_vol_put(struct snd_kcontrol *kcontrol,
316 struct snd_ctl_elem_value *ucontrol)
317{
318 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
319 int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
320 int changed = 0;
321 int is_capture = kcontrol->private_value;
322 int *stored_volume;
323 int i;
324
Ingo Molnar62932df2006-01-16 16:34:20 +0100325 mutex_lock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100326 if (is_capture)
327 stored_volume = chip->digital_capture_volume; /* digital capture */
328 else
329 stored_volume = chip->digital_playback_volume[idx]; /* digital playback */
330 for (i = 0; i < 2; i++) {
331 if (stored_volume[i] != ucontrol->value.integer.value[i]) {
332 stored_volume[i] = ucontrol->value.integer.value[i];
333 changed = 1;
334 if (is_capture) /* update capture volume */
335 pcxhr_update_audio_pipe_level(chip, 1, i);
336 }
337 }
338 if (! is_capture && changed)
339 pcxhr_update_playback_stream_level(chip, idx); /* update playback volume */
Ingo Molnar62932df2006-01-16 16:34:20 +0100340 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100341 return changed;
342}
343
344static struct snd_kcontrol_new snd_pcxhr_pcm_vol =
345{
346 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
Takashi Iwaic6ff77f2006-08-23 19:53:02 +0200347 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
348 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
Markus Bollingere12229b2005-12-06 13:55:26 +0100349 /* name will be filled later */
350 /* count will be filled later */
351 .info = pcxhr_digital_vol_info, /* shared */
352 .get = pcxhr_pcm_vol_get,
353 .put = pcxhr_pcm_vol_put,
Takashi Iwaic6ff77f2006-08-23 19:53:02 +0200354 .tlv = { .p = db_scale_digital },
Markus Bollingere12229b2005-12-06 13:55:26 +0100355};
356
357
358static int pcxhr_pcm_sw_get(struct snd_kcontrol *kcontrol,
359 struct snd_ctl_elem_value *ucontrol)
360{
361 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
362 int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
363
Ingo Molnar62932df2006-01-16 16:34:20 +0100364 mutex_lock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100365 ucontrol->value.integer.value[0] = chip->digital_playback_active[idx][0];
366 ucontrol->value.integer.value[1] = chip->digital_playback_active[idx][1];
Ingo Molnar62932df2006-01-16 16:34:20 +0100367 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100368 return 0;
369}
370
371static int pcxhr_pcm_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
372{
373 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
374 int changed = 0;
375 int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
376 int i, j;
377
Ingo Molnar62932df2006-01-16 16:34:20 +0100378 mutex_lock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100379 j = idx;
380 for (i = 0; i < 2; i++) {
381 if (chip->digital_playback_active[j][i] != ucontrol->value.integer.value[i]) {
382 chip->digital_playback_active[j][i] = ucontrol->value.integer.value[i];
383 changed = 1;
384 }
385 }
386 if (changed)
387 pcxhr_update_playback_stream_level(chip, idx);
Ingo Molnar62932df2006-01-16 16:34:20 +0100388 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100389 return changed;
390}
391
392static struct snd_kcontrol_new pcxhr_control_pcm_switch = {
393 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
394 .name = "PCM Playback Switch",
395 .count = PCXHR_PLAYBACK_STREAMS,
396 .info = pcxhr_sw_info, /* shared */
397 .get = pcxhr_pcm_sw_get,
398 .put = pcxhr_pcm_sw_put
399};
400
401
402/*
403 * monitoring level control
404 */
405
406static int pcxhr_monitor_vol_get(struct snd_kcontrol *kcontrol,
407 struct snd_ctl_elem_value *ucontrol)
408{
409 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
Ingo Molnar62932df2006-01-16 16:34:20 +0100410 mutex_lock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100411 ucontrol->value.integer.value[0] = chip->monitoring_volume[0];
412 ucontrol->value.integer.value[1] = chip->monitoring_volume[1];
Ingo Molnar62932df2006-01-16 16:34:20 +0100413 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100414 return 0;
415}
416
417static int pcxhr_monitor_vol_put(struct snd_kcontrol *kcontrol,
418 struct snd_ctl_elem_value *ucontrol)
419{
420 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
421 int changed = 0;
422 int i;
423
Ingo Molnar62932df2006-01-16 16:34:20 +0100424 mutex_lock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100425 for (i = 0; i < 2; i++) {
426 if (chip->monitoring_volume[i] != ucontrol->value.integer.value[i]) {
427 chip->monitoring_volume[i] = ucontrol->value.integer.value[i];
428 if(chip->monitoring_active[i]) /* do only when monitoring is unmuted */
429 /* update monitoring volume and mute */
430 pcxhr_update_audio_pipe_level(chip, 0, i);
431 changed = 1;
432 }
433 }
Ingo Molnar62932df2006-01-16 16:34:20 +0100434 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100435 return changed;
436}
437
438static struct snd_kcontrol_new pcxhr_control_monitor_vol = {
439 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
Takashi Iwaic6ff77f2006-08-23 19:53:02 +0200440 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
441 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
Markus Bollingere12229b2005-12-06 13:55:26 +0100442 .name = "Monitoring Volume",
443 .info = pcxhr_digital_vol_info, /* shared */
444 .get = pcxhr_monitor_vol_get,
445 .put = pcxhr_monitor_vol_put,
Takashi Iwaic6ff77f2006-08-23 19:53:02 +0200446 .tlv = { .p = db_scale_digital },
Markus Bollingere12229b2005-12-06 13:55:26 +0100447};
448
449/*
450 * monitoring switch control
451 */
452
453static int pcxhr_monitor_sw_get(struct snd_kcontrol *kcontrol,
454 struct snd_ctl_elem_value *ucontrol)
455{
456 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
Ingo Molnar62932df2006-01-16 16:34:20 +0100457 mutex_lock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100458 ucontrol->value.integer.value[0] = chip->monitoring_active[0];
459 ucontrol->value.integer.value[1] = chip->monitoring_active[1];
Ingo Molnar62932df2006-01-16 16:34:20 +0100460 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100461 return 0;
462}
463
464static int pcxhr_monitor_sw_put(struct snd_kcontrol *kcontrol,
465 struct snd_ctl_elem_value *ucontrol)
466{
467 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
468 int changed = 0;
469 int i;
470
Ingo Molnar62932df2006-01-16 16:34:20 +0100471 mutex_lock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100472 for (i = 0; i < 2; i++) {
473 if (chip->monitoring_active[i] != ucontrol->value.integer.value[i]) {
474 chip->monitoring_active[i] = ucontrol->value.integer.value[i];
475 changed |= (1<<i); /* mask 0x01 and 0x02 */
476 }
477 }
478 if(changed & 0x01)
479 /* update left monitoring volume and mute */
480 pcxhr_update_audio_pipe_level(chip, 0, 0);
481 if(changed & 0x02)
482 /* update right monitoring volume and mute */
483 pcxhr_update_audio_pipe_level(chip, 0, 1);
484
Ingo Molnar62932df2006-01-16 16:34:20 +0100485 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100486 return (changed != 0);
487}
488
489static struct snd_kcontrol_new pcxhr_control_monitor_sw = {
490 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
491 .name = "Monitoring Switch",
492 .info = pcxhr_sw_info, /* shared */
493 .get = pcxhr_monitor_sw_get,
494 .put = pcxhr_monitor_sw_put
495};
496
497
498
499/*
500 * audio source select
501 */
502#define PCXHR_SOURCE_AUDIO01_UER 0x000100
503#define PCXHR_SOURCE_AUDIO01_SYNC 0x000200
504#define PCXHR_SOURCE_AUDIO23_UER 0x000400
505#define PCXHR_SOURCE_AUDIO45_UER 0x001000
506#define PCXHR_SOURCE_AUDIO67_UER 0x040000
507
508static int pcxhr_set_audio_source(struct snd_pcxhr* chip)
509{
510 struct pcxhr_rmh rmh;
511 unsigned int mask, reg;
512 unsigned int codec;
513 int err, use_src, changed;
514
515 switch (chip->chip_idx) {
516 case 0 : mask = PCXHR_SOURCE_AUDIO01_UER; codec = CS8420_01_CS; break;
517 case 1 : mask = PCXHR_SOURCE_AUDIO23_UER; codec = CS8420_23_CS; break;
518 case 2 : mask = PCXHR_SOURCE_AUDIO45_UER; codec = CS8420_45_CS; break;
519 case 3 : mask = PCXHR_SOURCE_AUDIO67_UER; codec = CS8420_67_CS; break;
520 default: return -EINVAL;
521 }
522 reg = 0; /* audio source from analog plug */
523 use_src = 0; /* do not activate codec SRC */
524
525 if (chip->audio_capture_source != 0) {
526 reg = mask; /* audio source from digital plug */
527 if (chip->audio_capture_source == 2)
528 use_src = 1;
529 }
530 /* set the input source */
531 pcxhr_write_io_num_reg_cont(chip->mgr, mask, reg, &changed);
532 /* resync them (otherwise channel inversion possible) */
533 if (changed) {
534 pcxhr_init_rmh(&rmh, CMD_RESYNC_AUDIO_INPUTS);
535 rmh.cmd[0] |= (1 << chip->chip_idx);
536 err = pcxhr_send_msg(chip->mgr, &rmh);
537 if (err)
538 return err;
539 }
540 pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); /* set codec SRC on off */
541 rmh.cmd_len = 3;
542 rmh.cmd[0] |= IO_NUM_UER_CHIP_REG;
543 rmh.cmd[1] = codec;
544 rmh.cmd[2] = (CS8420_DATA_FLOW_CTL & CHIP_SIG_AND_MAP_SPI) | (use_src ? 0x41 : 0x54);
545 err = pcxhr_send_msg(chip->mgr, &rmh);
546 if(err)
547 return err;
548 rmh.cmd[2] = (CS8420_CLOCK_SRC_CTL & CHIP_SIG_AND_MAP_SPI) | (use_src ? 0x41 : 0x49);
549 err = pcxhr_send_msg(chip->mgr, &rmh);
550 return err;
551}
552
553static int pcxhr_audio_src_info(struct snd_kcontrol *kcontrol,
554 struct snd_ctl_elem_info *uinfo)
555{
556 static char *texts[3] = {"Analog", "Digital", "Digi+SRC"};
557
558 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
559 uinfo->count = 1;
560 uinfo->value.enumerated.items = 3;
561 if (uinfo->value.enumerated.item > 2)
562 uinfo->value.enumerated.item = 2;
563 strcpy(uinfo->value.enumerated.name,
564 texts[uinfo->value.enumerated.item]);
565 return 0;
566}
567
568static int pcxhr_audio_src_get(struct snd_kcontrol *kcontrol,
569 struct snd_ctl_elem_value *ucontrol)
570{
571 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
572 ucontrol->value.enumerated.item[0] = chip->audio_capture_source;
573 return 0;
574}
575
576static int pcxhr_audio_src_put(struct snd_kcontrol *kcontrol,
577 struct snd_ctl_elem_value *ucontrol)
578{
579 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
580 int ret = 0;
581
Ingo Molnar62932df2006-01-16 16:34:20 +0100582 mutex_lock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100583 if (chip->audio_capture_source != ucontrol->value.enumerated.item[0]) {
584 chip->audio_capture_source = ucontrol->value.enumerated.item[0];
585 pcxhr_set_audio_source(chip);
586 ret = 1;
587 }
Ingo Molnar62932df2006-01-16 16:34:20 +0100588 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100589 return ret;
590}
591
592static struct snd_kcontrol_new pcxhr_control_audio_src = {
593 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
594 .name = "Capture Source",
595 .info = pcxhr_audio_src_info,
596 .get = pcxhr_audio_src_get,
597 .put = pcxhr_audio_src_put,
598};
599
600
601/*
602 * clock type selection
603 * enum pcxhr_clock_type {
604 * PCXHR_CLOCK_TYPE_INTERNAL = 0,
605 * PCXHR_CLOCK_TYPE_WORD_CLOCK,
606 * PCXHR_CLOCK_TYPE_AES_SYNC,
607 * PCXHR_CLOCK_TYPE_AES_1,
608 * PCXHR_CLOCK_TYPE_AES_2,
609 * PCXHR_CLOCK_TYPE_AES_3,
610 * PCXHR_CLOCK_TYPE_AES_4,
611 * };
612 */
613
614static int pcxhr_clock_type_info(struct snd_kcontrol *kcontrol,
615 struct snd_ctl_elem_info *uinfo)
616{
617 static char *texts[7] = {
618 "Internal", "WordClock", "AES Sync", "AES 1", "AES 2", "AES 3", "AES 4"
619 };
620 struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
621 int clock_items = 3 + mgr->capture_chips;
622
623 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
624 uinfo->count = 1;
625 uinfo->value.enumerated.items = clock_items;
626 if (uinfo->value.enumerated.item >= clock_items)
627 uinfo->value.enumerated.item = clock_items-1;
628 strcpy(uinfo->value.enumerated.name,
629 texts[uinfo->value.enumerated.item]);
630 return 0;
631}
632
633static int pcxhr_clock_type_get(struct snd_kcontrol *kcontrol,
634 struct snd_ctl_elem_value *ucontrol)
635{
636 struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
637 ucontrol->value.enumerated.item[0] = mgr->use_clock_type;
638 return 0;
639}
640
641static int pcxhr_clock_type_put(struct snd_kcontrol *kcontrol,
642 struct snd_ctl_elem_value *ucontrol)
643{
644 struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
645 int rate, ret = 0;
646
Ingo Molnar62932df2006-01-16 16:34:20 +0100647 mutex_lock(&mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100648 if (mgr->use_clock_type != ucontrol->value.enumerated.item[0]) {
Ingo Molnar62932df2006-01-16 16:34:20 +0100649 mutex_lock(&mgr->setup_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100650 mgr->use_clock_type = ucontrol->value.enumerated.item[0];
651 if (mgr->use_clock_type)
652 pcxhr_get_external_clock(mgr, mgr->use_clock_type, &rate);
653 else
654 rate = mgr->sample_rate;
655 if (rate) {
656 pcxhr_set_clock(mgr, rate);
657 if (mgr->sample_rate)
658 mgr->sample_rate = rate;
659 }
Ingo Molnar62932df2006-01-16 16:34:20 +0100660 mutex_unlock(&mgr->setup_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100661 ret = 1; /* return 1 even if the set was not done. ok ? */
662 }
Ingo Molnar62932df2006-01-16 16:34:20 +0100663 mutex_unlock(&mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100664 return ret;
665}
666
667static struct snd_kcontrol_new pcxhr_control_clock_type = {
668 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
669 .name = "Clock Mode",
670 .info = pcxhr_clock_type_info,
671 .get = pcxhr_clock_type_get,
672 .put = pcxhr_clock_type_put,
673};
674
675/*
676 * clock rate control
677 * specific control that scans the sample rates on the external plugs
678 */
679static int pcxhr_clock_rate_info(struct snd_kcontrol *kcontrol,
680 struct snd_ctl_elem_info *uinfo)
681{
682 struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
683 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
684 uinfo->count = 3 + mgr->capture_chips;
685 uinfo->value.integer.min = 0; /* clock not present */
686 uinfo->value.integer.max = 192000; /* max sample rate 192 kHz */
687 return 0;
688}
689
690static int pcxhr_clock_rate_get(struct snd_kcontrol *kcontrol,
691 struct snd_ctl_elem_value *ucontrol)
692{
693 struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
694 int i, err, rate;
695
Ingo Molnar62932df2006-01-16 16:34:20 +0100696 mutex_lock(&mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100697 for(i = 0; i < 3 + mgr->capture_chips; i++) {
698 if (i == PCXHR_CLOCK_TYPE_INTERNAL)
699 rate = mgr->sample_rate_real;
700 else {
701 err = pcxhr_get_external_clock(mgr, i, &rate);
702 if (err)
703 break;
704 }
705 ucontrol->value.integer.value[i] = rate;
706 }
Ingo Molnar62932df2006-01-16 16:34:20 +0100707 mutex_unlock(&mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100708 return 0;
709}
710
711static struct snd_kcontrol_new pcxhr_control_clock_rate = {
712 .access = SNDRV_CTL_ELEM_ACCESS_READ,
713 .iface = SNDRV_CTL_ELEM_IFACE_CARD,
714 .name = "Clock Rates",
715 .info = pcxhr_clock_rate_info,
716 .get = pcxhr_clock_rate_get,
717};
718
719/*
720 * IEC958 status bits
721 */
722static int pcxhr_iec958_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
723{
724 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
725 uinfo->count = 1;
726 return 0;
727}
728
729static int pcxhr_iec958_capture_byte(struct snd_pcxhr *chip, int aes_idx, unsigned char* aes_bits)
730{
731 int i, err;
732 unsigned char temp;
733 struct pcxhr_rmh rmh;
734
735 pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ);
736 rmh.cmd[0] |= IO_NUM_UER_CHIP_REG;
737 switch (chip->chip_idx) {
738 case 0: rmh.cmd[1] = CS8420_01_CS; break; /* use CS8416_01_CS for AES SYNC plug */
739 case 1: rmh.cmd[1] = CS8420_23_CS; break;
740 case 2: rmh.cmd[1] = CS8420_45_CS; break;
741 case 3: rmh.cmd[1] = CS8420_67_CS; break;
742 default: return -EINVAL;
743 }
744 switch (aes_idx) {
745 case 0: rmh.cmd[2] = CS8420_CSB0; break; /* use CS8416_CSBx for AES SYNC plug */
746 case 1: rmh.cmd[2] = CS8420_CSB1; break;
747 case 2: rmh.cmd[2] = CS8420_CSB2; break;
748 case 3: rmh.cmd[2] = CS8420_CSB3; break;
749 case 4: rmh.cmd[2] = CS8420_CSB4; break;
750 default: return -EINVAL;
751 }
752 rmh.cmd[1] &= 0x0fffff; /* size and code the chip id for the fpga */
753 rmh.cmd[2] &= CHIP_SIG_AND_MAP_SPI; /* chip signature + map for spi read */
754 rmh.cmd_len = 3;
755 err = pcxhr_send_msg(chip->mgr, &rmh);
756 if (err)
757 return err;
758 temp = 0;
759 for (i = 0; i < 8; i++) {
760 /* attention : reversed bit order (not with CS8416_01_CS) */
761 temp <<= 1;
762 if (rmh.stat[1] & (1 << i))
763 temp |= 1;
764 }
765 snd_printdd("read iec958 AES %d byte %d = 0x%x\n", chip->chip_idx, aes_idx, temp);
766 *aes_bits = temp;
767 return 0;
768}
769
770static int pcxhr_iec958_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
771{
772 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
773 unsigned char aes_bits;
774 int i, err;
775
Ingo Molnar62932df2006-01-16 16:34:20 +0100776 mutex_lock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100777 for(i = 0; i < 5; i++) {
778 if (kcontrol->private_value == 0) /* playback */
779 aes_bits = chip->aes_bits[i];
780 else { /* capture */
781 err = pcxhr_iec958_capture_byte(chip, i, &aes_bits);
782 if (err)
783 break;
784 }
785 ucontrol->value.iec958.status[i] = aes_bits;
786 }
Ingo Molnar62932df2006-01-16 16:34:20 +0100787 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100788 return 0;
789}
790
791static int pcxhr_iec958_mask_get(struct snd_kcontrol *kcontrol,
792 struct snd_ctl_elem_value *ucontrol)
793{
794 int i;
795 for (i = 0; i < 5; i++)
796 ucontrol->value.iec958.status[i] = 0xff;
797 return 0;
798}
799
800static int pcxhr_iec958_update_byte(struct snd_pcxhr *chip, int aes_idx, unsigned char aes_bits)
801{
802 int i, err, cmd;
803 unsigned char new_bits = aes_bits;
804 unsigned char old_bits = chip->aes_bits[aes_idx];
805 struct pcxhr_rmh rmh;
806
807 for (i = 0; i < 8; i++) {
808 if ((old_bits & 0x01) != (new_bits & 0x01)) {
809 cmd = chip->chip_idx & 0x03; /* chip index 0..3 */
810 if(chip->chip_idx > 3)
811 /* new bit used if chip_idx>3 (PCX1222HR) */
812 cmd |= 1 << 22;
813 cmd |= ((aes_idx << 3) + i) << 2; /* add bit offset */
814 cmd |= (new_bits & 0x01) << 23; /* add bit value */
815 pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
816 rmh.cmd[0] |= IO_NUM_REG_CUER;
817 rmh.cmd[1] = cmd;
818 rmh.cmd_len = 2;
819 snd_printdd("write iec958 AES %d byte %d bit %d (cmd %x)\n",
820 chip->chip_idx, aes_idx, i, cmd);
821 err = pcxhr_send_msg(chip->mgr, &rmh);
822 if (err)
823 return err;
824 }
825 old_bits >>= 1;
826 new_bits >>= 1;
827 }
828 chip->aes_bits[aes_idx] = aes_bits;
829 return 0;
830}
831
832static int pcxhr_iec958_put(struct snd_kcontrol *kcontrol,
833 struct snd_ctl_elem_value *ucontrol)
834{
835 struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
836 int i, changed = 0;
837
838 /* playback */
Ingo Molnar62932df2006-01-16 16:34:20 +0100839 mutex_lock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100840 for (i = 0; i < 5; i++) {
841 if (ucontrol->value.iec958.status[i] != chip->aes_bits[i]) {
842 pcxhr_iec958_update_byte(chip, i, ucontrol->value.iec958.status[i]);
843 changed = 1;
844 }
845 }
Ingo Molnar62932df2006-01-16 16:34:20 +0100846 mutex_unlock(&chip->mgr->mixer_mutex);
Markus Bollingere12229b2005-12-06 13:55:26 +0100847 return changed;
848}
849
850static struct snd_kcontrol_new pcxhr_control_playback_iec958_mask = {
851 .access = SNDRV_CTL_ELEM_ACCESS_READ,
852 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
853 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
854 .info = pcxhr_iec958_info,
855 .get = pcxhr_iec958_mask_get
856};
857static struct snd_kcontrol_new pcxhr_control_playback_iec958 = {
858 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
859 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
860 .info = pcxhr_iec958_info,
861 .get = pcxhr_iec958_get,
862 .put = pcxhr_iec958_put,
863 .private_value = 0 /* playback */
864};
865
866static struct snd_kcontrol_new pcxhr_control_capture_iec958_mask = {
867 .access = SNDRV_CTL_ELEM_ACCESS_READ,
868 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
869 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK),
870 .info = pcxhr_iec958_info,
871 .get = pcxhr_iec958_mask_get
872};
873static struct snd_kcontrol_new pcxhr_control_capture_iec958 = {
874 .access = SNDRV_CTL_ELEM_ACCESS_READ,
875 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
876 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
877 .info = pcxhr_iec958_info,
878 .get = pcxhr_iec958_get,
879 .private_value = 1 /* capture */
880};
881
882static void pcxhr_init_audio_levels(struct snd_pcxhr *chip)
883{
884 int i;
885
886 for (i = 0; i < 2; i++) {
887 if (chip->nb_streams_play) {
888 int j;
889 /* at boot time the digital volumes are unmuted 0dB */
890 for (j = 0; j < PCXHR_PLAYBACK_STREAMS; j++) {
891 chip->digital_playback_active[j][i] = 1;
892 chip->digital_playback_volume[j][i] = PCXHR_DIGITAL_ZERO_LEVEL;
893 }
894 /* after boot, only two bits are set on the uer interface */
895 chip->aes_bits[0] = IEC958_AES0_PROFESSIONAL | IEC958_AES0_PRO_FS_48000;
896/* only for test purpose, remove later */
897#ifdef CONFIG_SND_DEBUG
898 /* analog volumes for playback (is LEVEL_MIN after boot) */
899 chip->analog_playback_active[i] = 1;
900 chip->analog_playback_volume[i] = PCXHR_ANALOG_PLAYBACK_ZERO_LEVEL;
901 pcxhr_update_analog_audio_level(chip, 0, i);
902#endif
903/* test end */
904 }
905 if (chip->nb_streams_capt) {
906 /* at boot time the digital volumes are unmuted 0dB */
907 chip->digital_capture_volume[i] = PCXHR_DIGITAL_ZERO_LEVEL;
908/* only for test purpose, remove later */
909#ifdef CONFIG_SND_DEBUG
910 /* analog volumes for playback (is LEVEL_MIN after boot) */
911 chip->analog_capture_volume[i] = PCXHR_ANALOG_CAPTURE_ZERO_LEVEL;
912 pcxhr_update_analog_audio_level(chip, 1, i);
913#endif
914/* test end */
915 }
916 }
917
918 return;
919}
920
921
922int pcxhr_create_mixer(struct pcxhr_mgr *mgr)
923{
924 struct snd_pcxhr *chip;
925 int err, i;
926
Ingo Molnar62932df2006-01-16 16:34:20 +0100927 mutex_init(&mgr->mixer_mutex); /* can be in another place */
Markus Bollingere12229b2005-12-06 13:55:26 +0100928
929 for (i = 0; i < mgr->num_cards; i++) {
930 struct snd_kcontrol_new temp;
931 chip = mgr->chip[i];
932
933 if (chip->nb_streams_play) {
934 /* analog output level control */
935 temp = pcxhr_control_analog_level;
936 temp.name = "Master Playback Volume";
937 temp.private_value = 0; /* playback */
Takashi Iwaic6ff77f2006-08-23 19:53:02 +0200938 temp.tlv.p = db_scale_analog_playback;
Markus Bollingere12229b2005-12-06 13:55:26 +0100939 if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
940 return err;
941 /* output mute controls */
942 if ((err = snd_ctl_add(chip->card,
943 snd_ctl_new1(&pcxhr_control_output_switch,
944 chip))) < 0)
945 return err;
946
947 temp = snd_pcxhr_pcm_vol;
948 temp.name = "PCM Playback Volume";
949 temp.count = PCXHR_PLAYBACK_STREAMS;
950 temp.private_value = 0; /* playback */
951 if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
952 return err;
953
954 if ((err = snd_ctl_add(chip->card,
955 snd_ctl_new1(&pcxhr_control_pcm_switch,
956 chip))) < 0)
957 return err;
958
959 /* IEC958 controls */
960 if ((err = snd_ctl_add(chip->card,
961 snd_ctl_new1(&pcxhr_control_playback_iec958_mask,
962 chip))) < 0)
963 return err;
964 if ((err = snd_ctl_add(chip->card,
965 snd_ctl_new1(&pcxhr_control_playback_iec958,
966 chip))) < 0)
967 return err;
968 }
969 if (chip->nb_streams_capt) {
970 /* analog input level control only on first two chips !*/
971 temp = pcxhr_control_analog_level;
972 temp.name = "Master Capture Volume";
973 temp.private_value = 1; /* capture */
Takashi Iwaic6ff77f2006-08-23 19:53:02 +0200974 temp.tlv.p = db_scale_analog_capture;
Markus Bollingere12229b2005-12-06 13:55:26 +0100975 if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
976 return err;
977
978 temp = snd_pcxhr_pcm_vol;
979 temp.name = "PCM Capture Volume";
980 temp.count = 1;
981 temp.private_value = 1; /* capture */
982 if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
983 return err;
984 /* Audio source */
985 if ((err = snd_ctl_add(chip->card,
986 snd_ctl_new1(&pcxhr_control_audio_src,
987 chip))) < 0)
988 return err;
989 /* IEC958 controls */
990 if ((err = snd_ctl_add(chip->card,
991 snd_ctl_new1(&pcxhr_control_capture_iec958_mask,
992 chip))) < 0)
993 return err;
994 if ((err = snd_ctl_add(chip->card,
995 snd_ctl_new1(&pcxhr_control_capture_iec958,
996 chip))) < 0)
997 return err;
998 }
999 /* monitoring only if playback and capture device available */
1000 if (chip->nb_streams_capt > 0 && chip->nb_streams_play > 0) {
1001 /* monitoring */
1002 if ((err = snd_ctl_add(chip->card,
1003 snd_ctl_new1(&pcxhr_control_monitor_vol,
1004 chip))) < 0)
1005 return err;
1006 if ((err = snd_ctl_add(chip->card,
1007 snd_ctl_new1(&pcxhr_control_monitor_sw,
1008 chip))) < 0)
1009 return err;
1010 }
1011
1012 if (i == 0) {
1013 /* clock mode only one control per pcxhr */
1014 if ((err = snd_ctl_add(chip->card,
1015 snd_ctl_new1(&pcxhr_control_clock_type,
1016 mgr))) < 0)
1017 return err;
1018 /* non standard control used to scan the external clock presence/frequencies */
1019 if ((err = snd_ctl_add(chip->card,
1020 snd_ctl_new1(&pcxhr_control_clock_rate,
1021 mgr))) < 0)
1022 return err;
1023 }
1024
1025 /* init values for the mixer data */
1026 pcxhr_init_audio_levels(chip);
1027 }
1028
1029 return 0;
1030}