[alsa-devel] How to set idle S/PDIF sample rate?

Takashi Iwai tiwai at suse.de
Thu Feb 28 12:43:25 CET 2008


At Tue, 26 Feb 2008 17:25:35 -0500,
Matt Whitlock wrote:
> 
> On Tuesday, 26 February 2008 9:01:17 am Takashi Iwai wrote:
> > There is a clear difference between "default" and "spdif" PCMs.
> > The default uses dmix plugin with the fixed 48kHz rate.  The spdif is
> > a direct access and can use all rates the codec chip supports (but no
> > soft-mixing).
> 
> Well yes, I knew that.  I was trying to show you the inconsistencies of state in ALSA's handling of the S/PDIF output under various sequences of actions.
> 
> Can I assume at this point that there is no way to set the idle S/PDIF output sample rate to 44100 Hz?  That is my original question.

The driver code resets the format verb of the relevant widgets at
closing streams.  This verb contains the sample rate, too.  Maybe
keeping this would prevent the reset.

The below is a test patch.  Give it a try.


Takashi

---

diff -r d960c4971891 pci/hda/hda_codec.c
--- a/pci/hda/hda_codec.c	Thu Feb 28 12:02:56 2008 +0100
+++ b/pci/hda/hda_codec.c	Thu Feb 28 12:46:43 2008 +0100
@@ -693,6 +693,19 @@ void snd_hda_codec_setup_stream(struct h
 			    (stream_tag << 4) | channel_id);
 	msleep(1);
 	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
+}
+
+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
 }
 
 /*
@@ -2179,7 +2192,7 @@ static int hda_pcm_default_cleanup(struc
 				   struct hda_codec *codec,
 				   struct snd_pcm_substream *substream)
 {
-	snd_hda_codec_setup_stream(codec, hinfo->nid, 0, 0, 0);
+	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
 	return 0;
 }
 
@@ -2564,7 +2577,7 @@ int snd_hda_multi_out_dig_open(struct hd
 	mutex_lock(&codec->spdif_mutex);
 	if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
 		/* already opened as analog dup; reset it once */
-		snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0);
+		snd_hda_codec_cleanup_stream(codec, mout->dig_out_nid);
 	mout->dig_out_used = HDA_DIG_EXCLUSIVE;
 	mutex_unlock(&codec->spdif_mutex);
 	return 0;
@@ -2659,8 +2672,7 @@ int snd_hda_multi_out_analog_prepare(str
 					     stream_tag, format);
 		} else {
 			mout->dig_out_used = 0;
-			snd_hda_codec_setup_stream(codec, mout->dig_out_nid,
-						   0, 0, 0);
+			snd_hda_codec_cleanup_stream(codec, mout->dig_out_nid);
 		}
 	}
 	mutex_unlock(&codec->spdif_mutex);
@@ -2702,17 +2714,16 @@ int snd_hda_multi_out_analog_cleanup(str
 	int i;
 
 	for (i = 0; i < mout->num_dacs; i++)
-		snd_hda_codec_setup_stream(codec, nids[i], 0, 0, 0);
+		snd_hda_codec_cleanup_stream(codec, nids[i]);
 	if (mout->hp_nid)
-		snd_hda_codec_setup_stream(codec, mout->hp_nid, 0, 0, 0);
+		snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
 	for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
 		if (mout->extra_out_nid[i])
-			snd_hda_codec_setup_stream(codec,
-						   mout->extra_out_nid[i],
-						   0, 0, 0);
+			snd_hda_codec_cleanup_stream(codec,
+						     mout->extra_out_nid[i]);
 	mutex_lock(&codec->spdif_mutex);
 	if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
-		snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0);
+		snd_hda_codec_cleanup_stream(codec, mout->dig_out_nid);
 		mout->dig_out_used = 0;
 	}
 	mutex_unlock(&codec->spdif_mutex);
