[Zrouter-src-freebsd] ZRouter.org: push to FreeBSD HEAD tree

zrouter-src-freebsd at zrouter.org zrouter-src-freebsd at zrouter.org
Wed Feb 1 10:56:11 UTC 2012


details:   http://zrouter.org/hg/FreeBSD/head//rev/5c82a43b1344
changeset: 298:5c82a43b1344
user:      ray at terran.dlink.ua
date:      Wed Feb 01 11:27:33 2012 +0200
description:
Update sound drivers

diffstat:

 head/sys/dev/sound/pci/allegro_code.h     |   218 +++
 head/sys/dev/sound/pci/allegro_reg.h      |   790 +++++++++++++
 head/sys/dev/sound/pci/csa.c              |     7 +-
 head/sys/dev/sound/pci/csareg.h           |    22 +-
 head/sys/dev/sound/pci/hda/hda_reg.h      |    50 +-
 head/sys/dev/sound/pci/hda/hdaa.c         |  1663 ++++++++++++++++++++++------
 head/sys/dev/sound/pci/hda/hdaa.h         |    58 +-
 head/sys/dev/sound/pci/hda/hdaa_patches.c |     8 +-
 head/sys/dev/sound/pci/hda/hdac.c         |   121 +-
 head/sys/dev/sound/pci/hda/hdac.h         |    98 +-
 head/sys/dev/sound/pci/hda/hdac_if.m      |     3 +-
 head/sys/dev/sound/pci/hda/hdac_private.h |     7 +-
 head/sys/dev/sound/pci/hda/hdacc.c        |   130 +-
 head/sys/dev/sound/pci/maestro3.c         |    77 +-
 head/sys/dev/sound/pcm/buffer.c           |    11 +-
 head/sys/dev/sound/pcm/buffer.h           |     3 +-
 head/sys/dev/sound/pcm/channel.c          |    73 +-
 17 files changed, 2794 insertions(+), 545 deletions(-)

diffs (4767 lines):

