Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 14 Mar 2017 15:19:15 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r315248 - in stable/11: share/man/man4 sys/dev/sound/usb sys/dev/usb sys/dev/usb/quirk
Message-ID:  <201703141519.v2EFJFrH099661@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Tue Mar 14 15:19:14 2017
New Revision: 315248
URL: https://svnweb.freebsd.org/changeset/base/315248

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

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

Modified: stable/11/share/man/man4/usb_quirk.4
==============================================================================
--- stable/11/share/man/man4/usb_quirk.4	Tue Mar 14 15:15:37 2017	(r315247)
+++ stable/11/share/man/man4/usb_quirk.4	Tue Mar 14 15:19:14 2017	(r315248)
@@ -16,7 +16,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd April 4, 2016
+.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/11/sys/dev/sound/usb/uaudio.c
==============================================================================
--- stable/11/sys/dev/sound/usb/uaudio.c	Tue Mar 14 15:15:37 2017	(r315247)
+++ stable/11/sys/dev/sound/usb/uaudio.c	Tue Mar 14 15:19:14 2017	(r315248)
@@ -337,6 +337,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;
@@ -354,6 +359,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;
@@ -885,6 +891,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)
 {
@@ -919,6 +965,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);
@@ -1055,6 +1107,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:
@@ -1139,6 +1196,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/11/sys/dev/usb/quirk/usb_quirk.c
==============================================================================
--- stable/11/sys/dev/usb/quirk/usb_quirk.c	Tue Mar 14 15:15:37 2017	(r315247)
+++ stable/11/sys/dev/usb/quirk/usb_quirk.c	Tue Mar 14 15:19:14 2017	(r315248)
@@ -519,6 +519,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
@@ -605,6 +606,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/11/sys/dev/usb/quirk/usb_quirk.h
==============================================================================
--- stable/11/sys/dev/usb/quirk/usb_quirk.h	Tue Mar 14 15:15:37 2017	(r315247)
+++ stable/11/sys/dev/usb/quirk/usb_quirk.h	Tue Mar 14 15:19:14 2017	(r315248)
@@ -109,6 +109,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/11/sys/dev/usb/usbdevs
==============================================================================
--- stable/11/sys/dev/usb/usbdevs	Tue Mar 14 15:15:37 2017	(r315247)
+++ stable/11/sys/dev/usb/usbdevs	Tue Mar 14 15:19:14 2017	(r315248)
@@ -1439,6 +1439,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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201703141519.v2EFJFrH099661>