[alsa-devel] ALC892 optical SPDIF not working

Takashi Iwai tiwai at suse.de
Mon Aug 2 10:02:48 CEST 2010


At Sun, 1 Aug 2010 01:32:23 +0200,
Manuel Lauss wrote:
> 
> > > >> Is there a way to insert an initial playback delay?  Under linux, the
> > > >> first 2-2.5 seconds
> > > >> of anything played are just silence; on windows audible playback
> > > >> starts immediately.
> > > >
> > > > It's the time for synchronization your digital receiver takes, I guess.
> > > > Maybe changing SPDIF status makes it resync, which happens at each
> > > > opening / closing the stream.
> > > 
> > > Yes, seems so. I've found a workaround in meantime.
> > 
> > Could you elaborate on the workaround please, so others having this
> > issue know it.
> 
> My receiver allows to mix analog and digital inputs; with analog mix
> enabled it syncs immediately.

Just wondering whether the patch below helps?

It's just a proof-of-concept, and it's not safe for multiple streams.
If this works, we can move on the improvement of the stream assignment.


thanks,

Takashi

---
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 4d5abbd..45f2bb3 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1181,38 +1181,30 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
 				u32 stream_tag,
 				int channel_id, int format)
 {
+	u32 oldval;
+
 	if (!nid)
 		return;
 
 	snd_printdd("hda_codec_setup_stream: "
 		    "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
 		    nid, stream_tag, channel_id, format);
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID,
-			    (stream_tag << 4) | channel_id);
-	msleep(1);
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
+	stream_tag = (stream_tag << 4) | channel_id;
+	oldval = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0);
+	if (stream_tag != oldval) {
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_CHANNEL_STREAMID, stream_tag);
+	}
+	oldval = snd_hda_codec_read(codec, nid, 0,
+				    AC_VERB_GET_STREAM_FORMAT, 0);
+	if (format != oldval) {
+		msleep(1);
+		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT,
+				    format);
+	}
 }
 EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
 
-/**
- * snd_hda_codec_cleanup_stream - clean up the codec for closing
- * @codec: the CODEC to clean up
- * @nid: the NID to clean up
- */
-void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
-{
-	if (!nid)
-		return;
-
-	snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
-#if 0 /* keep the format */
-	msleep(1);
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
-#endif
-}
-EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);
-
 /*
  * amp access functions
  */
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index a115c0c..61e177d 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -927,7 +927,10 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec);
 void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
 				u32 stream_tag,
 				int channel_id, int format);
-void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid);
+/*void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid);*/
+static inline void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid) {}
+
+
 unsigned int snd_hda_calc_stream_format(unsigned int rate,
 					unsigned int channels,
 					unsigned int format,


More information about the Alsa-devel mailing list