diff options
author | Oldřich Jedlička <oldium.pro@seznam.cz> | 2009-08-22 14:13:51 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-09-12 11:19:41 -0400 |
commit | 736dadaa17218b6e516053ee896dbb075eadba4b (patch) | |
tree | 1a7ef0b80e77bf7f65236abacfa7e0f35840692e | |
parent | ed44f66e4039dfc8fb7905078d546c83adf76811 (diff) |
V4L/DVB (12586): Update ALSA capture controls according to selected source.
The patch introduces new snd_saa7134_capsrc_set (code taken from
snd_saa7134_capsrc_put) that updates also the ALSA capture controls during
snd_card_saa7134_capture_prepare and snd_saa7134_capsrc_put.
There can be much more work done in order to unify the control of the card
(now the card's capture source is tuned/switched in saa7134-video.c too), but
I don't have enough time. This work could be a starting point, but it can be
applied as-is too (it doesn't need any further work to make it working).
Signed-off-by: Oldřich Jedlička <oldium.pro@seznam.cz>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/video/saa7134/saa7134-alsa.c | 228 |
1 files changed, 150 insertions, 78 deletions
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 7c0a3a3d61a6..d48c450ed77c 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c | |||
@@ -40,6 +40,7 @@ MODULE_PARM_DESC(debug,"enable debug messages [alsa]"); | |||
40 | */ | 40 | */ |
41 | 41 | ||
42 | /* defaults */ | 42 | /* defaults */ |
43 | #define MIXER_ADDR_UNSELECTED -1 | ||
43 | #define MIXER_ADDR_TVTUNER 0 | 44 | #define MIXER_ADDR_TVTUNER 0 |
44 | #define MIXER_ADDR_LINE1 1 | 45 | #define MIXER_ADDR_LINE1 1 |
45 | #define MIXER_ADDR_LINE2 2 | 46 | #define MIXER_ADDR_LINE2 2 |
@@ -68,7 +69,9 @@ typedef struct snd_card_saa7134 { | |||
68 | struct snd_card *card; | 69 | struct snd_card *card; |
69 | spinlock_t mixer_lock; | 70 | spinlock_t mixer_lock; |
70 | int mixer_volume[MIXER_ADDR_LAST+1][2]; | 71 | int mixer_volume[MIXER_ADDR_LAST+1][2]; |
71 | int capture_source[MIXER_ADDR_LAST+1][2]; | 72 | int capture_source_addr; |
73 | int capture_source[2]; | ||
74 | struct snd_kcontrol *capture_ctl[MIXER_ADDR_LAST+1]; | ||
72 | struct pci_dev *pci; | 75 | struct pci_dev *pci; |
73 | struct saa7134_dev *dev; | 76 | struct saa7134_dev *dev; |
74 | 77 | ||
@@ -314,6 +317,115 @@ static int dsp_buffer_free(struct saa7134_dev *dev) | |||
314 | return 0; | 317 | return 0; |
315 | } | 318 | } |
316 | 319 | ||
320 | /* | ||
321 | * Setting the capture source and updating the ALSA controls | ||
322 | */ | ||
323 | static int snd_saa7134_capsrc_set(struct snd_kcontrol *kcontrol, | ||
324 | int left, int right, bool force_notify) | ||
325 | { | ||
326 | snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); | ||
327 | int change = 0, addr = kcontrol->private_value; | ||
328 | int active, old_addr; | ||
329 | u32 anabar, xbarin; | ||
330 | int analog_io, rate; | ||
331 | struct saa7134_dev *dev; | ||
332 | |||
333 | dev = chip->dev; | ||
334 | |||
335 | spin_lock_irq(&chip->mixer_lock); | ||
336 | |||
337 | active = left != 0 || right != 0; | ||
338 | old_addr = chip->capture_source_addr; | ||
339 | |||
340 | /* The active capture source cannot be deactivated */ | ||
341 | if (active) { | ||
342 | change = old_addr != addr || | ||
343 | chip->capture_source[0] != left || | ||
344 | chip->capture_source[1] != right; | ||
345 | |||
346 | chip->capture_source[0] = left; | ||
347 | chip->capture_source[1] = right; | ||
348 | chip->capture_source_addr = addr; | ||
349 | dev->dmasound.input = addr; | ||
350 | } | ||
351 | spin_unlock_irq(&chip->mixer_lock); | ||
352 | |||
353 | if (change) { | ||
354 | switch (dev->pci->device) { | ||
355 | |||
356 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | ||
357 | switch (addr) { | ||
358 | case MIXER_ADDR_TVTUNER: | ||
359 | saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, | ||
360 | 0xc0, 0xc0); | ||
361 | saa_andorb(SAA7134_SIF_SAMPLE_FREQ, | ||
362 | 0x03, 0x00); | ||
363 | break; | ||
364 | case MIXER_ADDR_LINE1: | ||
365 | case MIXER_ADDR_LINE2: | ||
366 | analog_io = (MIXER_ADDR_LINE1 == addr) ? | ||
367 | 0x00 : 0x08; | ||
368 | rate = (32000 == dev->dmasound.rate) ? | ||
369 | 0x01 : 0x03; | ||
370 | saa_andorb(SAA7134_ANALOG_IO_SELECT, | ||
371 | 0x08, analog_io); | ||
372 | saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, | ||
373 | 0xc0, 0x80); | ||
374 | saa_andorb(SAA7134_SIF_SAMPLE_FREQ, | ||
375 | 0x03, rate); | ||
376 | break; | ||
377 | } | ||
378 | |||
379 | break; | ||
380 | case PCI_DEVICE_ID_PHILIPS_SAA7133: | ||
381 | case PCI_DEVICE_ID_PHILIPS_SAA7135: | ||
382 | xbarin = 0x03; /* adc */ | ||
383 | anabar = 0; | ||
384 | switch (addr) { | ||
385 | case MIXER_ADDR_TVTUNER: | ||
386 | xbarin = 0; /* Demodulator */ | ||
387 | anabar = 2; /* DACs */ | ||
388 | break; | ||
389 | case MIXER_ADDR_LINE1: | ||
390 | anabar = 0; /* aux1, aux1 */ | ||
391 | break; | ||
392 | case MIXER_ADDR_LINE2: | ||
393 | anabar = 9; /* aux2, aux2 */ | ||
394 | break; | ||
395 | } | ||
396 | |||
397 | /* output xbar always main channel */ | ||
398 | saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL1, | ||
399 | 0xbbbb10); | ||
400 | |||
401 | if (left || right) { | ||
402 | /* We've got data, turn the input on */ | ||
403 | saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, | ||
404 | xbarin); | ||
405 | saa_writel(SAA7133_ANALOG_IO_SELECT, anabar); | ||
406 | } else { | ||
407 | saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, | ||
408 | 0); | ||
409 | saa_writel(SAA7133_ANALOG_IO_SELECT, 0); | ||
410 | } | ||
411 | break; | ||
412 | } | ||
413 | } | ||
414 | |||
415 | if (change) { | ||
416 | if (force_notify) | ||
417 | snd_ctl_notify(chip->card, | ||
418 | SNDRV_CTL_EVENT_MASK_VALUE, | ||
419 | &chip->capture_ctl[addr]->id); | ||
420 | |||
421 | if (old_addr != MIXER_ADDR_UNSELECTED && old_addr != addr) | ||
422 | snd_ctl_notify(chip->card, | ||
423 | SNDRV_CTL_EVENT_MASK_VALUE, | ||
424 | &chip->capture_ctl[old_addr]->id); | ||
425 | } | ||
426 | |||
427 | return change; | ||
428 | } | ||
317 | 429 | ||
318 | /* | 430 | /* |
319 | * ALSA PCM preparation | 431 | * ALSA PCM preparation |
@@ -401,6 +513,10 @@ static int snd_card_saa7134_capture_prepare(struct snd_pcm_substream * substream | |||
401 | 513 | ||
402 | dev->dmasound.rate = runtime->rate; | 514 | dev->dmasound.rate = runtime->rate; |
403 | 515 | ||
516 | /* Setup and update the card/ALSA controls */ | ||
517 | snd_saa7134_capsrc_set(saa7134->capture_ctl[dev->dmasound.input], 1, 1, | ||
518 | true); | ||
519 | |||
404 | return 0; | 520 | return 0; |
405 | 521 | ||
406 | } | 522 | } |
@@ -846,8 +962,13 @@ static int snd_saa7134_capsrc_get(struct snd_kcontrol * kcontrol, | |||
846 | int addr = kcontrol->private_value; | 962 | int addr = kcontrol->private_value; |
847 | 963 | ||
848 | spin_lock_irq(&chip->mixer_lock); | 964 | spin_lock_irq(&chip->mixer_lock); |
849 | ucontrol->value.integer.value[0] = chip->capture_source[addr][0]; | 965 | if (chip->capture_source_addr == addr) { |
850 | ucontrol->value.integer.value[1] = chip->capture_source[addr][1]; | 966 | ucontrol->value.integer.value[0] = chip->capture_source[0]; |
967 | ucontrol->value.integer.value[1] = chip->capture_source[1]; | ||
968 | } else { | ||
969 | ucontrol->value.integer.value[0] = 0; | ||
970 | ucontrol->value.integer.value[1] = 0; | ||
971 | } | ||
851 | spin_unlock_irq(&chip->mixer_lock); | 972 | spin_unlock_irq(&chip->mixer_lock); |
852 | 973 | ||
853 | return 0; | 974 | return 0; |
@@ -856,87 +977,22 @@ static int snd_saa7134_capsrc_get(struct snd_kcontrol * kcontrol, | |||
856 | static int snd_saa7134_capsrc_put(struct snd_kcontrol * kcontrol, | 977 | static int snd_saa7134_capsrc_put(struct snd_kcontrol * kcontrol, |
857 | struct snd_ctl_elem_value * ucontrol) | 978 | struct snd_ctl_elem_value * ucontrol) |
858 | { | 979 | { |
859 | snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); | ||
860 | int change, addr = kcontrol->private_value; | ||
861 | int left, right; | 980 | int left, right; |
862 | u32 anabar, xbarin; | ||
863 | int analog_io, rate; | ||
864 | struct saa7134_dev *dev; | ||
865 | |||
866 | dev = chip->dev; | ||
867 | |||
868 | left = ucontrol->value.integer.value[0] & 1; | 981 | left = ucontrol->value.integer.value[0] & 1; |
869 | right = ucontrol->value.integer.value[1] & 1; | 982 | right = ucontrol->value.integer.value[1] & 1; |
870 | spin_lock_irq(&chip->mixer_lock); | ||
871 | 983 | ||
872 | change = chip->capture_source[addr][0] != left || | 984 | return snd_saa7134_capsrc_set(kcontrol, left, right, false); |
873 | chip->capture_source[addr][1] != right; | ||
874 | chip->capture_source[addr][0] = left; | ||
875 | chip->capture_source[addr][1] = right; | ||
876 | dev->dmasound.input=addr; | ||
877 | spin_unlock_irq(&chip->mixer_lock); | ||
878 | |||
879 | |||
880 | if (change) { | ||
881 | switch (dev->pci->device) { | ||
882 | |||
883 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | ||
884 | switch (addr) { | ||
885 | case MIXER_ADDR_TVTUNER: | ||
886 | saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0xc0); | ||
887 | saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, 0x00); | ||
888 | break; | ||
889 | case MIXER_ADDR_LINE1: | ||
890 | case MIXER_ADDR_LINE2: | ||
891 | analog_io = (MIXER_ADDR_LINE1 == addr) ? 0x00 : 0x08; | ||
892 | rate = (32000 == dev->dmasound.rate) ? 0x01 : 0x03; | ||
893 | saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x08, analog_io); | ||
894 | saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0x80); | ||
895 | saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, rate); | ||
896 | break; | ||
897 | } | ||
898 | |||
899 | break; | ||
900 | case PCI_DEVICE_ID_PHILIPS_SAA7133: | ||
901 | case PCI_DEVICE_ID_PHILIPS_SAA7135: | ||
902 | xbarin = 0x03; // adc | ||
903 | anabar = 0; | ||
904 | switch (addr) { | ||
905 | case MIXER_ADDR_TVTUNER: | ||
906 | xbarin = 0; // Demodulator | ||
907 | anabar = 2; // DACs | ||
908 | break; | ||
909 | case MIXER_ADDR_LINE1: | ||
910 | anabar = 0; // aux1, aux1 | ||
911 | break; | ||
912 | case MIXER_ADDR_LINE2: | ||
913 | anabar = 9; // aux2, aux2 | ||
914 | break; | ||
915 | } | ||
916 | |||
917 | /* output xbar always main channel */ | ||
918 | saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL1, 0xbbbb10); | ||
919 | |||
920 | if (left || right) { // We've got data, turn the input on | ||
921 | saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, xbarin); | ||
922 | saa_writel(SAA7133_ANALOG_IO_SELECT, anabar); | ||
923 | } else { | ||
924 | saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, 0); | ||
925 | saa_writel(SAA7133_ANALOG_IO_SELECT, 0); | ||
926 | } | ||
927 | break; | ||
928 | } | ||
929 | } | ||
930 | |||
931 | return change; | ||
932 | } | 985 | } |
933 | 986 | ||
934 | static struct snd_kcontrol_new snd_saa7134_controls[] = { | 987 | static struct snd_kcontrol_new snd_saa7134_volume_controls[] = { |
935 | SAA713x_VOLUME("Video Volume", 0, MIXER_ADDR_TVTUNER), | 988 | SAA713x_VOLUME("Video Volume", 0, MIXER_ADDR_TVTUNER), |
936 | SAA713x_CAPSRC("Video Capture Switch", 0, MIXER_ADDR_TVTUNER), | ||
937 | SAA713x_VOLUME("Line Volume", 1, MIXER_ADDR_LINE1), | 989 | SAA713x_VOLUME("Line Volume", 1, MIXER_ADDR_LINE1), |
938 | SAA713x_CAPSRC("Line Capture Switch", 1, MIXER_ADDR_LINE1), | ||
939 | SAA713x_VOLUME("Line Volume", 2, MIXER_ADDR_LINE2), | 990 | SAA713x_VOLUME("Line Volume", 2, MIXER_ADDR_LINE2), |
991 | }; | ||
992 | |||
993 | static struct snd_kcontrol_new snd_saa7134_capture_controls[] = { | ||
994 | SAA713x_CAPSRC("Video Capture Switch", 0, MIXER_ADDR_TVTUNER), | ||
995 | SAA713x_CAPSRC("Line Capture Switch", 1, MIXER_ADDR_LINE1), | ||
940 | SAA713x_CAPSRC("Line Capture Switch", 2, MIXER_ADDR_LINE2), | 996 | SAA713x_CAPSRC("Line Capture Switch", 2, MIXER_ADDR_LINE2), |
941 | }; | 997 | }; |
942 | 998 | ||
@@ -951,17 +1007,33 @@ SAA713x_CAPSRC("Line Capture Switch", 2, MIXER_ADDR_LINE2), | |||
951 | static int snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip) | 1007 | static int snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip) |
952 | { | 1008 | { |
953 | struct snd_card *card = chip->card; | 1009 | struct snd_card *card = chip->card; |
1010 | struct snd_kcontrol *kcontrol; | ||
954 | unsigned int idx; | 1011 | unsigned int idx; |
955 | int err; | 1012 | int err, addr; |
956 | 1013 | ||
957 | if (snd_BUG_ON(!chip)) | 1014 | if (snd_BUG_ON(!chip)) |
958 | return -EINVAL; | 1015 | return -EINVAL; |
959 | strcpy(card->mixername, "SAA7134 Mixer"); | 1016 | strcpy(card->mixername, "SAA7134 Mixer"); |
960 | 1017 | ||
961 | for (idx = 0; idx < ARRAY_SIZE(snd_saa7134_controls); idx++) { | 1018 | for (idx = 0; idx < ARRAY_SIZE(snd_saa7134_volume_controls); idx++) { |
962 | if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_saa7134_controls[idx], chip))) < 0) | 1019 | kcontrol = snd_ctl_new1(&snd_saa7134_volume_controls[idx], |
1020 | chip); | ||
1021 | err = snd_ctl_add(card, kcontrol); | ||
1022 | if (err < 0) | ||
963 | return err; | 1023 | return err; |
964 | } | 1024 | } |
1025 | |||
1026 | for (idx = 0; idx < ARRAY_SIZE(snd_saa7134_capture_controls); idx++) { | ||
1027 | kcontrol = snd_ctl_new1(&snd_saa7134_capture_controls[idx], | ||
1028 | chip); | ||
1029 | addr = snd_saa7134_capture_controls[idx].private_value; | ||
1030 | chip->capture_ctl[addr] = kcontrol; | ||
1031 | err = snd_ctl_add(card, kcontrol); | ||
1032 | if (err < 0) | ||
1033 | return err; | ||
1034 | } | ||
1035 | |||
1036 | chip->capture_source_addr = MIXER_ADDR_UNSELECTED; | ||
965 | return 0; | 1037 | return 0; |
966 | } | 1038 | } |
967 | 1039 | ||