--- sys/soundcard.h.orig	2025-05-07 08:10:36.598917000 +0900
+++ sys/soundcard.h	2025-05-07 15:18:50.889663000 +0900
@@ -170,6 +170,7 @@
 #define AFMT_U16_BE	0x00000100	/* Big endian unsigned 16-bit */
 #define AFMT_MPEG	0x00000200	/* MPEG MP2/MP3 audio */
 #define AFMT_AC3	0x00000400	/* Dolby Digital AC3 */
+#define AFMT_DSD	0x00000800	/* 1-bit DSD */
 
 /*
  * 32-bit formats below used for 24-bit audio data where the data is stored
--- dev/sound/pcm/channel.c.orig	2025-05-07 14:57:26.925222000 +0900
+++ dev/sound/pcm/channel.c	2025-05-07 07:24:54.917610000 +0900
@@ -1022,6 +1022,7 @@
 	{ "u32le",  NULL, NULL, AFMT_U32_LE },
 	{ "u32be",  NULL, NULL, AFMT_U32_BE },
 	{   "ac3",  NULL, NULL, AFMT_AC3    },
+	{   "dsd",  NULL, NULL, AFMT_DSD    },
 	{    NULL,  NULL, NULL, 0           }
 };
 
@@ -2413,8 +2414,10 @@
 {
 	struct pcm_channel *ch;
 	struct pcmchan_caps *caps;
+	struct snddev_info *d;
 	uint32_t bestformat, bestspeed, besthwformat, *vchanformat, *vchanrate;
 	uint32_t vpflags;
+	uint32_t oldformat;
 	int dirty, err, run, nrun;
 
 	CHN_LOCKASSERT(c);
@@ -2473,6 +2476,8 @@
 	}
 
 	if (flags & CHN_N_TRIGGER) {
+		oldformat = c->format;
+		d = c->parentsnddev;
 		if (c->direction == PCMDIR_PLAY) {
 			vchanformat = &c->parentsnddev->pvchanformat;
 			vchanrate = &c->parentsnddev->pvchanrate;
@@ -2500,8 +2505,16 @@
 			CHN_LOCK(ch);
 			if ((ch->format & AFMT_PASSTHROUGH) &&
 			    snd_fmtvalid(ch->format, caps->fmtlist)) {
-				bestformat = ch->format;
-				bestspeed = ch->speed;
+				if (ch->format & AFMT_DSD
+				    && d->flags & SD_F_DSD_TO_DOP) {
+				    oldformat = ch->format;
+				    bestspeed = ch->speed * 2;
+				    bestformat = SND_FORMAT(AFMT_S24_LE,2,0);
+				}
+				else {
+				    bestformat = ch->format;
+				    bestspeed = ch->speed;
+				}
 				CHN_UNLOCK(ch);
 				vpflags = CHN_F_PASSTHROUGH;
 				nrun++;
@@ -2602,6 +2615,7 @@
 		}
 
 		if (err == 0 && !(bestformat & AFMT_PASSTHROUGH) &&
+		    !(oldformat & AFMT_DSD && d->flags & SD_F_DSD_TO_DOP) &&
 		    (bestformat & AFMT_VCHAN)) {
 			*vchanformat = bestformat;
 			*vchanrate = bestspeed;
--- dev/sound/pcm/feeder.c.orig	2025-05-07 14:57:26.953802000 +0900
+++ dev/sound/pcm/feeder.c	2025-05-07 07:30:10.222585000 +0900
@@ -290,6 +290,8 @@
 		ret |= 1 << 12;
 	else if (fmt & AFMT_32BIT)
 		ret |= 1 << 13;
+	else if (fmt & AFMT_DSD)
+		ret |= 1 << 14;
 
 	return ret;
 }
@@ -317,13 +319,15 @@
 				continue;
 		if (oldscore == 0 ||
 			    (score_val(score2) == score_val(score)) ||
-			    (score_val(score2) == score_val(oldscore)) ||
-			    (score_val(score2) > score_val(oldscore) &&
+//			    (score_val(score2) == score_val(oldscore)) ||
+			    (AFMT_ENCODING(fmt) != AFMT_DSD &&
+			     AFMT_ENCODING(fmts[i]) != AFMT_DSD &&
+			     ((score_val(score2) > score_val(oldscore) &&
 			    score_val(score2) < score_val(score)) ||
 			    (score_val(score2) < score_val(oldscore) &&
 			    score_val(score2) > score_val(score)) ||
 			    (score_val(oldscore) < score_val(score) &&
-			    score_val(score2) > score_val(oldscore))) {
+			    score_val(score2) > score_val(oldscore))))) {
 			if (score_val(oldscore) != score_val(score2) ||
 				    score_cse(score) == score_cse(score2) ||
 				    ((score_cse(oldscore) != score_cse(score) &&
--- dev/sound/pcm/feeder_chain.c.orig	2025-05-07 14:57:27.053715000 +0900
+++ dev/sound/pcm/feeder_chain.c	2025-05-07 08:15:04.586731000 +0900
@@ -528,21 +528,28 @@
 /* Macrosses to ease our job doing stuffs later. */
 #define FEEDER_BW(c, t)		((c)->t.matrix->channels * (c)->t.rate)
 