diff -r f370dd4be562 -r 5c82a43b1344 head/sys/dev/sound/pci/allegro_code.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/sound/pci/allegro_code.h	Wed Feb 01 11:27:33 2012 +0200
@@ -0,0 +1,218 @@
+/* $FreeBSD: head/sys/dev/sound/pci/allegro_code.h 230401 2012-01-20 22:37:10Z pfg $ */
+/*-
+ * Copyright (C) 1996-2008, 4Front Technologies
+ * Copyright (C) 1997-1999 ESS Technology, Inc
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*---------------------------------------------------------------------------
+ * This source code, its compiled object code, and its associated data sets
+ * are copyright (C) 1997-1999 ESS Technology, Inc. This source code and its
+ * associated data sets are trade secrets of ESS Technology, Inc.
+ *---------------------------------------------------------------------------
+ * DESCRIPTION: DSP binaries
+ *---------------------------------------------------------------------------
+ * AUTHOR:  Henry Tang / Hong Kim / Alger Yeung/Don Kim
+ *---------------------------------------------------------------------------
+ * For practical purposes we only include what is necessary for current
+ *  Maestro3 driver. Files used in this header include:
+ *    kernel.dat
+ *    400m_src.dat
+ *    mini_src_lpf from srcmgr.h
+ *---------------------------------------------------------------------------
+ */
+#ifndef _DEV_SOUND_PCI_ALLEGRO_CODE_H
+#define _DEV_SOUND_PCI_ALLEGRO_CODE_H
+
+/*
+ * Kernel
+ */
+
+uint16_t gaw_kernel_vect_code[] = {
+    0x7980, 0x0030, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x00FB, 0x7980,
+    0x00DD, 0x7980, 0x03B4, 0x7980, 0x0332, 0x7980, 0x0287, 0x7980, 0x03B4,
+    0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x031A, 0x7980,
+    0x03B4, 0x7980, 0x022F, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x03B4,
+    0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x0063, 0x7980, 0x006B, 0x7980,
+    0x03B4, 0x7980, 0x03B4, 0xBF80, 0x2C7C, 0x8806, 0x8804, 0xBE40, 0xBC20,
+    0xAE09, 0x1000, 0xAE0A, 0x0001, 0x6938, 0xEB08, 0x0053, 0x695A, 0xEB08,
+    0x00D6, 0x0009, 0x8B88, 0x6980, 0xE388, 0x0036, 0xBE30, 0xBC20, 0x6909,
+    0xB801, 0x9009, 0xBE41, 0xBE41, 0x6928, 0xEB88, 0x0078, 0xBE41, 0xBE40,
+    0x7980, 0x0038, 0xBE41, 0xBE41, 0x903A, 0x6938, 0xE308, 0x0056, 0x903A,
+    0xBE41, 0xBE40, 0xEF00, 0x903A, 0x6939, 0xE308, 0x005E, 0x903A, 0xEF00,
+    0x690B, 0x660C, 0xEF8C, 0x690A, 0x660C, 0x620B, 0x6609, 0xEF00, 0x6910,
+    0x660F, 0xEF04, 0xE388, 0x0075, 0x690E, 0x660F, 0x6210, 0x660D, 0xEF00,
+    0x690E, 0x660D, 0xEF00, 0xAE70, 0x0001, 0xBC20, 0xAE27, 0x0001, 0x6939,
+    0xEB08, 0x005D, 0x6926, 0xB801, 0x9026, 0x0026, 0x8B88, 0x6980, 0xE388,
+    0x00CB, 0x9028, 0x0D28, 0x4211, 0xE100, 0x007A, 0x4711, 0xE100, 0x00A0,
+    0x7A80, 0x0063, 0xB811, 0x660A, 0x6209, 0xE304, 0x007A, 0x0C0B, 0x4005,
+    0x100A, 0xBA01, 0x9012, 0x0C12, 0x4002, 0x7980, 0x00AF, 0x7A80, 0x006B,
+    0xBE02, 0x620E, 0x660D, 0xBA10, 0xE344, 0x007A, 0x0C10, 0x4005, 0x100E,
+    0xBA01, 0x9012, 0x0C12, 0x4002, 0x1003, 0xBA02, 0x9012, 0x0C12, 0x4000, 
+    0x1003, 0xE388, 0x00BA, 0x1004, 0x7980, 0x00BC, 0x1004, 0xBA01, 0x9012,
+    0x0C12, 0x4001, 0x0C05, 0x4003, 0x0C06, 0x4004, 0x1011, 0xBFB0, 0x01FF,
+    0x9012, 0x0C12, 0x4006, 0xBC20, 0xEF00, 0xAE26, 0x1028, 0x6970, 0xBFD0,
+    0x0001, 0x9070, 0xE388, 0x007A, 0xAE28, 0x0000, 0xEF00, 0xAE70, 0x0300, 
+    0x0C70, 0xB00C, 0xAE5A, 0x0000, 0xEF00, 0x7A80, 0x038A, 0x697F, 0xB801,
+    0x907F, 0x0056, 0x8B88, 0x0CA0, 0xB008, 0xAF71, 0xB000, 0x4E71, 0xE200,
+    0x00F3, 0xAE56, 0x1057, 0x0056, 0x0CA0, 0xB008, 0x8056, 0x7980, 0x03A1,
+    0x0810, 0xBFA0, 0x1059, 0xE304, 0x03A1, 0x8056, 0x7980, 0x03A1, 0x7A80,
+    0x038A, 0xBF01, 0xBE43, 0xBE59, 0x907C, 0x6937, 0xE388, 0x010D, 0xBA01,
+    0xE308, 0x010C, 0xAE71, 0x0004, 0x0C71, 0x5000, 0x6936, 0x9037, 0xBF0A,
+    0x109E, 0x8B8A, 0xAF80, 0x8014, 0x4C80, 0xBF0A, 0x0560, 0xF500, 0xBF0A,
+    0x0520, 0xB900, 0xBB17, 0x90A0, 0x6917, 0xE388, 0x0148, 0x0D17, 0xE100,
+    0x0127, 0xBF0C, 0x0578, 0xBF0D, 0x057C, 0x7980, 0x012B, 0xBF0C, 0x0538,
+    0xBF0D, 0x053C, 0x6900, 0xE308, 0x0135, 0x8B8C, 0xBE59, 0xBB07, 0x90A0,
+    0xBC20, 0x7980, 0x0157, 0x030C, 0x8B8B, 0xB903, 0x8809, 0xBEC6, 0x013E,
+    0x69AC, 0x90AB, 0x69AD, 0x90AB, 0x0813, 0x660A, 0xE344, 0x0144, 0x0309,
+    0x830C, 0xBC20, 0x7980, 0x0157, 0x6955, 0xE388, 0x0157, 0x7C38, 0xBF0B,
+    0x0578, 0xF500, 0xBF0B, 0x0538, 0xB907, 0x8809, 0xBEC6, 0x0156, 0x10AB,
+    0x90AA, 0x6974, 0xE388, 0x0163, 0xAE72, 0x0540, 0xF500, 0xAE72, 0x0500,
+    0xAE61, 0x103B, 0x7A80, 0x02F6, 0x6978, 0xE388, 0x0182, 0x8B8C, 0xBF0C,
+    0x0560, 0xE500, 0x7C40, 0x0814, 0xBA20, 0x8812, 0x733D, 0x7A80, 0x0380,
+    0x733E, 0x7A80, 0x0380, 0x8B8C, 0xBF0C, 0x056C, 0xE500, 0x7C40, 0x0814,
+    0xBA2C, 0x8812, 0x733F, 0x7A80, 0x0380, 0x7340, 0x7A80, 0x0380, 0x6975,
+    0xE388, 0x018E, 0xAE72, 0x0548, 0xF500, 0xAE72, 0x0508, 0xAE61, 0x1041,
+    0x7A80, 0x02F6, 0x6979, 0xE388, 0x01AD, 0x8B8C, 0xBF0C, 0x0560, 0xE500,
+    0x7C40, 0x0814, 0xBA18, 0x8812, 0x7343, 0x7A80, 0x0380, 0x7344, 0x7A80,
+    0x0380, 0x8B8C, 0xBF0C, 0x056C, 0xE500, 0x7C40, 0x0814, 0xBA24, 0x8812,
+    0x7345, 0x7A80, 0x0380, 0x7346, 0x7A80, 0x0380, 0x6976, 0xE388, 0x01B9,
+    0xAE72, 0x0558, 0xF500, 0xAE72, 0x0518, 0xAE61, 0x1047, 0x7A80, 0x02F6,
+    0x697A, 0xE388, 0x01D8, 0x8B8C, 0xBF0C, 0x0560, 0xE500, 0x7C40, 0x0814,
+    0xBA08, 0x8812, 0x7349, 0x7A80, 0x0380, 0x734A, 0x7A80, 0x0380, 0x8B8C,
+    0xBF0C, 0x056C, 0xE500, 0x7C40, 0x0814, 0xBA14, 0x8812, 0x734B, 0x7A80,
+    0x0380, 0x734C, 0x7A80, 0x0380, 0xBC21, 0xAE1C, 0x1090, 0x8B8A, 0xBF0A,
+    0x0560, 0xE500, 0x7C40, 0x0812, 0xB804, 0x8813, 0x8B8D, 0xBF0D, 0x056C,
+    0xE500, 0x7C40, 0x0815, 0xB804, 0x8811, 0x7A80, 0x034A, 0x8B8A, 0xBF0A,
+    0x0560, 0xE500, 0x7C40, 0x731F, 0xB903, 0x8809, 0xBEC6, 0x01F9, 0x548A, 
+    0xBE03, 0x98A0, 0x7320, 0xB903, 0x8809, 0xBEC6, 0x0201, 0x548A, 0xBE03,
+    0x98A0, 0x1F20, 0x2F1F, 0x9826, 0xBC20, 0x6935, 0xE388, 0x03A1, 0x6933,
+    0xB801, 0x9033, 0xBFA0, 0x02EE, 0xE308, 0x03A1, 0x9033, 0xBF00, 0x6951,
+    0xE388, 0x021F, 0x7334, 0xBE80, 0x5760, 0xBE03, 0x9F7E, 0xBE59, 0x9034,
+    0x697E, 0x0D51, 0x9013, 0xBC20, 0x695C, 0xE388, 0x03A1, 0x735E, 0xBE80,
+    0x5760, 0xBE03, 0x9F7E, 0xBE59, 0x905E, 0x697E, 0x0D5C, 0x9013, 0x7980,
+    0x03A1, 0x7A80, 0x038A, 0xBF01, 0xBE43, 0x6977, 0xE388, 0x024E, 0xAE61,
+    0x104D, 0x0061, 0x8B88, 0x6980, 0xE388, 0x024E, 0x9071, 0x0D71, 0x000B,
+    0xAFA0, 0x8010, 0xAFA0, 0x8010, 0x0810, 0x660A, 0xE308, 0x0249, 0x0009,
+    0x0810, 0x660C, 0xE388, 0x024E, 0x800B, 0xBC20, 0x697B, 0xE388, 0x03A1,
+    0xBF0A, 0x109E, 0x8B8A, 0xAF80, 0x8014, 0x4C80, 0xE100, 0x0266, 0x697C,
+    0xBF90, 0x0560, 0x9072, 0x0372, 0x697C, 0xBF90, 0x0564, 0x9073, 0x0473,
+    0x7980, 0x0270, 0x697C, 0xBF90, 0x0520, 0x9072, 0x0372, 0x697C, 0xBF90,
+    0x0524, 0x9073, 0x0473, 0x697C, 0xB801, 0x907C, 0xBF0A, 0x10FD, 0x8B8A,
+    0xAF80, 0x8010, 0x734F, 0x548A, 0xBE03, 0x9880, 0xBC21, 0x7326, 0x548B,
+    0xBE03, 0x618B, 0x988C, 0xBE03, 0x6180, 0x9880, 0x7980, 0x03A1, 0x7A80,
+    0x038A, 0x0D28, 0x4711, 0xE100, 0x02BE, 0xAF12, 0x4006, 0x6912, 0xBFB0,
+    0x0C00, 0xE388, 0x02B6, 0xBFA0, 0x0800, 0xE388, 0x02B2, 0x6912, 0xBFB0,
+    0x0C00, 0xBFA0, 0x0400, 0xE388, 0x02A3, 0x6909, 0x900B, 0x7980, 0x02A5,
+    0xAF0B, 0x4005, 0x6901, 0x9005, 0x6902, 0x9006, 0x4311, 0xE100, 0x02ED,
+    0x6911, 0xBFC0, 0x2000, 0x9011, 0x7980, 0x02ED, 0x6909, 0x900B, 0x7980,
+    0x02B8, 0xAF0B, 0x4005, 0xAF05, 0x4003, 0xAF06, 0x4004, 0x7980, 0x02ED,
+    0xAF12, 0x4006, 0x6912, 0xBFB0, 0x0C00, 0xE388, 0x02E7, 0xBFA0, 0x0800,
+    0xE388, 0x02E3, 0x6912, 0xBFB0, 0x0C00, 0xBFA0, 0x0400, 0xE388, 0x02D4,
+    0x690D, 0x9010, 0x7980, 0x02D6, 0xAF10, 0x4005, 0x6901, 0x9005, 0x6902,
+    0x9006, 0x4311, 0xE100, 0x02ED, 0x6911, 0xBFC0, 0x2000, 0x9011, 0x7980,
+    0x02ED, 0x690D, 0x9010, 0x7980, 0x02E9, 0xAF10, 0x4005, 0xAF05, 0x4003,
+    0xAF06, 0x4004, 0xBC20, 0x6970, 0x9071, 0x7A80, 0x0078, 0x6971, 0x9070,
+    0x7980, 0x03A1, 0xBC20, 0x0361, 0x8B8B, 0x6980, 0xEF88, 0x0272, 0x0372,
+    0x7804, 0x9071, 0x0D71, 0x8B8A, 0x000B, 0xB903, 0x8809, 0xBEC6, 0x0309,
+    0x69A8, 0x90AB, 0x69A8, 0x90AA, 0x0810, 0x660A, 0xE344, 0x030F, 0x0009,
+    0x0810, 0x660C, 0xE388, 0x0314, 0x800B, 0xBC20, 0x6961, 0xB801, 0x9061,
+    0x7980, 0x02F7, 0x7A80, 0x038A, 0x5D35, 0x0001, 0x6934, 0xB801, 0x9034,
+    0xBF0A, 0x109E, 0x8B8A, 0xAF80, 0x8014, 0x4880, 0xAE72, 0x0550, 0xF500,
+    0xAE72, 0x0510, 0xAE61, 0x1051, 0x7A80, 0x02F6, 0x7980, 0x03A1, 0x7A80,
+    0x038A, 0x5D35, 0x0002, 0x695E, 0xB801, 0x905E, 0xBF0A, 0x109E, 0x8B8A,
+    0xAF80, 0x8014, 0x4780, 0xAE72, 0x0558, 0xF500, 0xAE72, 0x0518, 0xAE61,
+    0x105C, 0x7A80, 0x02F6, 0x7980, 0x03A1, 0x001C, 0x8B88, 0x6980, 0xEF88,
+    0x901D, 0x0D1D, 0x100F, 0x6610, 0xE38C, 0x0358, 0x690E, 0x6610, 0x620F,
+    0x660D, 0xBA0F, 0xE301, 0x037A, 0x0410, 0x8B8A, 0xB903, 0x8809, 0xBEC6,
+    0x036C, 0x6A8C, 0x61AA, 0x98AB, 0x6A8C, 0x61AB, 0x98AD, 0x6A8C, 0x61AD,
+    0x98A9, 0x6A8C, 0x61A9, 0x98AA, 0x7C04, 0x8B8B, 0x7C04, 0x8B8D, 0x7C04,
+    0x8B89, 0x7C04, 0x0814, 0x660E, 0xE308, 0x0379, 0x040D, 0x8410, 0xBC21,
+    0x691C, 0xB801, 0x901C, 0x7980, 0x034A, 0xB903, 0x8809, 0x8B8A, 0xBEC6,
+    0x0388, 0x54AC, 0xBE03, 0x618C, 0x98AA, 0xEF00, 0xBC20, 0xBE46, 0x0809,
+    0x906B, 0x080A, 0x906C, 0x080B, 0x906D, 0x081A, 0x9062, 0x081B, 0x9063,
+    0x081E, 0x9064, 0xBE59, 0x881E, 0x8065, 0x8166, 0x8267, 0x8368, 0x8469,
+    0x856A, 0xEF00, 0xBC20, 0x696B, 0x8809, 0x696C, 0x880A, 0x696D, 0x880B,
+    0x6962, 0x881A, 0x6963, 0x881B, 0x6964, 0x881E, 0x0065, 0x0166, 0x0267,
+    0x0368, 0x0469, 0x056A, 0xBE3A,
+};
+
+/*
+ * MINI Sample Rate Conversion
+ */
+
+uint16_t gaw_minisrc_code_0400[] = {
+    0xBF80, 0x101E, 0x906E, 0x006E, 0x8B88, 0x6980, 0xEF88, 0x906F, 0x0D6F,
+    0x6900, 0xEB08, 0x0412, 0xBC20, 0x696E, 0xB801, 0x906E, 0x7980, 0x0403,
+    0xB90E, 0x8807, 0xBE43, 0xBF01, 0xBE47, 0xBE41, 0x7A80, 0x002A, 0xBE40,
+    0x3029, 0xEFCC, 0xBE41, 0x7A80, 0x0028, 0xBE40, 0x3028, 0xEFCC, 0x6907,
+    0xE308, 0x042A, 0x6909, 0x902C, 0x7980, 0x042C, 0x690D, 0x902C, 0x1009,
+    0x881A, 0x100A, 0xBA01, 0x881B, 0x100D, 0x881C, 0x100E, 0xBA01, 0x881D,
+    0xBF80, 0x00ED, 0x881E, 0x050C, 0x0124, 0xB904, 0x9027, 0x6918, 0xE308,
+    0x04B3, 0x902D, 0x6913, 0xBFA0, 0x7598, 0xF704, 0xAE2D, 0x00FF, 0x8B8D,
+    0x6919, 0xE308, 0x0463, 0x691A, 0xE308, 0x0456, 0xB907, 0x8809, 0xBEC6,
+    0x0453, 0x10A9, 0x90AD, 0x7980, 0x047C, 0xB903, 0x8809, 0xBEC6, 0x0460,
+    0x1889, 0x6C22, 0x90AD, 0x10A9, 0x6E23, 0x6C22, 0x90AD, 0x7980, 0x047C,
+    0x101A, 0xE308, 0x046F, 0xB903, 0x8809, 0xBEC6, 0x046C, 0x10A9, 0x90A0,
+    0x90AD, 0x7980, 0x047C, 0xB901, 0x8809, 0xBEC6, 0x047B, 0x1889, 0x6C22,
+    0x90A0, 0x90AD, 0x10A9, 0x6E23, 0x6C22, 0x90A0, 0x90AD, 0x692D, 0xE308,
+    0x049C, 0x0124, 0xB703, 0xB902, 0x8818, 0x8B89, 0x022C, 0x108A, 0x7C04,
+    0x90A0, 0x692B, 0x881F, 0x7E80, 0x055B, 0x692A, 0x8809, 0x8B89, 0x99A0,
+    0x108A, 0x90A0, 0x692B, 0x881F, 0x7E80, 0x055B, 0x692A, 0x8809, 0x8B89,
+    0x99AF, 0x7B99, 0x0484, 0x0124, 0x060F, 0x101B, 0x2013, 0x901B, 0xBFA0,
+    0x7FFF, 0xE344, 0x04AC, 0x901B, 0x8B89, 0x7A80, 0x051A, 0x6927, 0xBA01,
+    0x9027, 0x7A80, 0x0523, 0x6927, 0xE308, 0x049E, 0x7980, 0x050F, 0x0624,
+    0x1026, 0x2013, 0x9026, 0xBFA0, 0x7FFF, 0xE304, 0x04C0, 0x8B8D, 0x7A80,
+    0x051A, 0x7980, 0x04B4, 0x9026, 0x1013, 0x3026, 0x901B, 0x8B8D, 0x7A80,
+    0x051A, 0x7A80, 0x0523, 0x1027, 0xBA01, 0x9027, 0xE308, 0x04B4, 0x0124,
+    0x060F, 0x8B89, 0x691A, 0xE308, 0x04EA, 0x6919, 0xE388, 0x04E0, 0xB903,
+    0x8809, 0xBEC6, 0x04DD, 0x1FA0, 0x2FAE, 0x98A9, 0x7980, 0x050F, 0xB901,
+    0x8818, 0xB907, 0x8809, 0xBEC6, 0x04E7, 0x10EE, 0x90A9, 0x7980, 0x050F,
+    0x6919, 0xE308, 0x04FE, 0xB903, 0x8809, 0xBE46, 0xBEC6, 0x04FA, 0x17A0,
+    0xBE1E, 0x1FAE, 0xBFBF, 0xFF00, 0xBE13, 0xBFDF, 0x8080, 0x99A9, 0xBE47,
+    0x7980, 0x050F, 0xB901, 0x8809, 0xBEC6, 0x050E, 0x16A0, 0x26A0, 0xBFB7,
+    0xFF00, 0xBE1E, 0x1EA0, 0x2EAE, 0xBFBF, 0xFF00, 0xBE13, 0xBFDF, 0x8080,
+    0x99A9, 0x850C, 0x860F, 0x6907, 0xE388, 0x0516, 0x0D07, 0x8510, 0xBE59,
+    0x881E, 0xBE4A, 0xEF00, 0x101E, 0x901C, 0x101F, 0x901D, 0x10A0, 0x901E,
+    0x10A0, 0x901F, 0xEF00, 0x101E, 0x301C, 0x9020, 0x731B, 0x5420, 0xBE03,
+    0x9825, 0x1025, 0x201C, 0x9025, 0x7325, 0x5414, 0xBE03, 0x8B8E, 0x9880,
+    0x692F, 0xE388, 0x0539, 0xBE59, 0xBB07, 0x6180, 0x9880, 0x8BA0, 0x101F,
+    0x301D, 0x9021, 0x731B, 0x5421, 0xBE03, 0x982E, 0x102E, 0x201D, 0x902E,
+    0x732E, 0x5415, 0xBE03, 0x9880, 0x692F, 0xE388, 0x054F, 0xBE59, 0xBB07,
+    0x6180, 0x9880, 0x8BA0, 0x6918, 0xEF08, 0x7325, 0x5416, 0xBE03, 0x98A0,
+    0x732E, 0x5417, 0xBE03, 0x98A0, 0xEF00, 0x8BA0, 0xBEC6, 0x056B, 0xBE59,
+    0xBB04, 0xAA90, 0xBE04, 0xBE1E, 0x99E0, 0x8BE0, 0x69A0, 0x90D0, 0x69A0, 
+    0x90D0, 0x081F, 0xB805, 0x881F, 0x8B90, 0x69A0, 0x90D0, 0x69A0, 0x9090,
+    0x8BD0, 0x8BD8, 0xBE1F, 0xEF00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+uint16_t minisrc_lpf[10] = {
+	0X0743, 0X1104, 0X0A4C, 0XF88D, 0X242C,
+	0X1023, 0X1AA9, 0X0B60, 0XEFDD, 0X186F
+};
+
+#endif	/* !_DEV_SOUND_PCI_ALLEGRO_CODE_H */
diff -r f370dd4be562 -r 5c82a43b1344 head/sys/dev/sound/pci/allegro_reg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/sound/pci/allegro_reg.h	Wed Feb 01 11:27:33 2012 +0200
@@ -0,0 +1,790 @@
+/* $FreeBSD: head/sys/dev/sound/pci/allegro_reg.h 230401 2012-01-20 22:37:10Z pfg $ */
+/*-
+ * Copyright (c) 1996-2008, 4Front Technologies
+ * Copyright (C) 1992-2000  Don Kim (don.kim at esstech.com)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*---------------------------------------------------------------------------
+ *              Copyright (C) 1997-1999, ESS Technology, Inc.
+ * This source code, its compiled object code, and its associated data sets
+ * are copyright (C) 1997-1999 ESS Technology, Inc.
+ *---------------------------------------------------------------------------
+ * This header contains data structures and registers taken from the
+ * 4Front OSS Allegro BSD licensed driver (in the Attic/ directory).
+ *  Files used for this header include:
+ *    hardware.h
+ *    kernel.h and hckernel.h
+ *    srcmgr.h
+ *---------------------------------------------------------------------------
+ */
+
+#ifndef _DEV_SOUND_PCI_ALLEGRO_REG_H
+#define _DEV_SOUND_PCI_ALLEGRO_REG_H
+
+/* Allegro PCI configuration registers */
+#define PCI_LEGACY_AUDIO_CTRL   0x40
+#define SOUND_BLASTER_ENABLE    0x00000001
+#define FM_SYNTHESIS_ENABLE     0x00000002
+#define GAME_PORT_ENABLE        0x00000004
+#define MPU401_IO_ENABLE        0x00000008
+#define MPU401_IRQ_ENABLE       0x00000010
+#define ALIAS_10BIT_IO          0x00000020
+#define SB_DMA_MASK             0x000000C0
+#define SB_DMA_0                0x00000040
+#define SB_DMA_1                0x00000040
+#define SB_DMA_R                0x00000080
+#define SB_DMA_3                0x000000C0
+#define SB_IRQ_MASK             0x00000700
+#define SB_IRQ_5                0x00000000
+#define SB_IRQ_7                0x00000100
+#define SB_IRQ_9                0x00000200
+#define SB_IRQ_10               0x00000300
+#define MIDI_IRQ_MASK           0x00003800
+#define SERIAL_IRQ_ENABLE       0x00004000
+#define DISABLE_LEGACY          0x00008000
+
+#define PCI_ALLEGRO_CONFIG      0x50
+#define SB_ADDR_240             0x00000004
+#define MPU_ADDR_MASK           0x00000018
+#define MPU_ADDR_330            0x00000000
+#define MPU_ADDR_300            0x00000008
+#define MPU_ADDR_320            0x00000010
+#define MPU_ADDR_340            0x00000018
+#define USE_PCI_TIMING          0x00000040
+#define POSTED_WRITE_ENABLE     0x00000080
+#define DMA_POLICY_MASK         0x00000700
+#define DMA_DDMA                0x00000000
+#define DMA_TDMA                0x00000100
+#define DMA_PCPCI               0x00000200
+#define DMA_WBDMA16             0x00000400
+#define DMA_WBDMA4              0x00000500
+#define DMA_WBDMA2              0x00000600
+#define DMA_WBDMA1              0x00000700
+#define DMA_SAFE_GUARD          0x00000800
+#define HI_PERF_GP_ENABLE       0x00001000
+#define PIC_SNOOP_MODE_0        0x00002000
+#define PIC_SNOOP_MODE_1        0x00004000
+#define SOUNDBLASTER_IRQ_MASK   0x00008000
+#define RING_IN_ENABLE          0x00010000
+#define SPDIF_TEST_MODE         0x00020000
+#define CLK_MULT_MODE_SELECT_2  0x00040000
+#define EEPROM_WRITE_ENABLE     0x00080000
+#define CODEC_DIR_IN            0x00100000
+#define HV_BUTTON_FROM_GD       0x00200000
+#define REDUCED_DEBOUNCE        0x00400000
+#define HV_CTRL_ENABLE          0x00800000
+#define SPDIF_ENABLE            0x01000000
+#define CLK_DIV_SELECT          0x06000000
+#define CLK_DIV_BY_48           0x00000000
+#define CLK_DIV_BY_49           0x02000000
+#define CLK_DIV_BY_50           0x04000000
+#define CLK_DIV_RESERVED        0x06000000
+#define PM_CTRL_ENABLE          0x08000000
+#define CLK_MULT_MODE_SELECT    0x30000000
+#define CLK_MULT_MODE_SHIFT     28
+#define CLK_MULT_MODE_0         0x00000000
+#define CLK_MULT_MODE_1         0x10000000
+#define CLK_MULT_MODE_2         0x20000000
+#define CLK_MULT_MODE_3         0x30000000
+#define INT_CLK_SELECT          0x40000000
+#define INT_CLK_MULT_RESET      0x80000000
+
+/* M3 */
+#define INT_CLK_SRC_NOT_PCI     0x00100000
+#define INT_CLK_MULT_ENABLE     0x80000000
+
+#define PCI_ACPI_CONTROL        0x54
+#define PCI_ACPI_D0             0x00000000
+#define PCI_ACPI_D1             0xB4F70000
+#define PCI_ACPI_D2             0xB4F7B4F7
+
+#define PCI_USER_CONFIG         0x58
+#define EXT_PCI_MASTER_ENABLE   0x00000001
+#define SPDIF_OUT_SELECT        0x00000002
+#define TEST_PIN_DIR_CTRL       0x00000004
+#define AC97_CODEC_TEST         0x00000020
+#define TRI_STATE_BUFFER        0x00000080
+#define IN_CLK_12MHZ_SELECT     0x00000100
+#define MULTI_FUNC_DISABLE      0x00000200
+#define EXT_MASTER_PAIR_SEL     0x00000400
+#define PCI_MASTER_SUPPORT      0x00000800
+#define STOP_CLOCK_ENABLE       0x00001000
+#define EAPD_DRIVE_ENABLE       0x00002000
+#define REQ_TRI_STATE_ENABLE    0x00004000
+#define REQ_LOW_ENABLE          0x00008000
+#define MIDI_1_ENABLE           0x00010000
+#define MIDI_2_ENABLE           0x00020000
+#define SB_AUDIO_SYNC           0x00040000
+#define HV_CTRL_TEST            0x00100000
+#define SOUNDBLASTER_TEST       0x00400000
+
+#define PCI_USER_CONFIG_C       0x5C
+
+#define PCI_DDMA_CTRL           0x60
+#define DDMA_ENABLE             0x00000001
+
+
+/* Allegro registers */
+#define HOST_INT_CTRL           0x18
+#define SB_INT_ENABLE           0x0001
+#define MPU401_INT_ENABLE       0x0002
+#define ASSP_INT_ENABLE         0x0010
+#define RING_INT_ENABLE         0x0020
+#define HV_INT_ENABLE           0x0040
+#define CLKRUN_GEN_ENABLE       0x0100
+#define HV_CTRL_TO_PME          0x0400
+#define SOFTWARE_RESET_ENABLE   0x8000
+
+#define HOST_INT_STATUS         0x1A
+#define SB_INT_PENDING          0x01
+#define MPU401_INT_PENDING      0x02
+#define ASSP_INT_PENDING        0x10
+#define RING_INT_PENDING        0x20
+#define HV_INT_PENDING          0x40
+
+#define HARDWARE_VOL_CTRL       0x1B
+#define SHADOW_MIX_REG_VOICE    0x1C
+#define HW_VOL_COUNTER_VOICE    0x1D
+#define SHADOW_MIX_REG_MASTER   0x1E
+#define HW_VOL_COUNTER_MASTER   0x1F
+
+#define CODEC_COMMAND           0x30
+#define CODEC_READ_B            0x80
+
+#define CODEC_STATUS            0x30
+#define CODEC_BUSY_B            0x01
+
+#define CODEC_DATA              0x32
+
+/* AC97 registers */
+#ifndef M3_MODEL
+#define AC97_RESET              0x00
+#endif
+
+#define AC97_VOL_MUTE_B         0x8000
+#define AC97_VOL_M              0x1F
+#define AC97_LEFT_VOL_S         8
+
+#define AC97_MASTER_VOL         0x02
+#define AC97_LINE_LEVEL_VOL     0x04
+#define AC97_MASTER_MONO_VOL    0x06
+#define AC97_PC_BEEP_VOL        0x0A
+#define AC97_PC_BEEP_VOL_M      0x0F
+#define AC97_SROUND_MASTER_VOL  0x38
+#define AC97_PC_BEEP_VOL_S      1
+
+#ifndef M3_MODEL
+#define AC97_PHONE_VOL          0x0C
+#define AC97_MIC_VOL            0x0E
+#endif
+#define AC97_MIC_20DB_ENABLE    0x40
+
+#ifndef M3_MODEL
+#define AC97_LINEIN_VOL         0x10
+#define AC97_CD_VOL             0x12
+#define AC97_VIDEO_VOL          0x14
+#define AC97_AUX_VOL            0x16
+#endif
+#define AC97_PCM_OUT_VOL        0x18
+#ifndef M3_MODEL
+#define AC97_RECORD_SELECT      0x1A
+#endif
+#define AC97_RECORD_MIC         0x00
+#define AC97_RECORD_CD          0x01
+#define AC97_RECORD_VIDEO       0x02
+#define AC97_RECORD_AUX         0x03
+#define AC97_RECORD_MONO_MUX    0x02
+#define AC97_RECORD_DIGITAL     0x03
+#define AC97_RECORD_LINE        0x04
+#define AC97_RECORD_STEREO      0x05
+#define AC97_RECORD_MONO        0x06
+#define AC97_RECORD_PHONE       0x07
+
+#ifndef M3_MODEL
+#define AC97_RECORD_GAIN        0x1C
+#endif
+#define AC97_RECORD_VOL_M       0x0F
+
+#ifndef M3_MODEL
+#define AC97_GENERAL_PURPOSE    0x20
+#endif
+#define AC97_POWER_DOWN_CTRL    0x26
+#define AC97_ADC_READY          0x0001
+#define AC97_DAC_READY          0x0002
+#define AC97_ANALOG_READY       0x0004
+#define AC97_VREF_ON            0x0008
+#define AC97_PR0                0x0100
+#define AC97_PR1                0x0200
+#define AC97_PR2                0x0400
+#define AC97_PR3                0x0800
+#define AC97_PR4                0x1000
+
+#define AC97_RESERVED1          0x28
+
+#define AC97_VENDOR_TEST        0x5A
+
+#define AC97_CLOCK_DELAY        0x5C
+#define AC97_LINEOUT_MUX_SEL    0x0001
+#define AC97_MONO_MUX_SEL       0x0002
+#define AC97_CLOCK_DELAY_SEL    0x1F
+#define AC97_DAC_CDS_SHIFT      6
+#define AC97_ADC_CDS_SHIFT      11
+
+#define AC97_MULTI_CHANNEL_SEL  0x74
+
+#ifndef M3_MODEL
+#define AC97_VENDOR_ID1         0x7C
+#define AC97_VENDOR_ID2         0x7E
+#endif
+
+#define RING_BUS_CTRL_A         0x36
+#define RAC_PME_ENABLE          0x0100
+#define RAC_SDFS_ENABLE         0x0200
+#define LAC_PME_ENABLE          0x0400
+#define LAC_SDFS_ENABLE         0x0800
+#define SERIAL_AC_LINK_ENABLE   0x1000
+#define IO_SRAM_ENABLE          0x2000
+#define IIS_INPUT_ENABLE        0x8000
+
+#define RING_BUS_CTRL_B         0x38
+#define SECOND_CODEC_ID_MASK    0x0003
+#define SPDIF_FUNC_ENABLE       0x0010
+#define SECOND_AC_ENABLE        0x0020
+#define SB_MODULE_INTF_ENABLE   0x0040
+#define SSPE_ENABLE             0x0040
+#define M3I_DOCK_ENABLE         0x0080
+
+#define SDO_OUT_DEST_CTRL       0x3A
+#define COMMAND_ADDR_OUT        0x0003
+#define PCM_LR_OUT_LOCAL        0x0000
+#define PCM_LR_OUT_REMOTE       0x0004
+#define PCM_LR_OUT_MUTE         0x0008
+#define PCM_LR_OUT_BOTH         0x000C
+#define LINE1_DAC_OUT_LOCAL     0x0000
+#define LINE1_DAC_OUT_REMOTE    0x0010
+#define LINE1_DAC_OUT_MUTE      0x0020
+#define LINE1_DAC_OUT_BOTH      0x0030
+#define PCM_CLS_OUT_LOCAL       0x0000
+#define PCM_CLS_OUT_REMOTE      0x0040
+#define PCM_CLS_OUT_MUTE        0x0080
+#define PCM_CLS_OUT_BOTH        0x00C0
+#define PCM_RLF_OUT_LOCAL       0x0000
+#define PCM_RLF_OUT_REMOTE      0x0100
+#define PCM_RLF_OUT_MUTE        0x0200
+#define PCM_RLF_OUT_BOTH        0x0300
+#define LINE2_DAC_OUT_LOCAL     0x0000
+#define LINE2_DAC_OUT_REMOTE    0x0400
+#define LINE2_DAC_OUT_MUTE      0x0800
+#define LINE2_DAC_OUT_BOTH      0x0C00
+#define HANDSET_OUT_LOCAL       0x0000
+#define HANDSET_OUT_REMOTE      0x1000
+#define HANDSET_OUT_MUTE        0x2000
+#define HANDSET_OUT_BOTH        0x3000
+#define IO_CTRL_OUT_LOCAL       0x0000
+#define IO_CTRL_OUT_REMOTE      0x4000
+#define IO_CTRL_OUT_MUTE        0x8000
+#define IO_CTRL_OUT_BOTH        0xC000
+
+#define SDO_IN_DEST_CTRL        0x3C
+#define STATUS_ADDR_IN          0x0003
+#define PCM_LR_IN_LOCAL         0x0000
+#define PCM_LR_IN_REMOTE        0x0004
+#define PCM_LR_RESERVED         0x0008
+#define PCM_LR_IN_BOTH          0x000C
+#define LINE1_ADC_IN_LOCAL      0x0000
+#define LINE1_ADC_IN_REMOTE     0x0010
+#define LINE1_ADC_IN_MUTE       0x0020
+#define MIC_ADC_IN_LOCAL        0x0000
+#define MIC_ADC_IN_REMOTE       0x0040
+#define MIC_ADC_IN_MUTE         0x0080
+#define LINE2_DAC_IN_LOCAL      0x0000
+#define LINE2_DAC_IN_REMOTE     0x0400
+#define LINE2_DAC_IN_MUTE       0x0800
+#define HANDSET_IN_LOCAL        0x0000
+#define HANDSET_IN_REMOTE       0x1000
+#define HANDSET_IN_MUTE         0x2000
+#define IO_STATUS_IN_LOCAL      0x0000
+#define IO_STATUS_IN_REMOTE     0x4000
+
+#define SPDIF_IN_CTRL           0x3E
+#define SPDIF_IN_ENABLE         0x0001
+
+#define GPIO_DATA               0x60
+#define GPIO_DATA_MASK          0x0FFF
+#define GPIO_HV_STATUS          0x3000
+#define GPIO_PME_STATUS         0x4000
+
+#define GPIO_MASK               0x64
+#define GPIO_DIRECTION          0x68
+#define GPO_PRIMARY_AC97        0x0001
+#define GPI_LINEOUT_SENSE       0x0004
+#define GPO_SECONDARY_AC97      0x0008
+#define GPI_VOL_DOWN            0x0010
+#define GPI_VOL_UP              0x0020
+#define GPI_IIS_CLK             0x0040
+#define GPI_IIS_LRCLK           0x0080
+#define GPI_IIS_DATA            0x0100
+#define GPI_DOCKING_STATUS      0x0100
+#define GPI_HEADPHONE_SENSE     0x0200
+#define GPO_EXT_AMP_SHUTDOWN    0x1000
+
+/* M3 */
+#define GPO_M3_EXT_AMP_SHUTDN   0x0002
+
+#define ASSP_INDEX_PORT         0x80
+#define ASSP_MEMORY_PORT        0x82
+#define ASSP_DATA_PORT          0x84
+
+#define MPU401_DATA_PORT        0x98
+#define MPU401_STATUS_PORT      0x99
+
+#define CLK_MULT_DATA_PORT      0x9C
+
+#define ASSP_CONTROL_A          0xA2
+#define ASSP_0_WS_ENABLE        0x01
+#define ASSP_CTRL_A_RESERVED1   0x02
+#define ASSP_CTRL_A_RESERVED2   0x04
+#define ASSP_CLK_49MHZ_SELECT   0x08
+#define FAST_PLU_ENABLE         0x10
+#define ASSP_CTRL_A_RESERVED3   0x20
+#define DSP_CLK_36MHZ_SELECT    0x40
+
+#define ASSP_CONTROL_B          0xA4
+#define RESET_ASSP              0x00
+#define RUN_ASSP                0x01
+#define ENABLE_ASSP_CLOCK       0x00
+#define STOP_ASSP_CLOCK         0x10
+#define RESET_TOGGLE            0x40
+
+#define ASSP_CONTROL_C          0xA6
+#define ASSP_HOST_INT_ENABLE    0x01
+#define FM_ADDR_REMAP_DISABLE   0x02
+#define HOST_WRITE_PORT_ENABLE  0x08
+
+#define ASSP_HOST_INT_STATUS    0xAC
+#define DSP2HOST_REQ_PIORECORD  0x01
+#define DSP2HOST_REQ_I2SRATE    0x02
+#define DSP2HOST_REQ_TIMER      0x04
+
+/*
+ * DSP memory map
+ */
+
+#define REV_A_CODE_MEMORY_BEGIN         0x0000
+#define REV_A_CODE_MEMORY_END           0x0FFF
+#define REV_A_CODE_MEMORY_UNIT_LENGTH   0x0040
+#define REV_A_CODE_MEMORY_LENGTH        (REV_A_CODE_MEMORY_END - REV_A_CODE_MEMORY_BEGIN + 1)
+
+#define REV_B_CODE_MEMORY_BEGIN         0x0000
+#define REV_B_CODE_MEMORY_END           0x0BFF
+#define REV_B_CODE_MEMORY_UNIT_LENGTH   0x0040
+#define REV_B_CODE_MEMORY_LENGTH        (REV_B_CODE_MEMORY_END - REV_B_CODE_MEMORY_BEGIN + 1)
+
+#if (REV_A_CODE_MEMORY_LENGTH % REV_A_CODE_MEMORY_UNIT_LENGTH)
+#error Assumption about code memory unit length failed.
+#endif
+#if (REV_B_CODE_MEMORY_LENGTH % REV_B_CODE_MEMORY_UNIT_LENGTH)
+#error Assumption about code memory unit length failed.
+#endif
+
+#define REV_A_DATA_MEMORY_BEGIN         0x1000
+#define REV_A_DATA_MEMORY_END           0x2FFF
+#define REV_A_DATA_MEMORY_UNIT_LENGTH   0x0080
+#define REV_A_DATA_MEMORY_LENGTH        (REV_A_DATA_MEMORY_END - REV_A_DATA_MEMORY_BEGIN + 1)
+
+#define REV_B_DATA_MEMORY_BEGIN         0x1000
+/*#define REV_B_DATA_MEMORY_END           0x23FF */
+#define REV_B_DATA_MEMORY_END           0x2BFF
+#define REV_B_DATA_MEMORY_UNIT_LENGTH   0x0080
+#define REV_B_DATA_MEMORY_LENGTH        (REV_B_DATA_MEMORY_END - REV_B_DATA_MEMORY_BEGIN + 1)
+
+#if (REV_A_DATA_MEMORY_LENGTH % REV_A_DATA_MEMORY_UNIT_LENGTH)
+#error Assumption about data memory unit length failed.
+#endif
+#if (REV_B_DATA_MEMORY_LENGTH % REV_B_DATA_MEMORY_UNIT_LENGTH)
+#error Assumption about data memory unit length failed.
+#endif
+
+#define CODE_MEMORY_MAP_LENGTH          (64 + 1)
+#define DATA_MEMORY_MAP_LENGTH          (64 + 1)
+
+#if (CODE_MEMORY_MAP_LENGTH < ((REV_A_CODE_MEMORY_LENGTH / REV_A_CODE_MEMORY_UNIT_LENGTH) + 1))
+#error Code memory map length too short.
+#endif
+#if (DATA_MEMORY_MAP_LENGTH < ((REV_A_DATA_MEMORY_LENGTH / REV_A_DATA_MEMORY_UNIT_LENGTH) + 1))
+#error Data memory map length too short.
+#endif
+#if (CODE_MEMORY_MAP_LENGTH < ((REV_B_CODE_MEMORY_LENGTH / REV_B_CODE_MEMORY_UNIT_LENGTH) + 1))
+#error Code memory map length too short.
+#endif
+#if (DATA_MEMORY_MAP_LENGTH < ((REV_B_DATA_MEMORY_LENGTH / REV_B_DATA_MEMORY_UNIT_LENGTH) + 1))
+#error Data memory map length too short.
+#endif
+
+
+/*
+ * Kernel code memory definition
+ */
+
+#define KCODE_VECTORS_BEGIN             0x0000
+#define KCODE_VECTORS_END               0x002F
+#define KCODE_VECTORS_UNIT_LENGTH       0x0002
+#define KCODE_VECTORS_LENGTH            (KCODE_VECTORS_END - KCODE_VECTORS_BEGIN + 1)
+
+
+/*
+ * Kernel data memory definition
+ */
+
+#define KDATA_BASE_ADDR                 0x1000
+#define KDATA_BASE_ADDR2                0x1080
+
+#define KDATA_TASK0                     (KDATA_BASE_ADDR + 0x0000)
+#define KDATA_TASK1                     (KDATA_BASE_ADDR + 0x0001)
+#define KDATA_TASK2                     (KDATA_BASE_ADDR + 0x0002)
+#define KDATA_TASK3                     (KDATA_BASE_ADDR + 0x0003)
+#define KDATA_TASK4                     (KDATA_BASE_ADDR + 0x0004)
+#define KDATA_TASK5                     (KDATA_BASE_ADDR + 0x0005)
+#define KDATA_TASK6                     (KDATA_BASE_ADDR + 0x0006)
+#define KDATA_TASK7                     (KDATA_BASE_ADDR + 0x0007)
+#define KDATA_TASK_ENDMARK              (KDATA_BASE_ADDR + 0x0008)
+
+#define KDATA_CURRENT_TASK              (KDATA_BASE_ADDR + 0x0009)
+#define KDATA_TASK_SWITCH               (KDATA_BASE_ADDR + 0x000A)
+
+#define KDATA_INSTANCE0_POS3D           (KDATA_BASE_ADDR + 0x000B)
+#define KDATA_INSTANCE1_POS3D           (KDATA_BASE_ADDR + 0x000C)
+#define KDATA_INSTANCE2_POS3D           (KDATA_BASE_ADDR + 0x000D)
+#define KDATA_INSTANCE3_POS3D           (KDATA_BASE_ADDR + 0x000E)
+#define KDATA_INSTANCE4_POS3D           (KDATA_BASE_ADDR + 0x000F)
+#define KDATA_INSTANCE5_POS3D           (KDATA_BASE_ADDR + 0x0010)
+#define KDATA_INSTANCE6_POS3D           (KDATA_BASE_ADDR + 0x0011)
+#define KDATA_INSTANCE7_POS3D           (KDATA_BASE_ADDR + 0x0012)
+#define KDATA_INSTANCE8_POS3D           (KDATA_BASE_ADDR + 0x0013)
+#define KDATA_INSTANCE_POS3D_ENDMARK    (KDATA_BASE_ADDR + 0x0014)
+
+#define KDATA_INSTANCE0_SPKVIRT         (KDATA_BASE_ADDR + 0x0015)
+#define KDATA_INSTANCE_SPKVIRT_ENDMARK  (KDATA_BASE_ADDR + 0x0016)
+
+#define KDATA_INSTANCE0_SPDIF           (KDATA_BASE_ADDR + 0x0017)
+#define KDATA_INSTANCE_SPDIF_ENDMARK    (KDATA_BASE_ADDR + 0x0018)
+
+#define KDATA_INSTANCE0_MODEM           (KDATA_BASE_ADDR + 0x0019)
+#define KDATA_INSTANCE_MODEM_ENDMARK    (KDATA_BASE_ADDR + 0x001A)
+
+#define KDATA_INSTANCE0_SRC             (KDATA_BASE_ADDR + 0x001B)
+#define KDATA_INSTANCE1_SRC             (KDATA_BASE_ADDR + 0x001C)
+#define KDATA_INSTANCE_SRC_ENDMARK      (KDATA_BASE_ADDR + 0x001D)
+
+#define KDATA_INSTANCE0_MINISRC         (KDATA_BASE_ADDR + 0x001E)
+#define KDATA_INSTANCE1_MINISRC         (KDATA_BASE_ADDR + 0x001F)
+#define KDATA_INSTANCE2_MINISRC         (KDATA_BASE_ADDR + 0x0020)
+#define KDATA_INSTANCE3_MINISRC         (KDATA_BASE_ADDR + 0x0021)
+#define KDATA_INSTANCE_MINISRC_ENDMARK  (KDATA_BASE_ADDR + 0x0022)
+
+#define KDATA_INSTANCE0_CPYTHRU         (KDATA_BASE_ADDR + 0x0023)
+#define KDATA_INSTANCE1_CPYTHRU         (KDATA_BASE_ADDR + 0x0024)
+#define KDATA_INSTANCE_CPYTHRU_ENDMARK  (KDATA_BASE_ADDR + 0x0025)
+
+#define KDATA_CURRENT_DMA               (KDATA_BASE_ADDR + 0x0026)
+#define KDATA_DMA_SWITCH                (KDATA_BASE_ADDR + 0x0027)
+#define KDATA_DMA_ACTIVE                (KDATA_BASE_ADDR + 0x0028)
+
+#define KDATA_DMA_XFER0                 (KDATA_BASE_ADDR + 0x0029)
+#define KDATA_DMA_XFER1                 (KDATA_BASE_ADDR + 0x002A)
+#define KDATA_DMA_XFER2                 (KDATA_BASE_ADDR + 0x002B)
+#define KDATA_DMA_XFER3                 (KDATA_BASE_ADDR + 0x002C)
+#define KDATA_DMA_XFER4                 (KDATA_BASE_ADDR + 0x002D)
+#define KDATA_DMA_XFER5                 (KDATA_BASE_ADDR + 0x002E)
+#define KDATA_DMA_XFER6                 (KDATA_BASE_ADDR + 0x002F)
+#define KDATA_DMA_XFER7                 (KDATA_BASE_ADDR + 0x0030)
+#define KDATA_DMA_XFER8                 (KDATA_BASE_ADDR + 0x0031)
+#define KDATA_DMA_XFER_ENDMARK          (KDATA_BASE_ADDR + 0x0032)
+
+#define KDATA_I2S_SAMPLE_COUNT          (KDATA_BASE_ADDR + 0x0033)
+#define KDATA_I2S_INT_METER             (KDATA_BASE_ADDR + 0x0034)
+#define KDATA_I2S_ACTIVE                (KDATA_BASE_ADDR + 0x0035)
+
+#define KDATA_TIMER_COUNT_RELOAD        (KDATA_BASE_ADDR + 0x0036)
+#define KDATA_TIMER_COUNT_CURRENT       (KDATA_BASE_ADDR + 0x0037)
+
+#define KDATA_HALT_SYNCH_CLIENT         (KDATA_BASE_ADDR + 0x0038)
+#define KDATA_HALT_SYNCH_DMA            (KDATA_BASE_ADDR + 0x0039)
+#define KDATA_HALT_ACKNOWLEDGE          (KDATA_BASE_ADDR + 0x003A)
+
+#define KDATA_ADC1_XFER0                (KDATA_BASE_ADDR + 0x003B)
+#define KDATA_ADC1_XFER_ENDMARK         (KDATA_BASE_ADDR + 0x003C)
+#define KDATA_ADC1_LEFT_VOLUME		(KDATA_BASE_ADDR + 0x003D)
+#define KDATA_ADC1_RIGHT_VOLUME  	(KDATA_BASE_ADDR + 0x003E)
+#define KDATA_ADC1_LEFT_SUR_VOL		(KDATA_BASE_ADDR + 0x003F)
+#define KDATA_ADC1_RIGHT_SUR_VOL	(KDATA_BASE_ADDR + 0x0040)
+
+#define KDATA_ADC2_XFER0                (KDATA_BASE_ADDR + 0x0041)
+#define KDATA_ADC2_XFER_ENDMARK         (KDATA_BASE_ADDR + 0x0042)
+#define KDATA_ADC2_LEFT_VOLUME		(KDATA_BASE_ADDR + 0x0043)
+#define KDATA_ADC2_RIGHT_VOLUME		(KDATA_BASE_ADDR + 0x0044)
+#define KDATA_ADC2_LEFT_SUR_VOL		(KDATA_BASE_ADDR + 0x0045)
+#define KDATA_ADC2_RIGHT_SUR_VOL	(KDATA_BASE_ADDR + 0x0046)
+
+#define KDATA_CD_XFER0			(KDATA_BASE_ADDR + 0x0047)
+#define KDATA_CD_XFER_ENDMARK		(KDATA_BASE_ADDR + 0x0048)
+#define KDATA_CD_LEFT_VOLUME		(KDATA_BASE_ADDR + 0x0049)
+#define KDATA_CD_RIGHT_VOLUME		(KDATA_BASE_ADDR + 0x004A)
+#define KDATA_CD_LEFT_SUR_VOL		(KDATA_BASE_ADDR + 0x004B)
+#define KDATA_CD_RIGHT_SUR_VOL		(KDATA_BASE_ADDR + 0x004C)
+
+#define KDATA_MIC_XFER0			(KDATA_BASE_ADDR + 0x004D)
+#define KDATA_MIC_XFER_ENDMARK		(KDATA_BASE_ADDR + 0x004E)
+#define KDATA_MIC_VOLUME		(KDATA_BASE_ADDR + 0x004F)
+#define KDATA_MIC_SUR_VOL		(KDATA_BASE_ADDR + 0x0050)
+
+#define KDATA_I2S_XFER0                 (KDATA_BASE_ADDR + 0x0051)
+#define KDATA_I2S_XFER_ENDMARK          (KDATA_BASE_ADDR + 0x0052)
+
+#define KDATA_CHI_XFER0                 (KDATA_BASE_ADDR + 0x0053)
+#define KDATA_CHI_XFER_ENDMARK          (KDATA_BASE_ADDR + 0x0054)
+
+#define KDATA_SPDIF_XFER                (KDATA_BASE_ADDR + 0x0055)
+#define KDATA_SPDIF_CURRENT_FRAME       (KDATA_BASE_ADDR + 0x0056)
+#define KDATA_SPDIF_FRAME0              (KDATA_BASE_ADDR + 0x0057)
+#define KDATA_SPDIF_FRAME1              (KDATA_BASE_ADDR + 0x0058)
+#define KDATA_SPDIF_FRAME2              (KDATA_BASE_ADDR + 0x0059)
+
+#define KDATA_SPDIF_REQUEST             (KDATA_BASE_ADDR + 0x005A)
+#define KDATA_SPDIF_TEMP                (KDATA_BASE_ADDR + 0x005B)
+
+/*AY SPDIF IN */
+#define KDATA_SPDIFIN_XFER0             (KDATA_BASE_ADDR + 0x005C)
+#define KDATA_SPDIFIN_XFER_ENDMARK      (KDATA_BASE_ADDR + 0x005D)
+#define KDATA_SPDIFIN_INT_METER         (KDATA_BASE_ADDR + 0x005E)
+
+#define KDATA_DSP_RESET_COUNT           (KDATA_BASE_ADDR + 0x005F)
+#define KDATA_DEBUG_OUTPUT              (KDATA_BASE_ADDR + 0x0060)
+
+#define KDATA_KERNEL_ISR_LIST           (KDATA_BASE_ADDR + 0x0061)
+
+#define KDATA_KERNEL_ISR_CBSR1          (KDATA_BASE_ADDR + 0x0062)
+#define KDATA_KERNEL_ISR_CBER1          (KDATA_BASE_ADDR + 0x0063)
+#define KDATA_KERNEL_ISR_CBCR           (KDATA_BASE_ADDR + 0x0064)
+#define KDATA_KERNEL_ISR_AR0            (KDATA_BASE_ADDR + 0x0065)
+#define KDATA_KERNEL_ISR_AR1            (KDATA_BASE_ADDR + 0x0066)
+#define KDATA_KERNEL_ISR_AR2            (KDATA_BASE_ADDR + 0x0067)
+#define KDATA_KERNEL_ISR_AR3            (KDATA_BASE_ADDR + 0x0068)
+#define KDATA_KERNEL_ISR_AR4            (KDATA_BASE_ADDR + 0x0069)
+#define KDATA_KERNEL_ISR_AR5            (KDATA_BASE_ADDR + 0x006A)
+#define KDATA_KERNEL_ISR_BRCR           (KDATA_BASE_ADDR + 0x006B)
+#define KDATA_KERNEL_ISR_PASR           (KDATA_BASE_ADDR + 0x006C)
+#define KDATA_KERNEL_ISR_PAER           (KDATA_BASE_ADDR + 0x006D)
+
+#define KDATA_CLIENT_SCRATCH0           (KDATA_BASE_ADDR + 0x006E)
+#define KDATA_CLIENT_SCRATCH1           (KDATA_BASE_ADDR + 0x006F)
+#define KDATA_KERNEL_SCRATCH            (KDATA_BASE_ADDR + 0x0070)
+#define KDATA_KERNEL_ISR_SCRATCH        (KDATA_BASE_ADDR + 0x0071)
+
+#define KDATA_OUEUE_LEFT                (KDATA_BASE_ADDR + 0x0072)
+#define KDATA_QUEUE_RIGHT               (KDATA_BASE_ADDR + 0x0073)
+
+#define KDATA_ADC1_REQUEST              (KDATA_BASE_ADDR + 0x0074)
+#define KDATA_ADC2_REQUEST              (KDATA_BASE_ADDR + 0x0075)
+#define KDATA_CD_REQUEST		(KDATA_BASE_ADDR + 0x0076)
+#define KDATA_MIC_REQUEST		(KDATA_BASE_ADDR + 0x0077)
+
+#define KDATA_ADC1_MIXER_REQUEST        (KDATA_BASE_ADDR + 0x0078)
+#define KDATA_ADC2_MIXER_REQUEST        (KDATA_BASE_ADDR + 0x0079)
+#define KDATA_CD_MIXER_REQUEST		(KDATA_BASE_ADDR + 0x007A)
+#define KDATA_MIC_MIXER_REQUEST		(KDATA_BASE_ADDR + 0x007B)
+#define KDATA_MIC_SYNC_COUNTER		(KDATA_BASE_ADDR + 0x007C)
+
+/*
+ * second segment
+ */
+
+/* smart mixer buffer */
+
+#define KDATA_MIXER_WORD0               (KDATA_BASE_ADDR2 + 0x0000)
+#define KDATA_MIXER_WORD1               (KDATA_BASE_ADDR2 + 0x0001)
+#define KDATA_MIXER_WORD2               (KDATA_BASE_ADDR2 + 0x0002)
+#define KDATA_MIXER_WORD3               (KDATA_BASE_ADDR2 + 0x0003)
+#define KDATA_MIXER_WORD4               (KDATA_BASE_ADDR2 + 0x0004)
+#define KDATA_MIXER_WORD5               (KDATA_BASE_ADDR2 + 0x0005)
+#define KDATA_MIXER_WORD6               (KDATA_BASE_ADDR2 + 0x0006)
+#define KDATA_MIXER_WORD7               (KDATA_BASE_ADDR2 + 0x0007)
+#define KDATA_MIXER_WORD8               (KDATA_BASE_ADDR2 + 0x0008)
+#define KDATA_MIXER_WORD9               (KDATA_BASE_ADDR2 + 0x0009)
+#define KDATA_MIXER_WORDA               (KDATA_BASE_ADDR2 + 0x000A)
+#define KDATA_MIXER_WORDB               (KDATA_BASE_ADDR2 + 0x000B)
+#define KDATA_MIXER_WORDC               (KDATA_BASE_ADDR2 + 0x000C)
+#define KDATA_MIXER_WORDD               (KDATA_BASE_ADDR2 + 0x000D)
+#define KDATA_MIXER_WORDE               (KDATA_BASE_ADDR2 + 0x000E)
+#define KDATA_MIXER_WORDF               (KDATA_BASE_ADDR2 + 0x000F)
+
+#define KDATA_MIXER_XFER0               (KDATA_BASE_ADDR2 + 0x0010)
+#define KDATA_MIXER_XFER1               (KDATA_BASE_ADDR2 + 0x0011)
+#define KDATA_MIXER_XFER2               (KDATA_BASE_ADDR2 + 0x0012)
+#define KDATA_MIXER_XFER3               (KDATA_BASE_ADDR2 + 0x0013)
+#define KDATA_MIXER_XFER4               (KDATA_BASE_ADDR2 + 0x0014)
+#define KDATA_MIXER_XFER5               (KDATA_BASE_ADDR2 + 0x0015)
+#define KDATA_MIXER_XFER6               (KDATA_BASE_ADDR2 + 0x0016)
+#define KDATA_MIXER_XFER7               (KDATA_BASE_ADDR2 + 0x0017)
+#define KDATA_MIXER_XFER8               (KDATA_BASE_ADDR2 + 0x0018)
+#define KDATA_MIXER_XFER9               (KDATA_BASE_ADDR2 + 0x0019)
+#define KDATA_MIXER_XFER_ENDMARK        (KDATA_BASE_ADDR2 + 0x001A)
+
+#define KDATA_MIXER_TASK_NUMBER         (KDATA_BASE_ADDR2 + 0x001B)
+#define KDATA_CURRENT_MIXER             (KDATA_BASE_ADDR2 + 0x001C)
+#define KDATA_MIXER_ACTIVE              (KDATA_BASE_ADDR2 + 0x001D)
+#define KDATA_MIXER_BANK_STATUS         (KDATA_BASE_ADDR2 + 0x001E)
+#define KDATA_DAC_LEFT_VOLUME	        (KDATA_BASE_ADDR2 + 0x001F)
+#define KDATA_DAC_RIGHT_VOLUME          (KDATA_BASE_ADDR2 + 0x0020)
+
+/*
+ * Client data memory definition
+ */
+
+#define CDATA_INSTANCE_READY            0x00
+
+#define CDATA_HOST_SRC_ADDRL            0x01
+#define CDATA_HOST_SRC_ADDRH            0x02
+#define CDATA_HOST_SRC_END_PLUS_1L      0x03
+#define CDATA_HOST_SRC_END_PLUS_1H      0x04
+#define CDATA_HOST_SRC_CURRENTL         0x05
+#define CDATA_HOST_SRC_CURRENTH         0x06
+
+#define CDATA_IN_BUF_CONNECT            0x07
+#define CDATA_OUT_BUF_CONNECT           0x08
+
+#define CDATA_IN_BUF_BEGIN              0x09
+#define CDATA_IN_BUF_END_PLUS_1         0x0A
+#define CDATA_IN_BUF_HEAD               0x0B
+#define CDATA_IN_BUF_TAIL               0x0C
+
+#define CDATA_OUT_BUF_BEGIN             0x0D
+#define CDATA_OUT_BUF_END_PLUS_1        0x0E
+#define CDATA_OUT_BUF_HEAD              0x0F
+#define CDATA_OUT_BUF_TAIL              0x10
+
+#define CDATA_DMA_CONTROL               0x11
+#define CDATA_RESERVED                  0x12
+
+#define CDATA_FREQUENCY                 0x13
+#define CDATA_LEFT_VOLUME               0x14
+#define CDATA_RIGHT_VOLUME              0x15
+#define CDATA_LEFT_SUR_VOL              0x16
+#define CDATA_RIGHT_SUR_VOL             0x17
+
+/* These are from Allegro hckernel.h */
+#define CDATA_HEADER_LEN                0x18
+#define SRC3_DIRECTION_OFFSET           CDATA_HEADER_LEN
+#define SRC3_MODE_OFFSET                CDATA_HEADER_LEN + 1
+#define SRC3_WORD_LENGTH_OFFSET         CDATA_HEADER_LEN + 2
+#define SRC3_PARAMETER_OFFSET           CDATA_HEADER_LEN + 3
+#define SRC3_COEFF_ADDR_OFFSET          CDATA_HEADER_LEN + 8
+#define SRC3_FILTAP_ADDR_OFFSET         CDATA_HEADER_LEN + 10
+#define SRC3_TEMP_INBUF_ADDR_OFFSET     CDATA_HEADER_LEN + 16
+#define SRC3_TEMP_OUTBUF_ADDR_OFFSET    CDATA_HEADER_LEN + 17
+#define FOR_FUTURE_USE                  10	/* for storing temporary variable in future */
+
+/*
+ * DMA control definition
+ */
+
+#define DMACONTROL_BLOCK_MASK           0x000F
+#define  DMAC_BLOCK0_SELECTOR           0x0000
+#define  DMAC_BLOCK1_SELECTOR           0x0001
+#define  DMAC_BLOCK2_SELECTOR           0x0002
+#define  DMAC_BLOCK3_SELECTOR           0x0003
+#define  DMAC_BLOCK4_SELECTOR           0x0004
+#define  DMAC_BLOCK5_SELECTOR           0x0005
+#define  DMAC_BLOCK6_SELECTOR           0x0006
+#define  DMAC_BLOCK7_SELECTOR           0x0007
+#define  DMAC_BLOCK8_SELECTOR           0x0008
+#define  DMAC_BLOCK9_SELECTOR           0x0009
+#define  DMAC_BLOCKA_SELECTOR           0x000A
+#define  DMAC_BLOCKB_SELECTOR           0x000B
+#define  DMAC_BLOCKC_SELECTOR           0x000C
+#define  DMAC_BLOCKD_SELECTOR           0x000D
+#define  DMAC_BLOCKE_SELECTOR           0x000E
+#define  DMAC_BLOCKF_SELECTOR           0x000F
+#define DMACONTROL_PAGE_MASK            0x00F0
+#define  DMAC_PAGE0_SELECTOR            0x0030
+#define  DMAC_PAGE1_SELECTOR            0x0020
+#define  DMAC_PAGE2_SELECTOR            0x0010
+#define  DMAC_PAGE3_SELECTOR            0x0000
+#define DMACONTROL_AUTOREPEAT           0x1000
+#define DMACONTROL_STOPPED              0x2000
+#define DMACONTROL_DIRECTION            0x0100
+
+/*
+ * Kernel/client memory allocation
+ */
+
+#define NUM_UNITS_KERNEL_CODE          16
+#define NUM_UNITS_KERNEL_DATA           2
+
+#define NUM_UNITS_KERNEL_CODE_WITH_HSP 16
+#ifdef M3_MODEL
+#define NUM_UNITS_KERNEL_DATA_WITH_HSP  5
+#else
+#define NUM_UNITS_KERNEL_DATA_WITH_HSP  4
+#endif
+
+#define NUM_UNITS( BYTES, UNITLEN )    ((((BYTES+1)>>1) + (UNITLEN-1)) / UNITLEN)
+
+/*
+ * DSP hardware
+ */
+
+#define DSP_PORT_TIMER_COUNT            0x06
+#define DSP_PORT_MEMORY_INDEX           0x80
+#define DSP_PORT_MEMORY_TYPE            0x82
+#define DSP_PORT_MEMORY_DATA            0x84
+#define DSP_PORT_CONTROL_REG_A          0xA2
+#define DSP_PORT_CONTROL_REG_B          0xA4
+#define DSP_PORT_CONTROL_REG_C          0xA6
+
+#define MEMTYPE_INTERNAL_CODE           0x0002
+#define MEMTYPE_INTERNAL_DATA           0x0003
+#define MEMTYPE_MASK                    0x0003
+
+#define REGB_ENABLE_RESET               0x01
+#define REGB_STOP_CLOCK                 0x10
+
+#define REGC_DISABLE_FM_MAPPING         0x02
+
+#define DP_SHIFT_COUNT                  7
+
+#define DMA_BLOCK_LENGTH                32
+
+/* These are from Allegro srcmgr.h */
+#define MINISRC_BIQUAD_STAGE    2
+#define MINISRC_IN_BUFFER_SIZE   ( 0x50 * 2 )
+#define MINISRC_OUT_BUFFER_SIZE  ( 0x50 * 2 * 2)
+#define MINISRC_TMP_BUFFER_SIZE  ( 112 + ( MINISRC_BIQUAD_STAGE * 3 + 4 ) * 2 * 2 )
+#define MINISRC_BIQUAD_STAGE    2
+/* M. SRC LPF coefficient could be changed in the DSP code */
+#define MINISRC_COEF_LOC          0X175
+
+#endif	/* !_DEV_SOUND_PCI_ALLEGRO_REG_H */
diff -r f370dd4be562 -r 5c82a43b1344 head/sys/dev/sound/pci/csa.c
--- a/head/sys/dev/sound/pci/csa.c	Wed Feb 01 11:27:03 2012 +0200
+++ b/head/sys/dev/sound/pci/csa.c	Wed Feb 01 11:27:33 2012 +0200
@@ -52,7 +52,7 @@
 
 #include <gnu/dev/sound/pci/csaimg.h>
 
-SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/csa.c 227843 2011-11-22 21:28:20Z marius $");
+SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/csa.c 230602 2012-01-26 21:43:11Z pfg $");
 
 /* This is the pci device id. */
 #define CS4610_PCI_ID 0x60011013
@@ -861,7 +861,7 @@
 csa_downloadimage(csa_res *resp)
 {
 	int i;
-	u_int32_t tmp, src, dst, count, data;
+	u_int32_t tmp, src, dst, count;
 
 	for (i = 0; i < CLEAR__COUNT; i++) {
 		dst = ClrStat[i].BA1__DestByteOffset;
@@ -875,8 +875,7 @@
 		dst = FillStat[i].Offset;
 		count = FillStat[i].Size;
 		for (tmp = 0; tmp < count; tmp += 4) {
-			data = FillStat[i].pFill[src];
-			csa_writemem(resp, dst + tmp, data);
+			csa_writemem(resp, dst + tmp, FillStat[i].pFill[src]);
 			src++;
 		}
 	}
diff -r f370dd4be562 -r 5c82a43b1344 head/sys/dev/sound/pci/csareg.h
--- a/head/sys/dev/sound/pci/csareg.h	Wed Feb 01 11:27:03 2012 +0200
+++ b/head/sys/dev/sound/pci/csareg.h	Wed Feb 01 11:27:33 2012 +0200
@@ -27,7 +27,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/sound/pci/csareg.h 230602 2012-01-26 21:43:11Z pfg $
  */
 
 #ifndef _CSA_REG_H
@@ -1949,24 +1949,4 @@
 #define CS_AC97_POWER_CONTROL_MIXVON_ON	0x0004
 #define CS_AC97_POWER_CONTROL_MIXVOFF_ON 0x0008
 
-/* The following struct holds the initialization array. */
-
-/*
- * this is 3*1024 for parameter, 3.5*1024 for sample and 2*3.5*1024 for code since 
- * each instruction is 40 bits and takes two dwords 
- */
-#define INKY_BA1_DWORD_SIZE (13 * 1024 + 512)
-#define INKY_MEMORY_COUNT 3
-
-struct BA1struct 
-{
-	struct
-	{
-		u_long ulDestByteOffset,
-		    ulSourceByteSize;
-	} MemoryStat[INKY_MEMORY_COUNT];
-
-	u_long BA1Array[INKY_BA1_DWORD_SIZE];
-};
-
 #endif /* _CSA_REG_H */
diff -r f370dd4be562 -r 5c82a43b1344 head/sys/dev/sound/pci/hda/hda_reg.h
--- a/head/sys/dev/sound/pci/hda/hda_reg.h	Wed Feb 01 11:27:03 2012 +0200
+++ b/head/sys/dev/sound/pci/hda/hda_reg.h	Wed Feb 01 11:27:33 2012 +0200
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/sys/dev/sound/pci/hda/hda_reg.h 230130 2012-01-15 13:21:36Z mav $
+ * $FreeBSD: head/sys/dev/sound/pci/hda/hda_reg.h 230312 2012-01-18 19:12:33Z mav $
  */
 
 #ifndef _HDA_REG_H_
@@ -419,6 +419,7 @@
     HDA_CMD_VERB_SET_PIN_SENSE, (payload)))
 
 #define HDA_CMD_GET_PIN_SENSE_PRESENCE_DETECT		0x80000000
