Patch attached.
This patch enables the SPDIF input of the Realtek ALC650 chip which is an AC97 compatible chip.
It also adds some data into the proc file system ac97 /proc/asound/card0/ac97#0 file so one can see if the SPDIF is locked or not.


I can now record AC3 non-audio data from an Optical SPDIF socket on my Motherboard.

This only works for ALC650 Rev.E or above, so I guess I should really check for that.

Cheers
James

diff -ur linux-2.6.0-test4/include/sound/ac97_codec.h 
/usr/src/linux-beta/include/sound/ac97_codec.h
--- linux-2.6.0-test4/include/sound/ac97_codec.h        2003-08-23 00:56:25.000000000 
+0100
+++ /usr/src/linux-beta/include/sound/ac97_codec.h      2003-08-30 16:19:46.000000000 
+0100
@@ -214,11 +214,50 @@
 #define AC97_CXR_SPDIF_AC3     0x2
 
 /* specific - ALC */
+#define AC97_ALC650_SPDIF_INPUT_STATUS1        0x60
+/* S/PDIF input status 1 bit defines */
+#define AC97_ALC650_PRO             0x0001  /* Professional status */
+#define AC97_ALC650_NAUDIO          0x0002  /* Non audio stream */
+#define AC97_ALC650_COPY            0x0004  /* Copyright status */
+#define AC97_ALC650_PRE             0x0038  /* Preemphasis status */
+#define AC97_ALC650_PRE_SHIFT       3
+#define AC97_ALC650_MODE            0x00C0  /* Preemphasis status */
+#define AC97_ALC650_MODE_SHIFT      6
+#define AC97_ALC650_CC_MASK         0x7f00  /* Category Code mask */
+#define AC97_ALC650_CC_SHIFT        8
+#define AC97_ALC650_L               0x8000  /* Generation Level status */
+
+#define AC97_ALC650_SPDIF_INPUT_STATUS2        0x62
+/* S/PDIF input status 2 bit defines */
+#define AC97_ALC650_SOUCE_MASK      0x000f  /* Source number */
+#define AC97_ALC650_CHANNEL_MASK    0x00f0  /* Channel number */
+#define AC97_ALC650_CHANNEL_SHIFT   4 
+#define AC97_ALC650_SPSR_MASK       0x0f00  /* S/PDIF Sample Rate bits */
+#define AC97_ALC650_SPSR_SHIFT      8
+#define AC97_ALC650_SPSR_44K        0x0000  /* Use 44.1kHz Sample rate */
+#define AC97_ALC650_SPSR_48K        0x0200  /* Use 48kHz Sample rate */
+#define AC97_ALC650_SPSR_32K        0x0300  /* Use 32kHz Sample rate */
+#define AC97_ALC650_CLOCK_ACCURACY  0x3000  /* Clock accuracy */
+#define AC97_ALC650_CLOCK_SHIFT     12
+#define AC97_ALC650_CLOCK_LOCK      0x4000  /* Clock locked status */
+#define AC97_ALC650_V               0x8000  /* Validity status */
+
 #define AC97_ALC650_SURR_DAC_VOL       0x64
 #define AC97_ALC650_LFE_DAC_VOL                0x66
+#define AC97_ALC650_UNKNOWN1           0x68
 #define AC97_ALC650_MULTICH    0x6a
+#define AC97_ALC650_UNKNOWN2           0x6c
+#define AC97_ALC650_REVISION    0x6e
+#define AC97_ALC650_UNKNOWN3           0x70
+#define AC97_ALC650_UNKNOWN4           0x72
+#define AC97_ALC650_MISC       0x74
+#define AC97_ALC650_GPIO_SETUP  0x76
+#define AC97_ALC650_GPIO_STATUS 0x78
 #define AC97_ALC650_CLOCK      0x7a
 
+
+
+
 /* specific - Yamaha YMF753 */
 #define AC97_YMF753_DIT_CTRL2  0x66    /* DIT Control 2 */
 #define AC97_YMF753_3D_MODE_SEL        0x68    /* 3D Mode Select */
diff -ur linux-2.6.0-test4/sound/pci/ac97/ac97_patch.c 
/usr/src/linux-beta/sound/pci/ac97/ac97_patch.c
--- linux-2.6.0-test4/sound/pci/ac97/ac97_patch.c       2003-08-23 01:00:10.000000000 
+0100
+++ /usr/src/linux-beta/sound/pci/ac97/ac97_patch.c     2003-08-30 17:35:31.488713520 
+0100
@@ -874,8 +874,10 @@
        val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS);
        if (val & AC97_EA_SPCV)
                spdif = 1;
-
        if (spdif) {
+               //enable AC97_ALC650_GPIO_SETUP, AC97_ALC650_CLOCK for R/W
+               snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_STATUS, 
+                       snd_ac97_read(ac97, AC97_ALC650_GPIO_STATUS) | 0x8000);
                /* enable spdif in */
                snd_ac97_write_cache(ac97, AC97_ALC650_CLOCK,
                                     snd_ac97_read(ac97, AC97_ALC650_CLOCK) | 0x03);