-#define FEEDRATE_UP(c)		((c)->target.rate > (c)->current.rate)
-#define FEEDRATE_DOWN(c)	((c)->target.rate < (c)->current.rate)
+#define FEEDRATE_UP(c)		(AFMT_ENCODING((c)->origin.afmt)!=AFMT_DSD && \
+				(c)->target.rate > (c)->current.rate)
+#define FEEDRATE_DOWN(c)	(AFMT_ENCODING((c)->origin.afmt)!=AFMT_DSD && \
+				(c)->target.rate < (c)->current.rate)
 #define FEEDRATE_REQUIRED(c)	(FEEDRATE_UP(c) || FEEDRATE_DOWN(c))
 
-#define FEEDMATRIX_UP(c)	((c)->target.matrix->channels >		\
+#define FEEDMATRIX_UP(c)	(AFMT_ENCODING((c)->origin.afmt)!=AFMT_DSD && \
+				 (c)->target.matrix->channels >		\
 				 (c)->current.matrix->channels)
-#define FEEDMATRIX_DOWN(c)	((c)->target.matrix->channels <		\
+#define FEEDMATRIX_DOWN(c)	(AFMT_ENCODING((c)->origin.afmt)!=AFMT_DSD && \
+				 (c)->target.matrix->channels <		\
 				 (c)->current.matrix->channels)
 #define FEEDMATRIX_REQUIRED(c)	(FEEDMATRIX_UP(c) ||			\
-				 FEEDMATRIX_DOWN(c) || (c)->use_matrix != 0)
+				 FEEDMATRIX_DOWN(c) ||			\
+				 (AFMT_ENCODING((c)->origin.afmt)!=AFMT_DSD && \
+				  (c)->use_matrix != 0))
 
 #define FEEDFORMAT_REQUIRED(c)	(AFMT_ENCODING((c)->current.afmt) !=	\
 				 AFMT_ENCODING((c)->target.afmt))
 
-#define FEEDVOLUME_REQUIRED(c)	((c)->use_volume != 0)
+#define FEEDVOLUME_REQUIRED(c)	(AFMT_ENCODING((c)->origin.afmt)!=AFMT_DSD && \
+				 (c)->use_volume != 0)
 
 #define FEEDEQ_VALIDRATE(c, t)	(feeder_eq_validrate((c)->t.rate) != 0)
 #define FEEDEQ_ECONOMY(c)	(FEEDER_BW(c, current) < FEEDER_BW(c, target))
@@ -583,6 +590,7 @@
 	struct feeder_chain_desc cdesc;
 	struct pcmchan_matrix *hwmatrix, *softmatrix;
 	uint32_t hwfmt, softfmt;
+	uint32_t hwspd;
 	int ret;
 
 	CHN_LOCKASSERT(c);
@@ -618,10 +626,6 @@
 				 CHN_F_PASSTHROUGH)) ==			\
 				 (CHN_F_VIRTUAL | CHN_F_PASSTHROUGH))
 