+#define HDA_CMD_GET_PIN_SENSE_ELD_VALID			0x40000000
 #define HDA_CMD_GET_PIN_SENSE_IMP_SENSE_MASK		0x7fffffff
 #define HDA_CMD_GET_PIN_SENSE_IMP_SENSE_SHIFT		0
 
@@ -675,17 +676,47 @@
     HDA_CMD_VERB_SET_CONV_CHAN_COUNT, (payload)))
 
 #define HDA_CMD_VERB_GET_HDMI_DIP_SIZE			0xf2e 
+
+#define HDA_CMD_GET_HDMI_DIP_SIZE(cad, nid, arg)			\
+    (HDA_CMD_12BIT((cad), (nid),					\
+    HDA_CMD_VERB_GET_HDMI_DIP_SIZE, (arg)))
+
 #define HDA_CMD_VERB_GET_HDMI_ELDD			0xf2f 
 
+#define HDA_CMD_GET_HDMI_ELDD(cad, nid, off)				\
+    (HDA_CMD_12BIT((cad), (nid),					\
+    HDA_CMD_VERB_GET_HDMI_ELDD, (off)))
+
 #define HDA_CMD_VERB_GET_HDMI_DIP_INDEX			0xf30 
 #define HDA_CMD_VERB_SET_HDMI_DIP_INDEX			0x730 
 
+#define HDA_CMD_GET_HDMI_DIP_INDEX(cad, nid)				\
+    (HDA_CMD_12BIT((cad), (nid),					\
+    HDA_CMD_VERB_GET_HDMI_DIP_INDEX, 0x0))
+#define HDA_CMD_SET_HDMI_DIP_INDEX(cad, nid, payload)			\
+    (HDA_CMD_12BIT((cad), (nid),					\
+    HDA_CMD_VERB_SET_HDMI_DIP_INDEX, (payload)))
+
 #define HDA_CMD_VERB_GET_HDMI_DIP_DATA			0xf31 
 #define HDA_CMD_VERB_SET_HDMI_DIP_DATA			0x731 
 
+#define HDA_CMD_GET_HDMI_DIP_DATA(cad, nid)				\
+    (HDA_CMD_12BIT((cad), (nid),					\
+    HDA_CMD_VERB_GET_HDMI_DIP_DATA, 0x0))
+#define HDA_CMD_SET_HDMI_DIP_DATA(cad, nid, payload)			\
+    (HDA_CMD_12BIT((cad), (nid),					\
+    HDA_CMD_VERB_SET_HDMI_DIP_DATA, (payload)))
+
 #define HDA_CMD_VERB_GET_HDMI_DIP_XMIT			0xf32 
 #define HDA_CMD_VERB_SET_HDMI_DIP_XMIT			0x732 
 
+#define HDA_CMD_GET_HDMI_DIP_XMIT(cad, nid)				\
+    (HDA_CMD_12BIT((cad), (nid),					\
+    HDA_CMD_VERB_GET_HDMI_DIP_XMIT, 0x0))
+#define HDA_CMD_SET_HDMI_DIP_XMIT(cad, nid, payload)			\
+    (HDA_CMD_12BIT((cad), (nid),					\
+    HDA_CMD_VERB_SET_HDMI_DIP_XMIT, (payload)))
+
 #define HDA_CMD_VERB_GET_HDMI_CP_CTRL			0xf33 
 #define HDA_CMD_VERB_SET_HDMI_CP_CTRL			0x733 
 
@@ -699,6 +730,23 @@
     (HDA_CMD_12BIT((cad), (nid),					\
     HDA_CMD_VERB_SET_HDMI_CHAN_SLOT, (payload)))
 
+#define	HDA_HDMI_CODING_TYPE_REF_STREAM_HEADER		0
+#define	HDA_HDMI_CODING_TYPE_LPCM			1
+#define	HDA_HDMI_CODING_TYPE_AC3			2
+#define	HDA_HDMI_CODING_TYPE_MPEG1			3
+#define	HDA_HDMI_CODING_TYPE_MP3			4
+#define	HDA_HDMI_CODING_TYPE_MPEG2			5
+#define	HDA_HDMI_CODING_TYPE_AACLC			6
+#define	HDA_HDMI_CODING_TYPE_DTS			7
+#define	HDA_HDMI_CODING_TYPE_ATRAC			8
+#define	HDA_HDMI_CODING_TYPE_SACD			9
+#define	HDA_HDMI_CODING_TYPE_EAC3			10
+#define	HDA_HDMI_CODING_TYPE_DTS_HD			11
+#define	HDA_HDMI_CODING_TYPE_MLP			12
+#define	HDA_HDMI_CODING_TYPE_DST			13
+#define	HDA_HDMI_CODING_TYPE_WMAPRO			14
+#define	HDA_HDMI_CODING_TYPE_REF_CTX			15
+
 /* Function Reset */
 #define HDA_CMD_VERB_FUNCTION_RESET			0x7ff
 
diff -r f370dd4be562 -r 5c82a43b1344 head/sys/dev/sound/pci/hda/hdaa.c
--- a/head/sys/dev/sound/pci/hda/hdaa.c	Wed Feb 01 11:27:03 2012 +0200
+++ b/head/sys/dev/sound/pci/hda/hdaa.c	Wed Feb 01 11:27:33 2012 +0200
@@ -45,7 +45,7 @@
 
 #include "mixer_if.h"
 
-SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdaa.c 230181 2012-01-16 00:26:52Z mav $");
+SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdaa.c 230641 2012-01-28 09:24:57Z mav $");
 
 #define hdaa_lock(devinfo)	snd_mtxlock((devinfo)->lock)
 #define hdaa_unlock(devinfo)	snd_mtxunlock((devinfo)->lock)
@@ -74,17 +74,6 @@
 #define HDAA_QUIRKS_TAB_LEN	\
 		(sizeof(hdaa_quirks_tab) / sizeof(hdaa_quirks_tab[0]))
 
-#define HDA_BDL_MIN	2
-#define HDA_BDL_MAX	256
-#define HDA_BDL_DEFAULT	HDA_BDL_MIN
-
-#define HDA_BLK_MIN	HDA_DMA_ALIGNMENT
-#define HDA_BLK_ALIGN	(~(HDA_BLK_MIN - 1))
-
-#define HDA_BUFSZ_MIN		4096
-#define HDA_BUFSZ_MAX		65536
-#define HDA_BUFSZ_DEFAULT	16384
-
 #define HDA_PARSE_MAXDEPTH	10
 
 MALLOC_DEFINE(M_HDAA, "hdaa", "HDA Audio");
@@ -116,6 +105,12 @@
 const char *HDA_GPIO_ACTIONS[8] = {
     "keep", "set", "clear", "disable", "input", "0x05", "0x06", "0x07"};
 
+const char *HDA_HDMI_CODING_TYPES[18] = {
+    "undefined", "LPCM", "AC-3", "MPEG1", "MP3", "MPEG2", "AAC-LC", "DTS",
+    "ATRAC", "DSD", "E-AC-3", "DTS-HD", "MLP", "DST", "WMAPro", "HE-AAC",
+    "HE-AACv2", "MPEG-Surround"
+};
+
 /* Default */
 static uint32_t hdaa_fmt[] = {
 	SND_FORMAT(AFMT_S16_LE, 2, 0),
@@ -169,6 +164,8 @@
 };
 #define HDA_RATE_TAB_LEN (sizeof(hda_rate_tab) / sizeof(hda_rate_tab[0]))
 
+const static char *ossnames[] = SOUND_DEVICE_NAMES;
+
 /****************************************************************************
  * Function prototypes
  ****************************************************************************/
@@ -187,7 +184,6 @@
 static char *
 hdaa_audio_ctl_ossmixer_mask2allname(uint32_t mask, char *buf, size_t len)
 {
-	static char *ossname[] = SOUND_DEVICE_NAMES;
 	int i, first = 1;
 
 	bzero(buf, len);
@@ -195,7 +191,7 @@
 		if (mask & (1 << i)) {
 			if (first == 0)
 				strlcat(buf, ", ", len);
-			strlcat(buf, ossname[i], len);
+			strlcat(buf, ossnames[i], len);
 			first = 0;
 		}
 	}
@@ -243,49 +239,30 @@
 }
 
 /*
- * Jack detection (Speaker/HP redirection) event handler.
+ * Headphones redirection change handler.
  */
 static void
