Author: hselasky
Date: Tue Mar 14 15:25:49 2017
New Revision: 315250
URL: https://svnweb.freebsd.org/changeset/base/315250

Log:
  MFC r312338:
  
  Add USB audio support for S/PDIF output with C-Media CM6206 devices.
  
  Submitted by:         Julien Nadeau <ve...@hypertriton.com>
  PR:                   216131

Modified:
  stable/9/share/man/man4/usb_quirk.4
  stable/9/sys/dev/sound/usb/uaudio.c
  stable/9/sys/dev/usb/quirk/usb_quirk.c
  stable/9/sys/dev/usb/quirk/usb_quirk.h
  stable/9/sys/dev/usb/usbdevs
Directory Properties:
  stable/9/share/   (props changed)
  stable/9/share/man/   (props changed)
  stable/9/share/man/man4/   (props changed)
  stable/9/sys/   (props changed)

Modified: stable/9/share/man/man4/usb_quirk.4
==============================================================================
--- stable/9/share/man/man4/usb_quirk.4 Tue Mar 14 15:21:41 2017        
(r315249)
+++ stable/9/share/man/man4/usb_quirk.4 Tue Mar 14 15:25:49 2017        
(r315250)
@@ -16,7 +16,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd September 26, 2015
+.Dd January 17, 2017
 .Dt USB_QUIRK 4
 .Os
 .Sh NAME
@@ -52,6 +52,10 @@ input is async despite claim of adaptive
 do not adjust for fractional samples
 .It UQ_AU_NO_XU
 audio device has broken extension unit
+.It UQ_AU_VENDOR_CLASS
+audio device uses vendor class to identify itself
+.It UQ_AU_SET_SPDIF_CM6206
+audio device needs special programming to enable S/PDIF audio output
 .It UQ_BAD_ADC
 bad audio spec version number
 .It UQ_BAD_AUDIO

Modified: stable/9/sys/dev/sound/usb/uaudio.c
==============================================================================
--- stable/9/sys/dev/sound/usb/uaudio.c Tue Mar 14 15:21:41 2017        
(r315249)
+++ stable/9/sys/dev/sound/usb/uaudio.c Tue Mar 14 15:25:49 2017        
(r315250)
@@ -317,6 +317,11 @@ struct uaudio_hid {
        uint8_t mute_id;
 };
 
