[alsa-devel] [PATCH 2/2] ASoC: sti: correction for HBRA support

Moise Gergaud moise.gergaud at st.com
Tue Nov 24 14:16:36 CET 2015


Detect HBRA based on rate and channels used in the pcm session
In case of HBRA:
  - CH_STS repeat is disabled
  - channel status sampling freq is not set if already set (because it can
    be a multiple of the runtime rate)

Signed-off-by: Moise Gergaud <moise.gergaud at st.com>
Acked-by: Arnaud Pouliquen <arnaud.pouliquen at st.com>
---
 sound/soc/sti/uniperif_player.c | 72 +++++++++++++++++++++++++----------------
 1 file changed, 44 insertions(+), 28 deletions(-)

diff --git a/sound/soc/sti/uniperif_player.c b/sound/soc/sti/uniperif_player.c
index 7aca6b9..d6b7cea 100644
--- a/sound/soc/sti/uniperif_player.c
+++ b/sound/soc/sti/uniperif_player.c
@@ -244,55 +244,70 @@ static void uni_player_set_channel_status(struct uniperif *player,
 {
 	int n;
 	unsigned int status;
+	unsigned char *aes3 = &player->stream_settings.iec958.status[3];
+	const unsigned int cs_rate[] = {
+		44100, 0, 48000, 32000, 22050, 24000,
+		88200, 768000, 176400, 192000
+	};
 
 	/*
 	 * Some AVRs and TVs require the channel status to contain a correct
-	 * sampling frequency. If no sample rate is already specified, then
-	 * set one.
+	 * sampling freq.
+	 * In case of HBRA is not detected:
+	 *   set the channel status sampling freq
+	 * In case of HBRA is detected:
+	 *   channel status sampling freq is already set; it can be a multiple
+	 *   of runtime rate
+	 *
+	 * HBRA is detected when:
+	 *   runtime channels is 8 and runtime->rate < channel status rate
 	 */
+
 	mutex_lock(&player->ctrl_lock);
-	if (runtime) {
+
+	if ((runtime->channels == 8) &&
+	    (runtime->rate < cs_rate[*aes3 & IEC958_AES3_CON_FS])) {
+		/*
+		 * Consecutive frames repetition of Z preamble needs to be
+		 * disabled in case of HBRA
+		 */
+		SET_UNIPERIF_CONFIG_REPEAT_CHL_STS_DISABLE(player);
+	} else {
+		SET_UNIPERIF_CONFIG_REPEAT_CHL_STS_ENABLE(player);
+
+		*aes3 &= ~IEC958_AES3_CON_FS;
+
 		switch (runtime->rate) {
 		case 22050:
-			player->stream_settings.iec958.status[3] =
-						IEC958_AES3_CON_FS_22050;
+			*aes3 |= IEC958_AES3_CON_FS_22050;
 			break;
 		case 44100:
-			player->stream_settings.iec958.status[3] =
-						IEC958_AES3_CON_FS_44100;
+			*aes3 |= IEC958_AES3_CON_FS_44100;
 			break;
 		case 88200:
-			player->stream_settings.iec958.status[3] =
-						IEC958_AES3_CON_FS_88200;
+			*aes3 |= IEC958_AES3_CON_FS_88200;
 			break;
 		case 176400:
-			player->stream_settings.iec958.status[3] =
-						IEC958_AES3_CON_FS_176400;
+			*aes3 |= IEC958_AES3_CON_FS_176400;
 			break;
 		case 24000:
-			player->stream_settings.iec958.status[3] =
-						IEC958_AES3_CON_FS_24000;
+			*aes3 |= IEC958_AES3_CON_FS_24000;
 			break;
 		case 48000:
-			player->stream_settings.iec958.status[3] =
-						IEC958_AES3_CON_FS_48000;
+			*aes3 |= IEC958_AES3_CON_FS_48000;
 			break;
 		case 96000:
-			player->stream_settings.iec958.status[3] =
-						IEC958_AES3_CON_FS_96000;
+			*aes3 |= IEC958_AES3_CON_FS_96000;
 			break;
 		case 192000:
-			player->stream_settings.iec958.status[3] =
-						IEC958_AES3_CON_FS_192000;
+			*aes3 |= IEC958_AES3_CON_FS_192000;
 			break;
 		case 32000:
-			player->stream_settings.iec958.status[3] =
-						IEC958_AES3_CON_FS_32000;
+			*aes3 |= IEC958_AES3_CON_FS_32000;
 			break;
 		default:
 			/* Mark as sampling frequency not indicated */
-			player->stream_settings.iec958.status[3] =
-						IEC958_AES3_CON_FS_NOTID;
+			*aes3 |= IEC958_AES3_CON_FS_NOTID;
 			break;
 		}
 	}
@@ -318,7 +333,7 @@ static void uni_player_set_channel_status(struct uniperif *player,
 	/* Program the new channel status */
 	for (n = 0; n < 6; ++n) {
 		status  =
-		player->stream_settings.iec958.status[0 + (n * 4)] & 0xf;
+		player->stream_settings.iec958.status[0 + (n * 4)] & 0xff;
 		status |=
 		player->stream_settings.iec958.status[1 + (n * 4)] << 8;
 		status |=
@@ -398,9 +413,6 @@ static int uni_player_prepare_iec958(struct uniperif *player,
 	/* Disable one-bit audio mode */
 	SET_UNIPERIF_CONFIG_ONE_BIT_AUD_DISABLE(player);
 
-	/* Enable consecutive frames repetition of Z preamble (not for HBRA) */
-	SET_UNIPERIF_CONFIG_REPEAT_CHL_STS_ENABLE(player);
-
 	/* Change to SUF0_SUBF1 and left/right channels swap! */
 	SET_UNIPERIF_CONFIG_SUBFRAME_SEL_SUBF1_SUBF0(player);
 
@@ -563,6 +575,7 @@ static int uni_player_ctl_iec958_get(struct snd_kcontrol *kcontrol,
 	ucontrol->value.iec958.status[1] = iec958->status[1];
 	ucontrol->value.iec958.status[2] = iec958->status[2];
 	ucontrol->value.iec958.status[3] = iec958->status[3];
+	ucontrol->value.iec958.status[4] = iec958->status[4];
 	mutex_unlock(&player->ctrl_lock);
 	return 0;
 }
@@ -574,15 +587,18 @@ static int uni_player_ctl_iec958_put(struct snd_kcontrol *kcontrol,
 	struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
 	struct uniperif *player = priv->dai_data.uni;
 	struct snd_aes_iec958 *iec958 =  &player->stream_settings.iec958;
+	struct snd_pcm_substream *substream = player->substream;
 
 	mutex_lock(&player->ctrl_lock);
 	iec958->status[0] = ucontrol->value.iec958.status[0];
 	iec958->status[1] = ucontrol->value.iec958.status[1];
 	iec958->status[2] = ucontrol->value.iec958.status[2];
 	iec958->status[3] = ucontrol->value.iec958.status[3];
+	iec958->status[4] = ucontrol->value.iec958.status[4];
 	mutex_unlock(&player->ctrl_lock);
 
-	uni_player_set_channel_status(player, NULL);
+	if (substream && substream->runtime)
+		uni_player_set_channel_status(player, substream->runtime);
 
 	return 0;
 }
-- 
1.9.1



More information about the Alsa-devel mailing list