diff options
author | Markus Bollinger <bollinger@digigram.com> | 2008-11-25 06:37:52 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2008-11-25 06:53:24 -0500 |
commit | c0193f39f43c79bde6c1c5804f5315f3983152b5 (patch) | |
tree | 682f6d5ad2ad776a446d08e6be281e941d7ea1b1 /sound/pci/pcxhr/pcxhr_mixer.c | |
parent | 7628700e08403618b0b07bd25b6456d8b2d074ef (diff) |
ALSA: pcxhr - add support for pcxhr stereo sound cards (mixer part)
- add support for pcxhr stereo cards mixer controls
- adjust tlv db scales to real dBu values
- fix bug with monitoring volume control pcxhr_monitor_vol_put
- do some cleanup
Signed-off-by: Markus Bollinger <bollinger@digigram.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/pcxhr/pcxhr_mixer.c')
-rw-r--r-- | sound/pci/pcxhr/pcxhr_mixer.c | 556 |
1 files changed, 382 insertions, 174 deletions
diff --git a/sound/pci/pcxhr/pcxhr_mixer.c b/sound/pci/pcxhr/pcxhr_mixer.c index aabc7bc5321e..2436e374586f 100644 --- a/sound/pci/pcxhr/pcxhr_mixer.c +++ b/sound/pci/pcxhr/pcxhr_mixer.c | |||
@@ -33,20 +33,24 @@ | |||
33 | #include <sound/tlv.h> | 33 | #include <sound/tlv.h> |
34 | #include <sound/asoundef.h> | 34 | #include <sound/asoundef.h> |
35 | #include "pcxhr_mixer.h" | 35 | #include "pcxhr_mixer.h" |
36 | #include "pcxhr_mix22.h" | ||
36 | 37 | ||
38 | #define PCXHR_LINE_CAPTURE_LEVEL_MIN 0 /* -112.0 dB */ | ||
39 | #define PCXHR_LINE_CAPTURE_LEVEL_MAX 255 /* +15.5 dB */ | ||
40 | #define PCXHR_LINE_CAPTURE_ZERO_LEVEL 224 /* 0.0 dB ( 0 dBu -> 0 dBFS ) */ | ||
37 | 41 | ||
38 | #define PCXHR_ANALOG_CAPTURE_LEVEL_MIN 0 /* -96.0 dB */ | 42 | #define PCXHR_LINE_PLAYBACK_LEVEL_MIN 0 /* -104.0 dB */ |
39 | #define PCXHR_ANALOG_CAPTURE_LEVEL_MAX 255 /* +31.5 dB */ | 43 | #define PCXHR_LINE_PLAYBACK_LEVEL_MAX 128 /* +24.0 dB */ |
40 | #define PCXHR_ANALOG_CAPTURE_ZERO_LEVEL 224 /* +16.0 dB ( +31.5 dB - fix level +15.5 dB ) */ | 44 | #define PCXHR_LINE_PLAYBACK_ZERO_LEVEL 104 /* 0.0 dB ( 0 dBFS -> 0 dBu ) */ |
41 | 45 | ||
42 | #define PCXHR_ANALOG_PLAYBACK_LEVEL_MIN 0 /* -128.0 dB */ | 46 | static const DECLARE_TLV_DB_SCALE(db_scale_analog_capture, -11200, 50, 1550); |
43 | #define PCXHR_ANALOG_PLAYBACK_LEVEL_MAX 128 /* 0.0 dB */ | ||
44 | #define PCXHR_ANALOG_PLAYBACK_ZERO_LEVEL 104 /* -24.0 dB ( 0.0 dB - fix level +24.0 dB ) */ | ||
45 | |||
46 | static const DECLARE_TLV_DB_SCALE(db_scale_analog_capture, -9600, 50, 3150); | ||
47 | static const DECLARE_TLV_DB_SCALE(db_scale_analog_playback, -10400, 100, 2400); | 47 | static const DECLARE_TLV_DB_SCALE(db_scale_analog_playback, -10400, 100, 2400); |
48 | 48 | ||
49 | static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip, int is_capture, int channel) | 49 | static const DECLARE_TLV_DB_SCALE(db_scale_a_hr222_capture, -11150, 50, 1600); |
50 | static const DECLARE_TLV_DB_SCALE(db_scale_a_hr222_playback, -2550, 50, 2400); | ||
51 | |||
52 | static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip, | ||
53 | int is_capture, int channel) | ||
50 | { | 54 | { |
51 | int err, vol; | 55 | int err, vol; |
52 | struct pcxhr_rmh rmh; | 56 | struct pcxhr_rmh rmh; |
@@ -60,15 +64,17 @@ static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip, int is_captur | |||
60 | if (chip->analog_playback_active[channel]) | 64 | if (chip->analog_playback_active[channel]) |
61 | vol = chip->analog_playback_volume[channel]; | 65 | vol = chip->analog_playback_volume[channel]; |
62 | else | 66 | else |
63 | vol = PCXHR_ANALOG_PLAYBACK_LEVEL_MIN; | 67 | vol = PCXHR_LINE_PLAYBACK_LEVEL_MIN; |
64 | rmh.cmd[2] = PCXHR_ANALOG_PLAYBACK_LEVEL_MAX - vol; /* playback analog levels are inversed */ | 68 | /* playback analog levels are inversed */ |
69 | rmh.cmd[2] = PCXHR_LINE_PLAYBACK_LEVEL_MAX - vol; | ||
65 | } | 70 | } |
66 | rmh.cmd[1] = 1 << ((2 * chip->chip_idx) + channel); /* audio mask */ | 71 | rmh.cmd[1] = 1 << ((2 * chip->chip_idx) + channel); /* audio mask */ |
67 | rmh.cmd_len = 3; | 72 | rmh.cmd_len = 3; |
68 | err = pcxhr_send_msg(chip->mgr, &rmh); | 73 | err = pcxhr_send_msg(chip->mgr, &rmh); |
69 | if (err < 0) { | 74 | if (err < 0) { |
70 | snd_printk(KERN_DEBUG "error update_analog_audio_level card(%d) " | 75 | snd_printk(KERN_DEBUG "error update_analog_audio_level card(%d)" |
71 | "is_capture(%d) err(%x)\n", chip->chip_idx, is_capture, err); | 76 | " is_capture(%d) err(%x)\n", |
77 | chip->chip_idx, is_capture, err); | ||
72 | return -EINVAL; | 78 | return -EINVAL; |
73 | } | 79 | } |
74 | return 0; | 80 | return 0; |
@@ -80,14 +86,34 @@ static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip, int is_captur | |||
80 | static int pcxhr_analog_vol_info(struct snd_kcontrol *kcontrol, | 86 | static int pcxhr_analog_vol_info(struct snd_kcontrol *kcontrol, |
81 | struct snd_ctl_elem_info *uinfo) | 87 | struct snd_ctl_elem_info *uinfo) |
82 | { | 88 | { |
89 | struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); | ||
90 | |||
83 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 91 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
84 | uinfo->count = 2; | 92 | uinfo->count = 2; |
85 | if (kcontrol->private_value == 0) { /* playback */ | 93 | if (kcontrol->private_value == 0) { /* playback */ |
86 | uinfo->value.integer.min = PCXHR_ANALOG_PLAYBACK_LEVEL_MIN; /* -128 dB */ | 94 | if (chip->mgr->is_hr_stereo) { |
87 | uinfo->value.integer.max = PCXHR_ANALOG_PLAYBACK_LEVEL_MAX; /* 0 dB */ | 95 | uinfo->value.integer.min = |
96 | HR222_LINE_PLAYBACK_LEVEL_MIN; /* -25 dB */ | ||
97 | uinfo->value.integer.max = | ||
98 | HR222_LINE_PLAYBACK_LEVEL_MAX; /* +24 dB */ | ||
99 | } else { | ||
100 | uinfo->value.integer.min = | ||
101 | PCXHR_LINE_PLAYBACK_LEVEL_MIN; /*-104 dB */ | ||
102 | uinfo->value.integer.max = | ||
103 | PCXHR_LINE_PLAYBACK_LEVEL_MAX; /* +24 dB */ | ||
104 | } | ||
88 | } else { /* capture */ | 105 | } else { /* capture */ |
89 | uinfo->value.integer.min = PCXHR_ANALOG_CAPTURE_LEVEL_MIN; /* -96 dB */ | 106 | if (chip->mgr->is_hr_stereo) { |
90 | uinfo->value.integer.max = PCXHR_ANALOG_CAPTURE_LEVEL_MAX; /* 31.5 dB */ | 107 | uinfo->value.integer.min = |
108 | HR222_LINE_CAPTURE_LEVEL_MIN; /*-112 dB */ | ||
109 | uinfo->value.integer.max = | ||
110 | HR222_LINE_CAPTURE_LEVEL_MAX; /* +15.5 dB */ | ||
111 | } else { | ||
112 | uinfo->value.integer.min = | ||
113 | PCXHR_LINE_CAPTURE_LEVEL_MIN; /*-112 dB */ | ||
114 | uinfo->value.integer.max = | ||
115 | PCXHR_LINE_CAPTURE_LEVEL_MAX; /* +15.5 dB */ | ||
116 | } | ||
91 | } | 117 | } |
92 | return 0; | 118 | return 0; |
93 | } | 119 | } |
@@ -98,11 +124,11 @@ static int pcxhr_analog_vol_get(struct snd_kcontrol *kcontrol, | |||
98 | struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); | 124 | struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); |
99 | mutex_lock(&chip->mgr->mixer_mutex); | 125 | mutex_lock(&chip->mgr->mixer_mutex); |
100 | if (kcontrol->private_value == 0) { /* playback */ | 126 | if (kcontrol->private_value == 0) { /* playback */ |
101 | ucontrol->value.integer.value[0] = chip->analog_playback_volume[0]; | 127 | ucontrol->value.integer.value[0] = chip->analog_playback_volume[0]; |
102 | ucontrol->value.integer.value[1] = chip->analog_playback_volume[1]; | 128 | ucontrol->value.integer.value[1] = chip->analog_playback_volume[1]; |
103 | } else { /* capture */ | 129 | } else { /* capture */ |
104 | ucontrol->value.integer.value[0] = chip->analog_capture_volume[0]; | 130 | ucontrol->value.integer.value[0] = chip->analog_capture_volume[0]; |
105 | ucontrol->value.integer.value[1] = chip->analog_capture_volume[1]; | 131 | ucontrol->value.integer.value[1] = chip->analog_capture_volume[1]; |
106 | } | 132 | } |
107 | mutex_unlock(&chip->mgr->mixer_mutex); | 133 | mutex_unlock(&chip->mgr->mixer_mutex); |
108 | return 0; | 134 | return 0; |
@@ -123,18 +149,35 @@ static int pcxhr_analog_vol_put(struct snd_kcontrol *kcontrol, | |||
123 | &chip->analog_capture_volume[i] : | 149 | &chip->analog_capture_volume[i] : |
124 | &chip->analog_playback_volume[i]; | 150 | &chip->analog_playback_volume[i]; |
125 | if (is_capture) { | 151 | if (is_capture) { |
126 | if (new_volume < PCXHR_ANALOG_CAPTURE_LEVEL_MIN || | 152 | if (chip->mgr->is_hr_stereo) { |
127 | new_volume > PCXHR_ANALOG_CAPTURE_LEVEL_MAX) | 153 | if (new_volume < HR222_LINE_CAPTURE_LEVEL_MIN || |
128 | continue; | 154 | new_volume > HR222_LINE_CAPTURE_LEVEL_MAX) |
155 | continue; | ||
156 | } else { | ||
157 | if (new_volume < PCXHR_LINE_CAPTURE_LEVEL_MIN || | ||
158 | new_volume > PCXHR_LINE_CAPTURE_LEVEL_MAX) | ||
159 | continue; | ||
160 | } | ||
129 | } else { | 161 | } else { |
130 | if (new_volume < PCXHR_ANALOG_PLAYBACK_LEVEL_MIN || | 162 | if (chip->mgr->is_hr_stereo) { |
131 | new_volume > PCXHR_ANALOG_PLAYBACK_LEVEL_MAX) | 163 | if (new_volume < HR222_LINE_PLAYBACK_LEVEL_MIN || |
132 | continue; | 164 | new_volume > HR222_LINE_PLAYBACK_LEVEL_MAX) |
165 | continue; | ||
166 | } else { | ||
167 | if (new_volume < PCXHR_LINE_PLAYBACK_LEVEL_MIN || | ||
168 | new_volume > PCXHR_LINE_PLAYBACK_LEVEL_MAX) | ||
169 | continue; | ||
170 | } | ||
133 | } | 171 | } |
134 | if (*stored_volume != new_volume) { | 172 | if (*stored_volume != new_volume) { |
135 | *stored_volume = new_volume; | 173 | *stored_volume = new_volume; |
136 | changed = 1; | 174 | changed = 1; |
137 | pcxhr_update_analog_audio_level(chip, is_capture, i); | 175 | if (chip->mgr->is_hr_stereo) |
176 | hr222_update_analog_audio_level(chip, | ||
177 | is_capture, i); | ||
178 | else | ||
179 | pcxhr_update_analog_audio_level(chip, | ||
180 | is_capture, i); | ||
138 | } | 181 | } |
139 | } | 182 | } |
140 | mutex_unlock(&chip->mgr->mixer_mutex); | 183 | mutex_unlock(&chip->mgr->mixer_mutex); |
@@ -153,6 +196,7 @@ static struct snd_kcontrol_new pcxhr_control_analog_level = { | |||
153 | }; | 196 | }; |
154 | 197 | ||
155 | /* shared */ | 198 | /* shared */ |
199 | |||
156 | #define pcxhr_sw_info snd_ctl_boolean_stereo_info | 200 | #define pcxhr_sw_info snd_ctl_boolean_stereo_info |
157 | 201 | ||
158 | static int pcxhr_audio_sw_get(struct snd_kcontrol *kcontrol, | 202 | static int pcxhr_audio_sw_get(struct snd_kcontrol *kcontrol, |
@@ -180,7 +224,10 @@ static int pcxhr_audio_sw_put(struct snd_kcontrol *kcontrol, | |||
180 | !!ucontrol->value.integer.value[i]; | 224 | !!ucontrol->value.integer.value[i]; |
181 | changed = 1; | 225 | changed = 1; |
182 | /* update playback levels */ | 226 | /* update playback levels */ |
183 | pcxhr_update_analog_audio_level(chip, 0, i); | 227 | if (chip->mgr->is_hr_stereo) |
228 | hr222_update_analog_audio_level(chip, 0, i); | ||
229 | else | ||
230 | pcxhr_update_analog_audio_level(chip, 0, i); | ||
184 | } | 231 | } |
185 | } | 232 | } |
186 | mutex_unlock(&chip->mgr->mixer_mutex); | 233 | mutex_unlock(&chip->mgr->mixer_mutex); |
@@ -251,7 +298,8 @@ static int pcxhr_update_playback_stream_level(struct snd_pcxhr* chip, int idx) | |||
251 | #define VALID_AUDIO_IO_MUTE_LEVEL 0x000004 | 298 | #define VALID_AUDIO_IO_MUTE_LEVEL 0x000004 |
252 | #define VALID_AUDIO_IO_MUTE_MONITOR_1 0x000008 | 299 | #define VALID_AUDIO_IO_MUTE_MONITOR_1 0x000008 |
253 | 300 | ||
254 | static int pcxhr_update_audio_pipe_level(struct snd_pcxhr* chip, int capture, int channel) | 301 | static int pcxhr_update_audio_pipe_level(struct snd_pcxhr *chip, |
302 | int capture, int channel) | ||
255 | { | 303 | { |
256 | int err; | 304 | int err; |
257 | struct pcxhr_rmh rmh; | 305 | struct pcxhr_rmh rmh; |
@@ -264,18 +312,20 @@ static int pcxhr_update_audio_pipe_level(struct snd_pcxhr* chip, int capture, in | |||
264 | 312 | ||
265 | pcxhr_init_rmh(&rmh, CMD_AUDIO_LEVEL_ADJUST); | 313 | pcxhr_init_rmh(&rmh, CMD_AUDIO_LEVEL_ADJUST); |
266 | /* add channel mask */ | 314 | /* add channel mask */ |
267 | pcxhr_set_pipe_cmd_params(&rmh, capture, 0, 0, 1 << (channel + pipe->first_audio)); | 315 | pcxhr_set_pipe_cmd_params(&rmh, capture, 0, 0, |
268 | /* TODO : if mask (3 << pipe->first_audio) is used, left and right channel | 316 | 1 << (channel + pipe->first_audio)); |
269 | * will be programmed to the same params | 317 | /* TODO : if mask (3 << pipe->first_audio) is used, left and right |
270 | */ | 318 | * channel will be programmed to the same params */ |
271 | if (capture) { | 319 | if (capture) { |
272 | rmh.cmd[0] |= VALID_AUDIO_IO_DIGITAL_LEVEL; | 320 | rmh.cmd[0] |= VALID_AUDIO_IO_DIGITAL_LEVEL; |
273 | /* VALID_AUDIO_IO_MUTE_LEVEL not yet handled (capture pipe level) */ | 321 | /* VALID_AUDIO_IO_MUTE_LEVEL not yet handled |
322 | * (capture pipe level) */ | ||
274 | rmh.cmd[2] = chip->digital_capture_volume[channel]; | 323 | rmh.cmd[2] = chip->digital_capture_volume[channel]; |
275 | } else { | 324 | } else { |
276 | rmh.cmd[0] |= VALID_AUDIO_IO_MONITOR_LEVEL | VALID_AUDIO_IO_MUTE_MONITOR_1; | 325 | rmh.cmd[0] |= VALID_AUDIO_IO_MONITOR_LEVEL | |
277 | /* VALID_AUDIO_IO_DIGITAL_LEVEL and VALID_AUDIO_IO_MUTE_LEVEL not yet | 326 | VALID_AUDIO_IO_MUTE_MONITOR_1; |
278 | * handled (playback pipe level) | 327 | /* VALID_AUDIO_IO_DIGITAL_LEVEL and VALID_AUDIO_IO_MUTE_LEVEL |
328 | * not yet handled (playback pipe level) | ||
279 | */ | 329 | */ |
280 | rmh.cmd[2] = chip->monitoring_volume[channel] << 10; | 330 | rmh.cmd[2] = chip->monitoring_volume[channel] << 10; |
281 | if (chip->monitoring_active[channel] == 0) | 331 | if (chip->monitoring_active[channel] == 0) |
@@ -284,8 +334,8 @@ static int pcxhr_update_audio_pipe_level(struct snd_pcxhr* chip, int capture, in | |||
284 | rmh.cmd_len = 3; | 334 | rmh.cmd_len = 3; |
285 | 335 | ||
286 | err = pcxhr_send_msg(chip->mgr, &rmh); | 336 | err = pcxhr_send_msg(chip->mgr, &rmh); |
287 | if(err<0) { | 337 | if (err < 0) { |
288 | snd_printk(KERN_DEBUG "error update_audio_level card(%d) err(%x)\n", | 338 | snd_printk(KERN_DEBUG "error update_audio_level(%d) err=%x\n", |
289 | chip->chip_idx, err); | 339 | chip->chip_idx, err); |
290 | return -EINVAL; | 340 | return -EINVAL; |
291 | } | 341 | } |
@@ -309,15 +359,15 @@ static int pcxhr_pcm_vol_get(struct snd_kcontrol *kcontrol, | |||
309 | struct snd_ctl_elem_value *ucontrol) | 359 | struct snd_ctl_elem_value *ucontrol) |
310 | { | 360 | { |
311 | struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); | 361 | struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); |
312 | int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ | 362 | int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ |
313 | int *stored_volume; | 363 | int *stored_volume; |
314 | int is_capture = kcontrol->private_value; | 364 | int is_capture = kcontrol->private_value; |
315 | 365 | ||
316 | mutex_lock(&chip->mgr->mixer_mutex); | 366 | mutex_lock(&chip->mgr->mixer_mutex); |
317 | if (is_capture) | 367 | if (is_capture) /* digital capture */ |
318 | stored_volume = chip->digital_capture_volume; /* digital capture */ | 368 | stored_volume = chip->digital_capture_volume; |
319 | else | 369 | else /* digital playback */ |
320 | stored_volume = chip->digital_playback_volume[idx]; /* digital playback */ | 370 | stored_volume = chip->digital_playback_volume[idx]; |
321 | ucontrol->value.integer.value[0] = stored_volume[0]; | 371 | ucontrol->value.integer.value[0] = stored_volume[0]; |
322 | ucontrol->value.integer.value[1] = stored_volume[1]; | 372 | ucontrol->value.integer.value[1] = stored_volume[1]; |
323 | mutex_unlock(&chip->mgr->mixer_mutex); | 373 | mutex_unlock(&chip->mgr->mixer_mutex); |
@@ -328,7 +378,7 @@ static int pcxhr_pcm_vol_put(struct snd_kcontrol *kcontrol, | |||
328 | struct snd_ctl_elem_value *ucontrol) | 378 | struct snd_ctl_elem_value *ucontrol) |
329 | { | 379 | { |
330 | struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); | 380 | struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); |
331 | int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ | 381 | int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ |
332 | int changed = 0; | 382 | int changed = 0; |
333 | int is_capture = kcontrol->private_value; | 383 | int is_capture = kcontrol->private_value; |
334 | int *stored_volume; | 384 | int *stored_volume; |
@@ -384,7 +434,8 @@ static int pcxhr_pcm_sw_get(struct snd_kcontrol *kcontrol, | |||
384 | return 0; | 434 | return 0; |
385 | } | 435 | } |
386 | 436 | ||
387 | static int pcxhr_pcm_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 437 | static int pcxhr_pcm_sw_put(struct snd_kcontrol *kcontrol, |
438 | struct snd_ctl_elem_value *ucontrol) | ||
388 | { | 439 | { |
389 | struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); | 440 | struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); |
390 | int changed = 0; | 441 | int changed = 0; |
@@ -444,8 +495,8 @@ static int pcxhr_monitor_vol_put(struct snd_kcontrol *kcontrol, | |||
444 | if (chip->monitoring_volume[i] != | 495 | if (chip->monitoring_volume[i] != |
445 | ucontrol->value.integer.value[i]) { | 496 | ucontrol->value.integer.value[i]) { |
446 | chip->monitoring_volume[i] = | 497 | chip->monitoring_volume[i] = |
447 | !!ucontrol->value.integer.value[i]; | 498 | ucontrol->value.integer.value[i]; |
448 | if(chip->monitoring_active[i]) | 499 | if (chip->monitoring_active[i]) |
449 | /* update monitoring volume and mute */ | 500 | /* update monitoring volume and mute */ |
450 | /* do only when monitoring is unmuted */ | 501 | /* do only when monitoring is unmuted */ |
451 | pcxhr_update_audio_pipe_level(chip, 0, i); | 502 | pcxhr_update_audio_pipe_level(chip, 0, i); |
@@ -460,7 +511,7 @@ static struct snd_kcontrol_new pcxhr_control_monitor_vol = { | |||
460 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 511 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
461 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | | 512 | .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | |
462 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), | 513 | SNDRV_CTL_ELEM_ACCESS_TLV_READ), |
463 | .name = "Monitoring Volume", | 514 | .name = "Monitoring Playback Volume", |
464 | .info = pcxhr_digital_vol_info, /* shared */ | 515 | .info = pcxhr_digital_vol_info, /* shared */ |
465 | .get = pcxhr_monitor_vol_get, | 516 | .get = pcxhr_monitor_vol_get, |
466 | .put = pcxhr_monitor_vol_put, | 517 | .put = pcxhr_monitor_vol_put, |
@@ -511,7 +562,7 @@ static int pcxhr_monitor_sw_put(struct snd_kcontrol *kcontrol, | |||
511 | 562 | ||
512 | static struct snd_kcontrol_new pcxhr_control_monitor_sw = { | 563 | static struct snd_kcontrol_new pcxhr_control_monitor_sw = { |
513 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 564 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
514 | .name = "Monitoring Switch", | 565 | .name = "Monitoring Playback Switch", |
515 | .info = pcxhr_sw_info, /* shared */ | 566 | .info = pcxhr_sw_info, /* shared */ |
516 | .get = pcxhr_monitor_sw_get, | 567 | .get = pcxhr_monitor_sw_get, |
517 | .put = pcxhr_monitor_sw_put | 568 | .put = pcxhr_monitor_sw_put |
@@ -533,7 +584,7 @@ static int pcxhr_set_audio_source(struct snd_pcxhr* chip) | |||
533 | struct pcxhr_rmh rmh; | 584 | struct pcxhr_rmh rmh; |
534 | unsigned int mask, reg; | 585 | unsigned int mask, reg; |
535 | unsigned int codec; | 586 | unsigned int codec; |
536 | int err, use_src, changed; | 587 | int err, changed; |
537 | 588 | ||
538 | switch (chip->chip_idx) { | 589 | switch (chip->chip_idx) { |
539 | case 0 : mask = PCXHR_SOURCE_AUDIO01_UER; codec = CS8420_01_CS; break; | 590 | case 0 : mask = PCXHR_SOURCE_AUDIO01_UER; codec = CS8420_01_CS; break; |
@@ -542,13 +593,10 @@ static int pcxhr_set_audio_source(struct snd_pcxhr* chip) | |||
542 | case 3 : mask = PCXHR_SOURCE_AUDIO67_UER; codec = CS8420_67_CS; break; | 593 | case 3 : mask = PCXHR_SOURCE_AUDIO67_UER; codec = CS8420_67_CS; break; |
543 | default: return -EINVAL; | 594 | default: return -EINVAL; |
544 | } | 595 | } |
545 | reg = 0; /* audio source from analog plug */ | ||
546 | use_src = 0; /* do not activate codec SRC */ | ||
547 | |||
548 | if (chip->audio_capture_source != 0) { | 596 | if (chip->audio_capture_source != 0) { |
549 | reg = mask; /* audio source from digital plug */ | 597 | reg = mask; /* audio source from digital plug */ |
550 | if (chip->audio_capture_source == 2) | 598 | } else { |
551 | use_src = 1; | 599 | reg = 0; /* audio source from analog plug */ |
552 | } | 600 | } |
553 | /* set the input source */ | 601 | /* set the input source */ |
554 | pcxhr_write_io_num_reg_cont(chip->mgr, mask, reg, &changed); | 602 | pcxhr_write_io_num_reg_cont(chip->mgr, mask, reg, &changed); |
@@ -560,29 +608,61 @@ static int pcxhr_set_audio_source(struct snd_pcxhr* chip) | |||
560 | if (err) | 608 | if (err) |
561 | return err; | 609 | return err; |
562 | } | 610 | } |
563 | pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); /* set codec SRC on off */ | 611 | if (chip->mgr->board_aes_in_192k) { |
564 | rmh.cmd_len = 3; | 612 | int i; |
565 | rmh.cmd[0] |= IO_NUM_UER_CHIP_REG; | 613 | unsigned int src_config = 0xC0; |
566 | rmh.cmd[1] = codec; | 614 | /* update all src configs with one call */ |
567 | rmh.cmd[2] = (CS8420_DATA_FLOW_CTL & CHIP_SIG_AND_MAP_SPI) | (use_src ? 0x41 : 0x54); | 615 | for (i = 0; (i < 4) && (i < chip->mgr->capture_chips); i++) { |
568 | err = pcxhr_send_msg(chip->mgr, &rmh); | 616 | if (chip->mgr->chip[i]->audio_capture_source == 2) |
569 | if(err) | 617 | src_config |= (1 << (3 - i)); |
570 | return err; | 618 | } |
571 | rmh.cmd[2] = (CS8420_CLOCK_SRC_CTL & CHIP_SIG_AND_MAP_SPI) | (use_src ? 0x41 : 0x49); | 619 | /* set codec SRC on off */ |
572 | err = pcxhr_send_msg(chip->mgr, &rmh); | 620 | pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); |
621 | rmh.cmd_len = 2; | ||
622 | rmh.cmd[0] |= IO_NUM_REG_CONFIG_SRC; | ||
623 | rmh.cmd[1] = src_config; | ||
624 | err = pcxhr_send_msg(chip->mgr, &rmh); | ||
625 | } else { | ||
626 | int use_src = 0; | ||
627 | if (chip->audio_capture_source == 2) | ||
628 | use_src = 1; | ||
629 | /* set codec SRC on off */ | ||
630 | pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); | ||
631 | rmh.cmd_len = 3; | ||
632 | rmh.cmd[0] |= IO_NUM_UER_CHIP_REG; | ||
633 | rmh.cmd[1] = codec; | ||
634 | rmh.cmd[2] = ((CS8420_DATA_FLOW_CTL & CHIP_SIG_AND_MAP_SPI) | | ||
635 | (use_src ? 0x41 : 0x54)); | ||
636 | err = pcxhr_send_msg(chip->mgr, &rmh); | ||
637 | if (err) | ||
638 | return err; | ||
639 | rmh.cmd[2] = ((CS8420_CLOCK_SRC_CTL & CHIP_SIG_AND_MAP_SPI) | | ||
640 | (use_src ? 0x41 : 0x49)); | ||
641 | err = pcxhr_send_msg(chip->mgr, &rmh); | ||
642 | } | ||
573 | return err; | 643 | return err; |
574 | } | 644 | } |
575 | 645 | ||
576 | static int pcxhr_audio_src_info(struct snd_kcontrol *kcontrol, | 646 | static int pcxhr_audio_src_info(struct snd_kcontrol *kcontrol, |
577 | struct snd_ctl_elem_info *uinfo) | 647 | struct snd_ctl_elem_info *uinfo) |
578 | { | 648 | { |
579 | static char *texts[3] = {"Analog", "Digital", "Digi+SRC"}; | 649 | static const char *texts[5] = { |
650 | "Line", "Digital", "Digi+SRC", "Mic", "Line+Mic" | ||
651 | }; | ||
652 | int i; | ||
653 | struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); | ||
580 | 654 | ||
655 | i = 2; /* no SRC, no Mic available */ | ||
656 | if (chip->mgr->board_has_aes1) { | ||
657 | i = 3; /* SRC available */ | ||
658 | if (chip->mgr->board_has_mic) | ||
659 | i = 5; /* Mic and MicroMix available */ | ||
660 | } | ||
581 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 661 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
582 | uinfo->count = 1; | 662 | uinfo->count = 1; |
583 | uinfo->value.enumerated.items = 3; | 663 | uinfo->value.enumerated.items = i; |
584 | if (uinfo->value.enumerated.item > 2) | 664 | if (uinfo->value.enumerated.item > (i-1)) |
585 | uinfo->value.enumerated.item = 2; | 665 | uinfo->value.enumerated.item = i-1; |
586 | strcpy(uinfo->value.enumerated.name, | 666 | strcpy(uinfo->value.enumerated.name, |
587 | texts[uinfo->value.enumerated.item]); | 667 | texts[uinfo->value.enumerated.item]); |
588 | return 0; | 668 | return 0; |
@@ -601,13 +681,21 @@ static int pcxhr_audio_src_put(struct snd_kcontrol *kcontrol, | |||
601 | { | 681 | { |
602 | struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); | 682 | struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); |
603 | int ret = 0; | 683 | int ret = 0; |
604 | 684 | int i = 2; /* no SRC, no Mic available */ | |
605 | if (ucontrol->value.enumerated.item[0] >= 3) | 685 | if (chip->mgr->board_has_aes1) { |
686 | i = 3; /* SRC available */ | ||
687 | if (chip->mgr->board_has_mic) | ||
688 | i = 5; /* Mic and MicroMix available */ | ||
689 | } | ||
690 | if (ucontrol->value.enumerated.item[0] >= i) | ||
606 | return -EINVAL; | 691 | return -EINVAL; |
607 | mutex_lock(&chip->mgr->mixer_mutex); | 692 | mutex_lock(&chip->mgr->mixer_mutex); |
608 | if (chip->audio_capture_source != ucontrol->value.enumerated.item[0]) { | 693 | if (chip->audio_capture_source != ucontrol->value.enumerated.item[0]) { |
609 | chip->audio_capture_source = ucontrol->value.enumerated.item[0]; | 694 | chip->audio_capture_source = ucontrol->value.enumerated.item[0]; |
610 | pcxhr_set_audio_source(chip); | 695 | if (chip->mgr->is_hr_stereo) |
696 | hr222_set_audio_source(chip); | ||
697 | else | ||
698 | pcxhr_set_audio_source(chip); | ||
611 | ret = 1; | 699 | ret = 1; |
612 | } | 700 | } |
613 | mutex_unlock(&chip->mgr->mixer_mutex); | 701 | mutex_unlock(&chip->mgr->mixer_mutex); |
@@ -626,25 +714,46 @@ static struct snd_kcontrol_new pcxhr_control_audio_src = { | |||
626 | /* | 714 | /* |
627 | * clock type selection | 715 | * clock type selection |
628 | * enum pcxhr_clock_type { | 716 | * enum pcxhr_clock_type { |
629 | * PCXHR_CLOCK_TYPE_INTERNAL = 0, | 717 | * PCXHR_CLOCK_TYPE_INTERNAL = 0, |
630 | * PCXHR_CLOCK_TYPE_WORD_CLOCK, | 718 | * PCXHR_CLOCK_TYPE_WORD_CLOCK, |
631 | * PCXHR_CLOCK_TYPE_AES_SYNC, | 719 | * PCXHR_CLOCK_TYPE_AES_SYNC, |
632 | * PCXHR_CLOCK_TYPE_AES_1, | 720 | * PCXHR_CLOCK_TYPE_AES_1, |
633 | * PCXHR_CLOCK_TYPE_AES_2, | 721 | * PCXHR_CLOCK_TYPE_AES_2, |
634 | * PCXHR_CLOCK_TYPE_AES_3, | 722 | * PCXHR_CLOCK_TYPE_AES_3, |
635 | * PCXHR_CLOCK_TYPE_AES_4, | 723 | * PCXHR_CLOCK_TYPE_AES_4, |
636 | * }; | 724 | * PCXHR_CLOCK_TYPE_MAX = PCXHR_CLOCK_TYPE_AES_4, |
725 | * HR22_CLOCK_TYPE_INTERNAL = PCXHR_CLOCK_TYPE_INTERNAL, | ||
726 | * HR22_CLOCK_TYPE_AES_SYNC, | ||
727 | * HR22_CLOCK_TYPE_AES_1, | ||
728 | * HR22_CLOCK_TYPE_MAX = HR22_CLOCK_TYPE_AES_1, | ||
729 | * }; | ||
637 | */ | 730 | */ |
638 | 731 | ||
639 | static int pcxhr_clock_type_info(struct snd_kcontrol *kcontrol, | 732 | static int pcxhr_clock_type_info(struct snd_kcontrol *kcontrol, |
640 | struct snd_ctl_elem_info *uinfo) | 733 | struct snd_ctl_elem_info *uinfo) |
641 | { | 734 | { |
642 | static char *texts[7] = { | 735 | static const char *textsPCXHR[7] = { |
643 | "Internal", "WordClock", "AES Sync", "AES 1", "AES 2", "AES 3", "AES 4" | 736 | "Internal", "WordClock", "AES Sync", |
737 | "AES 1", "AES 2", "AES 3", "AES 4" | ||
738 | }; | ||
739 | static const char *textsHR22[3] = { | ||
740 | "Internal", "AES Sync", "AES 1" | ||
644 | }; | 741 | }; |
742 | const char **texts; | ||
645 | struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol); | 743 | struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol); |
646 | int clock_items = 3 + mgr->capture_chips; | 744 | int clock_items = 2; /* at least Internal and AES Sync clock */ |
647 | 745 | if (mgr->board_has_aes1) { | |
746 | clock_items += mgr->capture_chips; /* add AES x */ | ||
747 | if (!mgr->is_hr_stereo) | ||
748 | clock_items += 1; /* add word clock */ | ||
749 | } | ||
750 | if (mgr->is_hr_stereo) { | ||
751 | texts = textsHR22; | ||
752 | snd_BUG_ON(clock_items > (HR22_CLOCK_TYPE_MAX+1)); | ||
753 | } else { | ||
754 | texts = textsPCXHR; | ||
755 | snd_BUG_ON(clock_items > (PCXHR_CLOCK_TYPE_MAX+1)); | ||
756 | } | ||
648 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 757 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
649 | uinfo->count = 1; | 758 | uinfo->count = 1; |
650 | uinfo->value.enumerated.items = clock_items; | 759 | uinfo->value.enumerated.items = clock_items; |
@@ -667,9 +776,13 @@ static int pcxhr_clock_type_put(struct snd_kcontrol *kcontrol, | |||
667 | struct snd_ctl_elem_value *ucontrol) | 776 | struct snd_ctl_elem_value *ucontrol) |
668 | { | 777 | { |
669 | struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol); | 778 | struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol); |
670 | unsigned int clock_items = 3 + mgr->capture_chips; | ||
671 | int rate, ret = 0; | 779 | int rate, ret = 0; |
672 | 780 | unsigned int clock_items = 2; /* at least Internal and AES Sync clock */ | |
781 | if (mgr->board_has_aes1) { | ||
782 | clock_items += mgr->capture_chips; /* add AES x */ | ||
783 | if (!mgr->is_hr_stereo) | ||
784 | clock_items += 1; /* add word clock */ | ||
785 | } | ||
673 | if (ucontrol->value.enumerated.item[0] >= clock_items) | 786 | if (ucontrol->value.enumerated.item[0] >= clock_items) |
674 | return -EINVAL; | 787 | return -EINVAL; |
675 | mutex_lock(&mgr->mixer_mutex); | 788 | mutex_lock(&mgr->mixer_mutex); |
@@ -677,7 +790,8 @@ static int pcxhr_clock_type_put(struct snd_kcontrol *kcontrol, | |||
677 | mutex_lock(&mgr->setup_mutex); | 790 | mutex_lock(&mgr->setup_mutex); |
678 | mgr->use_clock_type = ucontrol->value.enumerated.item[0]; | 791 | mgr->use_clock_type = ucontrol->value.enumerated.item[0]; |
679 | if (mgr->use_clock_type) | 792 | if (mgr->use_clock_type) |
680 | pcxhr_get_external_clock(mgr, mgr->use_clock_type, &rate); | 793 | pcxhr_get_external_clock(mgr, mgr->use_clock_type, |
794 | &rate); | ||
681 | else | 795 | else |
682 | rate = mgr->sample_rate; | 796 | rate = mgr->sample_rate; |
683 | if (rate) { | 797 | if (rate) { |
@@ -686,7 +800,7 @@ static int pcxhr_clock_type_put(struct snd_kcontrol *kcontrol, | |||
686 | mgr->sample_rate = rate; | 800 | mgr->sample_rate = rate; |
687 | } | 801 | } |
688 | mutex_unlock(&mgr->setup_mutex); | 802 | mutex_unlock(&mgr->setup_mutex); |
689 | ret = 1; /* return 1 even if the set was not done. ok ? */ | 803 | ret = 1; /* return 1 even if the set was not done. ok ? */ |
690 | } | 804 | } |
691 | mutex_unlock(&mgr->mixer_mutex); | 805 | mutex_unlock(&mgr->mixer_mutex); |
692 | return ret; | 806 | return ret; |
@@ -747,14 +861,16 @@ static struct snd_kcontrol_new pcxhr_control_clock_rate = { | |||
747 | /* | 861 | /* |
748 | * IEC958 status bits | 862 | * IEC958 status bits |
749 | */ | 863 | */ |
750 | static int pcxhr_iec958_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 864 | static int pcxhr_iec958_info(struct snd_kcontrol *kcontrol, |
865 | struct snd_ctl_elem_info *uinfo) | ||
751 | { | 866 | { |
752 | uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; | 867 | uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; |
753 | uinfo->count = 1; | 868 | uinfo->count = 1; |
754 | return 0; | 869 | return 0; |
755 | } | 870 | } |
756 | 871 | ||
757 | static int pcxhr_iec958_capture_byte(struct snd_pcxhr *chip, int aes_idx, unsigned char* aes_bits) | 872 | static int pcxhr_iec958_capture_byte(struct snd_pcxhr *chip, |
873 | int aes_idx, unsigned char *aes_bits) | ||
758 | { | 874 | { |
759 | int i, err; | 875 | int i, err; |
760 | unsigned char temp; | 876 | unsigned char temp; |
@@ -763,39 +879,61 @@ static int pcxhr_iec958_capture_byte(struct snd_pcxhr *chip, int aes_idx, unsign | |||
763 | pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ); | 879 | pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ); |
764 | rmh.cmd[0] |= IO_NUM_UER_CHIP_REG; | 880 | rmh.cmd[0] |= IO_NUM_UER_CHIP_REG; |
765 | switch (chip->chip_idx) { | 881 | switch (chip->chip_idx) { |
766 | case 0: rmh.cmd[1] = CS8420_01_CS; break; /* use CS8416_01_CS for AES SYNC plug */ | 882 | /* instead of CS8420_01_CS use CS8416_01_CS for AES SYNC plug */ |
883 | case 0: rmh.cmd[1] = CS8420_01_CS; break; | ||
767 | case 1: rmh.cmd[1] = CS8420_23_CS; break; | 884 | case 1: rmh.cmd[1] = CS8420_23_CS; break; |
768 | case 2: rmh.cmd[1] = CS8420_45_CS; break; | 885 | case 2: rmh.cmd[1] = CS8420_45_CS; break; |
769 | case 3: rmh.cmd[1] = CS8420_67_CS; break; | 886 | case 3: rmh.cmd[1] = CS8420_67_CS; break; |
770 | default: return -EINVAL; | 887 | default: return -EINVAL; |
771 | } | 888 | } |
772 | switch (aes_idx) { | 889 | if (chip->mgr->board_aes_in_192k) { |
773 | case 0: rmh.cmd[2] = CS8420_CSB0; break; /* use CS8416_CSBx for AES SYNC plug */ | 890 | switch (aes_idx) { |
774 | case 1: rmh.cmd[2] = CS8420_CSB1; break; | 891 | case 0: rmh.cmd[2] = CS8416_CSB0; break; |
775 | case 2: rmh.cmd[2] = CS8420_CSB2; break; | 892 | case 1: rmh.cmd[2] = CS8416_CSB1; break; |
776 | case 3: rmh.cmd[2] = CS8420_CSB3; break; | 893 | case 2: rmh.cmd[2] = CS8416_CSB2; break; |
777 | case 4: rmh.cmd[2] = CS8420_CSB4; break; | 894 | case 3: rmh.cmd[2] = CS8416_CSB3; break; |
778 | default: return -EINVAL; | 895 | case 4: rmh.cmd[2] = CS8416_CSB4; break; |
896 | default: return -EINVAL; | ||
897 | } | ||
898 | } else { | ||
899 | switch (aes_idx) { | ||
900 | /* instead of CS8420_CSB0 use CS8416_CSBx for AES SYNC plug */ | ||
901 | case 0: rmh.cmd[2] = CS8420_CSB0; break; | ||
902 | case 1: rmh.cmd[2] = CS8420_CSB1; break; | ||
903 | case 2: rmh.cmd[2] = CS8420_CSB2; break; | ||
904 | case 3: rmh.cmd[2] = CS8420_CSB3; break; | ||
905 | case 4: rmh.cmd[2] = CS8420_CSB4; break; | ||
906 | default: return -EINVAL; | ||
907 | } | ||
779 | } | 908 | } |
780 | rmh.cmd[1] &= 0x0fffff; /* size and code the chip id for the fpga */ | 909 | /* size and code the chip id for the fpga */ |
781 | rmh.cmd[2] &= CHIP_SIG_AND_MAP_SPI; /* chip signature + map for spi read */ | 910 | rmh.cmd[1] &= 0x0fffff; |
911 | /* chip signature + map for spi read */ | ||
912 | rmh.cmd[2] &= CHIP_SIG_AND_MAP_SPI; | ||
782 | rmh.cmd_len = 3; | 913 | rmh.cmd_len = 3; |
783 | err = pcxhr_send_msg(chip->mgr, &rmh); | 914 | err = pcxhr_send_msg(chip->mgr, &rmh); |
784 | if (err) | 915 | if (err) |
785 | return err; | 916 | return err; |
786 | temp = 0; | 917 | |
787 | for (i = 0; i < 8; i++) { | 918 | if (chip->mgr->board_aes_in_192k) { |
788 | /* attention : reversed bit order (not with CS8416_01_CS) */ | 919 | temp = (unsigned char)rmh.stat[1]; |
789 | temp <<= 1; | 920 | } else { |
790 | if (rmh.stat[1] & (1 << i)) | 921 | temp = 0; |
791 | temp |= 1; | 922 | /* reversed bit order (not with CS8416_01_CS) */ |
923 | for (i = 0; i < 8; i++) { | ||
924 | temp <<= 1; | ||
925 | if (rmh.stat[1] & (1 << i)) | ||
926 | temp |= 1; | ||
927 | } | ||
792 | } | 928 | } |
793 | snd_printdd("read iec958 AES %d byte %d = 0x%x\n", chip->chip_idx, aes_idx, temp); | 929 | snd_printdd("read iec958 AES %d byte %d = 0x%x\n", |
930 | chip->chip_idx, aes_idx, temp); | ||
794 | *aes_bits = temp; | 931 | *aes_bits = temp; |
795 | return 0; | 932 | return 0; |
796 | } | 933 | } |
797 | 934 | ||
798 | static int pcxhr_iec958_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 935 | static int pcxhr_iec958_get(struct snd_kcontrol *kcontrol, |
936 | struct snd_ctl_elem_value *ucontrol) | ||
799 | { | 937 | { |
800 | struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); | 938 | struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); |
801 | unsigned char aes_bits; | 939 | unsigned char aes_bits; |
@@ -806,7 +944,12 @@ static int pcxhr_iec958_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v | |||
806 | if (kcontrol->private_value == 0) /* playback */ | 944 | if (kcontrol->private_value == 0) /* playback */ |
807 | aes_bits = chip->aes_bits[i]; | 945 | aes_bits = chip->aes_bits[i]; |
808 | else { /* capture */ | 946 | else { /* capture */ |
809 | err = pcxhr_iec958_capture_byte(chip, i, &aes_bits); | 947 | if (chip->mgr->is_hr_stereo) |
948 | err = hr222_iec958_capture_byte(chip, i, | ||
949 | &aes_bits); | ||
950 | else | ||
951 | err = pcxhr_iec958_capture_byte(chip, i, | ||
952 | &aes_bits); | ||
810 | if (err) | 953 | if (err) |
811 | break; | 954 | break; |
812 | } | 955 | } |
@@ -825,7 +968,8 @@ static int pcxhr_iec958_mask_get(struct snd_kcontrol *kcontrol, | |||
825 | return 0; | 968 | return 0; |
826 | } | 969 | } |
827 | 970 | ||
828 | static int pcxhr_iec958_update_byte(struct snd_pcxhr *chip, int aes_idx, unsigned char aes_bits) | 971 | static int pcxhr_iec958_update_byte(struct snd_pcxhr *chip, |
972 | int aes_idx, unsigned char aes_bits) | ||
829 | { | 973 | { |
830 | int i, err, cmd; | 974 | int i, err, cmd; |
831 | unsigned char new_bits = aes_bits; | 975 | unsigned char new_bits = aes_bits; |
@@ -834,12 +978,12 @@ static int pcxhr_iec958_update_byte(struct snd_pcxhr *chip, int aes_idx, unsigne | |||
834 | 978 | ||
835 | for (i = 0; i < 8; i++) { | 979 | for (i = 0; i < 8; i++) { |
836 | if ((old_bits & 0x01) != (new_bits & 0x01)) { | 980 | if ((old_bits & 0x01) != (new_bits & 0x01)) { |
837 | cmd = chip->chip_idx & 0x03; /* chip index 0..3 */ | 981 | cmd = chip->chip_idx & 0x03; /* chip index 0..3 */ |
838 | if(chip->chip_idx > 3) | 982 | if (chip->chip_idx > 3) |
839 | /* new bit used if chip_idx>3 (PCX1222HR) */ | 983 | /* new bit used if chip_idx>3 (PCX1222HR) */ |
840 | cmd |= 1 << 22; | 984 | cmd |= 1 << 22; |
841 | cmd |= ((aes_idx << 3) + i) << 2; /* add bit offset */ | 985 | cmd |= ((aes_idx << 3) + i) << 2; /* add bit offset */ |
842 | cmd |= (new_bits & 0x01) << 23; /* add bit value */ | 986 | cmd |= (new_bits & 0x01) << 23; /* add bit value */ |
843 | pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); | 987 | pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); |
844 | rmh.cmd[0] |= IO_NUM_REG_CUER; | 988 | rmh.cmd[0] |= IO_NUM_REG_CUER; |
845 | rmh.cmd[1] = cmd; | 989 | rmh.cmd[1] = cmd; |
@@ -867,7 +1011,12 @@ static int pcxhr_iec958_put(struct snd_kcontrol *kcontrol, | |||
867 | mutex_lock(&chip->mgr->mixer_mutex); | 1011 | mutex_lock(&chip->mgr->mixer_mutex); |
868 | for (i = 0; i < 5; i++) { | 1012 | for (i = 0; i < 5; i++) { |
869 | if (ucontrol->value.iec958.status[i] != chip->aes_bits[i]) { | 1013 | if (ucontrol->value.iec958.status[i] != chip->aes_bits[i]) { |
870 | pcxhr_iec958_update_byte(chip, i, ucontrol->value.iec958.status[i]); | 1014 | if (chip->mgr->is_hr_stereo) |
1015 | hr222_iec958_update_byte(chip, i, | ||
1016 | ucontrol->value.iec958.status[i]); | ||
1017 | else | ||
1018 | pcxhr_iec958_update_byte(chip, i, | ||
1019 | ucontrol->value.iec958.status[i]); | ||
871 | changed = 1; | 1020 | changed = 1; |
872 | } | 1021 | } |
873 | } | 1022 | } |
@@ -917,29 +1066,53 @@ static void pcxhr_init_audio_levels(struct snd_pcxhr *chip) | |||
917 | /* at boot time the digital volumes are unmuted 0dB */ | 1066 | /* at boot time the digital volumes are unmuted 0dB */ |
918 | for (j = 0; j < PCXHR_PLAYBACK_STREAMS; j++) { | 1067 | for (j = 0; j < PCXHR_PLAYBACK_STREAMS; j++) { |
919 | chip->digital_playback_active[j][i] = 1; | 1068 | chip->digital_playback_active[j][i] = 1; |
920 | chip->digital_playback_volume[j][i] = PCXHR_DIGITAL_ZERO_LEVEL; | 1069 | chip->digital_playback_volume[j][i] = |
1070 | PCXHR_DIGITAL_ZERO_LEVEL; | ||
921 | } | 1071 | } |
922 | /* after boot, only two bits are set on the uer interface */ | 1072 | /* after boot, only two bits are set on the uer |
923 | chip->aes_bits[0] = IEC958_AES0_PROFESSIONAL | IEC958_AES0_PRO_FS_48000; | 1073 | * interface |
924 | /* only for test purpose, remove later */ | 1074 | */ |
1075 | chip->aes_bits[0] = (IEC958_AES0_PROFESSIONAL | | ||
1076 | IEC958_AES0_PRO_FS_48000); | ||
925 | #ifdef CONFIG_SND_DEBUG | 1077 | #ifdef CONFIG_SND_DEBUG |
926 | /* analog volumes for playback (is LEVEL_MIN after boot) */ | 1078 | /* analog volumes for playback |
1079 | * (is LEVEL_MIN after boot) | ||
1080 | */ | ||
927 | chip->analog_playback_active[i] = 1; | 1081 | chip->analog_playback_active[i] = 1; |
928 | chip->analog_playback_volume[i] = PCXHR_ANALOG_PLAYBACK_ZERO_LEVEL; | 1082 | if (chip->mgr->is_hr_stereo) |
929 | pcxhr_update_analog_audio_level(chip, 0, i); | 1083 | chip->analog_playback_volume[i] = |
1084 | HR222_LINE_PLAYBACK_ZERO_LEVEL; | ||
1085 | else { | ||
1086 | chip->analog_playback_volume[i] = | ||
1087 | PCXHR_LINE_PLAYBACK_ZERO_LEVEL; | ||
1088 | pcxhr_update_analog_audio_level(chip, 0, i); | ||
1089 | } | ||
930 | #endif | 1090 | #endif |
931 | /* test end */ | 1091 | /* stereo cards need to be initialised after boot */ |
1092 | if (chip->mgr->is_hr_stereo) | ||
1093 | hr222_update_analog_audio_level(chip, 0, i); | ||
932 | } | 1094 | } |
933 | if (chip->nb_streams_capt) { | 1095 | if (chip->nb_streams_capt) { |
934 | /* at boot time the digital volumes are unmuted 0dB */ | 1096 | /* at boot time the digital volumes are unmuted 0dB */ |
935 | chip->digital_capture_volume[i] = PCXHR_DIGITAL_ZERO_LEVEL; | 1097 | chip->digital_capture_volume[i] = |
936 | /* only for test purpose, remove later */ | 1098 | PCXHR_DIGITAL_ZERO_LEVEL; |
1099 | chip->analog_capture_active = 1; | ||
937 | #ifdef CONFIG_SND_DEBUG | 1100 | #ifdef CONFIG_SND_DEBUG |
938 | /* analog volumes for playback (is LEVEL_MIN after boot) */ | 1101 | /* analog volumes for playback |
939 | chip->analog_capture_volume[i] = PCXHR_ANALOG_CAPTURE_ZERO_LEVEL; | 1102 | * (is LEVEL_MIN after boot) |
940 | pcxhr_update_analog_audio_level(chip, 1, i); | 1103 | */ |
1104 | if (chip->mgr->is_hr_stereo) | ||
1105 | chip->analog_capture_volume[i] = | ||
1106 | HR222_LINE_CAPTURE_ZERO_LEVEL; | ||
1107 | else { | ||
1108 | chip->analog_capture_volume[i] = | ||
1109 | PCXHR_LINE_CAPTURE_ZERO_LEVEL; | ||
1110 | pcxhr_update_analog_audio_level(chip, 1, i); | ||
1111 | } | ||
941 | #endif | 1112 | #endif |
942 | /* test end */ | 1113 | /* stereo cards need to be initialised after boot */ |
1114 | if (chip->mgr->is_hr_stereo) | ||
1115 | hr222_update_analog_audio_level(chip, 1, i); | ||
943 | } | 1116 | } |
944 | } | 1117 | } |
945 | 1118 | ||
@@ -963,90 +1136,125 @@ int pcxhr_create_mixer(struct pcxhr_mgr *mgr) | |||
963 | temp = pcxhr_control_analog_level; | 1136 | temp = pcxhr_control_analog_level; |
964 | temp.name = "Master Playback Volume"; | 1137 | temp.name = "Master Playback Volume"; |
965 | temp.private_value = 0; /* playback */ | 1138 | temp.private_value = 0; /* playback */ |
966 | temp.tlv.p = db_scale_analog_playback; | 1139 | if (mgr->is_hr_stereo) |
967 | if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) | 1140 | temp.tlv.p = db_scale_a_hr222_playback; |
1141 | else | ||
1142 | temp.tlv.p = db_scale_analog_playback; | ||
1143 | err = snd_ctl_add(chip->card, | ||
1144 | snd_ctl_new1(&temp, chip)); | ||
1145 | if (err < 0) | ||
968 | return err; | 1146 | return err; |
1147 | |||
969 | /* output mute controls */ | 1148 | /* output mute controls */ |
970 | if ((err = snd_ctl_add(chip->card, | 1149 | err = snd_ctl_add(chip->card, |
971 | snd_ctl_new1(&pcxhr_control_output_switch, | 1150 | snd_ctl_new1(&pcxhr_control_output_switch, |
972 | chip))) < 0) | 1151 | chip)); |
1152 | if (err < 0) | ||
973 | return err; | 1153 | return err; |
974 | 1154 | ||
975 | temp = snd_pcxhr_pcm_vol; | 1155 | temp = snd_pcxhr_pcm_vol; |
976 | temp.name = "PCM Playback Volume"; | 1156 | temp.name = "PCM Playback Volume"; |
977 | temp.count = PCXHR_PLAYBACK_STREAMS; | 1157 | temp.count = PCXHR_PLAYBACK_STREAMS; |
978 | temp.private_value = 0; /* playback */ | 1158 | temp.private_value = 0; /* playback */ |
979 | if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) | 1159 | err = snd_ctl_add(chip->card, |
1160 | snd_ctl_new1(&temp, chip)); | ||
1161 | if (err < 0) | ||
980 | return err; | 1162 | return err; |
981 | 1163 | ||
982 | if ((err = snd_ctl_add(chip->card, | 1164 | err = snd_ctl_add(chip->card, |
983 | snd_ctl_new1(&pcxhr_control_pcm_switch, | 1165 | snd_ctl_new1(&pcxhr_control_pcm_switch, chip)); |
984 | chip))) < 0) | 1166 | if (err < 0) |
985 | return err; | 1167 | return err; |
986 | 1168 | ||
987 | /* IEC958 controls */ | 1169 | /* IEC958 controls */ |
988 | if ((err = snd_ctl_add(chip->card, | 1170 | err = snd_ctl_add(chip->card, |
989 | snd_ctl_new1(&pcxhr_control_playback_iec958_mask, | 1171 | snd_ctl_new1(&pcxhr_control_playback_iec958_mask, |
990 | chip))) < 0) | 1172 | chip)); |
1173 | if (err < 0) | ||
991 | return err; | 1174 | return err; |
992 | if ((err = snd_ctl_add(chip->card, | 1175 | |
993 | snd_ctl_new1(&pcxhr_control_playback_iec958, | 1176 | err = snd_ctl_add(chip->card, |
994 | chip))) < 0) | 1177 | snd_ctl_new1(&pcxhr_control_playback_iec958, |
1178 | chip)); | ||
1179 | if (err < 0) | ||
995 | return err; | 1180 | return err; |
996 | } | 1181 | } |
997 | if (chip->nb_streams_capt) { | 1182 | if (chip->nb_streams_capt) { |
998 | /* analog input level control only on first two chips !*/ | 1183 | /* analog input level control */ |
999 | temp = pcxhr_control_analog_level; | 1184 | temp = pcxhr_control_analog_level; |
1000 | temp.name = "Master Capture Volume"; | 1185 | temp.name = "Line Capture Volume"; |
1001 | temp.private_value = 1; /* capture */ | 1186 | temp.private_value = 1; /* capture */ |
1002 | temp.tlv.p = db_scale_analog_capture; | 1187 | if (mgr->is_hr_stereo) |
1003 | if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) | 1188 | temp.tlv.p = db_scale_a_hr222_capture; |
1189 | else | ||
1190 | temp.tlv.p = db_scale_analog_capture; | ||
1191 | |||
1192 | err = snd_ctl_add(chip->card, | ||
1193 | snd_ctl_new1(&temp, chip)); | ||
1194 | if (err < 0) | ||
1004 | return err; | 1195 | return err; |
1005 | 1196 | ||
1006 | temp = snd_pcxhr_pcm_vol; | 1197 | temp = snd_pcxhr_pcm_vol; |
1007 | temp.name = "PCM Capture Volume"; | 1198 | temp.name = "PCM Capture Volume"; |
1008 | temp.count = 1; | 1199 | temp.count = 1; |
1009 | temp.private_value = 1; /* capture */ | 1200 | temp.private_value = 1; /* capture */ |
1010 | if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) | 1201 | |
1202 | err = snd_ctl_add(chip->card, | ||
1203 | snd_ctl_new1(&temp, chip)); | ||
1204 | if (err < 0) | ||
1011 | return err; | 1205 | return err; |
1206 | |||
1012 | /* Audio source */ | 1207 | /* Audio source */ |
1013 | if ((err = snd_ctl_add(chip->card, | 1208 | err = snd_ctl_add(chip->card, |
1014 | snd_ctl_new1(&pcxhr_control_audio_src, | 1209 | snd_ctl_new1(&pcxhr_control_audio_src, chip)); |
1015 | chip))) < 0) | 1210 | if (err < 0) |
1016 | return err; | 1211 | return err; |
1212 | |||
1017 | /* IEC958 controls */ | 1213 | /* IEC958 controls */ |
1018 | if ((err = snd_ctl_add(chip->card, | 1214 | err = snd_ctl_add(chip->card, |
1019 | snd_ctl_new1(&pcxhr_control_capture_iec958_mask, | 1215 | snd_ctl_new1(&pcxhr_control_capture_iec958_mask, |
1020 | chip))) < 0) | 1216 | chip)); |
1217 | if (err < 0) | ||
1021 | return err; | 1218 | return err; |
1022 | if ((err = snd_ctl_add(chip->card, | 1219 | |
1023 | snd_ctl_new1(&pcxhr_control_capture_iec958, | 1220 | err = snd_ctl_add(chip->card, |
1024 | chip))) < 0) | 1221 | snd_ctl_new1(&pcxhr_control_capture_iec958, |
1222 | chip)); | ||
1223 | if (err < 0) | ||
1025 | return err; | 1224 | return err; |
1225 | |||
1226 | if (mgr->is_hr_stereo) { | ||
1227 | err = hr222_add_mic_controls(chip); | ||
1228 | if (err < 0) | ||
1229 | return err; | ||
1230 | } | ||
1026 | } | 1231 | } |
1027 | /* monitoring only if playback and capture device available */ | 1232 | /* monitoring only if playback and capture device available */ |
1028 | if (chip->nb_streams_capt > 0 && chip->nb_streams_play > 0) { | 1233 | if (chip->nb_streams_capt > 0 && chip->nb_streams_play > 0) { |
1029 | /* monitoring */ | 1234 | /* monitoring */ |
1030 | if ((err = snd_ctl_add(chip->card, | 1235 | err = snd_ctl_add(chip->card, |
1031 | snd_ctl_new1(&pcxhr_control_monitor_vol, | 1236 | snd_ctl_new1(&pcxhr_control_monitor_vol, chip)); |
1032 | chip))) < 0) | 1237 | if (err < 0) |
1033 | return err; | 1238 | return err; |
1034 | if ((err = snd_ctl_add(chip->card, | 1239 | |
1035 | snd_ctl_new1(&pcxhr_control_monitor_sw, | 1240 | err = snd_ctl_add(chip->card, |
1036 | chip))) < 0) | 1241 | snd_ctl_new1(&pcxhr_control_monitor_sw, chip)); |
1242 | if (err < 0) | ||
1037 | return err; | 1243 | return err; |
1038 | } | 1244 | } |
1039 | 1245 | ||
1040 | if (i == 0) { | 1246 | if (i == 0) { |
1041 | /* clock mode only one control per pcxhr */ | 1247 | /* clock mode only one control per pcxhr */ |
1042 | if ((err = snd_ctl_add(chip->card, | 1248 | err = snd_ctl_add(chip->card, |
1043 | snd_ctl_new1(&pcxhr_control_clock_type, | 1249 | snd_ctl_new1(&pcxhr_control_clock_type, mgr)); |
1044 | mgr))) < 0) | 1250 | if (err < 0) |
1045 | return err; | 1251 | return err; |
1046 | /* non standard control used to scan the external clock presence/frequencies */ | 1252 | /* non standard control used to scan |
1047 | if ((err = snd_ctl_add(chip->card, | 1253 | * the external clock presence/frequencies |
1048 | snd_ctl_new1(&pcxhr_control_clock_rate, | 1254 | */ |
1049 | mgr))) < 0) | 1255 | err = snd_ctl_add(chip->card, |
1256 | snd_ctl_new1(&pcxhr_control_clock_rate, mgr)); | ||
1257 | if (err < 0) | ||
1050 | return err; | 1258 | return err; |
1051 | } | 1259 | } |
1052 | 1260 | ||