-hdaa_hp_switch_handler(struct hdaa_devinfo *devinfo, int asid)
+hdaa_hpredir_handler(struct hdaa_widget *w)
 {
-	struct hdaa_audio_as *as;
-	struct hdaa_widget *w;
+	struct hdaa_devinfo *devinfo = w->devinfo;
+	struct hdaa_audio_as *as = &devinfo->as[w->bindas];
+	struct hdaa_widget *w1;
 	struct hdaa_audio_ctl *ctl;
-	uint32_t val, res;
-	int j;
-
-	as = &devinfo->as[asid];
-	if (as->hpredir < 0)
-		return;
-
-	w = hdaa_widget_get(devinfo, as->pins[15]);
-	if (w == NULL || w->enable == 0 || w->type !=
-	    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
-		return;
-
-	res = hda_command(devinfo->dev,
-	    HDA_CMD_GET_PIN_SENSE(0, as->pins[15]));
+	uint32_t val;
+	int j, connected = w->wclass.pin.connected;
 
 	HDA_BOOTVERBOSE(
-		device_printf(devinfo->dev,
-		    "Pin sense: nid=%d sence=0x%08x",
-		    as->pins[15], res);
+		device_printf((as->pdevinfo && as->pdevinfo->dev) ?
+		    as->pdevinfo->dev : devinfo->dev,
+		    "Redirect output to: %s\n",
+		    connected ? "headphones": "main");
 	);
-
-	res = (res & HDA_CMD_GET_PIN_SENSE_PRESENCE_DETECT) != 0;
-	if (devinfo->quirks & HDAA_QUIRK_SENSEINV)
-		res ^= 1;
-
-	HDA_BOOTVERBOSE(
-		printf(" %sconnected\n", res == 0 ? "dis" : "");
-	);
-
 	/* (Un)Mute headphone pin. */
 	ctl = hdaa_audio_ctl_amp_get(devinfo,
-	    as->pins[15], HDAA_CTL_IN, -1, 1);
+	    w->nid, HDAA_CTL_IN, -1, 1);
 	if (ctl != NULL && ctl->mute) {
 		/* If pin has muter - use it. */
-		val = (res != 0) ? 0 : 1;
+		val = connected ? 0 : 1;
 		if (val != ctl->forcemute) {
 			ctl->forcemute = val;
 			hdaa_audio_ctl_amp_set(ctl,
@@ -294,21 +271,17 @@
 		}
 	} else {
 		/* If there is no muter - disable pin output. */
-		w = hdaa_widget_get(devinfo, as->pins[15]);
-		if (w != NULL && w->type ==
-		    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) {
-			if (res != 0)
-				val = w->wclass.pin.ctrl |
-				    HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE;
-			else
-				val = w->wclass.pin.ctrl &
-				    ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE;
-			if (val != w->wclass.pin.ctrl) {
-				w->wclass.pin.ctrl = val;
-				hda_command(devinfo->dev,
-				    HDA_CMD_SET_PIN_WIDGET_CTRL(0,
-				    w->nid, w->wclass.pin.ctrl));
-			}
+		if (connected)
+			val = w->wclass.pin.ctrl |
+			    HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE;
+		else
+			val = w->wclass.pin.ctrl &
+			    ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE;
+		if (val != w->wclass.pin.ctrl) {
+			w->wclass.pin.ctrl = val;
+			hda_command(devinfo->dev,
+			    HDA_CMD_SET_PIN_WIDGET_CTRL(0,
+			    w->nid, w->wclass.pin.ctrl));
 		}
 	}
 	/* (Un)Mute other pins. */
@@ -319,7 +292,7 @@
 		    as->pins[j], HDAA_CTL_IN, -1, 1);
 		if (ctl != NULL && ctl->mute) {
 			/* If pin has muter - use it. */
-			val = (res != 0) ? 1 : 0;
+			val = connected ? 1 : 0;
 			if (val == ctl->forcemute)
 				continue;
 			ctl->forcemute = val;
@@ -329,32 +302,142 @@
 			continue;
 		}
 		/* If there is no muter - disable pin output. */
-		w = hdaa_widget_get(devinfo, as->pins[j]);
-		if (w != NULL && w->type ==
-		    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) {
-			if (res != 0)
-				val = w->wclass.pin.ctrl &
+		w1 = hdaa_widget_get(devinfo, as->pins[j]);
+		if (w1 != NULL) {
+			if (connected)
+				val = w1->wclass.pin.ctrl &
 				    ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE;
 			else
-				val = w->wclass.pin.ctrl |
+				val = w1->wclass.pin.ctrl |
 				    HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE;
-			if (val != w->wclass.pin.ctrl) {
-				w->wclass.pin.ctrl = val;
+			if (val != w1->wclass.pin.ctrl) {
+				w1->wclass.pin.ctrl = val;
 				hda_command(devinfo->dev,
 				    HDA_CMD_SET_PIN_WIDGET_CTRL(0,
-				    w->nid, w->wclass.pin.ctrl));
+				    w1->nid, w1->wclass.pin.ctrl));
 			}
 		}
 	}
 }
 
 /*
- * Callback for poll based jack detection.
+ * Recording source change handler.
+ */
+static void
+hdaa_autorecsrc_handler(struct hdaa_audio_as *as, struct hdaa_widget *w)
+{
+	struct hdaa_pcm_devinfo *pdevinfo = as->pdevinfo;
+	struct hdaa_devinfo *devinfo;
+	struct hdaa_widget *w1;
+	int i, mask, fullmask, prio, bestprio;
+	char buf[128];
+
+	if (!as->mixed || pdevinfo == NULL || pdevinfo->mixer == NULL)
+		return;
+	/* Don't touch anything if we asked not to. */
+	if (pdevinfo->autorecsrc == 0 ||
+	    (pdevinfo->autorecsrc == 1 && w != NULL))
+		return;
+	/* Don't touch anything if "mix" or "speaker" selected. */
+	if (pdevinfo->recsrc & (SOUND_MASK_IMIX | SOUND_MASK_SPEAKER))
+		return;
+	/* Don't touch anything if several selected. */
+	if (ffs(pdevinfo->recsrc) != fls(pdevinfo->recsrc))
+		return;
+	devinfo = pdevinfo->devinfo;
+	mask = fullmask = 0;
+	bestprio = 0;
+	for (i = 0; i < 16; i++) {
+		if (as->pins[i] <= 0)
+			continue;
+		w1 = hdaa_widget_get(devinfo, as->pins[i]);
+		if (w1 == NULL || w1->enable == 0)
+			continue;
+		if (w1->wclass.pin.connected == 0)
+			continue;
+		prio = (w1->wclass.pin.connected == 1) ? 2 : 1;
+		if (prio < bestprio)
+			continue;
+		if (prio > bestprio) {
+			mask = 0;
+			bestprio = prio;
+		}
+		mask |= (1 << w1->ossdev);
+		fullmask |= (1 << w1->ossdev);
+	}
+	if (mask == 0)
+		return;
+	/* Prefer newly connected input. */
+	if (w != NULL && (mask & (1 << w->ossdev)))
+		mask = (1 << w->ossdev);
+	/* Prefer previously selected input */
+	if (mask & pdevinfo->recsrc)
+		mask &= pdevinfo->recsrc;
+	/* Prefer mic. */
+	if (mask & SOUND_MASK_MIC)
+		mask = SOUND_MASK_MIC;
+	/* Prefer monitor (2nd mic). */
+	if (mask & SOUND_MASK_MONITOR)
+		mask = SOUND_MASK_MONITOR;
+	/* Just take first one. */
+	mask = (1 << (ffs(mask) - 1));
+	HDA_BOOTVERBOSE(
+		hdaa_audio_ctl_ossmixer_mask2allname(mask, buf, sizeof(buf));
+		device_printf(pdevinfo->dev,
+		    "Automatically set rec source to: %s\n", buf);
+	);
+	hdaa_unlock(devinfo);
+	mix_setrecsrc(pdevinfo->mixer, mask);
+	hdaa_lock(devinfo);
+}
+
+/*
+ * Jack presence detection event handler.
+ */
+static void
+hdaa_presence_handler(struct hdaa_widget *w)
+{
+	struct hdaa_devinfo *devinfo = w->devinfo;
+	struct hdaa_audio_as *as;
+	uint32_t res;
+	int connected;
+
+	if (w->enable == 0 || w->type !=
+	    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
+		return;
+
+	if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(w->wclass.pin.cap) == 0 ||
+	    (HDA_CONFIG_DEFAULTCONF_MISC(w->wclass.pin.config) & 1) != 0)
+		return;
+
+	res = hda_command(devinfo->dev, HDA_CMD_GET_PIN_SENSE(0, w->nid));
+	connected = (res & HDA_CMD_GET_PIN_SENSE_PRESENCE_DETECT) != 0;
+	if (devinfo->quirks & HDAA_QUIRK_SENSEINV)
+		connected = !connected;
+	if (connected == w->wclass.pin.connected)
+		return;
+	w->wclass.pin.connected = connected;
+	HDA_BOOTVERBOSE(
+		device_printf(devinfo->dev,
+		    "Pin sense: nid=%d sence=0x%08x (%sconnected)\n",
+		    w->nid, res, !w->wclass.pin.connected ? "dis" : "");
+	);
+
+	as = &devinfo->as[w->bindas];
+	if (as->hpredir >= 0 && as->pins[15] == w->nid)
+		hdaa_hpredir_handler(w);
+	if (as->dir == HDAA_CTL_IN)
+		hdaa_autorecsrc_handler(as, w);
+}
+
+/*
+ * Callback for poll based presence detection.
  */
 static void
 hdaa_jack_poll_callback(void *arg)
 {
 	struct hdaa_devinfo *devinfo = arg;
+	struct hdaa_widget *w;
 	int i;
 
 	hdaa_lock(devinfo);
@@ -365,56 +448,203 @@
 	for (i = 0; i < devinfo->ascnt; i++) {
 		if (devinfo->as[i].hpredir < 0)
 			continue;
-		hdaa_hp_switch_handler(devinfo, i);
+		w = hdaa_widget_get(devinfo, devinfo->as[i].pins[15]);
+		if (w == NULL || w->enable == 0 || w->type !=
+		    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
+			continue;
+		hdaa_presence_handler(w);
 	}
 	callout_reset(&devinfo->poll_jack, devinfo->poll_ival,
 	    hdaa_jack_poll_callback, devinfo);
 	hdaa_unlock(devinfo);
 }
 
+static void
+hdaa_eld_dump(struct hdaa_widget *w)
+{
+	struct hdaa_devinfo *devinfo = w->devinfo;
+	device_t dev = devinfo->dev;
+	uint8_t *sad;
+	int len, mnl, i, sadc, fmt;
+
+	if (w->eld == NULL || w->eld_len < 4)
+		return;
+	device_printf(dev,
+	    "ELD nid=%d: ELD_Ver=%u Baseline_ELD_Len=%u\n",
+	    w->nid, w->eld[0] >> 3, w->eld[2]);
+	if ((w->eld[0] >> 3) != 0x02)
+		return;
+	len = min(w->eld_len, (u_int)w->eld[2] * 4);
+	mnl = w->eld[4] & 0x1f;
+	device_printf(dev,
+	    "ELD nid=%d: CEA_EDID_Ver=%u MNL=%u\n",
+	    w->nid, w->eld[4] >> 5, mnl);
+	sadc = w->eld[5] >> 4;
+	device_printf(dev,
+	    "ELD nid=%d: SAD_Count=%u Conn_Type=%u S_AI=%u HDCP=%u\n",
+	    w->nid, sadc, (w->eld[5] >> 2) & 0x3,
+	    (w->eld[5] >> 1) & 0x1, w->eld[5] & 0x1);
+	device_printf(dev,
+	    "ELD nid=%d: Aud_Synch_Delay=%ums\n",
+	    w->nid, w->eld[6] * 2);
+	device_printf(dev,
+	    "ELD nid=%d: Channels=0x%b\n",
+	    w->nid, w->eld[7],
+	    "\020\07RLRC\06FLRC\05RC\04RLR\03FC\02LFE\01FLR");
+	device_printf(dev,
+	    "ELD nid=%d: Port_ID=0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+	    w->nid, w->eld[8], w->eld[9], w->eld[10], w->eld[11],
+	    w->eld[12], w->eld[13], w->eld[14], w->eld[15]);
+	device_printf(dev,
+	    "ELD nid=%d: Manufacturer_Name=0x%02x%02x\n",
+	    w->nid, w->eld[16], w->eld[17]);
+	device_printf(dev,
+	    "ELD nid=%d: Product_Code=0x%02x%02x\n",
+	    w->nid, w->eld[18], w->eld[19]);
+	device_printf(dev,
+	    "ELD nid=%d: Monitor_Name_String='%.*s'\n",
+	    w->nid, mnl, &w->eld[20]);
+	for (i = 0; i < sadc; i++) {
+		sad = &w->eld[20 + mnl + i * 3];
+		fmt = (sad[0] >> 3) & 0x0f;
+		if (fmt == HDA_HDMI_CODING_TYPE_REF_CTX) {
+			fmt = (sad[2] >> 3) & 0x1f;
+			if (fmt < 1 || fmt > 3)
+				fmt = 0;
+			else
+				fmt += 14;
+		}
+		device_printf(dev,
+		    "ELD nid=%d: %s %dch freqs=0x%b",
+		    w->nid, HDA_HDMI_CODING_TYPES[fmt], (sad[0] & 0x07) + 1,
+		    sad[1], "\020\007192\006176\00596\00488\00348\00244\00132");
+		switch (fmt) {
+		case HDA_HDMI_CODING_TYPE_LPCM:
+			printf(" sizes=0x%b",
+			    sad[2] & 0x07, "\020\00324\00220\00116");
+			break;
+		case HDA_HDMI_CODING_TYPE_AC3:
+		case HDA_HDMI_CODING_TYPE_MPEG1:
+		case HDA_HDMI_CODING_TYPE_MP3:
+		case HDA_HDMI_CODING_TYPE_MPEG2:
+		case HDA_HDMI_CODING_TYPE_AACLC:
+		case HDA_HDMI_CODING_TYPE_DTS:
+		case HDA_HDMI_CODING_TYPE_ATRAC:
+			printf(" max_bitrate=%d", sad[2] * 8000);
+			break;
+		case HDA_HDMI_CODING_TYPE_WMAPRO:
+			printf(" profile=%d", sad[2] & 0x07);
+			break;
+		}
+		printf("\n");
+	}
+}
+
+static void
+hdaa_eld_handler(struct hdaa_widget *w)
+{
+	struct hdaa_devinfo *devinfo = w->devinfo;
+	uint32_t res;
+	int i;
+
+	if (w->enable == 0 || w->type !=
+	    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
+		return;
+
+	if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(w->wclass.pin.cap) == 0 ||
+	    (HDA_CONFIG_DEFAULTCONF_MISC(w->wclass.pin.config) & 1) != 0)
+		return;
+
+	res = hda_command(devinfo->dev, HDA_CMD_GET_PIN_SENSE(0, w->nid));
+	if ((w->eld != 0) == ((res & HDA_CMD_GET_PIN_SENSE_ELD_VALID) != 0))
+		return;
+	if (w->eld != NULL) {
+		w->eld_len = 0;
+		free(w->eld, M_HDAA);
+		w->eld = NULL;
+	}
+	HDA_BOOTVERBOSE(
+		device_printf(devinfo->dev,
+		    "Pin sense: nid=%d sence=0x%08x "
+		    "(%sconnected, ELD %svalid)\n",
+		    w->nid, res,
+		    (res & HDA_CMD_GET_PIN_SENSE_PRESENCE_DETECT) ? "" : "dis",
+		    (res & HDA_CMD_GET_PIN_SENSE_ELD_VALID) ? "" : "in");
+	);
+	if ((res & HDA_CMD_GET_PIN_SENSE_ELD_VALID) == 0)
+		return;
+
+	res = hda_command(devinfo->dev,
+	    HDA_CMD_GET_HDMI_DIP_SIZE(0, w->nid, 0x08));
+	if (res == HDA_INVALID)
+		return;
+	w->eld_len = res & 0xff;
+	if (w->eld_len != 0)
+		w->eld = malloc(w->eld_len, M_HDAA, M_ZERO | M_NOWAIT);
+	if (w->eld == NULL) {
+		w->eld_len = 0;
+		return;
+	}
+
+	for (i = 0; i < w->eld_len; i++) {
+		res = hda_command(devinfo->dev,
+		    HDA_CMD_GET_HDMI_ELDD(0, w->nid, i));
+		if (res & 0x80000000)
+			w->eld[i] = res & 0xff;
+	}
+	HDA_BOOTVERBOSE(
+		hdaa_eld_dump(w);
+	);
+}
+
 /*
- * Jack detection initializer.
+ * Pin sense initializer.
  */
 static void
-hdaa_hp_switch_init(struct hdaa_devinfo *devinfo)
+hdaa_sense_init(struct hdaa_devinfo *devinfo)
 {
-	struct hdaa_audio_as *as = devinfo->as;
-        struct hdaa_widget *w;
-        int i, poll = 0;
-
-	for (i = 0; i < devinfo->ascnt; i++) {
-		if (as[i].hpredir < 0)
-			continue;
-
-		w = hdaa_widget_get(devinfo, as[i].pins[15]);
+	struct hdaa_audio_as *as;
+	struct hdaa_widget *w;
+	int i, poll = 0;
+
+	for (i = devinfo->startnode; i < devinfo->endnode; i++) {
+		w = hdaa_widget_get(devinfo, i);
 		if (w == NULL || w->enable == 0 || w->type !=
 		    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
 			continue;
-		if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(w->wclass.pin.cap) == 0 ||
-		    (HDA_CONFIG_DEFAULTCONF_MISC(w->wclass.pin.config) & 1) != 0) {
-			device_printf(devinfo->dev,
-			    "No jack detection support at pin %d\n",
-			    as[i].pins[15]);
-			continue;
-		}
-		if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap)) {
-			as[i].unsol = HDAC_UNSOL_ALLOC(
-			    device_get_parent(devinfo->dev), devinfo->dev,
-			    w->nid);
+		if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap) &&
+		    w->unsol < 0) {
+			w->unsol = HDAC_UNSOL_ALLOC(
+			    device_get_parent(devinfo->dev), devinfo->dev, w->nid);
 			hda_command(devinfo->dev,
 			    HDA_CMD_SET_UNSOLICITED_RESPONSE(0, w->nid,
-			    HDA_CMD_SET_UNSOLICITED_RESPONSE_ENABLE |
-			    as[i].unsol));
-		} else
-			poll = 1;
-		HDA_BOOTVERBOSE(
-			device_printf(devinfo->dev,
-			    "Headphones redirection "
-			    "for as=%d nid=%d using %s.\n",
-			    i, w->nid,
-			    (poll != 0) ? "polling" : "unsolicited responses");
-		);
-		hdaa_hp_switch_handler(devinfo, i);
+			    HDA_CMD_SET_UNSOLICITED_RESPONSE_ENABLE | w->unsol));
+		}
+		as = &devinfo->as[w->bindas];
+		if (as->hpredir >= 0 && as->pins[15] == w->nid) {
+			if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(w->wclass.pin.cap) == 0 ||
+			    (HDA_CONFIG_DEFAULTCONF_MISC(w->wclass.pin.config) & 1) != 0) {
+				device_printf(devinfo->dev,
+				    "No presence detection support at nid %d\n",
+				    as[i].pins[15]);
+			} else {
+				if (w->unsol < 0)
+					poll = 1;
+				HDA_BOOTVERBOSE(
+					device_printf(devinfo->dev,
+					    "Headphones redirection for "
+					    "association %d nid=%d using %s.\n",
+					    w->bindas, w->nid,
+					    (poll != 0) ? "polling" :
+					    "unsolicited responses");
+				);
+			};
+		}
+		hdaa_presence_handler(w);
+		if (!HDA_PARAM_PIN_CAP_DP(w->wclass.pin.cap) &&
+		    !HDA_PARAM_PIN_CAP_HDMI(w->wclass.pin.cap))
+			continue;
+		hdaa_eld_handler(w);
 	}
 	if (poll) {
 		callout_reset(&devinfo->poll_jack, 1,
@@ -423,25 +653,25 @@
 }
 
 static void
-hdaa_hp_switch_deinit(struct hdaa_devinfo *devinfo)
+hdaa_sense_deinit(struct hdaa_devinfo *devinfo)
 {
-	struct hdaa_audio_as *as = devinfo->as;
-        struct hdaa_widget *w;
-        int i;
-
-	for (i = 0; i < devinfo->ascnt; i++) {
-		if (as[i].unsol < 0)
-			continue;
-		w = hdaa_widget_get(devinfo, as[i].pins[15]);
+	struct hdaa_widget *w;
+	int i;
+
+	callout_stop(&devinfo->poll_jack);
+	for (i = devinfo->startnode; i < devinfo->endnode; i++) {
+		w = hdaa_widget_get(devinfo, i);
 		if (w == NULL || w->enable == 0 || w->type !=
 		    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
 			continue;
+		if (w->unsol < 0)
+			continue;
 		hda_command(devinfo->dev,
 		    HDA_CMD_SET_UNSOLICITED_RESPONSE(0, w->nid, 0));
 		HDAC_UNSOL_FREE(
 		    device_get_parent(devinfo->dev), devinfo->dev,
-		    as[i].unsol);
-		as[i].unsol = -1;
+		    w->unsol);
+		w->unsol = -1;
 	}
 }
 
@@ -902,6 +1132,11 @@
 			w->param.supp_pcm_size_rate =
 			    w->devinfo->supp_pcm_size_rate;
 		}
+		if (HDA_PARAM_AUDIO_WIDGET_CAP_STRIPE(w->param.widget_cap)) {
+			w->wclass.conv.stripecap = hda_command(dev,
+			    HDA_CMD_GET_STRIPE_CONTROL(0, w->nid)) >> 20;
+		} else
+			w->wclass.conv.stripecap = 1;
 	} else {
 		w->param.supp_stream_formats = 0;
 		w->param.supp_pcm_size_rate = 0;
@@ -938,6 +1173,7 @@
 		    hdaa_sysctl_config, "A", "Original pin configuration");
 		hdaa_lock(w->devinfo);
 	}
+	w->unsol = -1;
 }
 
 static void
@@ -1001,6 +1237,10 @@
 		}
 		strlcat(w->name, HDA_CONNS[conn], sizeof(w->name));
 		strlcat(w->name, ")", sizeof(w->name));
+
+		if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(w->wclass.pin.cap) == 0 ||
+		    (HDA_CONFIG_DEFAULTCONF_MISC(w->wclass.pin.config) & 1) != 0)
+			w->wclass.pin.connected = 2;
 	}
 }
 
@@ -1193,31 +1433,58 @@
 	return (fmt);
 }
 
+static int
+hdaa_allowed_stripes(uint16_t fmt)
+{
+	static const int bits[8] = { 8, 16, 20, 24, 32, 32, 32, 32 };
+	int size;
+
+	size = bits[(fmt >> 4) & 0x03];
+	size *= (fmt & 0x0f) + 1;
+	size *= ((fmt >> 11) & 0x07) + 1;
+	return (0xffffffffU >> (32 - fls(size / 8)));
+}
+
 static void
 hdaa_audio_setup(struct hdaa_chan *ch)
 {
 	struct hdaa_audio_as *as = &ch->devinfo->as[ch->as];
-	struct hdaa_widget *w;
-	int i, chn, totalchn, c;
+	struct hdaa_widget *w, *wp;
+	int i, j, k, chn, cchn, totalchn, totalextchn, c;
 	uint16_t fmt, dfmt;
-	uint16_t chmap[2][5] = {{ 0x0010, 0x0001, 0x0201, 0x0231, 0x0231 }, /* 5.1 */
-				{ 0x0010, 0x0001, 0x2001, 0x2031, 0x2431 }};/* 7.1 */
-	int map = -1;
+	/* Mapping channel pairs to codec pins/converters. */
+	const static uint16_t convmap[2][5] =
+	    {{ 0x0010, 0x0001, 0x0201, 0x0231, 0x0231 }, /* 5.1 */
+	     { 0x0010, 0x0001, 0x2001, 0x2031, 0x2431 }};/* 7.1 */
+	/* Mapping formats to HDMI channel allocations. */
+	const static uint8_t hdmica[2][8] =
+	    {{ 0x02, 0x00, 0x04, 0x08, 0x0a, 0x0e, 0x12, 0x12 }, /* x.0 */
+	     { 0x01, 0x03, 0x01, 0x03, 0x09, 0x0b, 0x0f, 0x13 }}; /* x.1 */
+	/* Mapping formats to HDMI channels order. */
+	const static uint32_t hdmich[2][8] =
+	    {{ 0xFFFF0F00, 0xFFFFFF10, 0xFFF2FF10, 0xFF32FF10,
+	       0xFF324F10, 0xF5324F10, 0x54326F10, 0x54326F10 }, /* x.0 */
+	     { 0xFFFFF000, 0xFFFF0100, 0xFFFFF210, 0xFFFF2310,
+	       0xFF32F410, 0xFF324510, 0xF6324510, 0x76325410 }}; /* x.1 */
+	int convmapid = -1;
+	nid_t nid;
+	uint8_t csum;
 
 	totalchn = AFMT_CHANNEL(ch->fmt);
+	totalextchn = AFMT_EXTCHANNEL(ch->fmt);
 	HDA_BOOTHVERBOSE(
 		device_printf(ch->pdevinfo->dev,
-		    "PCMDIR_%s: Stream setup fmt=%08x speed=%d\n",
+		    "PCMDIR_%s: Stream setup fmt=%08x (%d.%d) speed=%d\n",
 		    (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC",
-		    ch->fmt, ch->spd);
+		    ch->fmt, totalchn - totalextchn, totalextchn, ch->spd);
 	);
 	fmt = hdaa_stream_format(ch);
 
-	/* Set channel mapping for known speaker setups. */
+	/* Set channels to I/O converters mapping for known speaker setups. */
 	if ((as->pinset == 0x0007 || as->pinset == 0x0013)) /* Standard 5.1 */
-		map = 0;
+		convmapid = 0;
 	else if (as->pinset == 0x0017) /* Standard 7.1 */
-		map = 1;
+		convmapid = 1;
 
 	dfmt = HDA_CMD_SET_DIGITAL_CONV_FMT1_DIGEN;
 	if (ch->fmt & AFMT_AC3)
@@ -1234,22 +1501,16 @@
 		if (as->fakeredir && i == (as->pincnt - 1)) {
 			c = (ch->sid << 4);
 		} else {
-			if (map >= 0) /* Map known speaker setups. */
-				chn = (((chmap[map][totalchn / 2] >> i * 4) &
-				    0xf) - 1) * 2;
+			/* Map channels to I/O converters, if set. */
+			if (convmapid >= 0)
+				chn = (((convmap[convmapid][totalchn / 2]
+				    >> i * 4) & 0xf) - 1) * 2;
 			if (chn < 0 || chn >= totalchn) {
 				c = 0;
 			} else {
 				c = (ch->sid << 4) | chn;
 			}
 		}
-		HDA_BOOTHVERBOSE(
-			device_printf(ch->pdevinfo->dev,
-			    "PCMDIR_%s: Stream setup nid=%d: "
-			    "fmt=0x%04x, dfmt=0x%04x, chan=0x%04x\n",
-			    (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC",
-			    ch->io[i], fmt, dfmt, c);
-		);
 		hda_command(ch->devinfo->dev,
 		    HDA_CMD_SET_CONV_FMT(0, ch->io[i], fmt));
 		if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) {
@@ -1258,15 +1519,112 @@
 		}
 		hda_command(ch->devinfo->dev,
 		    HDA_CMD_SET_CONV_STREAM_CHAN(0, ch->io[i], c));
-#if 0
-		hda_command(ch->devinfo->dev,
-		    HDA_CMD_SET_CONV_CHAN_COUNT(0, ch->io[i], 1));
-		hda_command(ch->devinfo->dev,
-		    HDA_CMD_SET_HDMI_CHAN_SLOT(0, ch->io[i], 0x00));
-		hda_command(ch->devinfo->dev,
-		    HDA_CMD_SET_HDMI_CHAN_SLOT(0, ch->io[i], 0x11));
-#endif
-		chn += HDA_PARAM_AUDIO_WIDGET_CAP_CC(w->param.widget_cap) + 1;
+		if (HDA_PARAM_AUDIO_WIDGET_CAP_STRIPE(w->param.widget_cap)) {
+			hda_command(ch->devinfo->dev,
+			    HDA_CMD_SET_STRIPE_CONTROL(0, w->nid, ch->stripectl));
+		}
+		cchn = HDA_PARAM_AUDIO_WIDGET_CAP_CC(w->param.widget_cap);
+		if (cchn > 1 && chn < totalchn) {
+			cchn = min(cchn, totalchn - chn - 1);
+			hda_command(ch->devinfo->dev,
+			    HDA_CMD_SET_CONV_CHAN_COUNT(0, ch->io[i], cchn));
+		}
+		HDA_BOOTHVERBOSE(
+			device_printf(ch->pdevinfo->dev,
+			    "PCMDIR_%s: Stream setup nid=%d: "
+			    "fmt=0x%04x, dfmt=0x%04x, chan=0x%04x, "
+			    "chan_count=0x%02x, stripe=%d\n",
+			    (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC",
+			    ch->io[i], fmt, dfmt, c, cchn, ch->stripectl);
+		);
+		for (j = 0; j < 16; j++) {
+			if (as->dacs[ch->asindex][j] != ch->io[i])
+				continue;
+			nid = as->pins[j];
+			wp = hdaa_widget_get(ch->devinfo, nid);
+			if (wp == NULL)
+				continue;
+			if (!HDA_PARAM_PIN_CAP_DP(wp->wclass.pin.cap) &&
+			    !HDA_PARAM_PIN_CAP_HDMI(wp->wclass.pin.cap))
+				continue;
+
+			/* Set channel mapping. */
+			for (k = 0; k < 8; k++) {
+				hda_command(ch->devinfo->dev,
+				    HDA_CMD_SET_HDMI_CHAN_SLOT(0, nid,
+				    (((hdmich[totalextchn == 0 ? 0 : 1][totalchn - 1]
+				     >> (k * 4)) & 0xf) << 4) | k));
+			}
+
+			/*
+			 * Enable High Bit Rate (HBR) Encoded Packet Type
+			 * (EPT), if supported and needed (8ch data).
+			 */
+			if (HDA_PARAM_PIN_CAP_HDMI(wp->wclass.pin.cap) &&
+			    HDA_PARAM_PIN_CAP_HBR(wp->wclass.pin.cap)) {
+				wp->wclass.pin.ctrl &=
+				    ~HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK;
+				if ((ch->fmt & AFMT_AC3) && (cchn == 7))
+					wp->wclass.pin.ctrl |= 0x03;
+				hda_command(ch->devinfo->dev,
+				    HDA_CMD_SET_PIN_WIDGET_CTRL(0, nid,
+				    wp->wclass.pin.ctrl));
+			}
+
+			/* Stop audio infoframe transmission. */
+			hda_command(ch->devinfo->dev,
+			    HDA_CMD_SET_HDMI_DIP_INDEX(0, nid, 0x00));
+			hda_command(ch->devinfo->dev,
+			    HDA_CMD_SET_HDMI_DIP_XMIT(0, nid, 0x00));
+
+			/* Clear audio infoframe buffer. */
+			hda_command(ch->devinfo->dev,
+			    HDA_CMD_SET_HDMI_DIP_INDEX(0, nid, 0x00));
+			for (k = 0; k < 32; k++)
+				hda_command(ch->devinfo->dev,
+				    HDA_CMD_SET_HDMI_DIP_DATA(0, nid, 0x00));
+
+			/* Write HDMI/DisplayPort audio infoframe. */
+			hda_command(ch->devinfo->dev,
+			    HDA_CMD_SET_HDMI_DIP_INDEX(0, nid, 0x00));
+			if (w->eld != NULL && w->eld_len >= 6 &&
+			    ((w->eld[5] >> 2) & 0x3) == 1) { /* DisplayPort */
+				hda_command(ch->devinfo->dev,
+				    HDA_CMD_SET_HDMI_DIP_DATA(0, nid, 0x84));
+				hda_command(ch->devinfo->dev,
+				    HDA_CMD_SET_HDMI_DIP_DATA(0, nid, 0x1b));
+				hda_command(ch->devinfo->dev,
+				    HDA_CMD_SET_HDMI_DIP_DATA(0, nid, 0x44));
+			} else {	/* HDMI */
+				hda_command(ch->devinfo->dev,
+				    HDA_CMD_SET_HDMI_DIP_DATA(0, nid, 0x84));
+				hda_command(ch->devinfo->dev,
+				    HDA_CMD_SET_HDMI_DIP_DATA(0, nid, 0x01));
+				hda_command(ch->devinfo->dev,
+				    HDA_CMD_SET_HDMI_DIP_DATA(0, nid, 0x0a));
+				csum = 0;
+				csum -= 0x84 + 0x01 + 0x0a + (totalchn - 1) +
+				    hdmica[totalextchn == 0 ? 0 : 1][totalchn - 1];
+				hda_command(ch->devinfo->dev,
+				    HDA_CMD_SET_HDMI_DIP_DATA(0, nid, csum));
+			}
+			hda_command(ch->devinfo->dev,
+			    HDA_CMD_SET_HDMI_DIP_DATA(0, nid, totalchn - 1));
+			hda_command(ch->devinfo->dev,
+			    HDA_CMD_SET_HDMI_DIP_DATA(0, nid, 0x00));
+			hda_command(ch->devinfo->dev,
+			    HDA_CMD_SET_HDMI_DIP_DATA(0, nid, 0x00));
+			hda_command(ch->devinfo->dev,
+			    HDA_CMD_SET_HDMI_DIP_DATA(0, nid,
+			    hdmica[totalextchn == 0 ? 0 : 1][totalchn - 1]));
+
+			/* Start audio infoframe transmission. */
+			hda_command(ch->devinfo->dev,
+			    HDA_CMD_SET_HDMI_DIP_INDEX(0, nid, 0x00));
+			hda_command(ch->devinfo->dev,
+			    HDA_CMD_SET_HDMI_DIP_XMIT(0, nid, 0xc0));
+		}
+		chn += cchn + 1;
 	}
 }
 
@@ -1376,11 +1734,12 @@
 hdaa_channel_start(struct hdaa_chan *ch)
 {
 	struct hdaa_devinfo *devinfo = ch->devinfo;
-
-	ch->ptr = 0;
-	ch->prevptr = 0;
+	uint32_t fmt;
+
+	fmt = hdaa_stream_format(ch);
+	ch->stripectl = fls(ch->stripecap & hdaa_allowed_stripes(fmt)) - 1;
 	ch->sid = HDAC_STREAM_ALLOC(device_get_parent(devinfo->dev), devinfo->dev,
-	    ch->dir == PCMDIR_PLAY ? 1 : 0, hdaa_stream_format(ch), &ch->dmapos);
+	    ch->dir == PCMDIR_PLAY ? 1 : 0, fmt, ch->stripectl, &ch->dmapos);
 	if (ch->sid <= 0)
 		return (EBUSY);
 	hdaa_audio_setup(ch);
@@ -1470,11 +1829,11 @@
 	struct hdaa_pcm_devinfo *pdevinfo = mix_getdevinfo(m);
 	struct hdaa_devinfo *devinfo = pdevinfo->devinfo;
 	struct hdaa_widget *w, *cw;
-	struct hdaa_audio_ctl *ctl;
 	uint32_t mask, recmask;
-	int i, j, softpcmvol;
+	int i, j;
 
 	hdaa_lock(devinfo);
+	pdevinfo->mixer = m;
 
 	/* Make sure that in case of soft volume it won't stay muted. */
 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
@@ -1482,11 +1841,10 @@
 		pdevinfo->right[i] = 100;
 	}
 
-	mask = 0;
-	recmask = 0;
-
-	/* Declate EAPD as ogain control. */
+	/* Declare volume controls assigned to this association. */
+	mask = pdevinfo->ossmask;
 	if (pdevinfo->playas >= 0) {
+		/* Declate EAPD as ogain control. */
 		for (i = devinfo->startnode; i < devinfo->endnode; i++) {
 			w = hdaa_widget_get(devinfo, i);
 			if (w == NULL || w->enable == 0)
@@ -1498,23 +1856,36 @@
 			mask |= SOUND_MASK_OGAIN;
 			break;
 		}
-	}
-
-	/* Declare volume controls assigned to this association. */
-	i = 0;
-	ctl = NULL;
-	while ((ctl = hdaa_audio_ctl_each(devinfo, &i)) != NULL) {
-		if (ctl->enable == 0)
-			continue;
-		if ((pdevinfo->playas >= 0 &&
-		    ctl->widget->bindas == pdevinfo->playas) ||
-		    (pdevinfo->recas >= 0 &&
-		    ctl->widget->bindas == pdevinfo->recas) ||
-		    (ctl->widget->bindas == -2 && pdevinfo->index == 0))
-			mask |= ctl->ossmask;
+
+		/* Declare soft PCM volume if needed. */
+		if ((mask & SOUND_MASK_PCM) == 0 ||
+		    (devinfo->quirks & HDAA_QUIRK_SOFTPCMVOL) ||
+		    pdevinfo->minamp[SOUND_MIXER_PCM] ==
+		     pdevinfo->maxamp[SOUND_MIXER_PCM]) {
+			mask |= SOUND_MASK_PCM;
+			pcm_setflags(pdevinfo->dev, pcm_getflags(pdevinfo->dev) | SD_F_SOFTPCMVOL);
+			HDA_BOOTHVERBOSE(
+				device_printf(pdevinfo->dev,
+				    "Forcing Soft PCM volume\n");
+			);
+		}
+
+		/* Declare master volume if needed. */
+		if ((mask & SOUND_MASK_VOLUME) == 0) {
+			mask |= SOUND_MASK_VOLUME;
+			mix_setparentchild(m, SOUND_MIXER_VOLUME,
+			    SOUND_MASK_PCM);
+			mix_setrealdev(m, SOUND_MIXER_VOLUME,
+			    SOUND_MIXER_NONE);
+			HDA_BOOTHVERBOSE(
+				device_printf(pdevinfo->dev,
+				    "Forcing master volume with PCM\n");
+			);
+		}
 	}
 
 	/* Declare record sources available to this association. */
+	recmask = 0;
 	if (pdevinfo->recas >= 0) {
 		for (i = 0; i < 16; i++) {
 			if (devinfo->as[pdevinfo->recas].dacs[0][i] < 0)
@@ -1537,57 +1908,9 @@
 		}
 	}
 
-	/* Declare soft PCM volume if needed. */
-	if (pdevinfo->playas >= 0) {
-		ctl = NULL;
-		if ((mask & SOUND_MASK_PCM) == 0 ||
-		    (devinfo->quirks & HDAA_QUIRK_SOFTPCMVOL)) {
-			softpcmvol = 1;
-			mask |= SOUND_MASK_PCM;
-		} else {
-			softpcmvol = 0;
-			i = 0;
-			while ((ctl = hdaa_audio_ctl_each(devinfo, &i)) != NULL) {
-				if (ctl->enable == 0)
-					continue;
-				if (ctl->widget->bindas != pdevinfo->playas &&
-				    (ctl->widget->bindas != -2 || pdevinfo->index != 0))
-					continue;
-				if (!(ctl->ossmask & SOUND_MASK_PCM))
-					continue;
-				if (ctl->step > 0)
-					break;
-			}
-		}
-
-		if (softpcmvol == 1 || ctl == NULL) {
-			pcm_setflags(pdevinfo->dev, pcm_getflags(pdevinfo->dev) | SD_F_SOFTPCMVOL);
-			HDA_BOOTVERBOSE(
-				device_printf(pdevinfo->dev,
-				    "%s Soft PCM volume\n",
-				    (softpcmvol == 1) ? "Forcing" : "Enabling");
-			);
-		}
-	}
-
-	/* Declare master volume if needed. */
-	if (pdevinfo->playas >= 0) {
-		if ((mask & (SOUND_MASK_VOLUME | SOUND_MASK_PCM)) ==
-		    SOUND_MASK_PCM) {
-			mask |= SOUND_MASK_VOLUME;
-			mix_setparentchild(m, SOUND_MIXER_VOLUME,
-			    SOUND_MASK_PCM);
-			mix_setrealdev(m, SOUND_MIXER_VOLUME,
-			    SOUND_MIXER_NONE);
-			HDA_BOOTVERBOSE(
-				device_printf(pdevinfo->dev,
-				    "Forcing master volume with PCM\n");
-			);
-		}
-	}
-
 	recmask &= (1 << SOUND_MIXER_NRDEVICES) - 1;
 	mask &= (1 << SOUND_MIXER_NRDEVICES) - 1;
