From owner-svn-src-head@FreeBSD.ORG Mon Jan 23 17:05:11 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 75D4A1065672; Mon, 23 Jan 2012 17:05:11 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 648718FC08; Mon, 23 Jan 2012 17:05:11 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q0NH5BWK035681; Mon, 23 Jan 2012 17:05:11 GMT (envelope-from mav@svn.freebsd.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q0NH5B7C035679; Mon, 23 Jan 2012 17:05:11 GMT (envelope-from mav@svn.freebsd.org) Message-Id: <201201231705.q0NH5B7C035679@svn.freebsd.org> From: Alexander Motin Date: Mon, 23 Jan 2012 17:05:11 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r230488 - head/sys/dev/sound/pci/hda X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 23 Jan 2012 17:05:11 -0000 Author: mav Date: Mon Jan 23 17:05:11 2012 New Revision: 230488 URL: http://svn.freebsd.org/changeset/base/230488 Log: Realtek CODECs declare support for 32bit samples on S/PDIF input/output widgets. I am not sure if S/PDIF supports 32bit samples, but my Marantz SR4001 doesn't, producing only single clicks on playback start/stop. Because HDA controller requires 32bit alignment for all samples above 16bit, we can't handle this situation in regular way and have to set 32bit format in sound(4) for anything above 16bit. To workaround the problem, prefer to setup hardware to use 24/20bit samples when 32bit format requested. Add dev.pcm.X.play.32bit and dev.pcm.X.rec.32bit sysctls to control what format really use for 32bit samples. MFC after: 2 months Sponsored by: iXsystems, Inc. Modified: head/sys/dev/sound/pci/hda/hdaa.c Modified: head/sys/dev/sound/pci/hda/hdaa.c ============================================================================== --- head/sys/dev/sound/pci/hda/hdaa.c Mon Jan 23 16:43:13 2012 (r230487) +++ head/sys/dev/sound/pci/hda/hdaa.c Mon Jan 23 17:05:11 2012 (r230488) @@ -4897,12 +4897,12 @@ hdaa_pcmchannel_setup(struct hdaa_chan * ch->bit16 = 1; else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(pcmcap)) ch->bit16 = 0; - if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(pcmcap)) - ch->bit32 = 4; - else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(pcmcap)) + if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(pcmcap)) ch->bit32 = 3; else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(pcmcap)) ch->bit32 = 2; + else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(pcmcap)) + ch->bit32 = 4; if (!(devinfo->quirks & HDAA_QUIRK_FORCESTEREO)) { ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 1, 0); if (ch->bit32) @@ -6444,6 +6444,36 @@ hdaa_chan_formula(struct hdaa_devinfo *d } static int +hdaa_sysctl_32bit(SYSCTL_HANDLER_ARGS) +{ + struct hdaa_audio_as *as = (struct hdaa_audio_as *)oidp->oid_arg1; + struct hdaa_pcm_devinfo *pdevinfo = as->pdevinfo; + struct hdaa_devinfo *devinfo = pdevinfo->devinfo; + struct hdaa_chan *ch; + int error, val, i; + uint32_t pcmcap; + + ch = &devinfo->chans[as->chans[0]]; + val = (ch->bit32 == 4) ? 32 : ((ch->bit32 == 3) ? 24 : + ((ch->bit32 == 2) ? 20 : 0)); + error = sysctl_handle_int(oidp, &val, 0, req); + if (error != 0 || req->newptr == NULL) + return (error); + pcmcap = ch->supp_pcm_size_rate; + if (val == 32 && HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(pcmcap)) + ch->bit32 = 4; + else if (val == 24 && HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(pcmcap)) + ch->bit32 = 3; + else if (val == 20 && HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(pcmcap)) + ch->bit32 = 2; + else + return (EINVAL); + for (i = 1; i < as->num_chans; i++) + devinfo->chans[as->chans[i]].bit32 = ch->bit32; + return (0); +} + +static int hdaa_pcm_probe(device_t dev) { struct hdaa_pcm_devinfo *pdevinfo = @@ -6500,6 +6530,7 @@ hdaa_pcm_attach(device_t dev) (struct hdaa_pcm_devinfo *)device_get_ivars(dev); struct hdaa_devinfo *devinfo = pdevinfo->devinfo; struct hdaa_audio_as *as; + struct snddev_info *d; char status[SND_STATUSLEN]; int i; @@ -6576,17 +6607,28 @@ hdaa_pcm_attach(device_t dev) pdevinfo->registered++; + d = device_get_softc(dev); if (pdevinfo->playas >= 0) { as = &devinfo->as[pdevinfo->playas]; for (i = 0; i < as->num_chans; i++) pcm_addchan(dev, PCMDIR_PLAY, &hdaa_channel_class, &devinfo->chans[as->chans[i]]); + SYSCTL_ADD_PROC(&d->play_sysctl_ctx, + SYSCTL_CHILDREN(d->play_sysctl_tree), OID_AUTO, + "32bit", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, + as, sizeof(as), hdaa_sysctl_32bit, "I", + "Resolution of 32bit samples (20/24/32bit)"); } if (pdevinfo->recas >= 0) { as = &devinfo->as[pdevinfo->recas]; for (i = 0; i < as->num_chans; i++) pcm_addchan(dev, PCMDIR_REC, &hdaa_channel_class, &devinfo->chans[as->chans[i]]); + SYSCTL_ADD_PROC(&d->rec_sysctl_ctx, + SYSCTL_CHILDREN(d->rec_sysctl_tree), OID_AUTO, + "32bit", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, + as, sizeof(as), hdaa_sysctl_32bit, "I", + "Resolution of 32bit samples (20/24/32bit)"); } snprintf(status, SND_STATUSLEN, "on %s %s",