+#define        UAUDIO_SPDIF_OUT        0x01    /* Enable S/PDIF output */
+#define        UAUDIO_SPDIF_OUT_48K    0x02    /* Out sample rate = 48K */
+#define        UAUDIO_SPDIF_OUT_96K    0x04    /* Out sample rate = 96K */
+#define        UAUDIO_SPDIF_IN_MIX     0x10    /* Input mix enable */
+
 struct uaudio_softc {
        struct sbuf sc_sndstat;
        struct sndcard_func sc_sndcard_func;
@@ -334,6 +339,7 @@ struct uaudio_softc {
        struct usb_xfer *sc_mixer_xfer[1];
        struct uaudio_mixer_node *sc_mixer_root;
        struct uaudio_mixer_node *sc_mixer_curr;
+       int     (*sc_set_spdif_fn) (struct uaudio_softc *, int);
 
        uint32_t sc_mix_info;
        uint32_t sc_recsrc_info;
@@ -864,6 +870,46 @@ uaudio_probe(device_t dev)
        return (ENXIO);
 }
 
+/*
+ * Set Cmedia CM6206 S/PDIF settings
+ * Source: CM6206 Datasheet v2.3.
+ */
+static int
+uaudio_set_spdif_cm6206(struct uaudio_softc *sc, int flags)
+{
+       uint8_t cmd[2][4] = {
+               {0x20, 0x20, 0x00, 0},
+               {0x20, 0x30, 0x02, 1}
+       };
+       int i;
+
+       if (flags & UAUDIO_SPDIF_OUT)
+               cmd[1][1] = 0x00;
+       else
+               cmd[1][1] = 0x02;
+
+       if (flags & UAUDIO_SPDIF_OUT_96K)
+               cmd[0][1] = 0x60;       /* 96K: 3'b110 */
+
+       if (flags & UAUDIO_SPDIF_IN_MIX)
+               cmd[1][1] = 0x03;       /* SPDIFMIX */
+
+       for (i = 0; i < 2; i++) {
+               if (usbd_req_set_report(sc->sc_udev, NULL,
+                   cmd[i], sizeof(cmd[0]),
+                   sc->sc_mixer_iface_index, UHID_OUTPUT_REPORT, 0) != 0) {
+                       return (ENXIO);
+               }
+       }
+       return (0);
+}
+
+static int
+uaudio_set_spdif_dummy(struct uaudio_softc *sc, int flags)
+{
+       return (0);
+}
+
 static int
 uaudio_attach(device_t dev)
 {
@@ -898,6 +944,12 @@ uaudio_attach(device_t dev)
        if (usb_test_quirk(uaa, UQ_AU_VENDOR_CLASS))
                sc->sc_uq_au_vendor_class = 1;
 
+       /* set S/PDIF function */
+       if (usb_test_quirk(uaa, UQ_AU_SET_SPDIF_CM6206))
+               sc->sc_set_spdif_fn = uaudio_set_spdif_cm6206;
+       else
+               sc->sc_set_spdif_fn = uaudio_set_spdif_dummy;
+
        umidi_init(dev);
 
        device_set_usb_desc(dev);
@@ -1034,6 +1086,11 @@ uaudio_attach(device_t dev)
        /* reload all mixer settings */
        uaudio_mixer_reload_all(sc);
 
+       /* enable S/PDIF output, if any */
+       if (sc->sc_set_spdif_fn(sc,
+           UAUDIO_SPDIF_OUT | UAUDIO_SPDIF_OUT_48K) != 0) {
+               device_printf(dev, "Failed to enable S/PDIF at 48K\n");
+       }
        return (0);                     /* success */
 
 detach:
@@ -1114,6 +1171,9 @@ uaudio_detach_sub(device_t dev)
        struct uaudio_softc *sc = device_get_softc(device_get_parent(dev));
        int error = 0;
 
+       /* disable S/PDIF output, if any */
+       (void) sc->sc_set_spdif_fn(sc, 0);
+
 repeat:
        if (sc->sc_pcm_registered) {
                error = pcm_unregister(dev);

Modified: stable/9/sys/dev/usb/quirk/usb_quirk.c
==============================================================================
--- stable/9/sys/dev/usb/quirk/usb_quirk.c      Tue Mar 14 15:21:41 2017        
(r315249)
+++ stable/9/sys/dev/usb/quirk/usb_quirk.c      Tue Mar 14 15:25:49 2017        
(r315250)
@@ -517,6 +517,7 @@ static struct usb_quirk_entry usb_quirks
        /* Non-standard USB AUDIO devices */
        USB_QUIRK(MAUDIO, FASTTRACKULTRA, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
        USB_QUIRK(MAUDIO, FASTTRACKULTRA8R, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
+       USB_QUIRK(CMEDIA, CM6206, 0x0000, 0xffff, UQ_AU_SET_SPDIF_CM6206),
 
        /*
         * Quirks for manufacturers which USB devices does not respond
@@ -604,6 +605,7 @@ static const char *usb_quirk_str[USB_QUI
        [UQ_AU_VENDOR_CLASS]            = "UQ_AU_VENDOR_CLASS",
        [UQ_SINGLE_CMD_MIDI]            = "UQ_SINGLE_CMD_MIDI",
        [UQ_MSC_DYMO_EJECT]             = "UQ_MSC_DYMO_EJECT",
+       [UQ_AU_SET_SPDIF_CM6206]        = "UQ_AU_SET_SPDIF_CM6206",
 };
 
 /*------------------------------------------------------------------------*

Modified: stable/9/sys/dev/usb/quirk/usb_quirk.h
==============================================================================
--- stable/9/sys/dev/usb/quirk/usb_quirk.h      Tue Mar 14 15:21:41 2017        
(r315249)
+++ stable/9/sys/dev/usb/quirk/usb_quirk.h      Tue Mar 14 15:25:49 2017        
(r315250)
@@ -110,6 +110,7 @@ enum {
        UQ_AU_VENDOR_CLASS,     /* audio device uses vendor and not audio class 
*/
        UQ_SINGLE_CMD_MIDI,     /* at most one command per USB packet */
        UQ_MSC_DYMO_EJECT,      /* ejects Dymo MSC device */
+       UQ_AU_SET_SPDIF_CM6206, /* enable S/PDIF audio output */
 
        USB_QUIRK_MAX
 };

Modified: stable/9/sys/dev/usb/usbdevs
==============================================================================
--- stable/9/sys/dev/usb/usbdevs        Tue Mar 14 15:21:41 2017        
(r315249)
+++ stable/9/sys/dev/usb/usbdevs        Tue Mar 14 15:25:49 2017        
(r315250)
@@ -1438,6 +1438,9 @@ product CLIPSAL 5000CT2           0x0304  5000CT2 
 product CLIPSAL C5000CT2       0x0305  C5000CT2 C-Bus Touch Screen
 product CLIPSAL L51xx          0x0401  L51xx C-Bus Dimmer
 
+/* C-Media products */
+product CMEDIA CM6206          0x0102  CM106 compatible sound device
+
 /* CMOTECH products */
 product CMOTECH CNU510         0x5141  CDMA Technologies USB modem
 product CMOTECH CNU550         0x5543  CDMA 2000 1xRTT/1xEVDO USB modem
_______________________________________________
svn-src-stable-9@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-9
To unsubscribe, send any mail to "svn-src-stable-9-unsubscr...@freebsd.org"

Reply via email to