+	pdevinfo->ossmask = mask;
 
 	mix_setrecdevs(m, recmask);
 	mix_setdevs(m, mask);
@@ -1597,6 +1920,261 @@
 	return (0);
 }
 
+/*
+ * Update amplification per pdevinfo per ossdev, calculate summary coefficient
+ * and write it to codec, update *left and *right to reflect remaining error.
+ */
+static void
+hdaa_audio_ctl_dev_set(struct hdaa_audio_ctl *ctl, int ossdev,
+    int mute, int *left, int *right)
+{
+	int i, zleft, zright, sleft, sright, smute, lval, rval;
+
+	ctl->devleft[ossdev] = *left;
+	ctl->devright[ossdev] = *right;
+	ctl->devmute[ossdev] = mute;
+	smute = sleft = sright = zleft = zright = 0;
+	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+		sleft += ctl->devleft[i];
+		sright += ctl->devright[i];
+		smute |= ctl->devmute[i];
+		if (i == ossdev)
+			continue;
+		zleft += ctl->devleft[i];
+		zright += ctl->devright[i];
+	}
+	lval = QDB2VAL(ctl, sleft);
+	rval = QDB2VAL(ctl, sright);
+	hdaa_audio_ctl_amp_set(ctl, smute, lval, rval);
+	*left -= VAL2QDB(ctl, lval) - VAL2QDB(ctl, QDB2VAL(ctl, zleft));
+	*right -= VAL2QDB(ctl, rval) - VAL2QDB(ctl, QDB2VAL(ctl, zright));
+}
+
+/*
+ * Trace signal from source, setting volumes on the way.
+ */
+static void
+hdaa_audio_ctl_source_volume(struct hdaa_pcm_devinfo *pdevinfo,
+    int ossdev, nid_t nid, int index, int mute, int left, int right, int depth)
+{
+	struct hdaa_devinfo *devinfo = pdevinfo->devinfo;
+	struct hdaa_widget *w, *wc;
+	struct hdaa_audio_ctl *ctl;
+	int i, j, conns = 0;
+
+	if (depth > HDA_PARSE_MAXDEPTH)
+		return;
+
+	w = hdaa_widget_get(devinfo, nid);
+	if (w == NULL || w->enable == 0)
+		return;
+
+	/* Count number of active inputs. */
+	if (depth > 0) {
+		for (j = 0; j < w->nconns; j++) {
+			if (!w->connsenable[j])
+				continue;
+			conns++;
+		}
+	}
+
+	/* If this is not a first step - use input mixer.
+	   Pins have common input ctl so care must be taken. */
+	if (depth > 0 && (conns == 1 ||
+	    w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)) {
+		ctl = hdaa_audio_ctl_amp_get(devinfo, w->nid, HDAA_CTL_IN,
+		    index, 1);
+		if (ctl)
+			hdaa_audio_ctl_dev_set(ctl, ossdev, mute, &left, &right);
+	}
+
+	/* If widget has own ossdev - not traverse it.
+	   It will be traversed on it's own. */
+	if (w->ossdev >= 0 && depth > 0)
+		return;
+
+	/* We must not traverse pin */
+	if ((w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT ||
+	    w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) &&
+	    depth > 0)
+		return;
+
+	/*
+	 * If signals mixed, we can't assign controls farther.
+	 * Ignore this on depth zero. Caller must knows why.
+	 */
+	if (conns > 1 &&
+	    (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER ||
+	     w->selconn != index))
+		return;
+
+	ctl = hdaa_audio_ctl_amp_get(devinfo, w->nid, HDAA_CTL_OUT, -1, 1);
+	if (ctl)
+		hdaa_audio_ctl_dev_set(ctl, ossdev, mute, &left, &right);
+
+	for (i = devinfo->startnode; i < devinfo->endnode; i++) {
+		wc = hdaa_widget_get(devinfo, i);
+		if (wc == NULL || wc->enable == 0)
+			continue;
+		for (j = 0; j < wc->nconns; j++) {
+			if (wc->connsenable[j] && wc->conns[j] == nid) {
+				hdaa_audio_ctl_source_volume(pdevinfo, ossdev,
+				    wc->nid, j, mute, left, right, depth + 1);
+			}
+		}
+	}
+	return;
+}
+
+/*
+ * Trace signal from destination, setting volumes on the way.
+ */
+static void
+hdaa_audio_ctl_dest_volume(struct hdaa_pcm_devinfo *pdevinfo,
+    int ossdev, nid_t nid, int index, int mute, int left, int right, int depth)
+{
+	struct hdaa_devinfo *devinfo = pdevinfo->devinfo;
+	struct hdaa_audio_as *as = devinfo->as;
+	struct hdaa_widget *w, *wc;
+	struct hdaa_audio_ctl *ctl;
+	int i, j, consumers, cleft, cright;
+
+	if (depth > HDA_PARSE_MAXDEPTH)
+		return;
+
+	w = hdaa_widget_get(devinfo, nid);
+	if (w == NULL || w->enable == 0)
+		return;
+
+	if (depth > 0) {
+		/* If this node produce output for several consumers,
+		   we can't touch it. */
+		consumers = 0;
+		for (i = devinfo->startnode; i < devinfo->endnode; i++) {
+			wc = hdaa_widget_get(devinfo, i);
+			if (wc == NULL || wc->enable == 0)
+				continue;
+			for (j = 0; j < wc->nconns; j++) {
+				if (wc->connsenable[j] && wc->conns[j] == nid)
+					consumers++;
+			}
+		}
+		/* The only exception is if real HP redirection is configured
+		   and this is a duplication point.
+		   XXX: Actually exception is not completely correct.
+		   XXX: Duplication point check is not perfect. */
+		if ((consumers == 2 && (w->bindas < 0 ||
+		    as[w->bindas].hpredir < 0 || as[w->bindas].fakeredir ||
+		    (w->bindseqmask & (1 << 15)) == 0)) ||
+		    consumers > 2)
+			return;
+
+		/* Else use it's output mixer. */
+		ctl = hdaa_audio_ctl_amp_get(devinfo, w->nid,
+		    HDAA_CTL_OUT, -1, 1);
+		if (ctl)
+			hdaa_audio_ctl_dev_set(ctl, ossdev, mute, &left, &right);
+	}
+
+	/* We must not traverse pin */
+	if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
+	    depth > 0)
+		return;
+
+	for (i = 0; i < w->nconns; i++) {
+		if (w->connsenable[i] == 0)
+			continue;
+		if (index >= 0 && i != index)
+			continue;
+		cleft = left;
+		cright = right;
+		ctl = hdaa_audio_ctl_amp_get(devinfo, w->nid,
+		    HDAA_CTL_IN, i, 1);
+		if (ctl)
+			hdaa_audio_ctl_dev_set(ctl, ossdev, mute, &cleft, &cright);
+		hdaa_audio_ctl_dest_volume(pdevinfo, ossdev, w->conns[i], -1,
+		    mute, cleft, cright, depth + 1);
+	}
+}
+
+/*
+ * Set volumes for the specified pdevinfo and ossdev.
+ */
+static void
+hdaa_audio_ctl_dev_volume(struct hdaa_pcm_devinfo *pdevinfo, unsigned dev)
+{
+	struct hdaa_devinfo *devinfo = pdevinfo->devinfo;
+	struct hdaa_widget *w, *cw;
+	uint32_t mute;
+	int lvol, rvol;
+	int i, j;
+
+	mute = 0;
+	if (pdevinfo->left[dev] == 0) {
+		mute |= HDAA_AMP_MUTE_LEFT;
+		lvol = -4000;
+	} else
+		lvol = ((pdevinfo->maxamp[dev] - pdevinfo->minamp[dev]) *
+		    pdevinfo->left[dev] + 50) / 100 + pdevinfo->minamp[dev];
+	if (pdevinfo->right[dev] == 0) {
+		mute |= HDAA_AMP_MUTE_RIGHT;
+		rvol = -4000;
+	} else
+		rvol = ((pdevinfo->maxamp[dev] - pdevinfo->minamp[dev]) *
+		    pdevinfo->right[dev] + 50) / 100 + pdevinfo->minamp[dev];
+	for (i = devinfo->startnode; i < devinfo->endnode; i++) {
+		w = hdaa_widget_get(devinfo, i);
+		if (w == NULL || w->enable == 0)
+			continue;
+		if (w->bindas < 0 && pdevinfo->index != 0)
+			continue;
+		if (w->bindas != pdevinfo->playas &&
+		    w->bindas != pdevinfo->recas)
+			continue;
+		if (dev == SOUND_MIXER_RECLEV &&
+		    w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) {
+			hdaa_audio_ctl_dest_volume(pdevinfo, dev,
+			    w->nid, -1, mute, lvol, rvol, 0);
+			continue;
+		}
+		if (dev == SOUND_MIXER_VOLUME &&
+		    w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
+		    devinfo->as[w->bindas].dir == HDAA_CTL_OUT) {
+			hdaa_audio_ctl_dest_volume(pdevinfo, dev,
+			    w->nid, -1, mute, lvol, rvol, 0);
+			continue;
+		}
+		if (dev == SOUND_MIXER_IGAIN &&
+		    w->pflags & HDAA_ADC_MONITOR) {
+			for (j = 0; j < w->nconns; j++) {
+				if (!w->connsenable[j])
+				    continue;
+				cw = hdaa_widget_get(devinfo, w->conns[j]);
+				if (cw == NULL || cw->enable == 0)
+				    continue;
+				if (cw->bindas == -1)
+				    continue;
+				if (cw->bindas >= 0 &&
+				    devinfo->as[cw->bindas].dir != HDAA_CTL_IN)
+					continue;
+				hdaa_audio_ctl_dest_volume(pdevinfo, dev,
+				    w->nid, j, mute, lvol, rvol, 0);
+			}
+			continue;
+		}
+		if (w->ossdev != dev)
+			continue;
+		hdaa_audio_ctl_source_volume(pdevinfo, dev,
+		    w->nid, -1, mute, lvol, rvol, 0);
+		if (dev == SOUND_MIXER_IMIX && (w->pflags & HDAA_IMIX_AS_DST))
+			hdaa_audio_ctl_dest_volume(pdevinfo, dev,
+			    w->nid, -1, mute, lvol, rvol, 0);
+	}
+}
+
+/*
+ * OSS Mixer set method.
+ */
 static int
 hdaa_audio_ctl_ossmixer_set(struct snd_mixer *m, unsigned dev,
 					unsigned left, unsigned right)
@@ -1604,12 +2182,10 @@
 	struct hdaa_pcm_devinfo *pdevinfo = mix_getdevinfo(m);
 	struct hdaa_devinfo *devinfo = pdevinfo->devinfo;
 	struct hdaa_widget *w;
-	struct hdaa_audio_ctl *ctl;
-	uint32_t mute;
-	int lvol, rvol;
-	int i, j;
+	int i;
 
 	hdaa_lock(devinfo);
+
 	/* Save new values. */
 	pdevinfo->left[dev] = left;
 	pdevinfo->right[dev] = right;
@@ -1650,39 +2226,57 @@
 	}
 
 	/* Recalculate all controls related to this OSS device. */
-	i = 0;
-	while ((ctl = hdaa_audio_ctl_each(devinfo, &i)) != NULL) {
-		if (ctl->enable == 0 ||
-		    !(ctl->ossmask & (1 << dev)))
-			continue;
-		if (!((pdevinfo->playas >= 0 &&
-		    ctl->widget->bindas == pdevinfo->playas) ||
-		    (pdevinfo->recas >= 0 &&
-		    ctl->widget->bindas == pdevinfo->recas) ||
-		    ctl->widget->bindas == -2))
-			continue;
-
-		lvol = 100;
-		rvol = 100;
-		for (j = 0; j < SOUND_MIXER_NRDEVICES; j++) {
-			if (ctl->ossmask & (1 << j)) {
-				lvol = lvol * pdevinfo->left[j] / 100;
-				rvol = rvol * pdevinfo->right[j] / 100;
-			}
-		}
-		mute = (lvol == 0) ? HDAA_AMP_MUTE_LEFT : 0;
-		mute |= (rvol == 0) ? HDAA_AMP_MUTE_RIGHT : 0;
-		lvol = (lvol * ctl->step + 50) / 100;
-		rvol = (rvol * ctl->step + 50) / 100;
-		hdaa_audio_ctl_amp_set(ctl, mute, lvol, rvol);
-	}
+	hdaa_audio_ctl_dev_volume(pdevinfo, dev);
+
 	hdaa_unlock(devinfo);
-
 	return (left | (right << 8));
 }
 
 /*
- * Commutate specified record source.
+ * Set mixer settings to our own default values:
+ * +20dB for mics, -10dB for analog vol, mute for igain, 0dB for others.
+ */
+static void
+hdaa_audio_ctl_set_defaults(struct hdaa_pcm_devinfo *pdevinfo)
+{
+	int amp, vol, dev;
+
+	for (dev = 0; dev < SOUND_MIXER_NRDEVICES; dev++) {
+		if ((pdevinfo->ossmask & (1 << dev)) == 0)
+			continue;
+
+		/* If the value was overriden, leave it as is. */
+		if (resource_int_value(device_get_name(pdevinfo->dev),
+		    device_get_unit(pdevinfo->dev), ossnames[dev], &vol) == 0)
+			continue;
+
+		vol = -1;
+		if (dev == SOUND_MIXER_OGAIN)
+			vol = 100;
+		else if (dev == SOUND_MIXER_IGAIN)
+			vol = 0;
+		else if (dev == SOUND_MIXER_MIC ||
+		    dev == SOUND_MIXER_MONITOR)
+			amp = 20 * 4;	/* +20dB */
+		else if (dev == SOUND_MIXER_VOLUME && !pdevinfo->digital)
+			amp = -10 * 4;	/* -10dB */
+		else
+			amp = 0;
+		if (vol < 0 &&
+		    (pdevinfo->maxamp[dev] - pdevinfo->minamp[dev]) <= 0) {
+			vol = 100;
+		} else if (vol < 0) {
+			vol = ((amp - pdevinfo->minamp[dev]) * 100 +
+			    (pdevinfo->maxamp[dev] - pdevinfo->minamp[dev]) / 2) /
+			    (pdevinfo->maxamp[dev] - pdevinfo->minamp[dev]);
+			vol = imin(imax(vol, 1), 100);
+		}
+		mix_set(pdevinfo->mixer, dev, vol, vol);
+	}
+}
+
+/*
+ * Recursively commutate specified record source.
  */
 static uint32_t
 hdaa_audio_ctl_recsel_comm(struct hdaa_pcm_devinfo *pdevinfo, uint32_t src, nid_t nid, int depth)
@@ -1765,6 +2359,7 @@
 	struct hdaa_devinfo *devinfo = pdevinfo->devinfo;
 	struct hdaa_widget *w;
 	struct hdaa_audio_as *as;
+	struct hdaa_audio_ctl *ctl;
 	struct hdaa_chan *ch;
 	int i, j;
 	uint32_t ret = 0xffffffff;
@@ -1793,9 +2388,47 @@
 			    ch->io[i], 0);
 		}
 	}
-
+	if (ret == 0xffffffff)
+		ret = 0;
+
+	/*
+	 * Some controls could be shared. Reset volumes for controls
+	 * related to previously chosen devices, as they may no longer
+	 * affect the signal.
+	 */
+	i = 0;
+	while ((ctl = hdaa_audio_ctl_each(devinfo, &i)) != NULL) {
+		if (ctl->enable == 0 ||
+		    !(ctl->ossmask & pdevinfo->recsrc))
+			continue;
+		if (!((pdevinfo->playas >= 0 &&
+		    ctl->widget->bindas == pdevinfo->playas) ||
+		    (pdevinfo->recas >= 0 &&
+		    ctl->widget->bindas == pdevinfo->recas) ||
+		    (pdevinfo->index == 0 &&
+		    ctl->widget->bindas == -2)))
+			continue;
+		for (j = 0; j < SOUND_MIXER_NRDEVICES; j++) {
+			if (pdevinfo->recsrc & (1 << j)) {
+				ctl->devleft[j] = 0;
+				ctl->devright[j] = 0;
+				ctl->devmute[j] = 0;
+			}
+		}
+	}
+
+	/*
+	 * Some controls could be shared. Set volumes for controls
+	 * related to devices selected both previously and now.
+	 */
+	for (j = 0; j < SOUND_MIXER_NRDEVICES; j++) {
+		if ((ret | pdevinfo->recsrc) & (1 << j))
+			hdaa_audio_ctl_dev_volume(pdevinfo, j);
+	}
+
+	pdevinfo->recsrc = ret;
 	hdaa_unlock(devinfo);
-	return ((ret == 0xffffffff)? 0 : ret);
+	return (ret);
 }
 
 static kobj_method_t hdaa_audio_ctl_ossmixer_methods[] = {
@@ -2169,7 +2802,6 @@
 		as[i].hpredir = -1;
 		as[i].digital = 0;
 		as[i].num_chans = 1;
-		as[i].unsol = -1;
 		as[i].location = -1;
 	}
 
@@ -2226,12 +2858,11 @@
 				as[cnt].enable = 0;
 			}
 			if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) {
+				as[cnt].digital |= 0x1;
+				if (HDA_PARAM_PIN_CAP_HDMI(w->wclass.pin.cap))
+					as[cnt].digital |= 0x2;
 				if (HDA_PARAM_PIN_CAP_DP(w->wclass.pin.cap))
-					as[cnt].digital = 3;
-				else if (HDA_PARAM_PIN_CAP_HDMI(w->wclass.pin.cap))
-					as[cnt].digital = 2;
-				else
-					as[cnt].digital = 1;
+					as[cnt].digital |= 0x4;
 			}
 			if (as[cnt].location == -1) {
 				as[cnt].location =
@@ -3479,31 +4110,31 @@
 
 }
 
-#define HDA_CTL_GIVE(ctl)	((ctl)->step?1:0)
-
 /*
- * Find controls to control amplification for source.
+ * Find controls to control amplification for source and calculate possible
+ * amplification range.
  */
 static int
 hdaa_audio_ctl_source_amp(struct hdaa_devinfo *devinfo, nid_t nid, int index,
-    int ossdev, int ctlable, int depth, int need)
+    int ossdev, int ctlable, int depth, int *minamp, int *maxamp)
 {
 	struct hdaa_widget *w, *wc;
 	struct hdaa_audio_ctl *ctl;
-	int i, j, conns = 0, rneed;
+	int i, j, conns = 0, tminamp, tmaxamp, cminamp, cmaxamp, found = 0;
 
 	if (depth > HDA_PARSE_MAXDEPTH)
-		return (need);
+		return (found);
 
 	w = hdaa_widget_get(devinfo, nid);
 	if (w == NULL || w->enable == 0)
-		return (need);
+		return (found);
 
 	/* Count number of active inputs. */
 	if (depth > 0) {
 		for (j = 0; j < w->nconns; j++) {
-			if (w->connsenable[j])
-				conns++;
+			if (!w->connsenable[j])
+				continue;
+			conns++;
 		}
 	}
 
@@ -3514,81 +4145,96 @@
 		ctl = hdaa_audio_ctl_amp_get(devinfo, w->nid, HDAA_CTL_IN,
 		    index, 1);
 		if (ctl) {
-			if (HDA_CTL_GIVE(ctl) & need)
-				ctl->ossmask |= (1 << ossdev);
-			else
-				ctl->possmask |= (1 << ossdev);
-			need &= ~HDA_CTL_GIVE(ctl);
+			ctl->ossmask |= (1 << ossdev);
+			found++;
+			if (*minamp == *maxamp) {
+				*minamp += MINQDB(ctl);
+				*maxamp += MAXQDB(ctl);
+			}
 		}
 	}
 
 	/* If widget has own ossdev - not traverse it.
 	   It will be traversed on it's own. */
 	if (w->ossdev >= 0 && depth > 0)
-		return (need);
+		return (found);
 
 	/* We must not traverse pin */
 	if ((w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT ||
 	    w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) &&
 	    depth > 0)
-		return (need);
+		return (found);
 
 	/* record that this widget exports such signal, */
 	w->ossmask |= (1 << ossdev);
 
-	/* If signals mixed, we can't assign controls farther.
+	/*
+	 * If signals mixed, we can't assign controls farther.
 	 * Ignore this on depth zero. Caller must knows why.
-	 * Ignore this for static selectors if this input selected.
 	 */
-	if (conns > 1)
+	if (conns > 1 &&
+	    w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER)
 		ctlable = 0;
 
 	if (ctlable) {
 		ctl = hdaa_audio_ctl_amp_get(devinfo, w->nid, HDAA_CTL_OUT, -1, 1);
 		if (ctl) {
-			if (HDA_CTL_GIVE(ctl) & need)
-				ctl->ossmask |= (1 << ossdev);
-			else
-				ctl->possmask |= (1 << ossdev);
-			need &= ~HDA_CTL_GIVE(ctl);
-		}
-	}
-
-	rneed = 0;
+			ctl->ossmask |= (1 << ossdev);
+			found++;
+			if (*minamp == *maxamp) {
+				*minamp += MINQDB(ctl);
+				*maxamp += MAXQDB(ctl);
+			}
+		}
+	}
+
+	cminamp = cmaxamp = 0;
 	for (i = devinfo->startnode; i < devinfo->endnode; i++) {
 		wc = hdaa_widget_get(devinfo, i);
 		if (wc == NULL || wc->enable == 0)
 			continue;
 		for (j = 0; j < wc->nconns; j++) {
 			if (wc->connsenable[j] && wc->conns[j] == nid) {
-				rneed |= hdaa_audio_ctl_source_amp(devinfo,
-				    wc->nid, j, ossdev, ctlable, depth + 1, need);
+				tminamp = tmaxamp = 0;
+				found += hdaa_audio_ctl_source_amp(devinfo,
+				    wc->nid, j, ossdev, ctlable, depth + 1,
+				    &tminamp, &tmaxamp);
+				if (cminamp == 0 && cmaxamp == 0) {
+					cminamp = tminamp;
+					cmaxamp = tmaxamp;
+				} else if (tminamp != tmaxamp) {
+					cminamp = imax(cminamp, tminamp);
+					cmaxamp = imin(cmaxamp, tmaxamp);
+				}
 			}
 		}
 	}
-	rneed &= need;
-
-	return (rneed);
+	if (*minamp == *maxamp && cminamp < cmaxamp) {
+		*minamp += cminamp;
+		*maxamp += cmaxamp;
+	}
+	return (found);
 }
 
 /*
- * Find controls to control amplification for destination.
+ * Find controls to control amplification for destination and calculate
+ * possible amplification range.
  */
-static void
+static int
 hdaa_audio_ctl_dest_amp(struct hdaa_devinfo *devinfo, nid_t nid, int index,
-    int ossdev, int depth, int need)
+    int ossdev, int depth, int *minamp, int *maxamp)
 {
 	struct hdaa_audio_as *as = devinfo->as;
 	struct hdaa_widget *w, *wc;
 	struct hdaa_audio_ctl *ctl;
-	int i, j, consumers;
+	int i, j, consumers, tminamp, tmaxamp, cminamp, cmaxamp, found = 0;
 
 	if (depth > HDA_PARSE_MAXDEPTH)
-		return;
+		return (found);
 
 	w = hdaa_widget_get(devinfo, nid);
 	if (w == NULL || w->enable == 0)
-		return;
+		return (found);
 
 	if (depth > 0) {
 		/* If this node produce output for several consumers,
@@ -3611,43 +4257,58 @@
 		    as[w->bindas].hpredir < 0 || as[w->bindas].fakeredir ||
 		    (w->bindseqmask & (1 << 15)) == 0)) ||
 		    consumers > 2)
-			return;
+			return (found);
 
 		/* Else use it's output mixer. */
 		ctl = hdaa_audio_ctl_amp_get(devinfo, w->nid,
 		    HDAA_CTL_OUT, -1, 1);
 		if (ctl) {
-			if (HDA_CTL_GIVE(ctl) & need)
-				ctl->ossmask |= (1 << ossdev);
-			else
-				ctl->possmask |= (1 << ossdev);
-			need &= ~HDA_CTL_GIVE(ctl);
+			ctl->ossmask |= (1 << ossdev);
+			found++;
+			if (*minamp == *maxamp) {
+				*minamp += MINQDB(ctl);
+				*maxamp += MAXQDB(ctl);
+			}
 		}
 	}
 
 	/* We must not traverse pin */
 	if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
 	    depth > 0)
-		return;
-
+		return (found);
+
+	cminamp = cmaxamp = 0;
 	for (i = 0; i < w->nconns; i++) {
-		int tneed = need;
 		if (w->connsenable[i] == 0)
 			continue;
 		if (index >= 0 && i != index)
 			continue;
+		tminamp = tmaxamp = 0;
 		ctl = hdaa_audio_ctl_amp_get(devinfo, w->nid,
 		    HDAA_CTL_IN, i, 1);
 		if (ctl) {
-			if (HDA_CTL_GIVE(ctl) & tneed)
-				ctl->ossmask |= (1 << ossdev);
-			else
-				ctl->possmask |= (1 << ossdev);
-			tneed &= ~HDA_CTL_GIVE(ctl);
-		}
-		hdaa_audio_ctl_dest_amp(devinfo, w->conns[i], -1, ossdev,
-		    depth + 1, tneed);
-	}
+			ctl->ossmask |= (1 << ossdev);
+			found++;
+			if (*minamp == *maxamp) {
+				tminamp += MINQDB(ctl);
+				tmaxamp += MAXQDB(ctl);
+			}
+		}
+		found += hdaa_audio_ctl_dest_amp(devinfo, w->conns[i], -1, ossdev,
+		    depth + 1, &tminamp, &tmaxamp);
+		if (cminamp == 0 && cmaxamp == 0) {
+			cminamp = tminamp;
+			cmaxamp = tmaxamp;
+		} else if (tminamp != tmaxamp) {
+			cminamp = imax(cminamp, tminamp);
+			cmaxamp = imin(cmaxamp, tmaxamp);
+		}
+	}
+	if (*minamp == *maxamp && cminamp < cmaxamp) {
+		*minamp += cminamp;
+		*maxamp += cmaxamp;
+	}
+	return (found);
 }
 
 /*
@@ -3855,43 +4516,82 @@
 	hdaa_audio_trace_as_extra(devinfo);
 }
 
+/*
+ * Store in pdevinfo new data about whether and how we can control signal
+ * for OSS device to/from specified widget.
+ */
+static void
+hdaa_adjust_amp(struct hdaa_widget *w, int ossdev,
+    int found, int minamp, int maxamp)
+{
+	struct hdaa_devinfo *devinfo = w->devinfo;
+	struct hdaa_pcm_devinfo *pdevinfo;
+
+	if (w->bindas >= 0)
+		pdevinfo = devinfo->as[w->bindas].pdevinfo;
+	else
+		pdevinfo = &devinfo->devs[0];
+	if (found)
+		pdevinfo->ossmask |= (1 << ossdev);
+	if (minamp == 0 && maxamp == 0)
+		return;
+	if (pdevinfo->minamp[ossdev] == 0 && pdevinfo->maxamp[ossdev] == 0) {
+		pdevinfo->minamp[ossdev] = minamp;
+		pdevinfo->maxamp[ossdev] = maxamp;
+	} else {
+		pdevinfo->minamp[ossdev] = imax(pdevinfo->minamp[ossdev], minamp);
+		pdevinfo->maxamp[ossdev] = imin(pdevinfo->maxamp[ossdev], maxamp);
+	}
+}
+
+/*
+ * Trace signals from/to all possible sources/destionstions to find possible
+ * recording sources, OSS device control ranges and to assign controls.
+ */
 static void
 hdaa_audio_assign_mixers(struct hdaa_devinfo *devinfo)
 {
 	struct hdaa_audio_as *as = devinfo->as;
-	struct hdaa_audio_ctl *ctl;
 	struct hdaa_widget *w, *cw;
-	int i, j;
+	int i, j, minamp, maxamp, found;
 
 	/* Assign mixers to the tree. */
 	for (i = devinfo->startnode; i < devinfo->endnode; i++) {
 		w = hdaa_widget_get(devinfo, i);
 		if (w == NULL || w->enable == 0)
 			continue;
+		minamp = maxamp = 0;
 		if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT ||
 		    w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET ||
 		    (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
 		    as[w->bindas].dir == HDAA_CTL_IN)) {
 			if (w->ossdev < 0)
 				continue;
-			hdaa_audio_ctl_source_amp(devinfo, w->nid, -1,
-			    w->ossdev, 1, 0, 1);
+			found = hdaa_audio_ctl_source_amp(devinfo, w->nid, -1,
+			    w->ossdev, 1, 0, &minamp, &maxamp);
+			hdaa_adjust_amp(w, w->ossdev, found, minamp, maxamp);
 		} else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) {
-			hdaa_audio_ctl_dest_amp(devinfo, w->nid, -1,
-			    SOUND_MIXER_RECLEV, 0, 1);
+			found = hdaa_audio_ctl_dest_amp(devinfo, w->nid, -1,
+			    SOUND_MIXER_RECLEV, 0, &minamp, &maxamp);
+			hdaa_adjust_amp(w, SOUND_MIXER_RECLEV, found, minamp, maxamp);
 		} else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
 		    as[w->bindas].dir == HDAA_CTL_OUT) {
-			hdaa_audio_ctl_dest_amp(devinfo, w->nid, -1,
-			    SOUND_MIXER_VOLUME, 0, 1);
+			found = hdaa_audio_ctl_dest_amp(devinfo, w->nid, -1,
+			    SOUND_MIXER_VOLUME, 0, &minamp, &maxamp);
+			hdaa_adjust_amp(w, SOUND_MIXER_VOLUME, found, minamp, maxamp);
 		}
 		if (w->ossdev == SOUND_MIXER_IMIX) {
-			if (hdaa_audio_ctl_source_amp(devinfo, w->nid, -1,
-			    w->ossdev, 1, 0, 1)) {
+			minamp = maxamp = 0;
+			found = hdaa_audio_ctl_source_amp(devinfo, w->nid, -1,
+			    w->ossdev, 1, 0, &minamp, &maxamp);
+			if (minamp == maxamp) {
 				/* If we are unable to control input monitor
 				   as source - try to control it as destination. */
-				hdaa_audio_ctl_dest_amp(devinfo, w->nid, -1,
-				    w->ossdev, 0, 1);
+				found += hdaa_audio_ctl_dest_amp(devinfo, w->nid, -1,
+				    w->ossdev, 0, &minamp, &maxamp);
+				w->pflags |= HDAA_IMIX_AS_DST;
 			}
+			hdaa_adjust_amp(w, w->ossdev, found, minamp, maxamp);
 		}
 		if (w->pflags & HDAA_ADC_MONITOR) {
 			for (j = 0; j < w->nconns; j++) {
@@ -3905,17 +4605,15 @@
 				if (cw->bindas >= 0 &&
 				    as[cw->bindas].dir != HDAA_CTL_IN)
 					continue;
-				hdaa_audio_ctl_dest_amp(devinfo,
-				    w->nid, j, SOUND_MIXER_IGAIN, 0, 1);
+				minamp = maxamp = 0;
+				found = hdaa_audio_ctl_dest_amp(devinfo,
+				    w->nid, j, SOUND_MIXER_IGAIN, 0,
+				    &minamp, &maxamp);
+				hdaa_adjust_amp(w, SOUND_MIXER_IGAIN,
+				    found, minamp, maxamp);
 			}
 		}
 	}
