diff options
author | James Courtier-Dutton <James@superbug.co.uk> | 2006-04-09 08:01:34 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2006-06-22 15:32:35 -0400 |
commit | 6129daaa0d2b84c0e376b6b17b3d3740c4d1d1ca (patch) | |
tree | 8a043f22709ffa613f44a4bc1d3aeed256f488cf /sound/pci/ca0106/ca0106_mixer.c | |
parent | 52ab3f3dc711eeccbfbcc5d4f5c5d9b9ff59650f (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.c | 152 |
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 | ||
174 | static 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 | |||
190 | static 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 | |||
199 | static 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 | |||
174 | static int snd_ca0106_capture_mic_line_in_info(struct snd_kcontrol *kcontrol, | 230 | static 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, | |||
225 | static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in __devinitdata = | 281 | static 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 | ||
388 | static 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 | |||
398 | static 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 | |||
411 | static 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 | ||
342 | static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = { | 464 | static 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, |