-	/* Get the best possible hardware format. */
-	if (VCHAN_PASSTHROUGH(c))
-		hwfmt = c->parentchannel->format;
-	else {
 		caps = chn_getcaps(c);
 		if (caps == NULL || caps->fmtlist == NULL) {
 			device_printf(c->dev,
@@ -629,10 +633,19 @@
 			return (ENODEV);
 		}
 
+	/* Get the best possible hardware format. */
+	if (VCHAN_PASSTHROUGH(c)) {
+		hwfmt = c->parentchannel->format;
+		hwspd = c->parentchannel->speed;
+		if (!hwspd)
+			hwspd = sndbuf_getspd(c->bufhard);
+	}
+	else {
 		if ((c->format & AFMT_PASSTHROUGH) &&
 		    !snd_fmtvalid(c->format, caps->fmtlist))
 			return (ENODEV);
 
+		hwspd = sndbuf_getspd(c->bufhard);
 		hwfmt = snd_fmtbest(c->format, caps->fmtlist);
 		if (hwfmt == 0 || !snd_fmtvalid(hwfmt, caps->fmtlist)) {
 			device_printf(c->dev,
@@ -684,16 +697,34 @@
 		    "%s(): WARNING: %s Soft format 0x%08x -> 0x%08x\n",
 		    __func__, CHN_DIRSTR(c), c->format, softfmt);
 
+	d = c->parentsnddev;
+
 	/*
 	 * PLAY and REC are opposite.
 	 */
 	if (c->direction == PCMDIR_PLAY) {
-		cdesc.origin.afmt    = softfmt;
-		cdesc.origin.matrix  = softmatrix;
-		cdesc.origin.rate    = c->speed;
-		cdesc.target.afmt    = hwfmt;
-		cdesc.target.matrix  = hwmatrix;
-		cdesc.target.rate    = sndbuf_getspd(c->bufhard);
+		if (d->flags & SD_F_DSD_TO_DOP
+		    && AFMT_ENCODING(c->format) == AFMT_DSD) {
+			cdesc.origin.afmt    = c->format;
+			cdesc.origin.matrix  = softmatrix;
+			cdesc.origin.rate    = c->speed;
+			hwfmt	= SND_FORMAT(AFMT_S24_LE,2,0);
+			if (c->speed)
+				hwspd	= c->speed * 2;
+			RANGE(hwspd, caps->minspeed, caps->maxspeed);
+			cdesc.target.afmt    = hwfmt;
+			cdesc.target.matrix  = hwmatrix;
+			cdesc.target.rate    = hwspd;
+		}
+		else {
+			cdesc.origin.afmt    = softfmt;
+			cdesc.origin.matrix  = softmatrix;
+			cdesc.origin.rate    = c->speed;
+			RANGE(hwspd, caps->minspeed, caps->maxspeed);
+			cdesc.target.afmt    = hwfmt;
+			cdesc.target.matrix  = hwmatrix;
+			cdesc.target.rate    = hwspd;//sndbuf_getspd(c->bufhard);
+		}
 	} else {
 		cdesc.origin.afmt    = hwfmt;
 		cdesc.origin.matrix  = hwmatrix;
@@ -703,20 +734,27 @@
 		cdesc.target.rate    = c->speed;
 	}
 
-	d = c->parentsnddev;
-
 	/*
 	 * If channel is in bitperfect or passthrough mode, make it appear
 	 * that 'origin' and 'target' identical, skipping mostly chain
 	 * procedures.
 	 */
-	if (CHN_BITPERFECT(c) || (c->format & AFMT_PASSTHROUGH)) {
+	if (CHN_BITPERFECT(c) || (c->format & AFMT_AC3)
+	    || (c->format & AFMT_DSD && !(d->flags & SD_F_DSD_TO_DOP))) {
 		if (c->direction == PCMDIR_PLAY)
 			cdesc.origin = cdesc.target;
 		else
 			cdesc.target = cdesc.origin;
 		c->format = cdesc.target.afmt;
 		c->speed  = cdesc.target.rate;
+	} else if (c->format & AFMT_DSD) {
+		if (c->direction == PCMDIR_PLAY) {
+			c->format = cdesc.origin.afmt;
+			c->speed  = cdesc.origin.rate;
+		} else {
+			c->format = cdesc.target.afmt;
+			c->speed  = cdesc.target.rate;
+		}
 	} else {
 		/* hwfmt is not convertible, so 'dummy' it. */
 		if (hwfmt & AFMT_PASSTHROUGH)
@@ -849,6 +887,7 @@
 	sndbuf_setspd(c->bufsoft, c->speed);
 
 	sndbuf_setfmt(c->bufhard, hwfmt);
+	sndbuf_setspd(c->bufhard, hwspd);
 
 	chn_syncstate(c);
 
--- dev/sound/pcm/feeder_format.c.orig	2025-05-07 14:57:27.072740000 +0900
+++ dev/sound/pcm/feeder_format.c	2025-05-07 07:50:48.023724000 +0900
@@ -82,6 +82,25 @@
 		intpcm_write_##SIGN##BIT##ENDIAN			\
 	}
 
+static
+__inline
+void
+intpcm_write_DOP64TO96LE(uint8_t *dst, intpcm_t v)
+{
+	dst[0]	= v;
+	dst[1]	= v >> 8;
+	dst[2]	= 0x05;
+	dst[3]	= v >> 32;
+	dst[4]	= v >> 40;
+	dst[5]	= 0x05;
+	dst[6]	= v >> 16;
+	dst[7]	= v >> 24;
+	dst[8]	= 0xfa;
+	dst[9]	= v >> 48;
+	dst[10]	= v >> 56;
+	dst[11]	= 0xfa;
+}
+
 static const struct {
 	uint32_t format;
 	intpcm_read_t *read;
@@ -112,6 +131,10 @@
 	{
 		AFMT_AC3,
 		intpcm_read_null, intpcm_write_null
+	},
+	{
+		AFMT_DSD,
+		intpcm_read_S64LE, intpcm_write_DOP64TO96LE
 	}
 };
 
@@ -132,6 +155,12 @@
 
 	for (i = 0; i < nitems(feed_format_ops) &&
 	    (rd_op == NULL || wr_op == NULL); i++) {
+		if (AFMT_ENCODING(f->desc->in) == AFMT_DSD
+		    && feed_format_ops[i].format == AFMT_DSD) {
+			rd_op	= feed_format_ops[i].read;
+			wr_op	= feed_format_ops[i].write;
+			break;
+		}
 		if (rd_op == NULL &&
 		    AFMT_ENCODING(f->desc->in) == feed_format_ops[i].format)
 			rd_op = feed_format_ops[i].read;
@@ -151,15 +180,23 @@
 	if (info == NULL)
 		return (ENOMEM);
 
-	info->channels = AFMT_CHANNEL(f->desc->in);
-
-	info->ibps = AFMT_BPS(f->desc->in);
-	info->ialign = info->ibps * info->channels;
 	info->read = rd_op;
-
-	info->obps = AFMT_BPS(f->desc->out);
-	info->oalign = info->obps * info->channels;
 	info->write = wr_op;
+	if (AFMT_ENCODING(f->desc->in) == AFMT_DSD) {
+		info->channels = 1;
+		info->ibps = 8;//AFMT_BPS(f->desc->in) * info->channels;
+		info->ialign = info->ibps;
+		info->obps = 12;
+		info->oalign = info->obps;
+	}
+	else {
+		info->channels = AFMT_CHANNEL(f->desc->in);
+		/* printf("format %08x\n", f->desc->out); */
+		info->ibps = AFMT_BPS(f->desc->in);
+		info->ialign = info->ibps * info->channels;
+		info->obps = AFMT_BPS(f->desc->out);
+		info->oalign = info->obps * info->channels;
+	}
 
 	f->data = info;
 
--- dev/sound/pcm/feeder_mixer.c.orig	2024-10-07 03:54:44.607967000 +0900
+++ dev/sound/pcm/feeder_mixer.c	2024-10-07 05:46:57.031482000 +0900
@@ -122,6 +122,7 @@
 	FEEDMIXER_ENTRY(U, 32, BE),
 #endif
 	{    AFMT_AC3, PCM_16_BPS, NULL },
+	{    AFMT_DSD, PCM_32_BPS, NULL },
 	{ AFMT_MU_LAW,  PCM_8_BPS, feed_mixer_U8NE },	/* dummy */
 	{  AFMT_A_LAW,  PCM_8_BPS, feed_mixer_U8NE }	/* dummy */
 };
--- dev/sound/pcm/intpcm.h.orig	2024-03-02 05:47:15.000000000 +0900
+++ dev/sound/pcm/intpcm.h	2024-10-07 05:46:57.031814000 +0900
@@ -85,6 +85,21 @@
 	_PCM_WRITE_##SIGN##32##_##ENDIAN(dst, v);			\
 }
 
+#define INTPCM_DECLARE_OP_64(SIGN, ENDIAN)				\
+static __inline intpcm_t						\
+intpcm_read_##SIGN##64##ENDIAN(uint8_t *src)				\
+{									\
+									\
+	return (_PCM_READ_##SIGN##64##_##ENDIAN(src));			\
+}									\
+									\
+static __inline void							\
+intpcm_write_##SIGN##64##ENDIAN(uint8_t *dst, intpcm_t v)		\
+{									\
+									\
+	_PCM_WRITE_##SIGN##64##_##ENDIAN(dst, v);			\
+}
+
 #define INTPCM_DECLARE(t)						\
 									\
 G711_DECLARE_TABLE(t);							\
@@ -124,6 +139,7 @@
 INTPCM_DECLARE_OP_24(S, BE)						\
 INTPCM_DECLARE_OP_32(S, LE)						\
 INTPCM_DECLARE_OP_32(S, BE)						\
+INTPCM_DECLARE_OP_64(S, LE)						\
 INTPCM_DECLARE_OP_8(U,  NE)						\
 INTPCM_DECLARE_OP_16(U, LE)						\
 INTPCM_DECLARE_OP_16(U, BE)						\
--- dev/sound/pcm/pcm.h.orig	2024-03-02 05:47:15.000000000 +0900
+++ dev/sound/pcm/pcm.h	2024-10-07 05:46:57.032282000 +0900
@@ -49,7 +49,7 @@
 #define SND_PCM_64	1
 #endif
 
-typedef int32_t intpcm_t;
+typedef int64_t intpcm_t;
 
 typedef int32_t intpcm8_t;
 typedef int32_t intpcm16_t;
@@ -99,6 +99,7 @@
 #define PCM_16_BPS	2
 #define PCM_24_BPS	3
 #define PCM_32_BPS	4
+#define PCM_48_BPS	6
 
 #define INTPCM_T(v)	((intpcm_t)(v))
 #define INTPCM8_T(v)	((intpcm8_t)(v))
@@ -109,6 +110,7 @@
 #if BYTE_ORDER == LITTLE_ENDIAN
 #define _PCM_READ_S16_LE(b8)		INTPCM_T(*((int16_t *)(b8)))
 #define _PCM_READ_S32_LE(b8)		INTPCM_T(*((int32_t *)(b8)))
+#define _PCM_READ_S64_LE(b8)		INTPCM_T(*((int64_t *)(b8)))
 #define _PCM_READ_S16_BE(b8)						\
 	INTPCM_T((b8)[1] | (((int8_t)((b8)[0])) << 8))
 #define _PCM_READ_S32_BE(b8)						\
@@ -121,6 +123,9 @@
 #define _PCM_WRITE_S32_LE(b8, val)	do {				\
 	*((int32_t *)(b8)) = (val);					\
 } while (0)
+#define _PCM_WRITE_S64_LE(b8, val)	do {				\
+	*((int64_t *)(b8)) = (val);					\
+} while (0)
 #define _PCM_WRITE_S16_BE(bb8, vval)	do {				\
 	intpcm_t val = (vval); 						\
 	uint8_t *b8 = (bb8);						\
@@ -181,6 +186,11 @@
 #define _PCM_READ_S32_LE(b8)						\
 	INTPCM_T((b8)[0] | ((b8)[1] << 8) | ((b8)[2] << 16) |		\
 	    (((int8_t)((b8)[3])) << 24))
+#define _PCM_READ_S64_LE(b8)						\
+	INTPCM_T((b8)[0] | ((b8)[1] << 8) | ((b8)[2] << 16) |		\
+	    ((b8)[3]) << 24) |						\
+	    ((b8)[4] << 32) | ((b8)[5] << 40) | ((b8)[6] << 48) |	\
+	    (((int8_t)((b8)[7])) << 56))
 #define _PCM_READ_S16_BE(b8)		INTPCM_T(*((int16_t *)(b8)))
 #define _PCM_READ_S32_BE(b8)		INTPCM_T(*((int32_t *)(b8)))
 
@@ -197,6 +207,18 @@
 	b8[1] = val >> 8;						\
 	b8[2] = val >> 16;						\
 	b8[3] = val >> 24;						\
+} while (0)
+#define _PCM_WRITE_S64_LE(bb8, vval)	do {				\
+	intpcm_t val = (vval);						\
+	uint8_t *b8 = (bb8);						\
+	b8[0] = val;							\
+	b8[1] = val >> 8;						\
+	b8[2] = val >> 16;						\
+	b8[3] = val >> 24;						\
+	b8[4] = val >> 32;						\
+	b8[5] = val >> 40;						\
+	b8[6] = val >> 48;						\
+	b8[7] = val >> 56;						\
 } while (0)
 #define _PCM_WRITE_S16_BE(b8, val)	do {				\
 	*((int16_t *)(b8)) = (val);					\