-	/* Treat unrequired as possible. */
-	i = 0;
-	while ((ctl = hdaa_audio_ctl_each(devinfo, &i)) != NULL) {
-		if (ctl->ossmask == 0)
-			ctl->ossmask = ctl->possmask;
-	}
 }
 
 static void
@@ -4183,6 +4881,7 @@
 	ch->bit32 = 0;
 	ch->pcmrates[0] = 48000;
 	ch->pcmrates[1] = 0;
+	ch->stripecap = 0xff;
 
 	ret = 0;
 	channels = 0;
@@ -4225,6 +4924,7 @@
 			pcmcap &= w->param.supp_pcm_size_rate;
 		}
 		ch->io[ret++] = as[ch->as].dacs[ch->asindex][i];
+		ch->stripecap &= w->wclass.conv.stripecap;
 		/* Do not count redirection pin/dac channels. */
 		if (i == 15 && as[ch->as].hpredir >= 0)
 			continue;
@@ -4261,12 +4961,12 @@
 				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)
@@ -4277,21 +4977,51 @@
 				if (ch->bit32)
 					ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 2, 0);
 			}
-			if (channels == 4 || /* Any 4-channel */
-			    pinset == 0x0007 || /* 5.1 */
-			    pinset == 0x0013 || /* 5.1 */
-			    pinset == 0x0017) {  /* 7.1 */
+			if (channels >= 3 && !onlystereo) {
+				ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 3, 0);
+				if (ch->bit32)
+					ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 3, 0);
+				ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 3, 1);
+				if (ch->bit32)
+					ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 3, 1);
+			}
+			if (channels >= 4) {
 				ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 4, 0);
 				if (ch->bit32)
 					ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 4, 0);
+				if (!onlystereo) {
+					ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 4, 1);
+					if (ch->bit32)
+						ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 4, 1);
+				}
 			}
-			if (channels == 6 || /* Any 6-channel */
-			    pinset == 0x0017) {  /* 7.1 */
+			if (channels >= 5 && !onlystereo) {
+				ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 5, 0);
+				if (ch->bit32)
+					ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 5, 0);
+				ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 5, 1);
+				if (ch->bit32)
+					ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 5, 1);
+			}
+			if (channels >= 6) {
 				ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 6, 1);
 				if (ch->bit32)
 					ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 6, 1);
+				if (!onlystereo) {
+					ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 6, 0);
+					if (ch->bit32)
+						ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 6, 0);
+				}
 			}
-			if (channels == 8) { /* Any 8-channel */
+			if (channels >= 7 && !onlystereo) {
+				ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 7, 0);
+				if (ch->bit32)
+					ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 7, 0);
+				ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 7, 1);
+				if (ch->bit32)
+					ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 7, 1);
+			}
+			if (channels >= 8) {
 				ch->fmtlist[i++] = SND_FORMAT(AFMT_S16_LE, 8, 1);
 				if (ch->bit32)
 					ch->fmtlist[i++] = SND_FORMAT(AFMT_S32_LE, 8, 1);
@@ -4299,6 +5029,10 @@
 		}
 		if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(fmtcap)) {
 			ch->fmtlist[i++] = SND_FORMAT(AFMT_AC3, 2, 0);
+			if (channels >= 8) {
+				ch->fmtlist[i++] = SND_FORMAT(AFMT_AC3, 8, 0);
+				ch->fmtlist[i++] = SND_FORMAT(AFMT_AC3, 8, 1);
+			}
 		}
 		ch->fmtlist[i] = 0;
 		i = 0;
@@ -4336,7 +5070,7 @@
 }
 
 static void
-hdaa_create_pcms(struct hdaa_devinfo *devinfo)
+hdaa_prepare_pcms(struct hdaa_devinfo *devinfo)
 {
 	struct hdaa_audio_as *as = devinfo->as;
 	int i, j, k, apdev = 0, ardev = 0, dpdev = 0, drdev = 0;
@@ -4391,6 +5125,7 @@
 					continue;
 				devinfo->devs[j].playas = i;
 			}
+			as[i].pdevinfo = &devinfo->devs[j];
 			for (k = 0; k < as[i].num_chans; k++) {
 				devinfo->chans[as[i].chans[k]].pdevinfo =
 				    &devinfo->devs[j];
@@ -4399,6 +5134,13 @@
 			break;
 		}
 	}
+}
+
+static void
+hdaa_create_pcms(struct hdaa_devinfo *devinfo)
+{
+	int i;
+
 	for (i = 0; i < devinfo->num_devs; i++) {
 		struct hdaa_pcm_devinfo *pdevinfo = &devinfo->devs[i];
 
@@ -4447,9 +5189,15 @@
 				} else {
 					device_printf(pdevinfo->dev, "Unknown Ctl");
 				}
-				printf(" (OSS: %s)\n",
+				printf(" (OSS: %s)",
 				    hdaa_audio_ctl_ossmixer_mask2allname(1 << j,
 				    buf, sizeof(buf)));
+				if (pdevinfo->ossmask & (1 << j)) {
+					printf(": %+d/%+ddB\n",
+					    pdevinfo->minamp[j] / 4,
+					    pdevinfo->maxamp[j] / 4);
+				} else
+					printf("\n");
 				device_printf(pdevinfo->dev, "   |\n");
 				printed = 1;
 			}
@@ -4462,8 +5210,8 @@
 				printf("):    ");
 			if (ctl->step > 0) {
 				printf("%+d/%+ddB (%d steps)%s\n",
-				    (0 - ctl->offset) * (ctl->size + 1) / 4,
-				    (ctl->step - ctl->offset) * (ctl->size + 1) / 4,
+				    MINQDB(ctl) / 4,
+				    MAXQDB(ctl) / 4,
 				    ctl->step + 1,
 				    ctl->mute?" + mute":"");
 			} else
@@ -4584,8 +5332,18 @@
 		printf(" IN");
 	if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE)
 		printf(" OUT");
-	if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK)
-		printf(" VREFs");
+	if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) {
+		if ((w->wclass.pin.ctrl &
+		    HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK) == 0x03)
+			printf(" HBR");
+		else if ((w->wclass.pin.ctrl &
+		    HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK) != 0)
+			printf(" EPTs");
+	} else {
+		if ((w->wclass.pin.ctrl &
+		    HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK) != 0)
+			printf(" VREFs");
+	}
 	printf("\n");
 }
 
@@ -4640,7 +5398,6 @@
 static void
 hdaa_dump_nodes(struct hdaa_devinfo *devinfo)
 {
-	static char *ossname[] = SOUND_DEVICE_NAMES;
 	struct hdaa_widget *w, *cw;
 	char buf[64];
 	int i, j;
@@ -4680,7 +5437,8 @@
 			if (HDA_PARAM_AUDIO_WIDGET_CAP_PROC_WIDGET(w->param.widget_cap))
 			    printf(" PROC");
 			if (HDA_PARAM_AUDIO_WIDGET_CAP_STRIPE(w->param.widget_cap))
-			    printf(" STRIPE");
+			    printf(" STRIPE(x%d)",
+				1 << (fls(w->wclass.conv.stripecap) - 1));
 			j = HDA_PARAM_AUDIO_WIDGET_CAP_CC(w->param.widget_cap);
 			if (j == 1)
 			    printf(" STEREO");
@@ -4696,7 +5454,7 @@
 			device_printf(devinfo->dev, "            OSS: %s",
 			    hdaa_audio_ctl_ossmixer_mask2allname(w->ossmask, buf, sizeof(buf)));
 			if (w->ossdev >= 0)
-			    printf(" (%s)", ossname[w->ossdev]);
+			    printf(" (%s)", ossnames[w->ossdev]);
 			printf("\n");
 		}
 		if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT ||
@@ -4854,15 +5612,14 @@
 	int i;
 	int printed = 0;
 
-	if (pdevinfo->index != 0)
-		return;
-
 	for (i = devinfo->startnode; i < devinfo->endnode; i++) {
 		w = hdaa_widget_get(devinfo, i);
 		if (w == NULL || w->enable == 0)
 			continue;
 		if (w->ossdev != SOUND_MIXER_IMIX)
 			continue;
+		if (w->bindas != pdevinfo->recas)
+			continue;
 		if (printed == 0) {
 			printed = 1;
 			device_printf(pdevinfo->dev, "\n");
@@ -4956,9 +5713,12 @@
 				res = hda_command(dev, HDA_CMD_GET_PIN_SENSE(0,
 				    w->nid));
 			}
-			printf(" Sense: 0x%08x (%sconnected)", res,
+			printf(" Sense: 0x%08x (%sconnected%s)", res,
 			    (res & HDA_CMD_GET_PIN_SENSE_PRESENCE_DETECT) ?
-			     "" : "dis");
+			     "" : "dis",
+			    (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap) &&
+			     (res & HDA_CMD_GET_PIN_SENSE_ELD_VALID)) ?
+			      ", ELD valid" : "");
 			if (delay > 0)
 				printf(" delay %dus", delay * 10);
 		}
@@ -5048,6 +5808,10 @@
 	);
 	hdaa_audio_assign_names(devinfo);
 	HDA_BOOTHVERBOSE(
+		device_printf(dev, "Preparing PCM devices...\n");
+	);
+	hdaa_prepare_pcms(devinfo);
+	HDA_BOOTHVERBOSE(
 		device_printf(dev, "Assigning mixers to the tree...\n");
 	);
 	hdaa_audio_assign_mixers(devinfo);
@@ -5064,9 +5828,9 @@
 	);
 	hdaa_patch_direct(devinfo);
 	HDA_BOOTHVERBOSE(
-		device_printf(dev, "HP switch init...\n");
+		device_printf(dev, "Pin sense init...\n");
 	);
-	hdaa_hp_switch_init(devinfo);
+	hdaa_sense_init(devinfo);
 	HDA_BOOTHVERBOSE(
 		device_printf(dev, "Creating PCM devices...\n");
 	);
@@ -5131,9 +5895,9 @@
 	int i, j;
 
 	HDA_BOOTHVERBOSE(
-		device_printf(dev, "HP switch deinit...\n");
+		device_printf(dev, "Pin sense deinit...\n");
 	);
-	hdaa_hp_switch_deinit(devinfo);
+	hdaa_sense_deinit(devinfo);
 	free(devinfo->ctl, M_HDAA);
 	devinfo->ctl = NULL;
 	devinfo->ctlcnt = 0;
@@ -5159,7 +5923,13 @@
 		w->ossmask = 0;
 		for (j = 0; j < w->nconns; j++)
 			w->connsenable[j] = 1;
-		w->wclass.pin.config = w->wclass.pin.newconf;
+		if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
+			w->wclass.pin.config = w->wclass.pin.newconf;
+		if (w->eld != NULL) {
+			w->eld_len = 0;
+			free(w->eld, M_HDAA);
+			w->eld = NULL;
+		}
 	}
 }
 
@@ -5357,10 +6127,6 @@
 		}
 	}
 	HDA_BOOTHVERBOSE(
-		device_printf(dev, "HP switch deinit...\n");
-	);
-	hdaa_hp_switch_deinit(devinfo);
-	HDA_BOOTHVERBOSE(
 		device_printf(dev, "Power down FG"
 		    " nid=%d to the D3 state...\n",
 		    devinfo->nid);
@@ -5401,9 +6167,9 @@
 	);
 	hdaa_patch_direct(devinfo);
 	HDA_BOOTHVERBOSE(
-		device_printf(dev, "HP switch init...\n");
+		device_printf(dev, "Pin sense init...\n");
 	);
-	hdaa_hp_switch_init(devinfo);
+	hdaa_sense_init(devinfo);
 
 	hdaa_unlock(devinfo);
 	for (i = 0; i < devinfo->num_devs; i++) {
@@ -5656,12 +6422,29 @@
 hdaa_unsol_intr(device_t dev, uint32_t resp)
 {
 	struct hdaa_devinfo *devinfo = device_get_softc(dev);
-	int i, tag;
-
+	struct hdaa_widget *w;
+	int i, tag, flags;
+
+	HDA_BOOTHVERBOSE(
+		device_printf(dev, "Unsolicited response %08x\n", resp);
+	);
 	tag = resp >> 26;
-	for (i = 0; i < devinfo->ascnt; i++) {
-		if (devinfo->as[i].unsol == tag)
-			hdaa_hp_switch_handler(devinfo, i);
+	for (i = devinfo->startnode; i < devinfo->endnode; i++) {
+		w = hdaa_widget_get(devinfo, i);
+		if (w == NULL || w->enable == 0 || w->type !=
+		    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
+			continue;
+		if (w->unsol != tag)
+			continue;
+		if (HDA_PARAM_PIN_CAP_DP(w->wclass.pin.cap) ||
+		    HDA_PARAM_PIN_CAP_HDMI(w->wclass.pin.cap))
+			flags = resp & 0x03;
+		else
+			flags = 0x01;
+		if (flags & 0x01)
+			hdaa_presence_handler(w);
+		if (flags & 0x02)
+			hdaa_eld_handler(w);
 	}
 }
 
@@ -5702,9 +6485,12 @@
 	c = devinfo->chans[as->chans[0]].channels;
 	if (c == 1)
 		snprintf(buf, buflen, "mono");
-	else if (c == 2)
-		buf[0] = 0;
-	else if (as->pinset == 0x0003)
+	else if (c == 2) {
+		if (as->hpredir < 0)
+			buf[0] = 0;
+		else
+			snprintf(buf, buflen, "2.0");
+	} else if (as->pinset == 0x0003)
 		snprintf(buf, buflen, "3.1");
 	else if (as->pinset == 0x0005 || as->pinset == 0x0011)
 		snprintf(buf, buflen, "4.0");
@@ -5714,6 +6500,62 @@
 		snprintf(buf, buflen, "7.1");
 	else
 		snprintf(buf, buflen, "%dch", c);
+	if (as->hpredir >= 0)
+		strlcat(buf, "+HP", buflen);
+}
+
+static int
+hdaa_chan_type(struct hdaa_devinfo *devinfo, int asid)
+{
+	struct hdaa_audio_as *as;
+	struct hdaa_widget *w;
+	int i, t = -1, t1;
+
+	as = &devinfo->as[asid];
+	for (i = 0; i < 16; i++) {
+		w = hdaa_widget_get(devinfo, as->pins[i]);
+		if (w == NULL || w->enable == 0 || w->type !=
+		    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
+			continue;
+		t1 = HDA_CONFIG_DEFAULTCONF_DEVICE(w->wclass.pin.config);
+		if (t == -1)
+			t = t1;
+		else if (t != t1) {
+			t = -2;
+			break;
+		}
+	}
+	return (t);
+}
+
+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
@@ -5724,7 +6566,7 @@
 	struct hdaa_devinfo *devinfo = pdevinfo->devinfo;
 	char chans1[8], chans2[8];
 	char buf[128];
-	int loc1, loc2;
+	int loc1, loc2, t1, t2;
 
 	if (pdevinfo->playas >= 0)
 		loc1 = devinfo->as[pdevinfo->playas].location;
@@ -5740,12 +6582,17 @@
 		loc1 = -2;
 	chans1[0] = 0;
 	chans2[0] = 0;
-	if (pdevinfo->playas >= 0)
+	t1 = t2 = -1;
+	if (pdevinfo->playas >= 0) {
 		hdaa_chan_formula(devinfo, pdevinfo->playas,
 		    chans1, sizeof(chans1));
-	if (pdevinfo->recas >= 0)
+		t1 = hdaa_chan_type(devinfo, pdevinfo->playas);
+	}
+	if (pdevinfo->recas >= 0) {
 		hdaa_chan_formula(devinfo, pdevinfo->recas,
 		    chans2, sizeof(chans2));
+		t2 = hdaa_chan_type(devinfo, pdevinfo->recas);
+	}
 	if (chans1[0] != 0 || chans2[0] != 0) {
 		if (chans1[0] == 0 && pdevinfo->playas >= 0)
 			snprintf(chans1, sizeof(chans1), "2.0");
@@ -5754,14 +6601,24 @@
 		if (strcmp(chans1, chans2) == 0)
 			chans2[0] = 0;
 	}
-	snprintf(buf, sizeof(buf), "%s PCM (%s%s%s%s%s%s%s)",
+	if (t1 == -1)
+		t1 = t2;
+	else if (t2 == -1)
+		t2 = t1;
+	if (t1 != t2)
+		t1 = -2;
+	if (pdevinfo->digital)
+		t1 = -2;
+	snprintf(buf, sizeof(buf), "%s PCM (%s%s%s%s%s%s%s%s%s)",
 	    device_get_desc(device_get_parent(device_get_parent(dev))),
 	    loc1 >= 0 ? HDA_LOCS[loc1] : "", loc1 >= 0 ? " " : "",
-	    (pdevinfo->digital == 3)?"DisplayPort":
-	    ((pdevinfo->digital == 2)?"HDMI":
-	    ((pdevinfo->digital)?"Digital":"Analog")),
+	    (pdevinfo->digital == 0x7)?"HDMI/DP":
+	    ((pdevinfo->digital == 0x5)?"DisplayPort":
+	    ((pdevinfo->digital == 0x3)?"HDMI":
+	    ((pdevinfo->digital)?"Digital":"Analog"))),
 	    chans1[0] ? " " : "", chans1,
-	    chans2[0] ? "/" : "", chans2);
+	    chans2[0] ? "/" : "", chans2,
+	    t1 >= 0 ? " " : "", t1 >= 0 ? HDA_DEVS[t1] : "");
 	device_set_desc_copy(dev, buf);
 	return (BUS_PROBE_SPECIFIC);
 }
@@ -5773,6 +6630,7 @@
 	    (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;
 
@@ -5847,17 +6705,46 @@
 
 	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)");
+		pdevinfo->autorecsrc = 2;
+		resource_int_value(device_get_name(dev), device_get_unit(dev),
+		    "rec.autosrc", &pdevinfo->autorecsrc);
+		SYSCTL_ADD_INT(&d->rec_sysctl_ctx,
+		    SYSCTL_CHILDREN(d->rec_sysctl_tree), OID_AUTO,
+		    "autosrc", CTLTYPE_INT | CTLFLAG_RW,
+		    &pdevinfo->autorecsrc, 0,
+		    "Automatic recording source selection");
+	}
+
+	if (pdevinfo->mixer != NULL) {
+		hdaa_audio_ctl_set_defaults(pdevinfo);
+		if (pdevinfo->recas >= 0) {
+			as = &devinfo->as[pdevinfo->recas];
+			hdaa_lock(devinfo);
+			hdaa_autorecsrc_handler(as, NULL);
+			hdaa_unlock(devinfo);
+		}
 	}
 
 	snprintf(status, SND_STATUSLEN, "on %s %s",
diff -r f370dd4be562 -r 5c82a43b1344 head/sys/dev/sound/pci/hda/hdaa.h
--- a/head/sys/dev/sound/pci/hda/hdaa.h	Wed Feb 01 11:27:03 2012 +0200
+++ b/head/sys/dev/sound/pci/hda/hdaa.h	Wed Feb 01 11:27:33 2012 +0200
@@ -25,7 +25,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/sys/dev/sound/pci/hda/hdaa.h 230130 2012-01-15 13:21:36Z mav $
+ * $FreeBSD: head/sys/dev/sound/pci/hda/hdaa.h 230551 2012-01-25 20:46:10Z mav $
  */
 
 /*
@@ -74,7 +74,10 @@
 #define HDAA_AMP_LEFT_MUTED(v)	((v) & (HDAA_AMP_MUTE_LEFT))
 #define HDAA_AMP_RIGHT_MUTED(v)	(((v) & HDAA_AMP_MUTE_RIGHT) >> 1)
 
+/* Widget in playback receiving signal from recording. */
 #define HDAA_ADC_MONITOR		(1 << 0)
+/* Input mixer widget needs volume control as destination. */
+#define HDAA_IMIX_AS_DST		(2 << 0)
 
 #define HDAA_CTL_OUT		1
 #define HDAA_CTL_IN		2
@@ -82,6 +85,13 @@
 #define HDA_MAX_CONNS	32
 #define HDA_MAX_NAMELEN	32
 
+struct hdaa_audio_as;
+struct hdaa_audio_ctl;
+struct hdaa_chan;
+struct hdaa_devinfo;
+struct hdaa_pcm_devinfo;
+struct hdaa_widget;
+
 struct hdaa_widget {
 	nid_t nid;
 	int type;
@@ -93,9 +103,12 @@
 	int bindseqmask;
 	int ossdev;
 	uint32_t ossmask;
+	int unsol;
 	nid_t conns[HDA_MAX_CONNS];
 	u_char connsenable[HDA_MAX_CONNS];
 	char name[HDA_MAX_NAMELEN];
+	uint8_t	*eld;
+	int	eld_len;
 	struct hdaa_devinfo *devinfo;
 	struct {
 		uint32_t widget_cap;
@@ -112,7 +125,11 @@
 			uint32_t newconf;
 			uint32_t cap;
 			uint32_t ctrl;
+			int	connected;
 		} pin;
+		struct {
+			uint8_t	stripecap;
+		} conv;
 	} wclass;
 };
 
@@ -123,7 +140,10 @@
 	int mute, step, size, offset;
 	int left, right, forcemute;
 	uint32_t muted;
-	uint32_t ossmask, possmask;
+	uint32_t ossmask;	/* OSS devices that may affect control. */
+	int	devleft[SOUND_MIXER_NRDEVICES]; /* Left ampl in 1/4dB. */
+	int	devright[SOUND_MIXER_NRDEVICES]; /* Right ampl in 1/4dB. */
+	int	devmute[SOUND_MIXER_NRDEVICES]; /* Mutes per OSS device. */
 };
 
 /* Association is a group of pins bound for some special function. */
@@ -140,22 +160,28 @@
 	nid_t dacs[2][16];
 	int num_chans;
 	int chans[2];
-	int unsol;
 	int location;	/* Pins location, if all have the same */
 	int mixed;	/* Mixed/multiplexed recording, not multichannel. */
+	struct hdaa_pcm_devinfo *pdevinfo;
 };
 
 struct hdaa_pcm_devinfo {
 	device_t dev;
 	struct hdaa_devinfo *devinfo;
+	struct	snd_mixer *mixer;
 	int	index;
 	int	registered;
 	int	playas, recas;
 	u_char	left[SOUND_MIXER_NRDEVICES];
 	u_char	right[SOUND_MIXER_NRDEVICES];
+	int	minamp[SOUND_MIXER_NRDEVICES]; /* Minimal amps in 1/4dB. */
+	int	maxamp[SOUND_MIXER_NRDEVICES]; /* Maximal amps in 1/4dB. */
 	int	chan_size;
 	int	chan_blkcnt;
 	u_char	digital;
+	uint32_t	ossmask;	/* Mask of supported OSS devices. */
+	uint32_t	recsrc;		/* Mask of supported OSS sources. */
+	int		autorecsrc;
 };
 
 struct hdaa_devinfo {
@@ -197,9 +223,9 @@
 	struct pcmchan_caps caps;
 	struct hdaa_devinfo *devinfo;
 	struct hdaa_pcm_devinfo *pdevinfo;
-	uint32_t spd, fmt, fmtlist[16], pcmrates[16];
+	uint32_t spd, fmt, fmtlist[32], pcmrates[16];
 	uint32_t supp_stream_formats, supp_pcm_size_rate;
-	uint32_t ptr, prevptr, blkcnt, blksz;
+	uint32_t blkcnt, blksz;
 	uint32_t *dmapos;
 	uint32_t flags;
 	int dir;
@@ -210,15 +236,33 @@
 	int as;		/* Number of association. */
 	int asindex;	/* Index within association. */
 	nid_t io[16];
+	uint8_t	stripecap;	/* AND of stripecap of all ios. */
+	uint8_t	stripectl;	/* stripe to use to all ios. */
 };
 
+#define MINQDB(ctl)							\
+	((0 - (ctl)->offset) * ((ctl)->size + 1))
+
+#define MAXQDB(ctl)							\
+	(((ctl)->step - (ctl)->offset) * ((ctl)->size + 1))
+
+#define RANGEQDB(ctl)							\
+	((ctl)->step * ((ctl)->size + 1))
+
+#define VAL2QDB(ctl, val) 						\
+	(((ctl)->size + 1) * ((int)(val) - (ctl)->offset))
+
+#define QDB2VAL(ctl, qdb) 						\
+	imax(imin((((qdb) + (ctl)->size / 2 * ((qdb) > 0 ? 1 : -1)) /	\
+	 ((ctl)->size + 1) + (ctl)->offset), (ctl)->step), 0)
+
 #define hdaa_codec_id(devinfo)						\
 		(((uint32_t)hda_get_vendor_id(devinfo->dev) << 16) +	\
 		hda_get_device_id(devinfo->dev))
 
 #define hdaa_subvendor_id(devinfo)					\
-		(((uint32_t)hda_get_subvendor_id(devinfo->dev) << 16) +	\
-		hda_get_subdevice_id(devinfo->dev))
+		(((uint32_t)hda_get_subdevice_id(devinfo->dev) << 16) +	\
+		hda_get_subvendor_id(devinfo->dev))
 
 struct hdaa_widget	*hdaa_widget_get(struct hdaa_devinfo *, nid_t);
 uint32_t		hdaa_widget_pin_patch(uint32_t config, const char *str);
diff -r f370dd4be562 -r 5c82a43b1344 head/sys/dev/sound/pci/hda/hdaa_patches.c
--- a/head/sys/dev/sound/pci/hda/hdaa_patches.c	Wed Feb 01 11:27:03 2012 +0200
+++ b/head/sys/dev/sound/pci/hda/hdaa_patches.c	Wed Feb 01 11:27:33 2012 +0200
@@ -42,7 +42,7 @@
 #include <dev/sound/pci/hda/hdaa.h>
 #include <dev/sound/pci/hda/hda_reg.h>
 
-SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdaa_patches.c 230130 2012-01-15 13:21:36Z mav $");
+SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdaa_patches.c 230532 2012-01-25 09:57:34Z mav $");
 
 static const struct {
 	uint32_t model;
@@ -620,9 +620,9 @@
 		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
 		    0x7e7, 0));
 	if (id == HDA_CODEC_ALC269) {
-		if (subid == 0x104316e3 || subid == 0x1043831a ||
-		    subid == 0x1043834a || subid == 0x10438398 ||
-		    subid == 0x104383ce) {
+		if (subid == 0x16e31043 || subid == 0x831a1043 ||
+		    subid == 0x834a1043 || subid == 0x83981043 ||
+		    subid == 0x83ce1043) {
 			/*
 			 * The ditital mics on some Asus laptops produce
 			 * differential signals instead of expected stereo.
diff -r f370dd4be562 -r 5c82a43b1344 head/sys/dev/sound/pci/hda/hdac.c
--- a/head/sys/dev/sound/pci/hda/hdac.c	Wed Feb 01 11:27:03 2012 +0200
+++ b/head/sys/dev/sound/pci/hda/hdac.c	Wed Feb 01 11:27:33 2012 +0200
@@ -46,9 +46,9 @@
 #include <dev/sound/pci/hda/hda_reg.h>
 #include <dev/sound/pci/hda/hdac.h>
 
-#define HDA_DRV_TEST_REV	"20120111_0001"
+#define HDA_DRV_TEST_REV	"20120126_0002"
 
-SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdac.c 230130 2012-01-15 13:21:36Z mav $");
+SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdac.c 230807 2012-01-31 12:57:21Z mav $");
 
 #define hdac_lock(sc)		snd_mtxlock((sc)->lock)
 #define hdac_unlock(sc)		snd_mtxunlock((sc)->lock)
@@ -70,17 +70,6 @@
 #define HDAC_QUIRKS_TAB_LEN	\
 		(sizeof(hdac_quirks_tab) / sizeof(hdac_quirks_tab[0]))
 
-#define HDA_BDL_MIN	2
-#define HDA_BDL_MAX	256
-#define HDA_BDL_DEFAULT	HDA_BDL_MIN
-
-#define HDA_BLK_MIN	HDA_DMA_ALIGNMENT
-#define HDA_BLK_ALIGN	(~(HDA_BLK_MIN - 1))
-
-#define HDA_BUFSZ_MIN		4096
-#define HDA_BUFSZ_MAX		65536
-#define HDA_BUFSZ_DEFAULT	16384
-
 MALLOC_DEFINE(M_HDAC, "hdac", "HDA Controller");
 
 static const struct {
@@ -124,6 +113,17 @@
 	{ HDA_NVIDIA_MCP89_2, "NVIDIA MCP89",	0, 0 },
 	{ HDA_NVIDIA_MCP89_3, "NVIDIA MCP89",	0, 0 },
 	{ HDA_NVIDIA_MCP89_4, "NVIDIA MCP89",	0, 0 },
+	{ HDA_NVIDIA_0BE2,   "NVIDIA (0x0be2)",	0, HDAC_QUIRK_MSI },
+	{ HDA_NVIDIA_0BE3,   "NVIDIA (0x0be3)",	0, HDAC_QUIRK_MSI },
+	{ HDA_NVIDIA_0BE4,   "NVIDIA (0x0be4)",	0, HDAC_QUIRK_MSI },
+	{ HDA_NVIDIA_GT100,  "NVIDIA GT100",	0, HDAC_QUIRK_MSI },
+	{ HDA_NVIDIA_GT104,  "NVIDIA GT104",	0, HDAC_QUIRK_MSI },
+	{ HDA_NVIDIA_GT106,  "NVIDIA GT106",	0, HDAC_QUIRK_MSI },
+	{ HDA_NVIDIA_GT108,  "NVIDIA GT108",	0, HDAC_QUIRK_MSI },
+	{ HDA_NVIDIA_GT116,  "NVIDIA GT116",	0, HDAC_QUIRK_MSI },
+	{ HDA_NVIDIA_GF119,  "NVIDIA GF119",	0, 0 },
+	{ HDA_NVIDIA_GF110_1, "NVIDIA GF110",	0, HDAC_QUIRK_MSI },
+	{ HDA_NVIDIA_GF110_2, "NVIDIA GF110",	0, HDAC_QUIRK_MSI },
 	{ HDA_ATI_SB450,     "ATI SB450",	0, 0 },
 	{ HDA_ATI_SB600,     "ATI SB600",	0, 0 },
 	{ HDA_ATI_RS600,     "ATI RS600",	0, 0 },
@@ -143,12 +143,12 @@
 	{ HDA_SIS_966,       "SiS 966",		0, 0 },
 	{ HDA_ULI_M5461,     "ULI M5461",	0, 0 },
 	/* Unknown */
-	{ HDA_INTEL_ALL,  "Intel (Unknown)",	0, 0 },
-	{ HDA_NVIDIA_ALL, "NVIDIA (Unknown)",	0, 0 },
-	{ HDA_ATI_ALL,    "ATI (Unknown)",	0, 0 },
-	{ HDA_VIA_ALL,    "VIA (Unknown)",	0, 0 },
-	{ HDA_SIS_ALL,    "SiS (Unknown)",	0, 0 },
-	{ HDA_ULI_ALL,    "ULI (Unknown)",	0, 0 },
+	{ HDA_INTEL_ALL,  "Intel",		0, 0 },
+	{ HDA_NVIDIA_ALL, "NVIDIA",		0, 0 },
+	{ HDA_ATI_ALL,    "ATI",		0, 0 },
+	{ HDA_VIA_ALL,    "VIA",		0, 0 },
+	{ HDA_SIS_ALL,    "SiS",		0, 0 },
+	{ HDA_ULI_ALL,    "ULI",		0, 0 },
 };
 #define HDAC_DEVICES_LEN (sizeof(hdac_devices) / sizeof(hdac_devices[0]))
 
@@ -1006,26 +1006,27 @@
 	result = ENXIO;
 	for (i = 0; i < HDAC_DEVICES_LEN; i++) {
 		if (hdac_devices[i].model == model) {
-		    	strlcpy(desc, hdac_devices[i].desc, sizeof(desc));
-		    	result = BUS_PROBE_DEFAULT;
+			strlcpy(desc, hdac_devices[i].desc, sizeof(desc));
+			result = BUS_PROBE_DEFAULT;
 			break;
 		}
 		if (HDA_DEV_MATCH(hdac_devices[i].model, model) &&
 		    class == PCIC_MULTIMEDIA &&
 		    subclass == PCIS_MULTIMEDIA_HDA) {
-		    	strlcpy(desc, hdac_devices[i].desc, sizeof(desc));
-		    	result = BUS_PROBE_GENERIC;
+			snprintf(desc, sizeof(desc),
+			    "%s (0x%04x)",
+			    hdac_devices[i].desc, pci_get_device(dev));
+			result = BUS_PROBE_GENERIC;
 			break;
 		}
 	}
 	if (result == ENXIO && class == PCIC_MULTIMEDIA &&
 	    subclass == PCIS_MULTIMEDIA_HDA) {
-		strlcpy(desc, "Generic", sizeof(desc));
-	    	result = BUS_PROBE_GENERIC;
+		snprintf(desc, sizeof(desc), "Generic (0x%08x)", model);
+		result = BUS_PROBE_GENERIC;
 	}
 	if (result != ENXIO) {
-		strlcat(desc, " HDA Controller",
-		    sizeof(desc));
+		strlcat(desc, " HDA Controller", sizeof(desc));
 		device_set_desc_copy(dev, desc);
 	}
 
@@ -1328,10 +1329,10 @@
 }
 
 static int
-hdac_data_rate(uint16_t fmt)
+hdac_mdata_rate(uint16_t fmt)
 {
-	static const int bits[8] = { 8, 16, 20, 24, 32, 32, 32, 32 };
-	int rate;
+	static const int mbits[8] = { 8, 16, 32, 32, 32, 32, 32, 32 };
+	int rate, bits;
 
 	if (fmt & (1 << 14))
 		rate = 44100;
@@ -1339,8 +1340,24 @@
 		rate = 48000;
 	rate *= ((fmt >> 11) & 0x07) + 1;
 	rate /= ((fmt >> 8) & 0x07) + 1;
-	rate *= ((bits[(fmt >> 4) & 0x03]) * ((fmt & 0x0f) + 1) + 7) / 8;
-	return (rate);
+	bits = mbits[(fmt >> 4) & 0x03];
+	bits *= (fmt & 0x0f) + 1;
+	return (rate * bits);
+}
+
+static int
+hdac_bdata_rate(uint16_t fmt, int output)
+{
+	static const int bbits[8] = { 8, 16, 20, 24, 32, 32, 32, 32 };
+	int rate, bits;
+
+	rate = 48000;
+	rate *= ((fmt >> 11) & 0x07) + 1;
+	bits = bbits[(fmt >> 4) & 0x03];
+	bits *= (fmt & 0x0f) + 1;
+	if (!output)
+		bits = ((bits + 7) & ~0x07) + 10;
+	return (rate * bits);
 }
 
 static void
@@ -1358,7 +1375,7 @@
 		if (s->running == 0)
 			continue;
 		pollticks = ((uint64_t)hz * s->blksz) /
-		    hdac_data_rate(s->format);
+		    (hdac_mdata_rate(s->format) / 8);
 		pollticks >>= 1;
 		if (pollticks > hz)
 			pollticks = hz;
@@ -1779,11 +1796,12 @@
 }
 
 static int
-hdac_stream_alloc(device_t dev, device_t child, int dir, int format,
+hdac_stream_alloc(device_t dev, device_t child, int dir, int format, int stripe,
     uint32_t **dmapos)
 {
 	struct hdac_softc *sc = device_get_softc(dev);
-	int stream, ss;
+	nid_t cad = (uintptr_t)device_get_ivars(child);
+	int stream, ss, bw, maxbw, prevbw;
 
 	/* Look for empty stream. */
 	ss = hdac_find_stream(sc, dir, 0);
@@ -1792,6 +1810,28 @@
 	if (ss < 0)
 		return (0);
 
+	/* Check bus bandwidth. */
+	bw = hdac_bdata_rate(format, dir);
+	if (dir == 1) {
+		bw *= 1 << (sc->num_sdo - stripe);
+		prevbw = sc->sdo_bw_used;
+		maxbw = 48000 * 960 * (1 << sc->num_sdo);
+	} else {
+		prevbw = sc->codecs[cad].sdi_bw_used;
+		maxbw = 48000 * 464;
+	}
+	HDA_BOOTHVERBOSE(
+		device_printf(dev, "%dKbps of %dKbps bandwidth used%s\n",
+		    (bw + prevbw) / 1000, maxbw / 1000,
+		    bw + prevbw > maxbw ? " -- OVERFLOW!" : "");
+	);
+	if (bw + prevbw > maxbw)
+		return (0);
+	if (dir == 1)
+		sc->sdo_bw_used += bw;
+	else
+		sc->codecs[cad].sdi_bw_used += bw;
+
 	/* Allocate stream number */
 	if (ss >= sc->num_iss + sc->num_oss)
 		stream = 15 - (ss - sc->num_iss + sc->num_oss);
@@ -1803,7 +1843,9 @@
 	sc->streams[ss].dev = child;
 	sc->streams[ss].dir = dir;
 	sc->streams[ss].stream = stream;
+	sc->streams[ss].bw = bw;
 	sc->streams[ss].format = format;
+	sc->streams[ss].stripe = stripe;
 	if (dmapos != NULL) {
 		if (sc->pos_dma.dma_vaddr != NULL)
 			*dmapos = (uint32_t *)(sc->pos_dma.dma_vaddr + ss * 8);
@@ -1817,11 +1859,16 @@
 hdac_stream_free(device_t dev, device_t child, int dir, int stream)
 {
 	struct hdac_softc *sc = device_get_softc(dev);
+	nid_t cad = (uintptr_t)device_get_ivars(child);
 	int ss;
 
 	ss = hdac_find_stream(sc, dir, stream);
 	KASSERT(ss >= 0,
 	    ("Free for not allocated stream (%d/%d)\n", dir, stream));
+	if (dir == 1)
+		sc->sdo_bw_used -= sc->streams[ss].bw;
+	else
+		sc->codecs[cad].sdi_bw_used -= sc->streams[ss].bw;
 	sc->streams[ss].stream = 0;
 	sc->streams[ss].dev = NULL;
 }
@@ -1864,6 +1911,8 @@
 		ctl &= ~HDAC_SDCTL2_DIR;
 	ctl &= ~HDAC_SDCTL2_STRM_MASK;
 	ctl |= stream << HDAC_SDCTL2_STRM_SHIFT;
+	ctl &= ~HDAC_SDCTL2_STRIPE_MASK;
+	ctl |= sc->streams[ss].stripe << HDAC_SDCTL2_STRIPE_SHIFT;
 	HDAC_WRITE_1(&sc->mem, off + HDAC_SDCTL2, ctl);
 
 	HDAC_WRITE_2(&sc->mem, off + HDAC_SDFMT, sc->streams[ss].format);
@@ -1872,6 +1921,8 @@
 	ctl |= 1 << ss;
 	HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl);
 
+	HDAC_WRITE_1(&sc->mem, off + HDAC_SDSTS,
+	    HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS);
 	ctl = HDAC_READ_1(&sc->mem, off + HDAC_SDCTL0);
 	ctl |= HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE |
 	    HDAC_SDCTL_RUN;
diff -r f370dd4be562 -r 5c82a43b1344 head/sys/dev/sound/pci/hda/hdac.h
--- a/head/sys/dev/sound/pci/hda/hdac.h	Wed Feb 01 11:27:03 2012 +0200
+++ b/head/sys/dev/sound/pci/hda/hdac.h	Wed Feb 01 11:27:33 2012 +0200
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/sys/dev/sound/pci/hda/hdac.h 230130 2012-01-15 13:21:36Z mav $
+ * $FreeBSD: head/sys/dev/sound/pci/hda/hdac.h 230768 2012-01-30 09:59:33Z mav $
  */
 
 #ifndef _HDAC_H_
@@ -76,10 +76,21 @@
 #define HDA_NVIDIA_MCP79_2	HDA_MODEL_CONSTRUCT(NVIDIA, 0x0ac1)
 #define HDA_NVIDIA_MCP79_3	HDA_MODEL_CONSTRUCT(NVIDIA, 0x0ac2)
 #define HDA_NVIDIA_MCP79_4	HDA_MODEL_CONSTRUCT(NVIDIA, 0x0ac3)
+#define HDA_NVIDIA_0BE2		HDA_MODEL_CONSTRUCT(NVIDIA, 0x0be2)
+#define HDA_NVIDIA_0BE3		HDA_MODEL_CONSTRUCT(NVIDIA, 0x0be3)
+#define HDA_NVIDIA_0BE4		HDA_MODEL_CONSTRUCT(NVIDIA, 0x0be4)
+#define HDA_NVIDIA_GT100	HDA_MODEL_CONSTRUCT(NVIDIA, 0x0be5)
+#define HDA_NVIDIA_GT106	HDA_MODEL_CONSTRUCT(NVIDIA, 0x0be9)
+#define HDA_NVIDIA_GT108	HDA_MODEL_CONSTRUCT(NVIDIA, 0x0bea)
+#define HDA_NVIDIA_GT104	HDA_MODEL_CONSTRUCT(NVIDIA, 0x0beb)
+#define HDA_NVIDIA_GT116	HDA_MODEL_CONSTRUCT(NVIDIA, 0x0bee)
 #define HDA_NVIDIA_MCP89_1	HDA_MODEL_CONSTRUCT(NVIDIA, 0x0d94)
 #define HDA_NVIDIA_MCP89_2	HDA_MODEL_CONSTRUCT(NVIDIA, 0x0d95)
 #define HDA_NVIDIA_MCP89_3	HDA_MODEL_CONSTRUCT(NVIDIA, 0x0d96)
 #define HDA_NVIDIA_MCP89_4	HDA_MODEL_CONSTRUCT(NVIDIA, 0x0d97)
+#define HDA_NVIDIA_GF119	HDA_MODEL_CONSTRUCT(NVIDIA, 0x0e08)
+#define HDA_NVIDIA_GF110_1	HDA_MODEL_CONSTRUCT(NVIDIA, 0x0e09)
+#define HDA_NVIDIA_GF110_2	HDA_MODEL_CONSTRUCT(NVIDIA, 0x0e0c)
 #define HDA_NVIDIA_ALL		HDA_MODEL_CONSTRUCT(NVIDIA, 0xffff)
 
 /* ATI */
@@ -294,6 +305,8 @@
 #define HDA_CODEC_ALC662	HDA_CODEC_CONSTRUCT(REALTEK, 0x0662)
 #define HDA_CODEC_ALC663	HDA_CODEC_CONSTRUCT(REALTEK, 0x0663)
 #define HDA_CODEC_ALC665	HDA_CODEC_CONSTRUCT(REALTEK, 0x0665)
+#define HDA_CODEC_ALC670	HDA_CODEC_CONSTRUCT(REALTEK, 0x0670)
+#define HDA_CODEC_ALC680	HDA_CODEC_CONSTRUCT(REALTEK, 0x0680)
 #define HDA_CODEC_ALC861	HDA_CODEC_CONSTRUCT(REALTEK, 0x0861)
 #define HDA_CODEC_ALC861VD	HDA_CODEC_CONSTRUCT(REALTEK, 0x0862)
 #define HDA_CODEC_ALC880	HDA_CODEC_CONSTRUCT(REALTEK, 0x0880)
@@ -307,6 +320,18 @@
 #define HDA_CODEC_ALC899	HDA_CODEC_CONSTRUCT(REALTEK, 0x0899)
 #define HDA_CODEC_ALCXXXX	HDA_CODEC_CONSTRUCT(REALTEK, 0xffff)
 
+/* Motorola */
+#define MOTO_VENDORID		0x1057
+#define HDA_CODEC_MOTOXXXX	HDA_CODEC_CONSTRUCT(MOTO, 0xffff)
+
+/* Creative */
+#define CREATIVE_VENDORID	0x1102
+#define HDA_CODEC_CA0110	HDA_CODEC_CONSTRUCT(CREATIVE, 0x000a)
+#define HDA_CODEC_CA0110_2	HDA_CODEC_CONSTRUCT(CREATIVE, 0x000b)
+#define HDA_CODEC_SB0880	HDA_CODEC_CONSTRUCT(CREATIVE, 0x000d)
+#define HDA_CODEC_CA0132	HDA_CODEC_CONSTRUCT(CREATIVE, 0x0011)
+#define HDA_CODEC_CAXXXX	HDA_CODEC_CONSTRUCT(CREATIVE, 0xffff)
+
 /* Analog Devices */
 #define ANALOGDEVICES_VENDORID	0x11d4
 #define HDA_CODEC_AD1884A	HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x184a)
@@ -328,10 +353,14 @@
 #define HDA_CODEC_ADXXXX	HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0xffff)
 
 /* CMedia */
-#define CMEDIA_VENDORID		0x434d
-#define HDA_CODEC_CMI9880	HDA_CODEC_CONSTRUCT(CMEDIA, 0x4980)
+#define CMEDIA_VENDORID		0x13f6
+#define HDA_CODEC_CMI9880	HDA_CODEC_CONSTRUCT(CMEDIA, 0x9880)
 #define HDA_CODEC_CMIXXXX	HDA_CODEC_CONSTRUCT(CMEDIA, 0xffff)
 
+#define CMEDIA2_VENDORID	0x434d
+#define HDA_CODEC_CMI98802	HDA_CODEC_CONSTRUCT(CMEDIA2, 0x4980)
+#define HDA_CODEC_CMIXXXX2	HDA_CODEC_CONSTRUCT(CMEDIA2, 0xffff)
+
 /* Sigmatel */
 #define SIGMATEL_VENDORID	0x8384
 #define HDA_CODEC_STAC9230X	HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7612)
@@ -373,6 +402,10 @@
 #define HDA_CODEC_STAC9205D	HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a1)
 #define HDA_CODEC_STAC9204X	HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a2)
 #define HDA_CODEC_STAC9204D	HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a3)
+#define HDA_CODEC_STAC9255	HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a4)
+#define HDA_CODEC_STAC9255D	HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a5)
+#define HDA_CODEC_STAC9254	HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a6)
+#define HDA_CODEC_STAC9254D	HDA_CODEC_CONSTRUCT(SIGMATEL, 0x76a7)
 #define HDA_CODEC_STAC9220_A2	HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7880)
 #define HDA_CODEC_STAC9220_A1	HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7882)
 #define HDA_CODEC_STACXXXX	HDA_CODEC_CONSTRUCT(SIGMATEL, 0xffff)
@@ -387,10 +420,49 @@
 #define HDA_CODEC_IDT92HD73C1	HDA_CODEC_CONSTRUCT(IDT, 0x7675)
 #define HDA_CODEC_IDT92HD73E1	HDA_CODEC_CONSTRUCT(IDT, 0x7676)
 #define HDA_CODEC_IDT92HD71B8	HDA_CODEC_CONSTRUCT(IDT, 0x76b0)
+#define HDA_CODEC_IDT92HD71B8_2	HDA_CODEC_CONSTRUCT(IDT, 0x76b1)
 #define HDA_CODEC_IDT92HD71B7	HDA_CODEC_CONSTRUCT(IDT, 0x76b2)
+#define HDA_CODEC_IDT92HD71B7_2	HDA_CODEC_CONSTRUCT(IDT, 0x76b3)
+#define HDA_CODEC_IDT92HD71B6	HDA_CODEC_CONSTRUCT(IDT, 0x76b4)
+#define HDA_CODEC_IDT92HD71B6_2	HDA_CODEC_CONSTRUCT(IDT, 0x76b5)
 #define HDA_CODEC_IDT92HD71B5	HDA_CODEC_CONSTRUCT(IDT, 0x76b6)
+#define HDA_CODEC_IDT92HD71B5_2	HDA_CODEC_CONSTRUCT(IDT, 0x76b7)
+#define HDA_CODEC_IDT92HD89C3	HDA_CODEC_CONSTRUCT(IDT, 0x76c0)
+#define HDA_CODEC_IDT92HD89C2	HDA_CODEC_CONSTRUCT(IDT, 0x76c1)
+#define HDA_CODEC_IDT92HD89C1	HDA_CODEC_CONSTRUCT(IDT, 0x76c2)
+#define HDA_CODEC_IDT92HD89B3	HDA_CODEC_CONSTRUCT(IDT, 0x76c3)
+#define HDA_CODEC_IDT92HD89B2	HDA_CODEC_CONSTRUCT(IDT, 0x76c4)
+#define HDA_CODEC_IDT92HD89B1	HDA_CODEC_CONSTRUCT(IDT, 0x76c5)
+#define HDA_CODEC_IDT92HD89E3	HDA_CODEC_CONSTRUCT(IDT, 0x76c6)
+#define HDA_CODEC_IDT92HD89E2	HDA_CODEC_CONSTRUCT(IDT, 0x76c7)
+#define HDA_CODEC_IDT92HD89E1	HDA_CODEC_CONSTRUCT(IDT, 0x76c8)
+#define HDA_CODEC_IDT92HD89D3	HDA_CODEC_CONSTRUCT(IDT, 0x76c9)
+#define HDA_CODEC_IDT92HD89D2	HDA_CODEC_CONSTRUCT(IDT, 0x76ca)
+#define HDA_CODEC_IDT92HD89D1	HDA_CODEC_CONSTRUCT(IDT, 0x76cb)
+#define HDA_CODEC_IDT92HD89F3	HDA_CODEC_CONSTRUCT(IDT, 0x76cc)
+#define HDA_CODEC_IDT92HD89F2	HDA_CODEC_CONSTRUCT(IDT, 0x76cd)
+#define HDA_CODEC_IDT92HD89F1	HDA_CODEC_CONSTRUCT(IDT, 0x76ce)
+#define HDA_CODEC_IDT92HD87B1_3	HDA_CODEC_CONSTRUCT(IDT, 0x76d1)
 #define HDA_CODEC_IDT92HD83C1C	HDA_CODEC_CONSTRUCT(IDT, 0x76d4)
 #define HDA_CODEC_IDT92HD81B1C	HDA_CODEC_CONSTRUCT(IDT, 0x76d5)
+#define HDA_CODEC_IDT92HD87B2_4	HDA_CODEC_CONSTRUCT(IDT, 0x76d9)
+#define HDA_CODEC_IDT92HD93BXX	HDA_CODEC_CONSTRUCT(IDT, 0x76df)
+#define HDA_CODEC_IDT92HD91BXX	HDA_CODEC_CONSTRUCT(IDT, 0x76e0)
+#define HDA_CODEC_IDT92HD98BXX	HDA_CODEC_CONSTRUCT(IDT, 0x76e3)
+#define HDA_CODEC_IDT92HD99BXX	HDA_CODEC_CONSTRUCT(IDT, 0x76e5)
+#define HDA_CODEC_IDT92HD90BXX	HDA_CODEC_CONSTRUCT(IDT, 0x76e7)
+#define HDA_CODEC_IDT92HD66B1X5	HDA_CODEC_CONSTRUCT(IDT, 0x76e8)
+#define HDA_CODEC_IDT92HD66B2X5	HDA_CODEC_CONSTRUCT(IDT, 0x76e9)
+#define HDA_CODEC_IDT92HD66B3X5	HDA_CODEC_CONSTRUCT(IDT, 0x76ea)
+#define HDA_CODEC_IDT92HD66C1X5	HDA_CODEC_CONSTRUCT(IDT, 0x76eb)
+#define HDA_CODEC_IDT92HD66C2X5	HDA_CODEC_CONSTRUCT(IDT, 0x76ec)
+#define HDA_CODEC_IDT92HD66C3X5	HDA_CODEC_CONSTRUCT(IDT, 0x76ed)
+#define HDA_CODEC_IDT92HD66B1X3	HDA_CODEC_CONSTRUCT(IDT, 0x76ee)
+#define HDA_CODEC_IDT92HD66B2X3	HDA_CODEC_CONSTRUCT(IDT, 0x76ef)
+#define HDA_CODEC_IDT92HD66B3X3	HDA_CODEC_CONSTRUCT(IDT, 0x76f0)
+#define HDA_CODEC_IDT92HD66C1X3	HDA_CODEC_CONSTRUCT(IDT, 0x76f1)
+#define HDA_CODEC_IDT92HD66C2X3	HDA_CODEC_CONSTRUCT(IDT, 0x76f2)
+#define HDA_CODEC_IDT92HD66C3_65	HDA_CODEC_CONSTRUCT(IDT, 0x76f3)
 #define HDA_CODEC_IDTXXXX	HDA_CODEC_CONSTRUCT(IDT, 0xffff)
 
 /* Silicon Image */
@@ -484,7 +556,9 @@
 
 /* NVIDIA */
 #define HDA_CODEC_NVIDIAMCP78	HDA_CODEC_CONSTRUCT(NVIDIA, 0x0002)
-#define HDA_CODEC_NVIDIAMCP78_2	HDA_CODEC_CONSTRUCT(NVIDIA, 0x0006)
+#define HDA_CODEC_NVIDIAMCP78_2	HDA_CODEC_CONSTRUCT(NVIDIA, 0x0003)
+#define HDA_CODEC_NVIDIAMCP78_3	HDA_CODEC_CONSTRUCT(NVIDIA, 0x0005)
+#define HDA_CODEC_NVIDIAMCP78_4	HDA_CODEC_CONSTRUCT(NVIDIA, 0x0006)
 #define HDA_CODEC_NVIDIAMCP7A	HDA_CODEC_CONSTRUCT(NVIDIA, 0x0007)
 #define HDA_CODEC_NVIDIAGT220	HDA_CODEC_CONSTRUCT(NVIDIA, 0x000a)
 #define HDA_CODEC_NVIDIAGT21X	HDA_CODEC_CONSTRUCT(NVIDIA, 0x000b)
@@ -494,6 +568,10 @@
 #define HDA_CODEC_NVIDIAMCP73	HDA_CODEC_CONSTRUCT(NVIDIA, 0x8001)
 #define HDA_CODEC_NVIDIAXXXX	HDA_CODEC_CONSTRUCT(NVIDIA, 0xffff)
 
+/* Chrontel */
+#define CHRONTEL_VENDORID	0x17e8
+#define HDA_CODEC_CHXXXX	HDA_CODEC_CONSTRUCT(CHRONTEL, 0xffff)
+
 /* INTEL */
 #define HDA_CODEC_INTELIP	HDA_CODEC_CONSTRUCT(INTEL, 0x0054)
 #define HDA_CODEC_INTELBL	HDA_CODEC_CONSTRUCT(INTEL, 0x2801)
@@ -510,6 +588,18 @@
  ****************************************************************************/
 
 #define HDA_DMA_ALIGNMENT	128
+
+#define HDA_BDL_MIN		2
+#define HDA_BDL_MAX		256
+#define HDA_BDL_DEFAULT		HDA_BDL_MIN
+
+#define HDA_BLK_MIN		HDA_DMA_ALIGNMENT
+#define HDA_BLK_ALIGN		(~(HDA_BLK_MIN - 1))
+
+#define HDA_BUFSZ_MIN		(HDA_BDL_MIN * HDA_BLK_MIN)
+#define HDA_BUFSZ_MAX		262144
+#define HDA_BUFSZ_DEFAULT	65536
+
 #define HDA_GPIO_MAX		8
 
 #define HDA_DEV_MATCH(fl, v)	((fl) == (v) || \
diff -r f370dd4be562 -r 5c82a43b1344 head/sys/dev/sound/pci/hda/hdac_if.m
--- a/head/sys/dev/sound/pci/hda/hdac_if.m	Wed Feb 01 11:27:03 2012 +0200
+++ b/head/sys/dev/sound/pci/hda/hdac_if.m	Wed Feb 01 11:27:33 2012 +0200
@@ -22,7 +22,7 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #
-# $FreeBSD: head/sys/dev/sound/pci/hda/hdac_if.m 230130 2012-01-15 13:21:36Z mav $
+# $FreeBSD: head/sys/dev/sound/pci/hda/hdac_if.m 230326 2012-01-19 01:55:48Z mav $
 
 #include <sys/rman.h>
 
@@ -44,6 +44,7 @@
     device_t    child;
     int         dir;
     int         format;
+    int         stripe;
     uint32_t    **dmapos;
 };
 
diff -r f370dd4be562 -r 5c82a43b1344 head/sys/dev/sound/pci/hda/hdac_private.h
--- a/head/sys/dev/sound/pci/hda/hdac_private.h	Wed Feb 01 11:27:03 2012 +0200
+++ b/head/sys/dev/sound/pci/hda/hdac_private.h	Wed Feb 01 11:27:33 2012 +0200
@@ -24,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/sys/dev/sound/pci/hda/hdac_private.h 230130 2012-01-15 13:21:36Z mav $
+ * $FreeBSD: head/sys/dev/sound/pci/hda/hdac_private.h 230326 2012-01-19 01:55:48Z mav $
  */
 
 #ifndef _HDAC_PRIVATE_H_
@@ -155,6 +155,8 @@
 	int		stream;
 	int		blksz;
 	int		running;
+	int		bw;
+	int		stripe;
 	uint16_t	format;
 };
 
@@ -206,6 +208,8 @@
 	int		unsolq_st;
 	uint32_t	unsolq[HDAC_UNSOLQ_MAX];
 
+	int			sdo_bw_used;
+
 	struct hdac_stream	*streams;
 
 	struct {
@@ -216,6 +220,7 @@
 		uint8_t		stepping_id;
 		int		pending;
 		uint32_t	response;
+		int		sdi_bw_used;
 	} codecs[HDAC_CODEC_MAX];
 };
 
diff -r f370dd4be562 -r 5c82a43b1344 head/sys/dev/sound/pci/hda/hdacc.c
--- a/head/sys/dev/sound/pci/hda/hdacc.c	Wed Feb 01 11:27:03 2012 +0200
+++ b/head/sys/dev/sound/pci/hda/hdacc.c	Wed Feb 01 11:27:33 2012 +0200
@@ -41,7 +41,7 @@
 #include <dev/sound/pci/hda/hda_reg.h>
 #include <dev/sound/pci/hda/hdac.h>
 
-SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdacc.c 230130 2012-01-15 13:21:36Z mav $");
+SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdacc.c 230574 2012-01-26 10:30:50Z mav $");
 
 struct hdacc_fg {
 	device_t	dev;
@@ -92,6 +92,8 @@
 	{ HDA_CODEC_ALC662, 0,		"Realtek ALC662" },
 	{ HDA_CODEC_ALC663, 0,		"Realtek ALC663" },
 	{ HDA_CODEC_ALC665, 0,		"Realtek ALC665" },
+	{ HDA_CODEC_ALC670, 0,		"Realtek ALC670" },
+	{ HDA_CODEC_ALC680, 0,		"Realtek ALC680" },
 	{ HDA_CODEC_ALC861, 0x0340,	"Realtek ALC660" },
 	{ HDA_CODEC_ALC861, 0,		"Realtek ALC861" },
 	{ HDA_CODEC_ALC861VD, 0,	"Realtek ALC861-VD" },
@@ -123,7 +125,12 @@
 	{ HDA_CODEC_AD1988B, 0,		"Analog Devices AD1988B" },
 	{ HDA_CODEC_AD1989A, 0,		"Analog Devices AD1989A" },
 	{ HDA_CODEC_AD1989B, 0,		"Analog Devices AD1989B" },
+	{ HDA_CODEC_CA0110, 0,		"Creative CA0110-IBG" },
+	{ HDA_CODEC_CA0110_2, 0,	"Creative CA0110-IBG" },
+	{ HDA_CODEC_CA0132, 0,		"Creative CA0132" },
+	{ HDA_CODEC_SB0880, 0,		"Creative SB0880 X-Fi" },
 	{ HDA_CODEC_CMI9880, 0,		"CMedia CMI9880" },
+	{ HDA_CODEC_CMI98802, 0,	"CMedia CMI9880" },
 	{ HDA_CODEC_CXD9872RDK, 0,	"Sigmatel CXD9872RD/K" },
 	{ HDA_CODEC_CXD9872AKD, 0,	"Sigmatel CXD9872AKD" },
 	{ HDA_CODEC_STAC9200D, 0,	"Sigmatel STAC9200D" },
@@ -148,6 +155,10 @@
 	{ HDA_CODEC_STAC9230D, 0,	"Sigmatel STAC9230D" },
 	{ HDA_CODEC_STAC9250, 0, 	"Sigmatel STAC9250" },
 	{ HDA_CODEC_STAC9251, 0, 	"Sigmatel STAC9251" },
+	{ HDA_CODEC_STAC9255, 0, 	"Sigmatel STAC9255" },
+	{ HDA_CODEC_STAC9255D, 0, 	"Sigmatel STAC9255D" },
+	{ HDA_CODEC_STAC9254, 0, 	"Sigmatel STAC9254" },
+	{ HDA_CODEC_STAC9254D, 0, 	"Sigmatel STAC9254D" },
 	{ HDA_CODEC_STAC9271X, 0,	"Sigmatel STAC9271X" },
 	{ HDA_CODEC_STAC9271D, 0,	"Sigmatel STAC9271D" },
 	{ HDA_CODEC_STAC9272X, 0,	"Sigmatel STAC9272X" },
@@ -163,11 +174,28 @@
 	{ HDA_CODEC_IDT92HD005D, 0,	"IDT 92HD005D" },
 	{ HDA_CODEC_IDT92HD206X, 0,	"IDT 92HD206X" },
 	{ HDA_CODEC_IDT92HD206D, 0,	"IDT 92HD206D" },
+	{ HDA_CODEC_IDT92HD66B1X5, 0,	"IDT 92HD66B1X5" },
+	{ HDA_CODEC_IDT92HD66B2X5, 0,	"IDT 92HD66B2X5" },
+	{ HDA_CODEC_IDT92HD66B3X5, 0,	"IDT 92HD66B3X5" },
+	{ HDA_CODEC_IDT92HD66C1X5, 0,	"IDT 92HD66C1X5" },
+	{ HDA_CODEC_IDT92HD66C2X5, 0,	"IDT 92HD66C2X5" },
+	{ HDA_CODEC_IDT92HD66C3X5, 0,	"IDT 92HD66C3X5" },
+	{ HDA_CODEC_IDT92HD66B1X3, 0,	"IDT 92HD66B1X3" },
+	{ HDA_CODEC_IDT92HD66B2X3, 0,	"IDT 92HD66B2X3" },
+	{ HDA_CODEC_IDT92HD66B3X3, 0,	"IDT 92HD66B3X3" },
+	{ HDA_CODEC_IDT92HD66C1X3, 0,	"IDT 92HD66C1X3" },
+	{ HDA_CODEC_IDT92HD66C2X3, 0,	"IDT 92HD66C2X3" },
+	{ HDA_CODEC_IDT92HD66C3_65, 0,	"IDT 92HD66C3_65" },
 	{ HDA_CODEC_IDT92HD700X, 0,	"IDT 92HD700X" },
 	{ HDA_CODEC_IDT92HD700D, 0,	"IDT 92HD700D" },
 	{ HDA_CODEC_IDT92HD71B5, 0,	"IDT 92HD71B5" },
+	{ HDA_CODEC_IDT92HD71B5_2, 0,	"IDT 92HD71B5" },
+	{ HDA_CODEC_IDT92HD71B6, 0,	"IDT 92HD71B6" },
+	{ HDA_CODEC_IDT92HD71B6_2, 0,	"IDT 92HD71B6" },
 	{ HDA_CODEC_IDT92HD71B7, 0,	"IDT 92HD71B7" },
+	{ HDA_CODEC_IDT92HD71B7_2, 0,	"IDT 92HD71B7" },
 	{ HDA_CODEC_IDT92HD71B8, 0,	"IDT 92HD71B8" },
+	{ HDA_CODEC_IDT92HD71B8_2, 0,	"IDT 92HD71B8" },
 	{ HDA_CODEC_IDT92HD73C1, 0,	"IDT 92HD73C1" },
 	{ HDA_CODEC_IDT92HD73D1, 0,	"IDT 92HD73D1" },
 	{ HDA_CODEC_IDT92HD73E1, 0,	"IDT 92HD73E1" },
@@ -177,6 +205,28 @@
 	{ HDA_CODEC_IDT92HD81B1X, 0,	"IDT 92HD81B1X" },
 	{ HDA_CODEC_IDT92HD83C1C, 0,	"IDT 92HD83C1C" },
 	{ HDA_CODEC_IDT92HD83C1X, 0,	"IDT 92HD83C1X" },
+	{ HDA_CODEC_IDT92HD87B1_3, 0,	"IDT 92HD87B1/3" },
+	{ HDA_CODEC_IDT92HD87B2_4, 0,	"IDT 92HD87B2/4" },
+	{ HDA_CODEC_IDT92HD89C3, 0,	"IDT 92HD89C3" },
+	{ HDA_CODEC_IDT92HD89C2, 0,	"IDT 92HD89C2" },
+	{ HDA_CODEC_IDT92HD89C1, 0,	"IDT 92HD89C1" },
+	{ HDA_CODEC_IDT92HD89B3, 0,	"IDT 92HD89B3" },
+	{ HDA_CODEC_IDT92HD89B2, 0,	"IDT 92HD89B2" },
+	{ HDA_CODEC_IDT92HD89B1, 0,	"IDT 92HD89B1" },
+	{ HDA_CODEC_IDT92HD89E3, 0,	"IDT 92HD89E3" },
+	{ HDA_CODEC_IDT92HD89E2, 0,	"IDT 92HD89E2" },
+	{ HDA_CODEC_IDT92HD89E1, 0,	"IDT 92HD89E1" },
+	{ HDA_CODEC_IDT92HD89D3, 0,	"IDT 92HD89D3" },
+	{ HDA_CODEC_IDT92HD89D2, 0,	"IDT 92HD89D2" },
+	{ HDA_CODEC_IDT92HD89D1, 0,	"IDT 92HD89D1" },
+	{ HDA_CODEC_IDT92HD89F3, 0,	"IDT 92HD89F3" },
+	{ HDA_CODEC_IDT92HD89F2, 0,	"IDT 92HD89F2" },
+	{ HDA_CODEC_IDT92HD89F1, 0,	"IDT 92HD89F1" },
+	{ HDA_CODEC_IDT92HD90BXX, 0,	"IDT 92HD90BXX" },
+	{ HDA_CODEC_IDT92HD91BXX, 0,	"IDT 92HD91BXX" },
+	{ HDA_CODEC_IDT92HD93BXX, 0,	"IDT 92HD93BXX" },
+	{ HDA_CODEC_IDT92HD98BXX, 0,	"IDT 92HD98BXX" },
+	{ HDA_CODEC_IDT92HD99BXX, 0,	"IDT 92HD99BXX" },
 	{ HDA_CODEC_CX20549, 0,		"Conexant CX20549 (Venice)" },
 	{ HDA_CODEC_CX20551, 0,		"Conexant CX20551 (Waikiki)" },
 	{ HDA_CODEC_CX20561, 0,		"Conexant CX20561 (Hermosa)" },
@@ -250,6 +300,8 @@
 	{ HDA_CODEC_NVIDIAMCP73, 0,	"NVIDIA MCP73" },
 	{ HDA_CODEC_NVIDIAMCP78, 0,	"NVIDIA MCP78" },
 	{ HDA_CODEC_NVIDIAMCP78_2, 0,	"NVIDIA MCP78" },
+	{ HDA_CODEC_NVIDIAMCP78_3, 0,	"NVIDIA MCP78" },
+	{ HDA_CODEC_NVIDIAMCP78_4, 0,	"NVIDIA MCP78" },
 	{ HDA_CODEC_NVIDIAMCP7A, 0,	"NVIDIA MCP7A" },
 	{ HDA_CODEC_NVIDIAGT220, 0,	"NVIDIA GT220" },
 	{ HDA_CODEC_NVIDIAGT21X, 0,	"NVIDIA GT21x" },
@@ -266,44 +318,26 @@
 	{ HDA_CODEC_SII1390, 0,		"Silicon Image SiI1390" },
 	{ HDA_CODEC_SII1392, 0,		"Silicon Image SiI1392" },
 	/* Unknown CODECs */
-	{ HDA_CODEC_ALCXXXX, 0,		"Realtek (Unknown)" },
-	{ HDA_CODEC_ADXXXX, 0,		"Analog Devices (Unknown)" },
-	{ HDA_CODEC_CSXXXX, 0,		"Cirrus Logic (Unknown)" },
-	{ HDA_CODEC_CMIXXXX, 0,		"CMedia (Unknown)" },
-	{ HDA_CODEC_STACXXXX, 0,	"Sigmatel (Unknown)" },
-	{ HDA_CODEC_SIIXXXX, 0,		"Silicon Image (Unknown)" },
-	{ HDA_CODEC_AGEREXXXX, 0,	"Lucent/Agere Systems (Unknown)" },
-	{ HDA_CODEC_CXXXXX, 0,		"Conexant (Unknown)" },
-	{ HDA_CODEC_VTXXXX, 0,		"VIA (Unknown)" },
-	{ HDA_CODEC_ATIXXXX, 0,		"ATI (Unknown)" },
-	{ HDA_CODEC_NVIDIAXXXX, 0,	"NVIDIA (Unknown)" },
-	{ HDA_CODEC_INTELXXXX, 0,	"Intel (Unknown)" },
-	{ HDA_CODEC_IDTXXXX, 0,		"IDT (Unknown)" },
+	{ HDA_CODEC_ADXXXX, 0,		"Analog Devices" },
+	{ HDA_CODEC_AGEREXXXX, 0,	"Lucent/Agere Systems" },
+	{ HDA_CODEC_ALCXXXX, 0,		"Realtek" },
+	{ HDA_CODEC_ATIXXXX, 0,		"ATI" },
+	{ HDA_CODEC_CAXXXX, 0,		"Creative" },
+	{ HDA_CODEC_CMIXXXX, 0,		"CMedia" },
+	{ HDA_CODEC_CMIXXXX2, 0,	"CMedia" },
+	{ HDA_CODEC_CSXXXX, 0,		"Cirrus Logic" },
+	{ HDA_CODEC_CXXXXX, 0,		"Conexant" },
+	{ HDA_CODEC_CHXXXX, 0,		"Chrontel" },
+	{ HDA_CODEC_IDTXXXX, 0,		"IDT" },
+	{ HDA_CODEC_INTELXXXX, 0,	"Intel" },
+	{ HDA_CODEC_MOTOXXXX, 0,	"Motorola" },
+	{ HDA_CODEC_NVIDIAXXXX, 0,	"NVIDIA" },
+	{ HDA_CODEC_SIIXXXX, 0,		"Silicon Image" },
+	{ HDA_CODEC_STACXXXX, 0,	"Sigmatel" },
+	{ HDA_CODEC_VTXXXX, 0,		"VIA" },
 };
 #define HDACC_CODECS_LEN	(sizeof(hdacc_codecs) / sizeof(hdacc_codecs[0]))
 
-
-/****************************************************************************
- * Function prototypes
- ****************************************************************************/
-
-static char *
-hdacc_codec_name(uint32_t id, uint16_t revid)
-{
-	int i;
-
-	for (i = 0; i < HDACC_CODECS_LEN; i++) {
-		if (!HDA_DEV_MATCH(hdacc_codecs[i].id, id))
-			continue;
-		if (hdacc_codecs[i].revid != 0 &&
-		    hdacc_codecs[i].revid != revid)
-			continue;
-		return (hdacc_codecs[i].name);
-	}
-
-	return ((id == 0x00000000) ? "NULL CODEC" : "Unknown CODEC");
-}
-
 static int
 hdacc_suspend(device_t dev)
 {
@@ -337,10 +371,28 @@
 {
 	uint32_t id, revid;
 	char buf[128];
+	int i;
 
 	id = ((uint32_t)hda_get_vendor_id(dev) << 16) + hda_get_device_id(dev);
 	revid = ((uint32_t)hda_get_revision_id(dev) << 8) + hda_get_stepping_id(dev);
-	snprintf(buf, sizeof(buf), "%s HDA CODEC", hdacc_codec_name(id, revid));
+
+	for (i = 0; i < HDACC_CODECS_LEN; i++) {
+		if (!HDA_DEV_MATCH(hdacc_codecs[i].id, id))
+			continue;
+		if (hdacc_codecs[i].revid != 0 &&
+		    hdacc_codecs[i].revid != revid)
+			continue;
+		break;
+	}
+	if (i < HDACC_CODECS_LEN) {
+		if ((hdacc_codecs[i].id & 0xffff) != 0xffff)
+			strlcpy(buf, hdacc_codecs[i].name, sizeof(buf));
+		else
+			snprintf(buf, sizeof(buf), "%s (0x%04x)",
+			    hdacc_codecs[i].name, hda_get_device_id(dev));
+	} else
+		snprintf(buf, sizeof(buf), "Generic (0x%04x)", id);
+	strlcat(buf, " HDA CODEC", sizeof(buf));
 	device_set_desc_copy(dev, buf);
 	return (BUS_PROBE_DEFAULT);
 }
@@ -503,13 +555,13 @@
 
 static int
 hdacc_stream_alloc(device_t dev, device_t child, int dir, int format,
-    uint32_t **dmapos)
+    int stripe, uint32_t **dmapos)
 {
 	struct hdacc_softc *codec = device_get_softc(dev);
 	int stream;
 
 	stream = HDAC_STREAM_ALLOC(device_get_parent(dev), dev,
-	    dir, format, dmapos);
+	    dir, format, stripe, dmapos);
 	if (stream > 0)
 		codec->streams[dir][stream] = child;
 	return (stream);
diff -r f370dd4be562 -r 5c82a43b1344 head/sys/dev/sound/pci/maestro3.c
--- a/head/sys/dev/sound/pci/maestro3.c	Wed Feb 01 11:27:03 2012 +0200
+++ b/head/sys/dev/sound/pci/maestro3.c	Wed Feb 01 11:27:33 2012 +0200
@@ -62,10 +62,12 @@
 #include <dev/pci/pcireg.h>
 #include <dev/pci/pcivar.h>
 
-#include <gnu/dev/sound/pci/maestro3_reg.h>
-#include <gnu/dev/sound/pci/maestro3_dsp.h>
+#define M3_MODEL 1
 
-SND_DECLARE_FILE("$FreeBSD$");
+#include <dev/sound/pci/allegro_reg.h>
+#include <dev/sound/pci/allegro_code.h>
+
+SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/maestro3.c 230401 2012-01-20 22:37:10Z pfg $");
 
 /* -------------------------------------------------------------------- */
 
@@ -96,6 +98,7 @@
 #define M3_PCHANS 4 /* create /dev/dsp0.[0-N] to use more than one */
 #define M3_RCHANS 1
 #define M3_MAXADDR ((1 << 27) - 1)
+#define M3_DEFAULT_VOL 0x6800
 
 struct sc_info;
 
@@ -376,6 +379,31 @@
 	int idx, data_bytes, dac_data;
 	int dsp_in_size, dsp_out_size, dsp_in_buf, dsp_out_buf;
 
+	struct data_word {
+	    u_int16_t addr, val;
+	} pv[] = {
+	    {CDATA_LEFT_VOLUME, M3_DEFAULT_VOL},
+	    {CDATA_RIGHT_VOLUME, M3_DEFAULT_VOL},
+	    {SRC3_DIRECTION_OFFSET, 0} ,
+	    {SRC3_DIRECTION_OFFSET + 3, 0x0000},
+	    {SRC3_DIRECTION_OFFSET + 4, 0},
+	    {SRC3_DIRECTION_OFFSET + 5, 0},
+	    {SRC3_DIRECTION_OFFSET + 6, 0},
+	    {SRC3_DIRECTION_OFFSET + 7, 0},
+	    {SRC3_DIRECTION_OFFSET + 8, 0},
+	    {SRC3_DIRECTION_OFFSET + 9, 0},
+	    {SRC3_DIRECTION_OFFSET + 10, 0x8000},
+	    {SRC3_DIRECTION_OFFSET + 11, 0xFF00},
+	    {SRC3_DIRECTION_OFFSET + 13, 0},
+	    {SRC3_DIRECTION_OFFSET + 14, 0},
+	    {SRC3_DIRECTION_OFFSET + 15, 0},
+	    {SRC3_DIRECTION_OFFSET + 16, 8},
+	    {SRC3_DIRECTION_OFFSET + 17, 50*2},
+	    {SRC3_DIRECTION_OFFSET + 18, MINISRC_BIQUAD_STAGE - 1},
+	    {SRC3_DIRECTION_OFFSET + 20, 0},
+	    {SRC3_DIRECTION_OFFSET + 21, 0}
+	};
+
 	M3_LOCK(sc);
 	idx = sc->pch_cnt; /* dac instance number, no active reuse! */
         M3_DEBUG(CHANGE, ("m3_pchan_init(dac=%d)\n", idx));
@@ -729,6 +757,33 @@
 	int idx, data_bytes, adc_data;
 	int dsp_in_size, dsp_out_size, dsp_in_buf, dsp_out_buf; 
 
+	struct data_word {
+	u_int16_t addr, val;
+	} rv[] = {
+	    {CDATA_LEFT_VOLUME, M3_DEFAULT_VOL},
+	    {CDATA_RIGHT_VOLUME, M3_DEFAULT_VOL},
+	    {SRC3_DIRECTION_OFFSET, 1},
+	    {SRC3_DIRECTION_OFFSET + 3, 0x0000},
+	    {SRC3_DIRECTION_OFFSET + 4, 0},
+	    {SRC3_DIRECTION_OFFSET + 5, 0},
+	    {SRC3_DIRECTION_OFFSET + 6, 0},
+	    {SRC3_DIRECTION_OFFSET + 7, 0},
+	    {SRC3_DIRECTION_OFFSET + 8, 0},
+	    {SRC3_DIRECTION_OFFSET + 9, 0},
+	    {SRC3_DIRECTION_OFFSET + 10, 0x8000},
+	    {SRC3_DIRECTION_OFFSET + 11, 0xFF00},
+	    {SRC3_DIRECTION_OFFSET + 13, 0},
+	    {SRC3_DIRECTION_OFFSET + 14, 0},
+	    {SRC3_DIRECTION_OFFSET + 15, 0},
+	    {SRC3_DIRECTION_OFFSET + 16, 50},
+	    {SRC3_DIRECTION_OFFSET + 17, 8},
+	    {SRC3_DIRECTION_OFFSET + 18, 0},
+	    {SRC3_DIRECTION_OFFSET + 19, 0},
+	    {SRC3_DIRECTION_OFFSET + 20, 0},
+	    {SRC3_DIRECTION_OFFSET + 21, 0},
+	    {SRC3_DIRECTION_OFFSET + 22, 0xff}
+	};
+
 	M3_LOCK(sc);
 	idx = sc->rch_cnt; /* adc instance number, no active reuse! */
         M3_DEBUG(CHANGE, ("m3_rchan_init(adc=%d)\n", idx));
@@ -1189,25 +1244,25 @@
 	m3_wr_assp_data(sc, KDATA_CURRENT_DMA,
 			KDATA_DMA_XFER0);
 	/* write kernel into code memory */
-	size = sizeof(assp_kernel_image);
+	size = sizeof(gaw_kernel_vect_code);
 	for(i = 0 ; i < size / 2; i++) {
 		m3_wr_assp_code(sc, REV_B_CODE_MEMORY_BEGIN + i,
-				assp_kernel_image[i]);
+				gaw_kernel_vect_code[i]);
 	}
 	/*
 	 * We only have this one client and we know that 0x400 is free in
 	 * our kernel's mem map, so lets just drop it there.  It seems that
 	 * the minisrc doesn't need vectors, so we won't bother with them..
 	 */
-	size = sizeof(assp_minisrc_image);
+	size = sizeof(gaw_minisrc_code_0400);
 	for(i = 0 ; i < size / 2; i++) {
-		m3_wr_assp_code(sc, 0x400 + i, assp_minisrc_image[i]);
+		m3_wr_assp_code(sc, 0x400 + i, gaw_minisrc_code_0400[i]);
 	}
 	/* write the coefficients for the low pass filter? */
-	size = sizeof(minisrc_lpf_image);
+	size = sizeof(minisrc_lpf);
 	for(i = 0; i < size / 2 ; i++) {
 		m3_wr_assp_code(sc,0x400 + MINISRC_COEF_LOC + i,
-				minisrc_lpf_image[i]);
+				minisrc_lpf[i]);
 	}
 	m3_wr_assp_code(sc, 0x400 + MINISRC_COEF_LOC + size, 0x8000);
 	/* the minisrc is the only thing on our task list */
@@ -1215,8 +1270,8 @@
 	/* init the mixer number */
 	m3_wr_assp_data(sc, KDATA_MIXER_TASK_NUMBER, 0);
 	/* extreme kernel master volume */
-	m3_wr_assp_data(sc, KDATA_DAC_LEFT_VOLUME, ARB_VOLUME);
-	m3_wr_assp_data(sc, KDATA_DAC_RIGHT_VOLUME, ARB_VOLUME);
+	m3_wr_assp_data(sc, KDATA_DAC_LEFT_VOLUME, M3_DEFAULT_VOL);
+	m3_wr_assp_data(sc, KDATA_DAC_RIGHT_VOLUME, M3_DEFAULT_VOL);
 
 	m3_amp_enable(sc);
 
diff -r f370dd4be562 -r 5c82a43b1344 head/sys/dev/sound/pcm/buffer.c
--- a/head/sys/dev/sound/pcm/buffer.c	Wed Feb 01 11:27:03 2012 +0200
+++ b/head/sys/dev/sound/pcm/buffer.c	Wed Feb 01 11:27:33 2012 +0200
@@ -37,7 +37,7 @@
 #define SND_USE_FXDIV
 #include "snd_fxdiv_gen.h"
 
-SND_DECLARE_FILE("$FreeBSD$");
+SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pcm/buffer.c 230845 2012-01-31 21:46:28Z mav $");
 
 struct snd_dbuf *
 sndbuf_create(device_t dev, char *drv, char *desc, struct pcm_channel *channel)
@@ -301,6 +301,15 @@
 	b->rl = b->bufsize;
 }
 
+void
+sndbuf_fillsilence_rl(struct snd_dbuf *b, u_int rl)
+{
+	if (b->bufsize > 0)
+		memset(sndbuf_getbuf(b), sndbuf_zerodata(b->fmt), b->bufsize);
+	b->rp = 0;
+	b->rl = min(b->bufsize, rl);
+}
+
 /**
  * @brief Reset buffer w/o flushing statistics
  *
diff -r f370dd4be562 -r 5c82a43b1344 head/sys/dev/sound/pcm/buffer.h
--- a/head/sys/dev/sound/pcm/buffer.h	Wed Feb 01 11:27:03 2012 +0200
+++ b/head/sys/dev/sound/pcm/buffer.h	Wed Feb 01 11:27:33 2012 +0200
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/sound/pcm/buffer.h 230845 2012-01-31 21:46:28Z mav $
  */
 
 #define SND_DMA(b) (sndbuf_getflags((b)) & SNDBUF_F_DMA)
@@ -74,6 +74,7 @@
 void sndbuf_reset(struct snd_dbuf *b);
 void sndbuf_clear(struct snd_dbuf *b, unsigned int length);
 void sndbuf_fillsilence(struct snd_dbuf *b);
+void sndbuf_fillsilence_rl(struct snd_dbuf *b, u_int rl);
 void sndbuf_softreset(struct snd_dbuf *b);
 void sndbuf_clearshadow(struct snd_dbuf *b);
 
diff -r f370dd4be562 -r 5c82a43b1344 head/sys/dev/sound/pcm/channel.c
--- a/head/sys/dev/sound/pcm/channel.c	Wed Feb 01 11:27:03 2012 +0200
+++ b/head/sys/dev/sound/pcm/channel.c	Wed Feb 01 11:27:33 2012 +0200
@@ -38,7 +38,7 @@
 
 #include "feeder_if.h"
 
-SND_DECLARE_FILE("$FreeBSD$");
+SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pcm/channel.c 230845 2012-01-31 21:46:28Z mav $");
 
 int report_soft_formats = 1;
 SYSCTL_INT(_hw_snd, OID_AUTO, report_soft_formats, CTLFLAG_RW,
@@ -395,24 +395,28 @@
 {
     	struct snd_dbuf *b = c->bufhard;
     	struct snd_dbuf *bs = c->bufsoft;
-	unsigned int amt;
+	unsigned int amt, want, wasfree;
 
 	CHN_LOCKASSERT(c);
 
 	if ((c->flags & CHN_F_MMAP) && !(c->flags & CHN_F_CLOSING))
 		sndbuf_acquire(bs, NULL, sndbuf_getfree(bs));
 
-	amt = sndbuf_getfree(b);
+	wasfree = sndbuf_getfree(b);
+	want = min(sndbuf_getsize(b),
+	    imax(0, sndbuf_xbytes(sndbuf_getsize(bs), bs, b) -
+	     sndbuf_getready(b)));
+	amt = min(wasfree, want);
 	if (amt > 0)
 		sndbuf_feed(bs, b, c, c->feeder, amt);
 
 	/*
 	 * Possible xruns. There should be no empty space left in buffer.
 	 */
-	if (sndbuf_getfree(b) > 0)
+	if (sndbuf_getready(b) < want)
 		c->xruns++;
 
-	if (sndbuf_getfree(b) < amt)
+	if (sndbuf_getfree(b) < wasfree)
 		chn_wakeup(c);
 }
 
@@ -721,7 +725,8 @@
 		}
 		if (c->parentchannel == NULL) {
 			if (c->direction == PCMDIR_PLAY)
-				sndbuf_fillsilence(b);
+				sndbuf_fillsilence_rl(b,
+				    sndbuf_xbytes(sndbuf_getsize(bs), bs, b));
 			if (snd_verbose > 3)
 				device_printf(c->dev,
 				    "%s(): %s starting! (%s/%s) "
@@ -1728,7 +1733,7 @@
 					int blkcnt, int blksz)
 {
 	struct snd_dbuf *b, *bs, *pb;
-	int sblksz, sblkcnt, hblksz, hblkcnt, limit = 1;
+	int sblksz, sblkcnt, hblksz, hblkcnt, limit = 0, nsblksz, nsblkcnt;
 	int ret;
 
 	CHN_LOCKASSERT(c);
@@ -1748,7 +1753,6 @@
 		return EINVAL;
 	else {
 		c->latency = latency;
-		limit = 0;
 	}
 
 	bs = c->bufsoft;
@@ -1783,19 +1787,22 @@
 		 */
 		sblksz = round_blksz(blksz, sndbuf_getalign(bs));
 		sblkcnt = round_pow2(blkcnt);
-		limit = 0;
 	}
 
 	if (c->parentchannel != NULL) {
-		pb = CHN_BUF_PARENT(c, NULL);
+		pb = c->parentchannel->bufsoft;
 		CHN_UNLOCK(c);
 		CHN_LOCK(c->parentchannel);
 		chn_notify(c->parentchannel, CHN_N_BLOCKSIZE);
 		CHN_UNLOCK(c->parentchannel);
 		CHN_LOCK(c);
-		limit = (limit != 0 && pb != NULL) ?
-		    sndbuf_xbytes(sndbuf_getsize(pb), pb, bs) : 0;
-		c->timeout = c->parentchannel->timeout;
+		if (c->direction == PCMDIR_PLAY) {
+			limit = (pb != NULL) ?
+			    sndbuf_xbytes(sndbuf_getsize(pb), pb, bs) : 0;
+		} else {
+			limit = (pb != NULL) ?
+			    sndbuf_xbytes(sndbuf_getblksz(pb), pb, bs) * 2 : 0;
+		}
 	} else {
 		hblkcnt = 2;
 		if (c->flags & CHN_F_HAS_SIZE) {
@@ -1836,21 +1843,22 @@
 		CHN_LOCK(c);
 
 		if (!CHN_EMPTY(c, children)) {
-			sblksz = round_blksz(
-			    sndbuf_xbytes(sndbuf_getsize(b) >> 1, b, bs),
+			nsblksz = round_blksz(
+			    sndbuf_xbytes(sndbuf_getblksz(b), b, bs),
 			    sndbuf_getalign(bs));
-			sblkcnt = 2;
+			nsblkcnt = sndbuf_getblkcnt(b);
+			if (c->direction == PCMDIR_PLAY) {
+				do {
+					nsblkcnt--;
+				} while (nsblkcnt >= 2 &&
+				    nsblksz * nsblkcnt >= sblksz * sblkcnt);
+				nsblkcnt++;
+			}
+			sblksz = nsblksz;
+			sblkcnt = nsblkcnt;
 			limit = 0;
-		} else if (limit != 0)
-			limit = sndbuf_xbytes(sndbuf_getsize(b), b, bs);
-
-		/*
-		 * Interrupt timeout
-		 */
-		c->timeout = ((u_int64_t)hz * sndbuf_getsize(b)) /
-		    ((u_int64_t)sndbuf_getspd(b) * sndbuf_getalign(b));
-		if (c->timeout < 1)
-			c->timeout = 1;
+		} else
+			limit = sndbuf_xbytes(sndbuf_getblksz(b), b, bs) * 2;
 	}
 
 	if (limit > CHN_2NDBUFMAXSIZE)
@@ -1887,6 +1895,16 @@
 	}
 
 	/*
+	 * Interrupt timeout
+	 */
+	c->timeout = ((u_int64_t)hz * sndbuf_getsize(bs)) /
+	    ((u_int64_t)sndbuf_getspd(bs) * sndbuf_getalign(bs));
+	if (c->parentchannel != NULL)
+		c->timeout = min(c->timeout, c->parentchannel->timeout);
+	if (c->timeout < 1)
+		c->timeout = 1;
+
+	/*
 	 * OSSv4 docs: "By default OSS will set the low water level equal
 	 * to the fragment size which is optimal in most cases."
 	 */
@@ -2000,9 +2018,10 @@
 	int ret;
 
 	/* XXX force stereo */
-	if (format & AFMT_PASSTHROUGH)
+	if ((format & AFMT_PASSTHROUGH) && AFMT_CHANNEL(format) < 2) {
 		format = SND_FORMAT(format, AFMT_PASSTHROUGH_CHANNEL,
 		    AFMT_PASSTHROUGH_EXTCHANNEL);
+	}
 
 	oldformat = c->format;
 	oldspeed = c->speed;


More information about the Zrouter-src-freebsd mailing list