@@ -891,18 +893,18 @@
                int mic_off;
                mic_off = snd_ac97_read(ac97, AC97_ALC650_MULTICH) & (1 << 10);
                /* GPIO0 direction */
-               val = snd_ac97_read(ac97, 0x76);
+               val = snd_ac97_read(ac97, AC97_ALC650_GPIO_SETUP);
                if (mic_off)
                        val &= ~0x01;
                else
                        val |= 0x01;
-               snd_ac97_write_cache(ac97, 0x76, val);
-               val = snd_ac97_read(ac97, 0x78);
+               snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_SETUP, val);
+               val = snd_ac97_read(ac97, AC97_ALC650_GPIO_STATUS);
                if (mic_off)
                        val &= ~0x100;
                else
                        val = val | 0x100;
-               snd_ac97_write_cache(ac97, 0x78, val);
+               snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_STATUS, val);
        }
 
        /* full DAC volume */
diff -ur linux-2.6.0-test4/sound/pci/ac97/ac97_proc.c 
/usr/src/linux-beta/sound/pci/ac97/ac97_proc.c
--- linux-2.6.0-test4/sound/pci/ac97/ac97_proc.c        2003-08-23 01:03:01.000000000 
+0100
+++ /usr/src/linux-beta/sound/pci/ac97/ac97_proc.c      2003-08-30 16:55:06.000000000 
+0100
@@ -38,7 +38,7 @@
 {
        char name[64];
        unsigned int id;
-       unsigned short val, tmp, ext, mext;
+       unsigned short val, tmp, ext, mext, spdif_in;
        static const char *spdif_slots[4] = { " SPDIF=3/4", " SPDIF=7/8", " 
SPDIF=6/9", " SPDIF=res" };
        static const char *spdif_rates[4] = { " Rate=44.1kHz", " Rate=res", " 
Rate=48kHz", " Rate=32kHz" };
        static const char *spdif_rates_cs4205[4] = { " Rate=48kHz", " Rate=44.1kHz", " 
Rate=res", " Rate=res" };
@@ -151,7 +151,7 @@
                snd_iprintf(buffer, "SPDIF Control    :%s%s%s%s Category=0x%x 
Generation=%i%s%s%s\n",
                        val & AC97_SC_PRO ? " PRO" : " Consumer",
                        val & AC97_SC_NAUDIO ? " Non-audio" : " PCM",
-                       val & AC97_SC_COPY ? " Copyright" : "",
+                       val & AC97_SC_COPY ? "" : " Copyright",
                        val & AC97_SC_PRE ? " Preemph50/15" : "",
                        (val & AC97_SC_CC_MASK) >> AC97_SC_CC_SHIFT,
                        (val & AC97_SC_L) >> 11,
@@ -165,6 +165,29 @@
                            (val & AC97_SC_V ? " Enabled" : "") :
                            (val & AC97_SC_V ? " Validity" : ""));
        }
+       spdif_in = snd_ac97_read(ac97, AC97_ALC650_CLOCK);
+       if (spdif_in & 0x01) {
+          val = snd_ac97_read(ac97, AC97_ALC650_SPDIF_INPUT_STATUS2);
+           if (val & AC97_ALC650_CLOCK_LOCK) {
+               val = snd_ac97_read(ac97, AC97_ALC650_SPDIF_INPUT_STATUS1);
+               snd_iprintf(buffer, "SPDIF In Status  :%s%s%s%s Category=0x%x 
Generation=%i",
+                       val & AC97_ALC650_PRO ? " PRO" : " Consumer",
+                       val & AC97_ALC650_NAUDIO ? " Non-audio" : " PCM",
+                       val & AC97_ALC650_COPY ? "" : " Copyright",
+                       val & AC97_ALC650_PRE ? " Preemph50/15" : "",
+                       (val & AC97_ALC650_CC_MASK) >> AC97_ALC650_CC_SHIFT,
+                       (val & AC97_ALC650_L) >> 15);
+               val = snd_ac97_read(ac97, AC97_ALC650_SPDIF_INPUT_STATUS2);
+               snd_iprintf(buffer, "%s Accuracy=%i%s%s\n",
+                       spdif_rates[(val & AC97_ALC650_SPSR_MASK) >> 
AC97_ALC650_SPSR_SHIFT],
+                       (val & AC97_ALC650_CLOCK_ACCURACY) >> AC97_ALC650_CLOCK_SHIFT,
+                       (val & AC97_ALC650_CLOCK_LOCK ? " Locked" : " Unlocked"),
+                       (val & AC97_ALC650_V ? " Validity?" : ""));
+           } else {
+               snd_iprintf(buffer, "SPDIF In Status  : Not Locked\n");
+           }
+       }
+
 
       __modem:
        mext = snd_ac97_read(ac97, AC97_EXTENDED_MID);

Reply via email to