aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/ca0106/ca0106_mixer.c
diff options
context:
space:
mode:
authorJames Courtier-Dutton <James@superbug.co.uk>2006-04-09 08:01:34 -0400
committerJaroslav Kysela <perex@suse.cz>2006-06-22 15:32:35 -0400
commit6129daaa0d2b84c0e376b6b17b3d3740c4d1d1ca (patch)
tree8a043f22709ffa613f44a4bc1d3aeed256f488cf /sound/pci/ca0106/ca0106_mixer.c
parent52ab3f3dc711eeccbfbcc5d4f5c5d9b9ff59650f (diff)
[ALSA] ca0106: Add analog capture controls.
Signed-off-by: James Courtier-Dutton <James@superbug.co.uk>
Diffstat (limited to 'sound/pci/ca0106/ca0106_mixer.c')
-rw-r--r--sound/pci/ca0106/ca0106_mixer.c152
1 files changed, 143 insertions, 9 deletions
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c
index 06fe055674fb..8a5833317b0a 100644
--- a/sound/pci/ca0106/ca0106_mixer.c
+++ b/sound/pci/ca0106/ca0106_mixer.c
@@ -171,6 +171,62 @@ static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol,
171 return change; 171 return change;
172} 172}
173 173
174static int snd_ca0106_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
175 struct snd_ctl_elem_info *uinfo)
176{
177 static char *texts[6] = {
178 "Phone", "Mic", "Line in", "Aux"
179 };
180
181 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
182 uinfo->count = 1;
183 uinfo->value.enumerated.items = 4;
184 if (uinfo->value.enumerated.item > 3)
185 uinfo->value.enumerated.item = 3;
186 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
187 return 0;
188}
189
190static int snd_ca0106_i2c_capture_source_get(struct snd_kcontrol *kcontrol,
191 struct snd_ctl_elem_value *ucontrol)
192{
193 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
194
195 ucontrol->value.enumerated.item[0] = emu->i2c_capture_source;
196 return 0;
197}
198
199static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
200 struct snd_ctl_elem_value *ucontrol)
201{
202 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
203 unsigned int source_id;
204 unsigned int ngain, ogain;
205 int change = 0;
206 u32 source;
207 /* If the capture source has changed,
208 * update the capture volume from the cached value
209 * for the particular source.
210 */
211 source_id = ucontrol->value.enumerated.item[0] ;
212 change = (emu->i2c_capture_source != source_id);
213 if (change) {
214 snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
215 ngain = emu->i2c_capture_volume[source_id][0]; /* Left */
216 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
217 if (ngain != ogain)
218 snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff));
219 ngain = emu->i2c_capture_volume[source_id][1]; /* Left */
220 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Left */
221 if (ngain != ogain)
222 snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
223 source = 1 << source_id;
224 snd_ca0106_i2c_write(emu, ADC_MUX, source); /* Set source */
225 emu->i2c_capture_source = source_id;
226 }
227 return change;
228}
229
174static int snd_ca0106_capture_mic_line_in_info(struct snd_kcontrol *kcontrol, 230static int snd_ca0106_capture_mic_line_in_info(struct snd_kcontrol *kcontrol,
175 struct snd_ctl_elem_info *uinfo) 231 struct snd_ctl_elem_info *uinfo)
176{ 232{
@@ -207,16 +263,16 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
207 if (change) { 263 if (change) {
208 emu->capture_mic_line_in = val; 264 emu->capture_mic_line_in = val;
209 if (val) { 265 if (val) {
210 snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_PHONE); /* Mute input */ 266 //snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
211 tmp = inl(emu->port+GPIO) & ~0x400; 267 tmp = inl(emu->port+GPIO) & ~0x400;
212 tmp = tmp | 0x400; 268 tmp = tmp | 0x400;
213 outl(tmp, emu->port+GPIO); 269 outl(tmp, emu->port+GPIO);
214 snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC); 270 //snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC);
215 } else { 271 } else {
216 snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_PHONE); /* Mute input */ 272 //snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
217 tmp = inl(emu->port+GPIO) & ~0x400; 273 tmp = inl(emu->port+GPIO) & ~0x400;
218 outl(tmp, emu->port+GPIO); 274 outl(tmp, emu->port+GPIO);
219 snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN); 275 //snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN);
220 } 276 }
221 } 277 }
222 return change; 278 return change;
@@ -225,7 +281,7 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
225static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in __devinitdata = 281static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in __devinitdata =
226{ 282{
227 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 283 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
228 .name = "Mic/Line in Capture", 284 .name = "Shared Mic/Line in Capture Switch",
229 .info = snd_ca0106_capture_mic_line_in_info, 285 .info = snd_ca0106_capture_mic_line_in_info,
230 .get = snd_ca0106_capture_mic_line_in_get, 286 .get = snd_ca0106_capture_mic_line_in_get,
231 .put = snd_ca0106_capture_mic_line_in_put 287 .put = snd_ca0106_capture_mic_line_in_put
@@ -329,15 +385,81 @@ static int snd_ca0106_volume_put(struct snd_kcontrol *kcontrol,
329 return 1; 385 return 1;
330} 386}
331 387
388static int snd_ca0106_i2c_volume_info(struct snd_kcontrol *kcontrol,
389 struct snd_ctl_elem_info *uinfo)
390{
391 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
392 uinfo->count = 2;
393 uinfo->value.integer.min = 0;
394 uinfo->value.integer.max = 255;
395 return 0;
396}
397
398static int snd_ca0106_i2c_volume_get(struct snd_kcontrol *kcontrol,
399 struct snd_ctl_elem_value *ucontrol)
400{
401 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
402 int source_id;
403
404 source_id = kcontrol->private_value;
405
406 ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0];
407 ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1];
408 return 0;
409}
410
411static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol,
412 struct snd_ctl_elem_value *ucontrol)
413{
414 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
415 unsigned int ogain;
416 unsigned int ngain;
417 int source_id;
418 int change = 0;
419
420 source_id = kcontrol->private_value;
421 ogain = emu->i2c_capture_volume[source_id][0]; /* Left */
422 ngain = ucontrol->value.integer.value[0];
423 if (ngain > 0xff)
424 return 0;
425 if (ogain != ngain) {
426 if (emu->i2c_capture_source == source_id)
427 snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) );
428 emu->i2c_capture_volume[source_id][0] = ucontrol->value.integer.value[0];
429 change = 1;
430 }
431 ogain = emu->i2c_capture_volume[source_id][1]; /* Right */
432 ngain = ucontrol->value.integer.value[1];
433 if (ngain > 0xff)
434 return 0;
435 if (ogain != ngain) {
436 if (emu->i2c_capture_source == source_id)
437 snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
438 emu->i2c_capture_volume[source_id][1] = ucontrol->value.integer.value[1];
439 change = 1;
440 }
441
442 return change;
443}
444
332#define CA_VOLUME(xname,chid,reg) \ 445#define CA_VOLUME(xname,chid,reg) \
333{ \ 446{ \
334 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 447 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
335 .info = snd_ca0106_volume_info, \ 448 .info = snd_ca0106_volume_info, \
336 .get = snd_ca0106_volume_get, \ 449 .get = snd_ca0106_volume_get, \
337 .put = snd_ca0106_volume_put, \ 450 .put = snd_ca0106_volume_put, \
338 .private_value = ((chid) << 8) | (reg) \ 451 .private_value = ((chid) << 8) | (reg) \
339} 452}
340 453
454#define I2C_VOLUME(xname,chid) \
455{ \
456 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
457 .info = snd_ca0106_i2c_volume_info, \
458 .get = snd_ca0106_i2c_volume_get, \
459 .put = snd_ca0106_i2c_volume_put, \
460 .private_value = chid \
461}
462
341 463
342static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = { 464static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
343 CA_VOLUME("Analog Front Playback Volume", 465 CA_VOLUME("Analog Front Playback Volume",
@@ -361,6 +483,11 @@ static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
361 CA_VOLUME("CAPTURE feedback Playback Volume", 483 CA_VOLUME("CAPTURE feedback Playback Volume",
362 1, CAPTURE_CONTROL), 484 1, CAPTURE_CONTROL),
363 485
486 I2C_VOLUME("Phone Capture Volume", 0),
487 I2C_VOLUME("Mic Capture Volume", 1),
488 I2C_VOLUME("Line in Capture Volume", 2),
489 I2C_VOLUME("Aux Capture Volume", 3),
490
364 { 491 {
365 .access = SNDRV_CTL_ELEM_ACCESS_READ, 492 .access = SNDRV_CTL_ELEM_ACCESS_READ,
366 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 493 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -378,12 +505,19 @@ static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
378 }, 505 },
379 { 506 {
380 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 507 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
381 .name = "Capture Source", 508 .name = "Digital Capture Source",
382 .info = snd_ca0106_capture_source_info, 509 .info = snd_ca0106_capture_source_info,
383 .get = snd_ca0106_capture_source_get, 510 .get = snd_ca0106_capture_source_get,
384 .put = snd_ca0106_capture_source_put 511 .put = snd_ca0106_capture_source_put
385 }, 512 },
386 { 513 {
514 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
515 .name = "Capture Source",
516 .info = snd_ca0106_i2c_capture_source_info,
517 .get = snd_ca0106_i2c_capture_source_get,
518 .put = snd_ca0106_i2c_capture_source_put
519 },
520 {
387 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 521 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
388 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), 522 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
389 .count = 4, 523 .count = 4,