Date: Fri, 2 Jul 2004 03:16:57 -0500 (CDT) From: Jonathan Noack <noackj@concordiacrusaders.org> To: FreeBSD-gnats-submit@FreeBSD.org Cc: Mathew Kanner <mat@cnd.mcgill.ca> Subject: kern/68594: [PATCH] enable S/PDIF output for es137x sound cards Message-ID: <200407020816.i628Gvxa001684@compgeek.noacks.org> Resent-Message-ID: <200407020820.i628KM9U033827@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 68594 >Category: kern >Synopsis: [PATCH] enable S/PDIF output for es137x sound cards >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Fri Jul 02 08:20:22 GMT 2004 >Closed-Date: >Last-Modified: >Originator: Jonathan Noack >Release: FreeBSD 5.2-CURRENT i386 >Organization: Concordia Lutheran High School >Environment: System: FreeBSD compgeek.noacks.org 5.2-CURRENT FreeBSD 5.2-CURRENT #11: Wed Jun 30 19:53:45 CDT 2004 noackjr@compgeek.noacks.org:/usr/obj/usr/src/sys/COMPGEEK i386 >Description: Filing PR so this doesn't get lost. I have been using this patch for four months now with no problems (other than generic pcm issues such as the locking...). See freebsd-multimedia archive for original discussion: http://docs.freebsd.org/cgi/mid.cgi?402624D7.4060009 This code was adapted from the via8233 driver. The es1373 white paper at http://www.corbac.com/Data/Misc/es1373.ps.gz was also invaluable. I added a hw.snd.pcmX.spdif_enabled sysctl to enable/disable the S/PDIF support. Enabling this sysctl does three things: 1) ENABLE_SPDIF output 2) Set to SPDIF_OUT instead of SPDIF_THRU 3) Mute analog input to get clean digital out (with RECEN_B) Disabling the sysctl just reverts these three steps. Things to ponder/shake_your_fist_at_the_world_over: 1) Mathew Kanner said he was working on revamping the pcm(4) man page. As a result, there is no man page update with this PR. 2) This may not work for all es137x sound cards. I do not know what will happen if S/PDIF is enabled on a card that doesn't support it. Most sources say only revision 4+ cards support S/PDIF, but some disagree with this. *shrug* 3) Enabling S/PDIF causes a degradation in the quality of the analog sound outputs. I believe this degradation is caused by the sound card outputting both the analog and digital signals to the same analog output plug. This may be due to some versions of the card not having a separate digital out plug (the line out serves as both the analog and digital out). If so, it may be necessary to mute the analog portion in order to get a clean digital signal on these cards. 4) Master volume control has no effect (although individual pcm stream volume is properly handled. >How-To-Repeat: N/A >Fix: See patch below. --- es137x.diff begins here --- Index: es137x.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pci/es137x.c,v retrieving revision 1.50 diff -u -r1.50 es137x.c --- es137x.c 17 Mar 2004 17:50:44 -0000 1.50 +++ es137x.c 25 May 2004 12:35:15 -0000 @@ -831,6 +831,59 @@ } } +static int es1371x_spdif_en; + +static int +sysctl_es1371x_spdif_enable(SYSCTL_HANDLER_ARGS) +{ + struct es_info *es; + device_t dev; + int err, new_en, r; + + new_en = es1371x_spdif_en; + err = sysctl_handle_int(oidp, &new_en, sizeof(new_en), req); + if (err || req->newptr == NULL) + return err; + + if (new_en < 0 || new_en > 1) + return EINVAL; + es1371x_spdif_en = new_en; + + dev = oidp->oid_arg1; + es = pcm_getdevinfo(dev); + r = bus_space_read_4(es->st, es->sh, ES1370_REG_STATUS); + if (new_en) { + r |= ENABLE_SPDIF; + es->ctrl |= SPDIFEN_B; + es->ctrl |= RECEN_B; + } else { + r &= ~ENABLE_SPDIF; + es->ctrl &= ~SPDIFEN_B; + es->ctrl &= ~RECEN_B; + } + bus_space_write_4(es->st, es->sh, ES1370_REG_CONTROL, es->ctrl); + bus_space_write_4(es->st, es->sh, ES1370_REG_STATUS, r); + return 0; +} + +static void +es_init_sysctls(device_t dev) +{ + struct es_info *es; + int r; + + es = pcm_getdevinfo(dev); + r = bus_space_read_4(es->st, es->sh, ES1370_REG_STATUS); + es1371x_spdif_en = (r & ENABLE_SPDIF) ? 1 : 0; + + SYSCTL_ADD_PROC(snd_sysctl_tree(dev), + SYSCTL_CHILDREN(snd_sysctl_tree_top(dev)), + OID_AUTO, "spdif_enabled", + CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev), + sysctl_es1371x_spdif_enable, "I", + "Enable S/PDIF output on primary playback channel"); +} + static int es_pci_attach(device_t dev) { @@ -931,6 +984,9 @@ if (pcm_register(dev, es, 1, 1)) goto bad; pcm_addchan(dev, PCMDIR_REC, ct, es); pcm_addchan(dev, PCMDIR_PLAY, ct, es); + + es_init_sysctls(dev); + pcm_setstatus(dev, status); return 0; Index: es137x.h =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pci/es137x.h,v retrieving revision 1.4 diff -u -r1.4 es137x.h --- es137x.h 5 Apr 2000 00:38:00 -0000 1.4 +++ es137x.h 25 May 2004 12:35:15 -0000 @@ -167,6 +167,17 @@ #define ES1371_SRC_RAM_DATAI(i) (((i)>>0)&0xffff) /* current value of the sample rate converter */ /* + * S/PDIF specific + */ + +/* Use ES1370_REG_CONTROL */ +#define RECEN_B 0x08000000 /* Used to control mixing of analog with digital data */ +#define SPDIFEN_B 0x04000000 /* Reset to switch digital output mux to "THRU" mode */ +/* Use ES1370_REG_STATUS */ +#define ENABLE_SPDIF 0x00040000 /* Used to enable the S/PDIF circuitry */ +#define TEST_SPDIF 0x00020000 /* Used to put the S/PDIF module in "test mode" */ + +/* * Sample rate converter addresses */ --- es137x.diff ends here --- >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200407020816.i628Gvxa001684>