diff -r d960c4971891 pci/hda/hda_codec.h
--- a/pci/hda/hda_codec.h	Thu Feb 28 12:02:56 2008 +0100
+++ b/pci/hda/hda_codec.h	Thu Feb 28 12:46:43 2008 +0100
@@ -722,6 +722,7 @@ void snd_hda_codec_setup_stream(struct h
 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);
 unsigned int snd_hda_calc_stream_format(unsigned int rate,
 					unsigned int channels,
 					unsigned int format,
diff -r d960c4971891 pci/hda/hda_generic.c
--- a/pci/hda/hda_generic.c	Thu Feb 28 12:02:56 2008 +0100
+++ b/pci/hda/hda_generic.c	Thu Feb 28 12:46:43 2008 +0100
@@ -1007,8 +1007,8 @@ static int generic_pcm2_cleanup(struct h
 {
 	struct hda_gspec *spec = codec->spec;
 
-	snd_hda_codec_setup_stream(codec, hinfo->nid, 0, 0, 0);
-	snd_hda_codec_setup_stream(codec, spec->dac_node[1]->nid, 0, 0, 0);
+	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
+	snd_hda_codec_cleanup_stream(codec, spec->dac_node[1]->nid);
 	return 0;
 }
 
diff -r d960c4971891 pci/hda/patch_analog.c
--- a/pci/hda/patch_analog.c	Thu Feb 28 12:02:56 2008 +0100
+++ b/pci/hda/patch_analog.c	Thu Feb 28 12:46:43 2008 +0100
@@ -295,8 +295,7 @@ static int ad198x_capture_pcm_cleanup(st
 				      struct snd_pcm_substream *substream)
 {
 	struct ad198x_spec *spec = codec->spec;
-	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
-				   0, 0, 0);
+	snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
 	return 0;
 }
 
@@ -3324,8 +3323,7 @@ static int ad1984_pcm_dmic_cleanup(struc
 				   struct hda_codec *codec,
 				   struct snd_pcm_substream *substream)
 {
-	snd_hda_codec_setup_stream(codec, 0x05 + substream->number,
-				   0, 0, 0);
+	snd_hda_codec_cleanup_stream(codec, 0x05 + substream->number);
 	return 0;
 }
 
diff -r d960c4971891 pci/hda/patch_cmedia.c
--- a/pci/hda/patch_cmedia.c	Thu Feb 28 12:02:56 2008 +0100
+++ b/pci/hda/patch_cmedia.c	Thu Feb 28 12:46:43 2008 +0100
@@ -512,7 +512,7 @@ static int cmi9880_capture_pcm_cleanup(s
 {
 	struct cmi_spec *spec = codec->spec;
 
-	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
+	snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
 	return 0;
 }
 
diff -r d960c4971891 pci/hda/patch_conexant.c
--- a/pci/hda/patch_conexant.c	Thu Feb 28 12:02:56 2008 +0100
+++ b/pci/hda/patch_conexant.c	Thu Feb 28 12:46:43 2008 +0100
@@ -173,8 +173,7 @@ static int conexant_capture_pcm_cleanup(
 				      struct snd_pcm_substream *substream)
 {
 	struct conexant_spec *spec = codec->spec;
-	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
-				   0, 0, 0);
+	snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
 	return 0;
 }
 
@@ -242,7 +241,7 @@ static int cx5051_capture_pcm_cleanup(st
 				      struct snd_pcm_substream *substream)
 {
 	struct conexant_spec *spec = codec->spec;
-	snd_hda_codec_setup_stream(codec, spec->cur_adc, 0, 0, 0);
+	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
 	spec->cur_adc = 0;
 	return 0;
 }
@@ -1544,7 +1543,7 @@ static void cxt5051_portc_automic(struct
 	new_adc = spec->adc_nids[spec->cur_adc_idx];
 	if (spec->cur_adc && spec->cur_adc != new_adc) {
 		/* stream is running, let's swap the current ADC */
-		snd_hda_codec_setup_stream(codec, spec->cur_adc, 0, 0, 0);
+		snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
 		spec->cur_adc = new_adc;
 		snd_hda_codec_setup_stream(codec, new_adc,
 					   spec->cur_adc_stream_tag, 0,
diff -r d960c4971891 pci/hda/patch_realtek.c
--- a/pci/hda/patch_realtek.c	Thu Feb 28 12:02:56 2008 +0100
+++ b/pci/hda/patch_realtek.c	Thu Feb 28 12:46:43 2008 +0100
@@ -2405,8 +2405,8 @@ static int alc880_alt_capture_pcm_cleanu
 {
 	struct alc_spec *spec = codec->spec;
 
-	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
-				   0, 0, 0);
+	snd_hda_codec_cleanup_stream(codec,
+				     spec->adc_nids[substream->number + 1]);
 	return 0;
 }
 
diff -r d960c4971891 pci/hda/patch_sigmatel.c
--- a/pci/hda/patch_sigmatel.c	Thu Feb 28 12:02:56 2008 +0100
+++ b/pci/hda/patch_sigmatel.c	Thu Feb 28 12:46:43 2008 +0100
@@ -1891,7 +1891,7 @@ static int stac92xx_capture_pcm_cleanup(
 {
 	struct sigmatel_spec *spec = codec->spec;
 
-	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
+	snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
 	return 0;
 }
 
diff -r d960c4971891 pci/hda/patch_via.c
--- a/pci/hda/patch_via.c	Thu Feb 28 12:02:56 2008 +0100
+++ b/pci/hda/patch_via.c	Thu Feb 28 12:46:43 2008 +0100
@@ -431,8 +431,7 @@ static int via_capture_pcm_cleanup(struc
 				   struct snd_pcm_substream *substream)
 {
 	struct via_spec *spec = codec->spec;
-	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
-				   0, 0, 0);
+	snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
 	return 0;
 }
 


More information about the Alsa-devel mailing list