[ALSA] oxygen: make all DMA channels configurable
authorClemens Ladisch <clemens@ladisch.de>
Wed, 16 Jan 2008 07:30:38 +0000 (08:30 +0100)
committerJaroslav Kysela <perex@perex.cz>
Thu, 31 Jan 2008 16:30:00 +0000 (17:30 +0100)
Allow the card models to specify whether each of the hardware DMA
channels is used.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
sound/pci/oxygen/oxygen.c
sound/pci/oxygen/oxygen.h
sound/pci/oxygen/oxygen_pcm.c
sound/pci/oxygen/virtuoso.c

index 83c6fab425feef7db9bfc8bb36ddccb2a328e07c..e2dda16d5dcc0caa8fc2a327738b53c9811ccbbb 100644 (file)
@@ -256,6 +256,11 @@ static const struct oxygen_model model_generic = {
        .update_dac_volume = update_ak4396_volume,
        .update_dac_mute = update_ak4396_mute,
        .dac_tlv = ak4396_db_scale,
+       .used_channels = OXYGEN_CHANNEL_A |
+                        OXYGEN_CHANNEL_C |
+                        OXYGEN_CHANNEL_SPDIF |
+                        OXYGEN_CHANNEL_MULTICH |
+                        OXYGEN_CHANNEL_AC97,
        .function_flags = OXYGEN_FUNCTION_ENABLE_SPI_4_5,
 };
 static const struct oxygen_model model_meridian = {
@@ -270,7 +275,11 @@ static const struct oxygen_model model_meridian = {
        .update_dac_volume = update_ak4396_volume,
        .update_dac_mute = update_ak4396_mute,
        .dac_tlv = ak4396_db_scale,
-       .record_from_dma_b = 1,
+       .used_channels = OXYGEN_CHANNEL_B |
+                        OXYGEN_CHANNEL_C |
+                        OXYGEN_CHANNEL_SPDIF |
+                        OXYGEN_CHANNEL_MULTICH |
+                        OXYGEN_CHANNEL_AC97,
        .function_flags = OXYGEN_FUNCTION_ENABLE_SPI_4_5,
 };
 
index fb9cb36b87b1171589fffbe5780c98d50bf7d881..9b0234d81d4e1e62684602e427cae10b170c8d95 100644 (file)
@@ -80,7 +80,7 @@ struct oxygen_model {
        void (*update_dac_volume)(struct oxygen *chip);
        void (*update_dac_mute)(struct oxygen *chip);
        const unsigned int *dac_tlv;
-       u8 record_from_dma_b;
+       u8 used_channels;
        u8 cd_in_from_video_in;
        u8 dac_minimum_volume;
        u8 function_flags;
index 0f67defc2b2df754a192daa69e68e7737e0c0833..5f15d355a4311fd00c6eaea22c752d1f3b4520dc 100644 (file)
@@ -681,15 +681,22 @@ static void oxygen_pcm_free(struct snd_pcm *pcm)
 int __devinit oxygen_pcm_init(struct oxygen *chip)
 {
        struct snd_pcm *pcm;
+       int outs, ins;
        int err;
 
-       err = snd_pcm_new(chip->card, "Analog", 0, 1, 1, &pcm);
+       outs = 1; /* OXYGEN_CHANNEL_MULTICH is always used */
+       ins = !!(chip->model->used_channels & (OXYGEN_CHANNEL_A |
+                                              OXYGEN_CHANNEL_B));
+       err = snd_pcm_new(chip->card, "Analog", 0, outs, ins, &pcm);
        if (err < 0)
                return err;
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &oxygen_multich_ops);
-       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
-                       chip->model->record_from_dma_b ?
-                       &oxygen_rec_b_ops : &oxygen_rec_a_ops);
+       if (chip->model->used_channels & OXYGEN_CHANNEL_A)
+               snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+                               &oxygen_rec_a_ops);
+       else if (chip->model->used_channels & OXYGEN_CHANNEL_B)
+               snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+                               &oxygen_rec_b_ops);
        pcm->private_data = chip;
        pcm->private_free = oxygen_pcm_free;
        strcpy(pcm->name, "Analog");
