[ALSA] Improve SPDIF playback via the P16V/CA0151 chip.
authorJames Courtier-Dutton <James@superbug.co.uk>
Sat, 9 Apr 2005 21:38:25 +0000 (23:38 +0200)
committerJaroslav Kysela <perex@suse.cz>
Sun, 29 May 2005 07:58:49 +0000 (09:58 +0200)
EMU10K1/EMU10K2 driver
Although we can set 44100 as the output rate, the SPDIF can do it, but the Analog output cannot.
The SPDIF has the bug, whereby the Left channel arrives one sample late, so although we don't do any resampling,
it is not good for AC3 non-audio output.

Signed-off-by: James Courtier-Dutton <James@superbug.co.uk>
include/sound/emu10k1.h
sound/pci/emu10k1/emumixer.c
sound/pci/emu10k1/emuproc.c
sound/pci/emu10k1/p16v.c

index f5babd3f84529d86466ae1cb019cc4ccd9b2cc3e..61a3f418f3027d02bc371ddebf2b21d0533d811e 100644 (file)
                                                /* Assumes sample lock                          */
 
 /* These three bitfields apply to CDSRCS, GPSRCS, and (except as noted) ZVSRCS.                        */
+#define SRCS_SPDIFVALID                0x04000000      /* SPDIF stream valid                           */
 #define SRCS_SPDIFLOCKED       0x02000000      /* SPDIF stream locked                          */
 #define SRCS_RATELOCKED                0x01000000      /* Sample rate locked                           */
 #define SRCS_ESTSAMPLERATE     0x0007ffff      /* Do not modify this field.                    */
index d0b296587cc061241769169bd57863825d4ee168..b544c258266383649c584c118d7e9344cd0c57a1 100644 (file)
@@ -935,10 +935,12 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
                        return -ENOMEM;
                if ((err = snd_ctl_add(card, kctl)))
                        return err;
+#if 0
                if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL)
                        return -ENOMEM;
                if ((err = snd_ctl_add(card, kctl)))
                        return err;
+#endif
        } else if (! emu->card_capabilities->ecard) {
                /* sb live! */
                if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL)
index 187a4e60a5fe411e0704207357f0d6f7b59c48c9..356fb71042531877d9f77421436053251daf36c6 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/init.h>
 #include <sound/core.h>
 #include <sound/emu10k1.h>
+#include "p16v.h"
 
 static void snd_emu10k1_proc_spdif_status(emu10k1_t * emu,
                                          snd_info_buffer_t * buffer,
@@ -62,6 +63,7 @@ static void snd_emu10k1_proc_spdif_status(emu10k1_t * emu,
 
                if (rate_reg > 0) {
                        rate = snd_emu10k1_ptr_read(emu, rate_reg, 0);
+                       snd_iprintf(buffer, "S/PDIF Valid          : %s\n", rate & SRCS_SPDIFVALID ? "on" : "off");
                        snd_iprintf(buffer, "S/PDIF Locked         : %s\n", rate & SRCS_SPDIFLOCKED ? "on" : "off");
                        snd_iprintf(buffer, "Rate Locked           : %s\n", rate & SRCS_RATELOCKED ? "on" : "off");
                        /* From ((Rate * 48000 ) / 262144); */
@@ -244,6 +246,21 @@ static void snd_emu10k1_proc_spdif_read(snd_info_entry_t *entry,
 #endif
 }
 
+static void snd_emu10k1_proc_rates_read(snd_info_entry_t *entry, 
+                                 snd_info_buffer_t * buffer)
+{
+       static int samplerate[8] = { 44100, 48000, 96000, 192000, 4, 5, 6, 7 };
+       emu10k1_t *emu = entry->private_data;
+       unsigned int val, tmp, n;
+       val = snd_emu10k1_ptr20_read(emu, CAPTURE_RATE_STATUS, 0);
+       tmp = (val >> 16) & 0x8;
+       for (n=0;n<4;n++) {
+               tmp = val >> (16 + (n*4));
+               if (tmp & 0x8) snd_iprintf(buffer, "Channel %d: Rate=%d\n", n, samplerate[tmp & 0x7]);
+               else snd_iprintf(buffer, "Channel %d: No input\n", n);
+       }
+}
+
 static void snd_emu10k1_proc_acode_read(snd_info_entry_t *entry, 
                                        snd_info_buffer_t * buffer)
 {
@@ -540,6 +557,10 @@ int __devinit snd_emu10k1_proc_init(emu10k1_t * emu)
                if (! snd_card_proc_new(emu->card, "spdif-in", &entry))
                        snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_spdif_read);
        }
+       if (emu->card_capabilities->ca0151_chip) {
+               if (! snd_card_proc_new(emu->card, "capture-rates", &entry))
+                       snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_rates_read);
+       }
 
        if (! snd_card_proc_new(emu->card, "voices", &entry))
                snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_voices_read);
index dd6ce9927e10ef07c488cfd5d49b4364827f23b2..8dd87838fb228404693f44225459e7b6b8d422cc 100644 (file)
@@ -119,8 +119,8 @@ static snd_pcm_hardware_t snd_p16v_playback_hw = {
                                 SNDRV_PCM_INFO_BLOCK_TRANSFER |
                                 SNDRV_PCM_INFO_MMAP_VALID),
        .formats =              SNDRV_PCM_FMTBIT_S32_LE, /* Only supports 24-bit samples padded to 32 bits. */
-       .rates =                SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 ,
-       .rate_min =             48000,
+       .rates =                SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100, 
+       .rate_min =             44100,
        .rate_max =             192000,
        .channels_min =         8, 
        .channels_max =         8,
@@ -324,19 +324,17 @@ static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream)
        tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel);
         switch (runtime->rate) {
        case 44100:
-         snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x8000); /* FIXME: This will change the capture rate as well! */
-         break;
-       case 48000:
-         snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x0000); /* FIXME: This will change the capture rate as well! */
+         snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x8080);
          break;
        case 96000:
-         snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x4000); /* FIXME: This will change the capture rate as well! */
+         snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x4040);
          break;
        case 192000:
-         snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x2000); /* FIXME: This will change the capture rate as well! */
+         snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x2020);
          break;
+       case 48000:
        default:
-         snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, 0x0000); /* FIXME: This will change the capture rate as well! */
+         snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x0000);
          break;
        }
        /* FIXME: Check emu->buffer.size before actually writing to it. */