--- dev/sound/pcm/sound.c.orig	2025-05-07 14:57:27.205537000 +0900
+++ dev/sound/pcm/sound.c	2025-05-07 07:54:51.404341000 +0900
@@ -412,6 +412,43 @@
 	return (err);
 }
 
+static int
+sysctl_dev_pcm_dsd_to_dop(SYSCTL_HANDLER_ARGS)
+{
+	struct snddev_info *d;
+	int err, val;
+
+	d = oidp->oid_arg1;
+	if (!PCM_REGISTERED(d))
+		return (ENODEV);
+
+	PCM_LOCK(d);
+	PCM_WAIT(d);
+	val = (d->flags & SD_F_DSD_TO_DOP) ? 1 : 0;
+	PCM_ACQUIRE(d);
+	PCM_UNLOCK(d);
+
+	err = sysctl_handle_int(oidp, &val, 0, req);
+
+	if (err == 0 && req->newptr != NULL) {
+		if (!(val == 0 || val == 1)) {
+			PCM_RELEASE_QUICK(d);
+			return (EINVAL);
+		}
+
+		PCM_LOCK(d);
+
+		d->flags &= ~SD_F_DSD_TO_DOP;
+		d->flags |= (val != 0) ? SD_F_DSD_TO_DOP : 0;
+
+		PCM_RELEASE(d);
+		PCM_UNLOCK(d);
+	} else
+		PCM_RELEASE_QUICK(d);
+
+	return (err);
+}
+
 static u_int8_t
 pcm_mode_init(struct snddev_info *d)
 {
@@ -445,6 +482,11 @@
 	    "bitperfect", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, d,
 	    sizeof(d), sysctl_dev_pcm_bitperfect, "I",
 	    "bit-perfect playback/recording (0=disable, 1=enable)");