@@ -697,32 +704,51 @@ int __devinit oxygen_pcm_init(struct oxygen *chip)
                                      SNDRV_DMA_TYPE_DEV,
                                      snd_dma_pci_data(chip->pci),
                                      512 * 1024, 2048 * 1024);
-       snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
-                                     SNDRV_DMA_TYPE_DEV,
-                                     snd_dma_pci_data(chip->pci),
-                                     128 * 1024, 256 * 1024);
-
-       err = snd_pcm_new(chip->card, "Digital", 1, 1, 1, &pcm);
-       if (err < 0)
-               return err;
-       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &oxygen_spdif_ops);
-       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &oxygen_rec_c_ops);
-       pcm->private_data = chip;
-       pcm->private_free = oxygen_pcm_free;
-       strcpy(pcm->name, "Digital");
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+       if (ins)
+               snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
+                                             SNDRV_DMA_TYPE_DEV,
                                              snd_dma_pci_data(chip->pci),
                                              128 * 1024, 256 * 1024);
 
-       if (chip->has_ac97_1) {
-               err = snd_pcm_new(chip->card, "AC97", 2, 1, 0, &pcm);
+       outs = !!(chip->model->used_channels & OXYGEN_CHANNEL_SPDIF);
+       ins = !!(chip->model->used_channels & OXYGEN_CHANNEL_C);
+       if (outs | ins) {
+               err = snd_pcm_new(chip->card, "Digital", 1, outs, ins, &pcm);
+               if (err < 0)
+                       return err;
+               if (outs)
+                       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+                                       &oxygen_spdif_ops);
+               if (ins)
+                       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+                                       &oxygen_rec_c_ops);
+               pcm->private_data = chip;
+               pcm->private_free = oxygen_pcm_free;
+               strcpy(pcm->name, "Digital");
+               snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                                     snd_dma_pci_data(chip->pci),
+                                                     128 * 1024, 256 * 1024);
+       }
+
+       outs = chip->has_ac97_1 &&
+               (chip->model->used_channels & OXYGEN_CHANNEL_AC97);
+       ins = (chip->model->used_channels & (OXYGEN_CHANNEL_A |
+                                            OXYGEN_CHANNEL_B))
+               == (OXYGEN_CHANNEL_A | OXYGEN_CHANNEL_B);
+       if (outs | ins) {
+               err = snd_pcm_new(chip->card, ins ? "Analog2" : "AC97",
+                                 2, outs, ins, &pcm);
                if (err < 0)
                        return err;
-               snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
-                               &oxygen_ac97_ops);
+               if (outs)
+                       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+                                       &oxygen_ac97_ops);
+               if (ins)
+                       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+                                       &oxygen_rec_b_ops);
                pcm->private_data = chip;
                pcm->private_free = oxygen_pcm_free;
-               strcpy(pcm->name, "Front Panel");
+               strcpy(pcm->name, ins ? "Analog 2" : "Front Panel");
                snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
                                                      snd_dma_pci_data(chip->pci),
                                                      128 * 1024, 256 * 1024);
index 247d5e1ccb68a31e258f91c012ee2eb4ece58ed3..0574fa19dca6ac79e9886592cc4412006ce0d0bd 100644 (file)
@@ -224,7 +224,10 @@ static const struct oxygen_model model_xonar = {
        .update_dac_volume = update_pcm1796_volume,
        .update_dac_mute = update_pcm1796_mute,
        .dac_tlv = pcm1796_db_scale,
-       .record_from_dma_b = 1,
+       .used_channels = OXYGEN_CHANNEL_B |
+                        OXYGEN_CHANNEL_C |
+                        OXYGEN_CHANNEL_SPDIF |
+                        OXYGEN_CHANNEL_MULTICH,
        .cd_in_from_video_in = 1,
        .dac_minimum_volume = 15,
        .function_flags = OXYGEN_FUNCTION_ENABLE_SPI_4_5,