]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ALSA: aoa: onyx: Update IEC958 sample-rate status for PCM playback
authorCássio Gabriel <cassiogabrielcontato@gmail.com>
Fri, 3 Apr 2026 03:47:13 +0000 (00:47 -0300)
committerTakashi Iwai <tiwai@suse.de>
Mon, 6 Apr 2026 08:41:00 +0000 (10:41 +0200)
onyx_prepare() accepts 32/44.1/48 kHz PCM playback, but it leaves the
Onyx IEC958 sample-rate status bits at the driver's initial 44.1 kHz
setting in DIG_INFO3. As a result, 32 kHz and 48 kHz PCM streams
advertise a stale IEC958 sample rate unless userspace rewrites IEC958
Playback Default first.

Update only the consumer sample-frequency bits in DIG_INFO3 from the PCM
runtime during prepare, resolving the long-standing FIXME in the PCM
playback path while leaving the other user-controlled IEC958 status bits
unchanged.

Mark IEC958 Playback Default as volatile as well, since prepare() now
changes the exposed register contents outside the control put callback.

Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
Link: https://patch.msgid.link/20260403-onyx-spdif-pcm-rate-v1-1-dcfaf931cf83@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/aoa/codecs/onyx.c

index da0eebf5dfbc2db85e85ef2c881d19d52ff5178b..4fb593e88fb18de82a26ae50e2d98d533d7b35bf 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/slab.h>
+#include <sound/asoundef.h>
 MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("pcm3052 (onyx) codec driver for snd-aoa");
@@ -514,8 +515,36 @@ static int onyx_spdif_put(struct snd_kcontrol *kcontrol,
        return 1;
 }
 
+static int onyx_set_spdif_pcm_rate(struct onyx *onyx, unsigned int rate)
+{
+       u8 dig_info3, fs;
+
+       switch (rate) {
+       case 32000:
+               fs = IEC958_AES3_CON_FS_32000;
+               break;
+       case 44100:
+               fs = IEC958_AES3_CON_FS_44100;
+               break;
+       case 48000:
+               fs = IEC958_AES3_CON_FS_48000;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (onyx_read_register(onyx, ONYX_REG_DIG_INFO3, &dig_info3))
+               return -EBUSY;
+       dig_info3 = (dig_info3 & ~IEC958_AES3_CON_FS) | fs;
+       if (onyx_write_register(onyx, ONYX_REG_DIG_INFO3, dig_info3))
+               return -EBUSY;
+
+       return 0;
+}
+
 static const struct snd_kcontrol_new onyx_spdif_ctrl = {
-       .access =       SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .access =       SNDRV_CTL_ELEM_ACCESS_READWRITE |
+                       SNDRV_CTL_ELEM_ACCESS_VOLATILE,
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
        .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
        .info =         onyx_spdif_info,
@@ -695,9 +724,9 @@ static int onyx_prepare(struct codec_info_item *cii,
        case 32000:
        case 44100:
        case 48000:
-               /* these rates are ok for all outputs */
-               /* FIXME: program spdif channel control bits here so that
-                *        userspace doesn't have to if it only plays pcm! */
+               if (onyx->codec.connected & 2)
+                       return onyx_set_spdif_pcm_rate(onyx,
+                                                      substream->runtime->rate);
                return 0;
        default:
                /* got some rate that the digital output can't do,