+	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
+	    "dsd_to_dop", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, d,
+	    sizeof(d), sysctl_dev_pcm_dsd_to_dop, "I",
+	    "playback dsd as dop (0=disable, 1=enable)");
 	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
 	    OID_AUTO, "mode", CTLFLAG_RD, NULL, mode,
--- dev/sound/pcm/sound.h.orig	2025-05-07 14:57:27.240296000 +0900
+++ dev/sound/pcm/sound.h	2025-05-07 07:14:16.841730000 +0900
@@ -115,6 +115,7 @@
 #define SD_F_EQ_ENABLED		0x00000800	/* EQ enabled */
 #define SD_F_EQ_BYPASSED	0x00001000	/* EQ bypassed */
 #define SD_F_EQ_PC		0x00002000	/* EQ per-channel */
+#define SD_F_DSD_TO_DOP		0x00004000	/* convert DSD to DoP */
 
 #define SD_F_EQ_DEFAULT		(SD_F_EQ | SD_F_EQ_ENABLED)
 #define SD_F_EQ_MASK		(SD_F_EQ | SD_F_EQ_ENABLED |		\
@@ -138,6 +139,7 @@
 				"\014EQ_ENABLED"			\
 				"\015EQ_BYPASSED"			\
 				"\016EQ_PC"				\
+				"\017DSD_TO_DOP"			\
 				"\035PRIO_RD"				\
 				"\036PRIO_WR"
 
@@ -172,7 +174,7 @@
 /* Supported vchan mixing formats */
 #define AFMT_VCHAN		(AFMT_CONVERTIBLE & ~AFMT_G711)
 
-#define AFMT_PASSTHROUGH		AFMT_AC3
+#define AFMT_PASSTHROUGH		(AFMT_AC3|AFMT_DSD)
 #define AFMT_PASSTHROUGH_RATE		48000
 #define AFMT_PASSTHROUGH_CHANNEL	2
 #define AFMT_PASSTHROUGH_EXTCHANNEL	0
@@ -197,10 +199,10 @@
 #define AFMT_CHANNEL(v)		(((v) & AFMT_CHANNEL_MASK) >>		\
 				AFMT_CHANNEL_SHIFT)
 
-#define AFMT_BIT(v)		(((v) & AFMT_32BIT) ? 32 :		\
+#define AFMT_BIT(v)		(((v) & (AFMT_32BIT|AFMT_DSD)) ? 32 :	\
 				(((v) & AFMT_24BIT) ? 24 :		\
 				((((v) & AFMT_16BIT) ||			\
-				((v) & AFMT_PASSTHROUGH)) ? 16 : 8)))
+				((v) & AFMT_AC3)) ? 16 : 8)))
 
 #define AFMT_BPS(v)		(AFMT_BIT(v) >> 3)
 #define AFMT_ALIGN(v)		(AFMT_BPS(v) * AFMT_CHANNEL(v))
--- dev/sound/pcm/vchan.c.orig	2025-05-07 14:57:27.245501000 +0900
+++ dev/sound/pcm/vchan.c	2025-05-07 08:07:23.974884000 +0900
@@ -41,10 +41,11 @@
 #include <dev/sound/pcm/vchan.h>
 
 /*
- * [ac3 , dts , linear , 0, linear, 0]
+ * [ac3 , dts , linear , linear, linear, 0, linear, 0]
  */
