vserver 2.0 rc7
[linux-2.6.git] / sound / pci / au88x0 / au88x0_pcm.c
index 066e6c6..04dcefd 100644 (file)
@@ -20,7 +20,7 @@
  * Supports ADB and WT DMA. Unfortunately, WT channels do not run yet.
  * It remains stuck,and DMA transfers do not happen. 
  */
-
+#include <sound/asoundef.h>
 #include <sound/driver.h>
 #include <linux/time.h>
 #include <sound/core.h>
@@ -431,61 +431,77 @@ static char *vortex_pcm_name[VORTEX_PCM_LAST] = {
 };
 
 /* SPDIF kcontrol */
-static int
-snd_vortex_spdif_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
-{
-       static char *texts[] = { "32000", "44100", "48000" };
 
-       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+static int snd_vortex_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
        uinfo->count = 1;
-       uinfo->value.enumerated.items = 3;
-       if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
-               uinfo->value.enumerated.item =
-                   uinfo->value.enumerated.items - 1;
-       strcpy(uinfo->value.enumerated.name,
-              texts[uinfo->value.enumerated.item]);
        return 0;
 }
-static int
-snd_vortex_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
-       vortex_t *vortex = snd_kcontrol_chip(kcontrol);
 
-       if (vortex->spdif_sr == 32000)
-               ucontrol->value.enumerated.item[0] = 0;
-       if (vortex->spdif_sr == 44100)
-               ucontrol->value.enumerated.item[0] = 1;
-       if (vortex->spdif_sr == 48000)
-               ucontrol->value.enumerated.item[0] = 2;
+static int snd_vortex_spdif_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+       ucontrol->value.iec958.status[0] = 0xff;
+       ucontrol->value.iec958.status[1] = 0xff;
+       ucontrol->value.iec958.status[2] = 0xff;
+       ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS;
        return 0;
 }
-static int
-snd_vortex_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+
+static int snd_vortex_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
        vortex_t *vortex = snd_kcontrol_chip(kcontrol);
-       static unsigned int sr[3] = { 32000, 44100, 48000 };
+       ucontrol->value.iec958.status[0] = 0x00;
+       ucontrol->value.iec958.status[1] = IEC958_AES1_CON_ORIGINAL|IEC958_AES1_CON_DIGDIGCONV_ID;
+       ucontrol->value.iec958.status[2] = 0x00;
+       switch (vortex->spdif_sr) {
+       case 32000: ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_32000; break;
+       case 44100: ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_44100; break;
+       case 48000: ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_48000; break;
+       }
+       return 0;
+}
 
-       //printk("vortex: spdif sr = %d\n", ucontrol->value.enumerated.item[0]);
-       vortex->spdif_sr = sr[ucontrol->value.enumerated.item[0] % 3];
-       vortex_spdif_init(vortex,
-                         sr[ucontrol->value.enumerated.item[0] % 3], 1);
+static int snd_vortex_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+       vortex_t *vortex = snd_kcontrol_chip(kcontrol);
+       int spdif_sr = 48000;
+       switch (ucontrol->value.iec958.status[3] & IEC958_AES3_CON_FS) {
+       case IEC958_AES3_CON_FS_32000: spdif_sr = 32000; break;
+       case IEC958_AES3_CON_FS_44100: spdif_sr = 44100; break;
+       case IEC958_AES3_CON_FS_48000: spdif_sr = 48000; break;
+       }
+       if (spdif_sr == vortex->spdif_sr)
+               return 0;
+       vortex->spdif_sr = spdif_sr;
+       vortex_spdif_init(vortex, vortex->spdif_sr, 1);
        return 1;
 }
-static snd_kcontrol_new_t vortex_spdif_kcontrol __devinitdata = {
-       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-       .name = "SPDIF SR",
-       .index = 0,
-       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
-       .private_value = 0,
-       .info = snd_vortex_spdif_info,
-       .get = snd_vortex_spdif_get,
-       .put = snd_vortex_spdif_put
+
+/* spdif controls */
+static snd_kcontrol_new_t snd_vortex_mixer_spdif[] __devinitdata = {
+       {
+               .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
+               .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
+               .info =         snd_vortex_spdif_info,
+               .get =          snd_vortex_spdif_get,
+               .put =          snd_vortex_spdif_put,
+       },
+       {
+               .access =       SNDRV_CTL_ELEM_ACCESS_READ,
+               .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
+               .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
+               .info =         snd_vortex_spdif_info,
+               .get =          snd_vortex_spdif_mask_get
+       },
 };
 
 /* create a pcm device */
 static int __devinit snd_vortex_new_pcm(vortex_t * chip, int idx, int nr)
 {
        snd_pcm_t *pcm;
+       snd_kcontrol_t *kctl;
+       int i;
        int err, nr_capt;
 
        if ((chip == 0) || (idx < 0) || (idx > VORTEX_PCM_LAST))
@@ -520,13 +536,13 @@ static int __devinit snd_vortex_new_pcm(vortex_t * chip, int idx, int nr)
                                              0x10000, 0x10000);
 
        if (VORTEX_PCM_TYPE(pcm) == VORTEX_PCM_SPDIF) {
-               snd_kcontrol_t *kcontrol;
-
-               if ((kcontrol =
-                    snd_ctl_new1(&vortex_spdif_kcontrol, chip)) == NULL)
-                       return -ENOMEM;
-               if ((err = snd_ctl_add(chip->card, kcontrol)) < 0)
-                       return err;
+               for (i = 0; i < ARRAY_SIZE(snd_vortex_mixer_spdif); i++) {
+                       kctl = snd_ctl_new1(&snd_vortex_mixer_spdif[i], chip);
+                       if (!kctl)
+                               return -ENOMEM;
+                       if ((err = snd_ctl_add(chip->card, kctl)) < 0)
+                               return err;
+               }
        }
        return 0;
 }