-#define FMTLIST_MAX		6
-#define FMTLIST_OFFSET		4
+#define FMTLIST_MAX		9
+#define FMTLIST_OFFSET		7
+#define LINEARFMTS_MAX		6
 #define DIGFMTS_MAX		2
 
 #ifdef SND_DEBUG
@@ -88,6 +89,10 @@
 		if (fmtlist[i] & AFMT_PASSTHROUGH)
 			info->fmtlist[j++] = fmtlist[i];
 	}
+	for (i = 0; fmtlist[i] != 0 && j < LINEARFMTS_MAX; i++) {
+		if (!(fmtlist[i] & AFMT_PASSTHROUGH))
+			info->fmtlist[j++] = fmtlist[i];
+	}
 	if (p->format & AFMT_VCHAN)
 		info->fmtlist[j] = p->format;
 	else
@@ -193,10 +198,12 @@
 {
 	struct vchan_info *info;
 	struct pcm_channel *c;
+	struct snddev_info *d;
 	uint32_t pformat, pspeed, pflags, i;
 
 	info = data;
 	c = info->channel;
+	d = c->parentsnddev;
 	pformat = c->parentchannel->format;
 	pspeed = c->parentchannel->speed;
 	pflags = c->parentchannel->flags;
@@ -214,10 +221,18 @@
 			info->caps.fmtlist[i] = pformat;
 		}
 		if (c->format & AFMT_PASSTHROUGH)
+		    if (c->format & AFMT_DSD && d->flags & SD_F_DSD_TO_DOP) {
 			info->caps.minspeed = c->speed;
-		else 
+			info->caps.maxspeed = info->caps.minspeed * 2;
+		    }
+		    else {
+			info->caps.minspeed = c->speed;
+			info->caps.maxspeed = info->caps.minspeed;
+		    }
+		else  {
 			info->caps.minspeed = pspeed;
-		info->caps.maxspeed = info->caps.minspeed;
+			info->caps.maxspeed = info->caps.minspeed;
+		}
 	} else {
 		info->caps.fmtlist = info->fmtlist + FMTLIST_OFFSET;
 		if (pformat & AFMT_VCHAN)
--- dev/sound/usb/uaudio.c.orig	2025-05-07 14:57:27.282164000 +0900
+++ dev/sound/usb/uaudio.c	2025-08-30 15:46:40.926119000 +0900
@@ -213,7 +213,7 @@
 	struct uaudio_softc *sc;
 };
 
-#define	CHAN_MAX_ALT 24
+#define	CHAN_MAX_ALT 128
 
 struct uaudio_chan_alt {
 	union uaudio_asf1d p_asf1d;
@@ -253,7 +253,8 @@
 
 	int feedback_rate;
 
-	uint32_t pcm_format[2];
+	uint32_t pcm_format_count;
+	uint32_t pcm_format[CHAN_MAX_ALT+1];
 
 	uint16_t bytes_per_frame[2];
 
@@ -426,7 +427,7 @@
 };
 
 struct uaudio_format {
-	uint16_t wFormat;
+	uint32_t wFormat;
 	uint8_t	bPrecision;
 	uint32_t freebsd_fmt;
 	const char *description;
@@ -461,6 +462,8 @@
 
 	{UA20_FMT_ALAW, 8, AFMT_A_LAW, "8-bit A-Law"},
 	{UA20_FMT_MULAW, 8, AFMT_MU_LAW, "8-bit mu-Law"},
+
+	{UA20_FMT_RAW, 32, AFMT_DSD, "1-bit DSD"},
 	{0, 0, 0, NULL}
 };
 
@@ -511,6 +514,8 @@
 static void	uaudio_mixer_find_inputs_sub(struct uaudio_terminal_node *,
 		    const uint8_t *, uint8_t, struct uaudio_search_result *);
 static const void *uaudio_mixer_verify_desc(const void *, uint32_t);
+static usb_error_t uaudio_set_format(struct usb_device *, uint8_t,
+		    uint8_t, uint32_t);
 static usb_error_t uaudio_set_speed(struct usb_device *, uint8_t, uint32_t);
 static int	uaudio_mixer_get(struct usb_device *, uint16_t, uint8_t,
 		    struct uaudio_mixer_node *);
@@ -531,6 +536,9 @@
 static const void *uaudio20_mixer_verify_desc(const void *, uint32_t);
 static usb_error_t uaudio20_set_speed(struct usb_device *, uint8_t,
 		    uint8_t, uint32_t);
+static usb_error_t
+uaudio20_set_format(struct usb_device *udev, uint8_t iface_no,
+    uint8_t clockid, uint32_t format);
 
 /* USB audio v1.0 and v2.0 */
 
@@ -1467,6 +1475,11 @@
 				DPRINTF("setting of sample rate failed! "
 				    "(continuing anyway)\n");
 			}
+			if (uaudio20_set_format(sc->sc_udev,
+			    sc->sc_mixer_iface_no, x, chan_alt->p_fmt->wFormat)) {
+				DPRINTF("setting of format failed! "
+				    "(continuing anyway)\n");
+			}
 		}
 	} else if (chan_alt->p_sed.v1->bmAttributes & UA_SED_FREQ_CONTROL) {
 		if (uaudio_set_speed(sc->sc_udev,
@@ -1629,7 +1642,7 @@
 {
 	struct usb_device_request req;
 	usb_error_t error;
-#define	UAUDIO20_MAX_RATES 32	/* we support at maximum 32 rates */
+#define	UAUDIO20_MAX_RATES 64	/* we support at maximum 32 rates */
 	uint8_t data[2 + UAUDIO20_MAX_RATES * 12];
 	uint16_t actlen;
 	uint16_t rates;
@@ -1766,6 +1779,7 @@
 	uint8_t audio_if = 0;
 	uint8_t midi_if = 0;
 	uint8_t uma_if_class;
+	uint32_t i;
 
 	while ((desc = usb_desc_foreach(cd, desc))) {
 		if ((desc->bDescriptorType == UDESC_INTERFACE) &&
@@ -1957,13 +1971,17 @@
 
 			if ((bChannels != channels) ||
 			    (bBitResolution != bit_resolution)) {
-				DPRINTF("Wrong number of channels\n");
+				DPRINTF("Wrong number of "
+					"bChannels:%d channels:%d, "
+					"bBitResolution:%d, bit_resolution:%d\n",
+					(int)bChannels, (int)channels,
+					(int)bBitResolution,(int)bit_resolution);
 				goto next_ep;
 			}
 
 			for (p_fmt = uaudio20_formats;
 			    p_fmt->wFormat != 0; p_fmt++) {
-				if ((p_fmt->wFormat & dwFormat) &&
+				if ((p_fmt->wFormat == dwFormat) &&
 				    (p_fmt->bPrecision == bBitResolution))
 					break;
 			}
@@ -1991,8 +2009,8 @@
 				if (uaudio20_check_rate(udev,
 				    sc->sc_mixer_iface_no, x, rate)) {
 					DPRINTF("Unsupported sampling "
-					    "rate, id=%d\n", x);
-					goto next_ep;
+					    "rate=%d, id=%d\n", rate, x);
+					continue;//goto next_ep;
 				}
 			}
 		} else {
@@ -2035,7 +2053,11 @@
 
 			if ((bChannels != channels) ||
 			    (bBitResolution != bit_resolution)) {
-				DPRINTF("Wrong number of channels\n");
+				DPRINTF("Wrong number of "
+					"bChannels:%d channels:%d, "
+					"bBitResolution:%d, bit_resolution:%d\n",
+					(int)bChannels, (int)channels,
+					(int)bBitResolution,(int)bit_resolution);
 				goto next_ep;
 			}
 		}
@@ -2064,8 +2086,10 @@
 		uaudio_chan_dump_ep_desc(ed1);
 #endif
 		DPRINTF("Sample rate = %dHz, channels = %d, "
-		    "bits = %d, format = %s, ep 0x%02x, chan %p\n", rate, channels,
-		    bit_resolution, p_fmt->description, ed1->bEndpointAddress, chan);
+		    "bits = %d, format = %s, ep 0x%02x, alt_idx %d, chan %p\n",
+		    rate, channels,
+		    bit_resolution, p_fmt->description, ed1->bEndpointAddress,
+		    alt_index, chan);
 
 		chan_alt->sample_rate = rate;
 		chan_alt->p_asf1d = asf1d;
@@ -2120,21 +2144,29 @@
 			goto next_ep;
 		}
 		if (chan->num_alt > 1) {
-			/* we only accumulate one format at different sample rates */
-			if (chan->pcm_format[0] != format) {
-				DPRINTF("Multiple formats is not supported\n");
+			/* ignore if duplicate format and sample rate entry */
+			if (format == chan->usb_alt[chan->num_alt - 2].p_fmt->freebsd_fmt &&
+			    rate == chan->usb_alt[chan->num_alt - 2].sample_rate) {
+				DPRINTF("Duplicate format and sample rate detected\n");
 				chan->num_alt--;
 				goto next_ep;
 			}
-			/* ignore if duplicate sample rate entry */
-			if (rate == chan->usb_alt[chan->num_alt - 2].sample_rate) {
-				DPRINTF("Duplicate sample rate detected\n");
-				chan->num_alt--;
-				goto next_ep;
-			}
 		}
 		chan->pcm_cap.fmtlist = chan->pcm_format;
-		chan->pcm_cap.fmtlist[0] = format;
+		for (i = 0; i< chan->pcm_format_count; i++) {
+			if (chan->pcm_format[i] == format) {
+				break;
+			}
+		}
+		if (i == chan->pcm_format_count) {
+			if (chan->pcm_format_count >= CHAN_MAX_ALT) {
+				printf("pcm_format_count over.\n");
+			}
+			else {
+				chan->pcm_cap.fmtlist[chan->pcm_format_count] = format;
+				chan->pcm_format_count++;
+			}
+		}
 
 		/* check if device needs bitperfect */
 		if (chan_alt->channels > UAUDIO_MATRIX_MAX)
@@ -2154,6 +2186,8 @@
 /* This structure defines all the supported rates. */
 
 static const uint32_t uaudio_rate_list[CHAN_MAX_ALT] = {
+	768000,
+	705600,
 	384000,
 	352800,
 	192000,
@@ -2286,7 +2320,7 @@
 
 		temp = UGETDW(buf);
 
-		DPRINTF("Value = 0x%08x\n", (int)temp);
+		DPRINTFN(2,"Value = 0x%08x\n", (int)temp);
 
 		/* auto-detect SYNC format */
 
@@ -2309,7 +2343,7 @@
 		while (temp > (sample_rate + (sample_rate / 2)))
 			temp /= 2;
 
-		DPRINTF("Comparing %d Hz :: %d Hz\n",
+		DPRINTFN(2,"Comparing %d Hz :: %d Hz\n",
 		    (int)temp, (int)sample_rate);
 
 		/*
@@ -2722,6 +2756,13 @@
 }
 
 int
+uaudio_chan_reset(struct uaudio_chan *ch)
+{
+        msleep(ch, ch->pcm_mtx, 0, "reset", 50);
+	return (0);
+}
+
+int
 uaudio_chan_set_param_blocksize(struct uaudio_chan *ch, uint32_t blocksize)
 {
 	uint32_t temp = 2 * uaudio_get_buffer_size(ch, ch->set_alt);
@@ -2822,7 +2863,30 @@
 int
 uaudio_chan_set_param_format(struct uaudio_chan *ch, uint32_t format)
 {
+	struct uaudio_softc *sc;
+	/* struct uaudio_chan_alt *chan_alt; */
+	uint32_t dop_format, dop_speed;
+	uint8_t next_alt;
+
 	DPRINTF("Selecting format 0x%08x\n", (unsigned int)format);
+
+	sc = ch->priv_sc;
+	dop_speed	= sndbuf_getspd(ch->pcm_ch->bufhard);
+	dop_format	= format;
+
+	for (next_alt = 0; next_alt < ch->num_alt; next_alt++) {
+		if (dop_speed == ch->usb_alt[next_alt].sample_rate
+		    && AFMT_ENCODING(dop_format)
+		    == AFMT_ENCODING(ch->usb_alt[next_alt].p_fmt->freebsd_fmt))
+ 			break;
+	}
+	if (next_alt == ch->num_alt)
+		next_alt--;
+
+	usb_proc_explore_lock(sc->sc_udev);
+	ch->set_alt = next_alt;
+	usb_proc_explore_unlock(sc->sc_udev);
+
 	return (0);
 }
 
@@ -5360,6 +5424,34 @@
 	data[1] = speed >> 8;
 	data[2] = speed >> 16;
 	data[3] = speed >> 24;
+
+	return (usbd_do_request(udev, NULL, &req, data));
+}
+
+static usb_error_t
+uaudio20_set_format(struct usb_device *udev, uint8_t iface_no,
+    uint8_t clockid, uint32_t format)
+{
+	struct usb_device_request req;
+	uint8_t data[8];
+
+	DPRINTFN(6, "ifaceno=%d clockid=%d format=0x%08x\n",
+	    iface_no, clockid, format);
+
+	req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
+	req.bRequest = UA20_CS_CUR;
+	USETW2(req.wValue, UA20_CS_AUDIO_FORMAT_CONTROL, 0);
+	USETW2(req.wIndex, clockid, iface_no);
+	USETW(req.wLength, 8);
+	/* USETDW(data,format); */
+	data[0] = format;
+	data[1] = format >> 8;
+	data[2] = format >> 16;
+	data[3] = format >> 24;
+	data[4] = 0;//format >> 24;
+	data[5] = 0;//format >> 16;
+	data[6] = 0;//format >> 8;
+	data[7] = 0;//format;
 
 	return (usbd_do_request(udev, NULL, &req, data));
 }
--- dev/sound/usb/uaudio.h.orig	2024-03-02 05:47:15.000000000 +0900
+++ dev/sound/usb/uaudio.h	2024-10-07 06:03:44.366335000 +0900
@@ -43,6 +43,7 @@
 extern void	*uaudio_chan_init(struct uaudio_chan *ch, struct snd_dbuf *b,
 		    struct pcm_channel *c, int dir);
 extern int	uaudio_chan_free(struct uaudio_chan *ch);
+extern int	uaudio_chan_reset(struct uaudio_chan *ch);
 extern int	uaudio_chan_set_param_blocksize(struct uaudio_chan *ch,
 		    uint32_t blocksize);
 extern int	uaudio_chan_set_param_fragments(struct uaudio_chan *ch,
--- dev/sound/usb/uaudio_pcm.c.orig	2025-05-07 08:24:49.069912000 +0900
+++ dev/sound/usb/uaudio_pcm.c	2025-05-07 07:09:45.174877000 +0900
@@ -50,6 +50,12 @@
 }
 
 static int
+ua_chan_reset(kobj_t obj, void *data)
+{
+	return (uaudio_chan_reset(data));
+}
+
+static int
 ua_chan_setformat(kobj_t obj, void *data, uint32_t format)
 {
 	/*
@@ -111,6 +117,7 @@
 static kobj_method_t ua_chan_methods[] = {
 	KOBJMETHOD(channel_init, ua_chan_init),
 	KOBJMETHOD(channel_free, ua_chan_free),
+	KOBJMETHOD(channel_reset, ua_chan_reset),
 	KOBJMETHOD(channel_setformat, ua_chan_setformat),
 	KOBJMETHOD(channel_setspeed, ua_chan_setspeed),
 	KOBJMETHOD(channel_setblocksize, ua_chan_setblocksize),
--- dev/sound/usb/uaudioreg.h.orig	2024-03-02 05:47:15.000000000 +0900
+++ dev/sound/usb/uaudioreg.h	2024-10-07 06:03:44.450403000 +0900
@@ -782,6 +782,7 @@
 
 #define	UA20_CS_SAM_FREQ_CONTROL	0x01
 #define	UA20_CS_CLOCK_VALID_CONTROL 	0x02
+#define	UA20_CS_AUDIO_FORMAT_CONTROL 	0x03
 
 #define	UA20_TE_COPY_PROTECT_CONTROL	0x01
 #define	UA20_TE_CONNECTOR_CONTROL	0x02
