Index: /trunk/src/VBox/Devices/Audio/DevHDA.cpp
===================================================================
--- /trunk/src/VBox/Devices/Audio/DevHDA.cpp	(revision 87798)
+++ /trunk/src/VBox/Devices/Audio/DevHDA.cpp	(revision 87799)
@@ -674,4 +674,5 @@
 }
 
+#endif /* IN_RING3 */
 
 /**
@@ -687,5 +688,5 @@
  * @todo r=andy Break this up into two functions?
  */
-static int hdaR3CmdSync(PPDMDEVINS pDevIns, PHDASTATE pThis, bool fLocal)
+static int hdaCmdSync(PPDMDEVINS pDevIns, PHDASTATE pThis, bool fLocal)
 {
     int rc = VINF_SUCCESS;
@@ -701,5 +702,5 @@
             rc = PDMDevHlpPhysRead(pDevIns, pThis->u64CORBBase, pThis->au32CorbBuf,
                                    RT_MIN(pThis->cbCorbBuf, sizeof(pThis->au32CorbBuf)));
-            Log(("hdaR3CmdSync/CORB: read %RGp LB %#x (%Rrc)\n", pThis->u64CORBBase, pThis->cbCorbBuf, rc));
+            Log3Func(("CORB: read %RGp LB %#x (%Rrc)\n", pThis->u64CORBBase, pThis->cbCorbBuf, rc));
             AssertRCReturn(rc, rc);
         }
@@ -713,5 +714,5 @@
             rc = PDMDevHlpPCIPhysWrite(pDevIns, pThis->u64RIRBBase, pThis->au64RirbBuf,
                                        RT_MIN(pThis->cbRirbBuf, sizeof(pThis->au64RirbBuf)));
-            Log(("hdaR3CmdSync/RIRB: phys read %RGp LB %#x (%Rrc)\n", pThis->u64RIRBBase, pThis->cbRirbBuf, rc));
+            Log3Func(("RIRB: phys read %RGp LB %#x (%Rrc)\n", pThis->u64RIRBBase, pThis->cbRirbBuf, rc));
             AssertRCReturn(rc, rc);
         }
@@ -762,17 +763,21 @@
 }
 
-/**
- * Processes the next CORB buffer command in the queue.
+#ifdef IN_RING3
+
+/**
+ * Processes the next CORB buffer command in the queue (ring-3).
  *
- * This will invoke the HDA codec verb dispatcher.
+ * Note: This function only will be called when the ring-0 version did not have an appropriate dispatcher.
+ *
+ * This will invoke the HDA codec ring-3 verb dispatcher.
  *
  * @returns VBox status code suitable for MMIO write return.
  * @param   pDevIns             The device instance.
  * @param   pThis               The shared HDA device state.
- * @param   pThisCC             The ring-3 HDA device state.
+ * @param   pThisCC             The ring-0 HDA device state.
  */
 static int hdaR3CORBCmdProcess(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER3 pThisCC)
 {
-    Log3Func(("CORB(RP:%x, WP:%x) RIRBWP:%x\n", HDA_REG(pThis, CORBRP), HDA_REG(pThis, CORBWP), HDA_REG(pThis, RIRBWP)));
+    Log3Func(("ENTER CORB(RP:%x, WP:%x) RIRBWP:%x\n", HDA_REG(pThis, CORBRP), HDA_REG(pThis, CORBWP), HDA_REG(pThis, RIRBWP)));
 
     if (!(HDA_REG(pThis, CORBCTL) & HDA_CORBCTL_DMA))
@@ -782,8 +787,9 @@
     }
 
+    /* Note: Command buffer syncing was already done in R0. */
+
     Assert(pThis->cbCorbBuf);
 
-    int rc = hdaR3CmdSync(pDevIns, pThis, true /* Sync from guest */);
-    AssertRCReturn(rc, rc);
+    int rc;
 
     /*
@@ -795,5 +801,5 @@
 
     uint32_t const cCorbEntries = RT_MIN(RT_MAX(pThis->cbCorbBuf, 1), sizeof(pThis->au32CorbBuf)) / HDA_CORB_ELEMENT_SIZE;
-    uint8_t const  corbWp       = HDA_REG(pThis, CORBWP) % cCorbEntries;
+    uint8_t  const corbWp       = HDA_REG(pThis, CORBWP) % cCorbEntries;
     uint8_t        corbRp       = HDA_REG(pThis, CORBRP);
     uint8_t        rirbWp       = HDA_REG(pThis, RIRBWP);
@@ -813,7 +819,11 @@
          */
         uint64_t uResp = 0;
-        rc = pThisCC->pCodec->pfnLookup(pThisCC->pCodec, HDA_CODEC_CMD(uCmd, 0 /* Codec index */), &uResp);
-        if (RT_FAILURE(rc))
-            LogFunc(("Codec lookup failed with rc=%Rrc\n", rc));
+        rc = pThisCC->pCodec->pfnLookup(&pThis->Codec, pThisCC->pCodec, HDA_CODEC_CMD(uCmd, 0 /* Codec index */), &uResp);
+        if (RT_FAILURE(rc)) /* Can return VERR_NOT_FOUND. */
+            Log3Func(("Lookup for codec verb %08x failed: %Rrc\n", uCmd, rc));
+
+        /* Note: No return here (as we're doing for the ring-0 version);
+                 we still need to do the interrupt handling below. */
+
         Log3Func(("Codec verb %08x -> response %016RX64\n", uCmd, uResp));
 
@@ -874,5 +884,5 @@
      * Write out the response.
      */
-    rc = hdaR3CmdSync(pDevIns, pThis, false /* Sync to guest */);
+    rc = hdaCmdSync(pDevIns, pThis, false /* Sync to guest */);
     AssertRC(rc);
 
@@ -881,4 +891,125 @@
 
 #endif /* IN_RING3 */
+
+/**
+ * Processes the next CORB buffer command in the queue (ring-0).
+ *
+ * This will invoke the HDA codec verb dispatcher.
+ *
+ * @returns VBox status code suitable for MMIO write return.
+ * @param   pDevIns             The device instance.
+ * @param   pThis               The shared HDA device state.
+ * @param   pThisCC             The ring-0 HDA device state.
+ */
+static int hdaR0CORBCmdProcess(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER0 pThisCC)
+{
+    Log3Func(("CORB(RP:%x, WP:%x) RIRBWP:%x\n", HDA_REG(pThis, CORBRP), HDA_REG(pThis, CORBWP), HDA_REG(pThis, RIRBWP)));
+
+    if (!(HDA_REG(pThis, CORBCTL) & HDA_CORBCTL_DMA))
+    {
+        LogFunc(("CORB DMA not active, skipping\n"));
+        return VINF_SUCCESS;
+    }
+
+    Assert(pThis->cbCorbBuf);
+
+    int rc = hdaCmdSync(pDevIns, pThis, true /* Sync from guest */);
+    AssertRCReturn(rc, rc);
+
+    /*
+     * Prepare local copies of relevant registers.
+     */
+    uint16_t cIntCnt = HDA_REG(pThis, RINTCNT) & 0xff;
+    if (!cIntCnt) /* 0 means 256 interrupts. */
+        cIntCnt = HDA_MAX_RINTCNT;
+
+    uint32_t const cCorbEntries = RT_MIN(RT_MAX(pThis->cbCorbBuf, 1), sizeof(pThis->au32CorbBuf)) / HDA_CORB_ELEMENT_SIZE;
+    uint8_t  const corbWp       = HDA_REG(pThis, CORBWP) % cCorbEntries;
+    uint8_t        corbRp       = HDA_REG(pThis, CORBRP);
+    uint8_t        rirbWp       = HDA_REG(pThis, RIRBWP);
+
+    /*
+     * The loop.
+     */
+    Log3Func(("START CORB(RP:%x, WP:%x) RIRBWP:%x, RINTCNT:%RU8/%RU8\n", corbRp, corbWp, rirbWp, pThis->u16RespIntCnt, cIntCnt));
+    while (corbRp != corbWp)
+    {
+        /* Fetch the command from the CORB. */
+        corbRp = (corbRp + 1) /* Advance +1 as the first command(s) are at CORBWP + 1. */ % cCorbEntries;
+        uint32_t const uCmd = pThis->au32CorbBuf[corbRp];
+
+        /*
+         * Execute the command.
+         */
+        uint64_t uResp = 0;
+        rc = pThisCC->Codec.pfnLookup(&pThis->Codec, &pThisCC->Codec, HDA_CODEC_CMD(uCmd, 0 /* Codec index */), &uResp);
+        if (RT_FAILURE(rc)) /* Can return VERR_NOT_FOUND. */
+        {
+            Log3Func(("Lookup for codec verb %08x failed: %Rrc\n", uCmd, rc));
+            return rc;
+        }
+        Log3Func(("Codec verb %08x -> response %016RX64\n", uCmd, uResp));
+
+        if (   (uResp & CODEC_RESPONSE_UNSOLICITED)
+            && !(HDA_REG(pThis, GCTL) & HDA_GCTL_UNSOL))
+        {
+            LogFunc(("Unexpected unsolicited response.\n"));
+            HDA_REG(pThis, CORBRP) = corbRp;
+            /** @todo r=andy No RIRB syncing to guest required in that case? */
+            /** @todo r=bird: Why isn't RIRBWP updated here.  The response might come
+             *        after already processing several commands, can't it?  (When you think
+             *        about it, it is bascially the same question as Andy is asking.) */
+            return VINF_SUCCESS;
+        }
+
+        /*
+         * Store the response in the RIRB.
+         */
+        AssertCompile(HDA_RIRB_SIZE == RT_ELEMENTS(pThis->au64RirbBuf));
+        rirbWp = (rirbWp + 1) % HDA_RIRB_SIZE;
+        pThis->au64RirbBuf[rirbWp] = uResp;
+
+        /*
+         * Send interrupt if needed.
+         */
+        bool fSendInterrupt = false;
+        pThis->u16RespIntCnt++;
+        if (pThis->u16RespIntCnt >= cIntCnt) /* Response interrupt count reached? */
+        {
+            pThis->u16RespIntCnt = 0; /* Reset internal interrupt response counter. */
+
+            Log3Func(("Response interrupt count reached (%RU16)\n", pThis->u16RespIntCnt));
+            fSendInterrupt = true;
+        }
+        else if (corbRp == corbWp) /* Did we reach the end of the current command buffer? */
+        {
+            Log3Func(("Command buffer empty\n"));
+            fSendInterrupt = true;
+        }
+        if (fSendInterrupt)
+        {
+            if (HDA_REG(pThis, RIRBCTL) & HDA_RIRBCTL_RINTCTL) /* Response Interrupt Control (RINTCTL) enabled? */
+            {
+                HDA_REG(pThis, RIRBSTS) |= HDA_RIRBSTS_RINTFL;
+                HDA_PROCESS_INTERRUPT(pDevIns, pThis);
+            }
+        }
+    }
+
+    /*
+     * Put register locals back.
+     */
+    Log3Func(("END CORB(RP:%x, WP:%x) RIRBWP:%x, RINTCNT:%RU8/%RU8\n", corbRp, corbWp, rirbWp, pThis->u16RespIntCnt, cIntCnt));
+    HDA_REG(pThis, CORBRP) = corbRp;
+    HDA_REG(pThis, RIRBWP) = rirbWp;
+
+    /*
+     * Write out the response.
+     */
+    rc = hdaCmdSync(pDevIns, pThis, false /* Sync to guest */);
+    AssertRC(rc);
+
+    return rc;
+}
 
 /* Register access handlers. */
@@ -1094,18 +1225,21 @@
 static VBOXSTRICTRC hdaRegWriteCORBCTL(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
 {
-#ifdef IN_RING3
     VBOXSTRICTRC rc = hdaRegWriteU8(pDevIns, pThis, iReg, u32Value);
     AssertRCSuccess(VBOXSTRICTRC_VAL(rc));
 
-    if (HDA_REG(pThis, CORBCTL) & HDA_CORBCTL_DMA) /* Start DMA engine. */
-        rc = hdaR3CORBCmdProcess(pDevIns, pThis, PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3));
+    if (HDA_REG(pThis, CORBCTL) & HDA_CORBCTL_DMA) /* DMA engine started? */
+    {
+#ifdef IN_RING3
+        /* ignore rc */ hdaR3CORBCmdProcess(pDevIns, pThis, PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3));
+
+#else
+        if (hdaR0CORBCmdProcess(pDevIns, pThis, PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER0)) == VERR_NOT_FOUND)
+            return VINF_IOM_R3_MMIO_WRITE; /* Try ring-3. */
+#endif
+    }
     else
         LogFunc(("CORB DMA not running, skipping\n"));
 
-    return rc;
-#else
-    RT_NOREF(pDevIns, pThis, iReg, u32Value);
-    return VINF_IOM_R3_MMIO_WRITE;
-#endif
+    return VINF_SUCCESS;
 }
 
@@ -1167,13 +1301,18 @@
 static VBOXSTRICTRC hdaRegWriteCORBWP(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
 {
-#ifdef IN_RING3
     VBOXSTRICTRC rc = hdaRegWriteU16(pDevIns, pThis, iReg, u32Value);
     AssertRCSuccess(VBOXSTRICTRC_VAL(rc));
 
-    return hdaR3CORBCmdProcess(pDevIns, pThis, PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3));
+#ifdef IN_RING3
+    rc = hdaR3CORBCmdProcess(pDevIns, pThis, PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3));
+    if (rc == VERR_NOT_FOUND)
+        rc = VINF_SUCCESS;
 #else
-    RT_NOREF(pDevIns, pThis, iReg, u32Value);
-    return VINF_IOM_R3_MMIO_WRITE;
+    rc = hdaR0CORBCmdProcess(pDevIns, pThis, PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER0));
+    if (rc == VERR_NOT_FOUND) /* Try ring-3. */
+        rc = VINF_IOM_R3_MMIO_WRITE;
 #endif
+
+    return rc;
 }
 
@@ -1677,5 +1816,5 @@
             pCfg->Props.cShift      = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pCfg->Props.cbSample, pCfg->Props.cChannels);
 
-            rc = hdaCodecAddStream(pThisCC->pCodec, PDMAUDIOMIXERCTL_FRONT, pCfg);
+            rc = hdaR3CodecAddStream(pThisCC->pCodec, PDMAUDIOMIXERCTL_FRONT, pCfg);
         }
 
@@ -1692,5 +1831,5 @@
             pCfg->Props.cShift      = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pCfg->Props.cbSample, pCfg->Props.cChannels);
 
-            rc = hdaCodecAddStream(pThisCC->pCodec, PDMAUDIOMIXERCTL_CENTER_LFE, pCfg);
+            rc = hdaR3CodecAddStream(pThisCC->pCodec, PDMAUDIOMIXERCTL_CENTER_LFE, pCfg);
         }
 
@@ -1706,5 +1845,5 @@
             pCfg->Props.cShift      = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pCfg->Props.cbSample, pCfg->Props.cChannels);
 
-            rc = hdaCodecAddStream(pThisCC->pCodec, PDMAUDIOMIXERCTL_REAR, pCfg);
+            rc = hdaR3CodecAddStream(pThisCC->pCodec, PDMAUDIOMIXERCTL_REAR, pCfg);
         }
 # endif /* VBOX_WITH_AUDIO_HDA_51_SURROUND */
@@ -1735,9 +1874,9 @@
     {
         case PDMAUDIORECSRC_LINE:
-            rc = hdaCodecAddStream(pThisCC->pCodec, PDMAUDIOMIXERCTL_LINE_IN, pCfg);
+            rc = hdaR3CodecAddStream(pThisCC->pCodec, PDMAUDIOMIXERCTL_LINE_IN, pCfg);
             break;
 # ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
         case PDMAUDIORECSRC_MIC:
-            rc = hdaCodecAddStream(pThisCC->pCodec, PDMAUDIOMIXERCTL_MIC_IN, pCfg);
+            rc = hdaR3CodecAddStream(pThisCC->pCodec, PDMAUDIOMIXERCTL_MIC_IN, pCfg);
             break;
 # endif
@@ -1848,5 +1987,5 @@
         && enmMixerCtl != PDMAUDIOMIXERCTL_UNKNOWN)
     {
-        rc = hdaCodecRemoveStream(pThisCC->pCodec, enmMixerCtl);
+        rc = hdaR3CodecRemoveStream(pThisCC->pCodec, enmMixerCtl);
     }
 
@@ -1956,5 +2095,5 @@
         PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
         uint64_t    uResp   = 0;
-        int rc2 = pThisCC->pCodec->pfnLookup(pThisCC->pCodec, HDA_CODEC_CMD(uCmd, 0 /* LUN */), &uResp);
+        int rc2 = pThisCC->pCodec->pfnLookup(&pThis->Codec, pThisCC->pCodec, HDA_CODEC_CMD(uCmd, 0 /* LUN */), &uResp);
         if (RT_FAILURE(rc2))
             LogFunc(("Codec lookup failed with rc2=%Rrc\n", rc2));
@@ -2903,9 +3042,5 @@
      * Reset the codec.
      */
-    if (   pThisCC->pCodec
-        && pThisCC->pCodec->pfnReset)
-    {
-        pThisCC->pCodec->pfnReset(pThisCC->pCodec);
-    }
+    hdaCodecReset(&pThis->Codec);
 
     /*
@@ -3492,5 +3627,5 @@
 
     /* Save Codec nodes states. */
-    hdaCodecSaveState(pDevIns, pThisCC->pCodec, pSSM);
+    hdaCodecSaveState(pDevIns, &pThis->Codec, pSSM);
 
     /* Save MMIO registers. */
@@ -3823,5 +3958,5 @@
      * Load Codec nodes states.
      */
-    int rc = hdaCodecLoadState(pDevIns, pThisCC->pCodec, pSSM, uVersion);
+    int rc = hdaR3CodecLoadState(pDevIns, &pThis->Codec, pThisCC->pCodec, pSSM, uVersion);
     if (RT_FAILURE(rc))
     {
@@ -4251,8 +4386,9 @@
 static DECLCALLBACK(void) hdaR3DbgInfoCodecNodes(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
 {
+    PHDASTATE   pThis   = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
     PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
 
     if (pThisCC->pCodec->pfnDbgListNodes)
-        pThisCC->pCodec->pfnDbgListNodes(pThisCC->pCodec, pHlp, pszArgs);
+        pThisCC->pCodec->pfnDbgListNodes(&pThis->Codec, pThisCC->pCodec, pHlp, pszArgs);
     else
         pHlp->pfnPrintf(pHlp, "Codec implementation doesn't provide corresponding callback\n");
@@ -4264,8 +4400,9 @@
 static DECLCALLBACK(void) hdaR3DbgInfoCodecSelector(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
 {
+    PHDASTATE   pThis   = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
     PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
 
     if (pThisCC->pCodec->pfnDbgSelector)
-        pThisCC->pCodec->pfnDbgSelector(pThisCC->pCodec, pHlp, pszArgs);
+        pThisCC->pCodec->pfnDbgSelector(&pThis->Codec, pThisCC->pCodec, pHlp, pszArgs);
     else
         pHlp->pfnPrintf(pHlp, "Codec implementation doesn't provide corresponding callback\n");
@@ -4510,5 +4647,5 @@
 
     /* Ditto goes for the codec, which in turn uses the mixer. */
-    hdaCodecPowerOff(pThisCC->pCodec);
+    hdaR3CodecPowerOff(pThisCC->pCodec);
 
     /*
@@ -4595,9 +4732,9 @@
     if (pThisCC->pCodec)
     {
-        hdaCodecDestruct(pThisCC->pCodec);
-
         RTMemFree(pThisCC->pCodec);
         pThisCC->pCodec = NULL;
     }
+
+    hdaCodecDestruct(&pThis->Codec);
 
     for (uint8_t i = 0; i < HDA_MAX_STREAMS; i++)
@@ -4730,11 +4867,11 @@
     PDMPciDevSetInterruptPin(  pPciDev, 0x01);   /* 3d ro - INTA#. */
 
-#if defined(HDA_AS_PCI_EXPRESS)
+# if defined(HDA_AS_PCI_EXPRESS)
     PDMPciDevSetCapabilityList(pPciDev, 0x80);
-#elif defined(VBOX_WITH_MSI_DEVICES)
+# elif defined(VBOX_WITH_MSI_DEVICES)
     PDMPciDevSetCapabilityList(pPciDev, 0x60);
-#else
+# else
     PDMPciDevSetCapabilityList(pPciDev, 0x50);   /* ICH6 datasheet 18.1.16 */
-#endif
+# endif
 
     /// @todo r=michaln: If there are really no PDMPciDevSetXx for these, the
@@ -4748,5 +4885,5 @@
     PDMPciDevSetWord(          pPciDev, 0x50 + 2, VBOX_PCI_PM_CAP_DSI | 0x02 /* version, PM1.1 */ );
 
-#ifdef HDA_AS_PCI_EXPRESS
+# ifdef HDA_AS_PCI_EXPRESS
     /* PCI Express */
     PDMPciDevSetByte(          pPciDev, 0x80 + 0, VBOX_PCI_CAP_ID_EXP); /* PCI_Express */
@@ -4789,5 +4926,5 @@
     /* Slot control 2 */
     PDMPciDevSetWord(          pPciDev, 0x80 + 56, 0);
-#endif
+# endif /* HDA_AS_PCI_EXPRESS */
 
     /*
@@ -4807,5 +4944,5 @@
     AssertRCReturn(rc, rc);
 
-#ifdef VBOX_WITH_MSI_DEVICES
+# ifdef VBOX_WITH_MSI_DEVICES
     PDMMSIREG MsiReg;
     RT_ZERO(MsiReg);
@@ -4819,12 +4956,12 @@
         PDMPciDevSetCapabilityList(pPciDev, 0x50);
     }
-#endif
+# endif
 
     rc = PDMDevHlpSSMRegister(pDevIns, HDA_SAVED_STATE_VERSION, sizeof(*pThis), hdaR3SaveExec, hdaR3LoadExec);
     AssertRCReturn(rc, rc);
 
-#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
+# ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
     LogRel(("HDA: Asynchronous I/O enabled\n"));
-#endif
+# endif
 
     /*
@@ -4861,5 +4998,5 @@
      * Add mixer output sinks.
      */
-#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
+# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
     rc = AudioMixerCreateSink(pThisCC->pMixer, "[Playback] Front", AUDMIXSINKDIR_OUTPUT, &pThisCC->SinkFront.pMixSink);
     AssertRCReturn(rc, rc);
@@ -4868,8 +5005,8 @@
     rc = AudioMixerCreateSink(pThisCC->pMixer, "[Playback] Rear", AUDMIXSINKDIR_OUTPUT, &pThisCC->SinkRear.pMixSink);
     AssertRCReturn(rc, rc);
-#else
+# else
     rc = AudioMixerCreateSink(pThisCC->pMixer, "[Playback] PCM Output", AUDMIXSINKDIR_OUTPUT, &pThisCC->SinkFront.pMixSink);
     AssertRCReturn(rc, rc);
-#endif
+# endif /* VBOX_WITH_AUDIO_HDA_51_SURROUND */
 
     /*
@@ -4878,8 +5015,8 @@
     rc = AudioMixerCreateSink(pThisCC->pMixer, "[Recording] Line In", AUDMIXSINKDIR_INPUT, &pThisCC->SinkLineIn.pMixSink);
     AssertRCReturn(rc, rc);
-#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
+# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
     rc = AudioMixerCreateSink(pThisCC->pMixer, "[Recording] Microphone In", AUDMIXSINKDIR_INPUT, &pThisCC->SinkMicIn.pMixSink);
     AssertRCReturn(rc, rc);
-#endif
+# endif
 
     /* There is no master volume control. Set the master to max. */
@@ -4889,25 +5026,26 @@
 
     /* Allocate codec. */
-    PHDACODEC pCodec = (PHDACODEC)RTMemAllocZ(sizeof(HDACODEC));
-    pThisCC->pCodec = pCodec;
-    AssertReturn(pCodec, VERR_NO_MEMORY);
+    PHDACODECR3 pCodecR3 = (PHDACODECR3)RTMemAllocZ(sizeof(HDACODECR3));
+    AssertPtrReturn(pCodecR3, VERR_NO_MEMORY);
 
     /* Set codec callbacks to this controller. */
-    pCodec->pDevIns                = pDevIns;
-    pCodec->pfnCbMixerAddStream    = hdaR3MixerAddStream;
-    pCodec->pfnCbMixerRemoveStream = hdaR3MixerRemoveStream;
-    pCodec->pfnCbMixerControl      = hdaR3MixerControl;
-    pCodec->pfnCbMixerSetVolume    = hdaR3MixerSetVolume;
-
-    /* Construct the codec. */
-    rc = hdaCodecConstruct(pDevIns, pCodec, 0 /* Codec index */, pCfg);
+    pCodecR3->pDevIns                = pDevIns;
+    pCodecR3->pfnCbMixerAddStream    = hdaR3MixerAddStream;
+    pCodecR3->pfnCbMixerRemoveStream = hdaR3MixerRemoveStream;
+    pCodecR3->pfnCbMixerControl      = hdaR3MixerControl;
+    pCodecR3->pfnCbMixerSetVolume    = hdaR3MixerSetVolume;
+
+    /* Construct the common + R3 codec part. */
+    rc = hdaR3CodecConstruct(pDevIns, &pThis->Codec, pCodecR3, 0 /* Codec index */, pCfg);
     AssertRCReturn(rc, rc);
+
+    pThisCC->pCodec = pCodecR3;
 
     /* ICH6 datasheet defines 0 values for SVID and SID (18.1.14-15), which together with values returned for
        verb F20 should provide device/codec recognition. */
-    Assert(pCodec->u16VendorId);
-    Assert(pCodec->u16DeviceId);
-    PDMPciDevSetSubSystemVendorId(pPciDev, pCodec->u16VendorId); /* 2c ro - intel.) */
-    PDMPciDevSetSubSystemId(      pPciDev, pCodec->u16DeviceId); /* 2e ro. */
+    Assert(pThis->Codec.u16VendorId);
+    Assert(pThis->Codec.u16DeviceId);
+    PDMPciDevSetSubSystemVendorId(pPciDev, pThis->Codec.u16VendorId); /* 2c ro - intel.) */
+    PDMPciDevSetSubSystemId(      pPciDev, pThis->Codec.u16DeviceId); /* 2e ro. */
 
     /*
@@ -4948,5 +5086,5 @@
     }
 
-#ifdef VBOX_WITH_AUDIO_HDA_ONETIME_INIT
+# ifdef VBOX_WITH_AUDIO_HDA_ONETIME_INIT
     /*
      * Initialize the driver chain.
@@ -4966,16 +5104,16 @@
 
         bool fValidLineIn = AudioMixerStreamIsValid(pDrv->LineIn.pMixStrm);
-# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
+#  ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
         bool fValidMicIn  = AudioMixerStreamIsValid(pDrv->MicIn.pMixStrm);
-# endif
+#  endif
         bool fValidOut    = AudioMixerStreamIsValid(pDrv->Front.pMixStrm);
-# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
+#  ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
         /** @todo Anything to do here? */
-# endif
+#  endif
 
         if (    !fValidLineIn
-# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
+#  ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
              && !fValidMicIn
-# endif
+#  endif
              && !fValidOut)
         {
@@ -4997,5 +5135,5 @@
                 if (BackendCfg.cMaxStreamsIn)
                 {
-# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
+#  ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
                     /* If the audio backend supports two or more input streams at once,
                      * warn if one of our two inputs (microphone-in and line-in) failed to initialize. */
@@ -5008,8 +5146,8 @@
                         fWarn = !fValidLineIn && !fValidMicIn;
                     /* Don't warn if our backend is not able of supporting any input streams at all. */
-# else  /* !VBOX_WITH_AUDIO_HDA_MIC_IN */
+#  else  /* !VBOX_WITH_AUDIO_HDA_MIC_IN */
                     /* We only have line-in as input source. */
                     fWarn = !fValidLineIn;
-# endif /* !VBOX_WITH_AUDIO_HDA_MIC_IN */
+#  endif /* !VBOX_WITH_AUDIO_HDA_MIC_IN */
                 }
 
@@ -5033,5 +5171,5 @@
                     len = RTStrPrintf(szMissingStreams, sizeof(szMissingStreams), "PCM Input");
                 }
-# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
+#  ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
                 if (!fValidMicIn)
                 {
@@ -5040,5 +5178,5 @@
                                        sizeof(szMissingStreams) - len, len ? ", PCM Microphone" : "PCM Microphone");
                 }
-# endif
+#  endif /* VBOX_WITH_AUDIO_HDA_MIC_IN */
                 if (!fValidOut)
                 {
@@ -5056,5 +5194,5 @@
         }
     }
-#endif /* VBOX_WITH_AUDIO_HDA_ONETIME_INIT */
+# endif /* VBOX_WITH_AUDIO_HDA_ONETIME_INIT */
 
     hdaR3Reset(pDevIns);
@@ -5177,5 +5315,6 @@
 {
     PDMDEV_CHECK_VERSIONS_RETURN(pDevIns); /* this shall come first */
-    PHDASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
+    PHDASTATE   pThis   = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
+    PHDASTATER0 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER0);
 
     int rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
@@ -5183,4 +5322,8 @@
 
     rc = PDMDevHlpMmioSetUpContext(pDevIns, pThis->hMmio, hdaMmioWrite, hdaMmioRead, NULL /*pvUser*/);
+    AssertRCReturn(rc, rc);
+
+    /* Construct the R0 codec part. */
+    rc = hdaR0CodecConstruct(pDevIns, &pThis->Codec, &pThisCC->Codec);
     AssertRCReturn(rc, rc);
 
@@ -5203,5 +5346,5 @@
     /* .uSharedVersion = */         42,
     /* .cbInstanceShared = */       sizeof(HDASTATE),
-    /* .cbInstanceCC = */           CTX_EXPR(sizeof(HDASTATER3), 0, 0),
+    /* .cbInstanceCC = */           CTX_EXPR(sizeof(HDASTATER3), sizeof(HDASTATER0), 0),
     /* .cbInstanceRC = */           0,
     /* .cMaxPciDevices = */         1,
Index: /trunk/src/VBox/Devices/Audio/DevHDA.h
===================================================================
--- /trunk/src/VBox/Devices/Audio/DevHDA.h	(revision 87798)
+++ /trunk/src/VBox/Devices/Audio/DevHDA.h	(revision 87799)
@@ -147,4 +147,7 @@
     IOMMMIOHANDLE           hMmio;
 
+    /** Shared R0/R3 HDA codec to use. */
+    HDACODEC                Codec;
+
 #ifdef VBOX_WITH_STATISTICS
     STAMPROFILE             StatIn;
@@ -215,4 +218,14 @@
 #define HDASTATE_ALIGNMENT_CHECK_MAGIC  UINT64_C(0x1298afb75893e059)
 
+/**
+ * Ring-0 ICH Intel HD audio controller state.
+ */
+typedef struct HDASTATER0
+{
+    /** Pointer to HDA codec to use. */
+    HDACODECR0              Codec;
+} HDASTATER0;
+/** Pointer to a ring-0 HDA device state.  */
+typedef HDASTATER0 *PHDASTATER0;
 
 /**
@@ -233,5 +246,5 @@
     PDMIBASE                IBase;
     /** Pointer to HDA codec to use. */
-    R3PTRTYPE(PHDACODEC)    pCodec;
+    R3PTRTYPE(PHDACODECR3)  pCodec;
     /** List of associated LUN drivers (HDADRIVER). */
     RTLISTANCHORR3          lstDrv;
Index: /trunk/src/VBox/Devices/Audio/HDACodec.cpp
===================================================================
--- /trunk/src/VBox/Devices/Audio/HDACodec.cpp	(revision 87798)
+++ /trunk/src/VBox/Devices/Audio/HDACodec.cpp	(revision 87799)
@@ -24,7 +24,10 @@
 *********************************************************************************************************************************/
 #define LOG_GROUP LOG_GROUP_DEV_HDA_CODEC
+#include <VBox/log.h>
+
 #include <VBox/AssertGuest.h>
 #include <VBox/vmm/pdmdev.h>
 #include <VBox/vmm/pdmaudioifs.h>
+
 #include <iprt/assert.h>
 #include <iprt/uuid.h>
@@ -44,547 +47,6 @@
 *   Defined Constants And Macros                                                                                                 *
 *********************************************************************************************************************************/
-/* PRM 5.3.1 */
-/** Codec address mask. */
-#define CODEC_CAD_MASK                                     0xF0000000
-/** Codec address shift. */
-#define CODEC_CAD_SHIFT                                    28
-#define CODEC_DIRECT_MASK                                  RT_BIT(27)
-/** Node ID mask. */
-#define CODEC_NID_MASK                                     0x07F00000
-/** Node ID shift. */
-#define CODEC_NID_SHIFT                                    20
-#define CODEC_VERBDATA_MASK                                0x000FFFFF
-#define CODEC_VERB_4BIT_CMD                                0x000FFFF0
-#define CODEC_VERB_4BIT_DATA                               0x0000000F
-#define CODEC_VERB_8BIT_CMD                                0x000FFF00
-#define CODEC_VERB_8BIT_DATA                               0x000000FF
-#define CODEC_VERB_16BIT_CMD                               0x000F0000
-#define CODEC_VERB_16BIT_DATA                              0x0000FFFF
-
-#define CODEC_CAD(cmd)                                     (((cmd) & CODEC_CAD_MASK) >> CODEC_CAD_SHIFT)
-#define CODEC_DIRECT(cmd)                                  ((cmd) & CODEC_DIRECT_MASK)
-#define CODEC_NID(cmd)                                     ((((cmd) & CODEC_NID_MASK)) >> CODEC_NID_SHIFT)
-#define CODEC_VERBDATA(cmd)                                ((cmd) & CODEC_VERBDATA_MASK)
-#define CODEC_VERB_CMD(cmd, mask, x)                       (((cmd) & (mask)) >> (x))
-#define CODEC_VERB_CMD4(cmd)                               (CODEC_VERB_CMD((cmd), CODEC_VERB_4BIT_CMD, 4))
-#define CODEC_VERB_CMD8(cmd)                               (CODEC_VERB_CMD((cmd), CODEC_VERB_8BIT_CMD, 8))
-#define CODEC_VERB_CMD16(cmd)                              (CODEC_VERB_CMD((cmd), CODEC_VERB_16BIT_CMD, 16))
-#define CODEC_VERB_PAYLOAD4(cmd)                           ((cmd) & CODEC_VERB_4BIT_DATA)
-#define CODEC_VERB_PAYLOAD8(cmd)                           ((cmd) & CODEC_VERB_8BIT_DATA)
-#define CODEC_VERB_PAYLOAD16(cmd)                          ((cmd) & CODEC_VERB_16BIT_DATA)
-
-#define CODEC_VERB_GET_AMP_DIRECTION                       RT_BIT(15)
-#define CODEC_VERB_GET_AMP_SIDE                            RT_BIT(13)
-#define CODEC_VERB_GET_AMP_INDEX                           0x7
-
-/* HDA spec 7.3.3.7 NoteA */
-#define CODEC_GET_AMP_DIRECTION(cmd)                       (((cmd) & CODEC_VERB_GET_AMP_DIRECTION) >> 15)
-#define CODEC_GET_AMP_SIDE(cmd)                            (((cmd) & CODEC_VERB_GET_AMP_SIDE) >> 13)
-#define CODEC_GET_AMP_INDEX(cmd)                           (CODEC_GET_AMP_DIRECTION(cmd) ? 0 : ((cmd) & CODEC_VERB_GET_AMP_INDEX))
-
-/* HDA spec 7.3.3.7 NoteC */
-#define CODEC_VERB_SET_AMP_OUT_DIRECTION                   RT_BIT(15)
-#define CODEC_VERB_SET_AMP_IN_DIRECTION                    RT_BIT(14)
-#define CODEC_VERB_SET_AMP_LEFT_SIDE                       RT_BIT(13)
-#define CODEC_VERB_SET_AMP_RIGHT_SIDE                      RT_BIT(12)
-#define CODEC_VERB_SET_AMP_INDEX                           (0x7 << 8)
-#define CODEC_VERB_SET_AMP_MUTE                            RT_BIT(7)
-/** Note: 7-bit value [6:0]. */
-#define CODEC_VERB_SET_AMP_GAIN                            0x7F
-
-#define CODEC_SET_AMP_IS_OUT_DIRECTION(cmd)                (((cmd) & CODEC_VERB_SET_AMP_OUT_DIRECTION) != 0)
-#define CODEC_SET_AMP_IS_IN_DIRECTION(cmd)                 (((cmd) & CODEC_VERB_SET_AMP_IN_DIRECTION) != 0)
-#define CODEC_SET_AMP_IS_LEFT_SIDE(cmd)                    (((cmd) & CODEC_VERB_SET_AMP_LEFT_SIDE) != 0)
-#define CODEC_SET_AMP_IS_RIGHT_SIDE(cmd)                   (((cmd) & CODEC_VERB_SET_AMP_RIGHT_SIDE) != 0)
-#define CODEC_SET_AMP_INDEX(cmd)                           (((cmd) & CODEC_VERB_SET_AMP_INDEX) >> 7)
-#define CODEC_SET_AMP_MUTE(cmd)                            ((cmd) & CODEC_VERB_SET_AMP_MUTE)
-#define CODEC_SET_AMP_GAIN(cmd)                            ((cmd) & CODEC_VERB_SET_AMP_GAIN)
-
-/* HDA spec 7.3.3.1 defines layout of configuration registers/verbs (0xF00) */
-/* VendorID (7.3.4.1) */
-#define CODEC_MAKE_F00_00(vendorID, deviceID)              (((vendorID) << 16) | (deviceID))
-#define CODEC_F00_00_VENDORID(f00_00)                      (((f00_00) >> 16) & 0xFFFF)
-#define CODEC_F00_00_DEVICEID(f00_00)                      ((f00_00) & 0xFFFF)
-
-/** RevisionID (7.3.4.2). */
-#define CODEC_MAKE_F00_02(majRev, minRev, venFix, venProg, stepFix, stepProg) \
-    (  (((majRev)   & 0xF) << 20) \
-     | (((minRev)   & 0xF) << 16) \
-     | (((venFix)   & 0xF) << 12) \
-     | (((venProg)  & 0xF) << 8)  \
-     | (((stepFix)  & 0xF) << 4)  \
-     |  ((stepProg) & 0xF))
-
-/** Subordinate node count (7.3.4.3). */
-#define CODEC_MAKE_F00_04(startNodeNumber, totalNodeNumber) ((((startNodeNumber) & 0xFF) << 16)|((totalNodeNumber) & 0xFF))
-#define CODEC_F00_04_TO_START_NODE_NUMBER(f00_04)          (((f00_04) >> 16) & 0xFF)
-#define CODEC_F00_04_TO_NODE_COUNT(f00_04)                 ((f00_04) & 0xFF)
-/*
- * Function Group Type  (7.3.4.4)
- * 0 & [0x3-0x7f] are reserved types
- * [0x80 - 0xff] are vendor defined function groups
- */
-#define CODEC_MAKE_F00_05(UnSol, NodeType)                 (((UnSol) << 8)|(NodeType))
-#define CODEC_F00_05_UNSOL                                 RT_BIT(8)
-#define CODEC_F00_05_AFG                                   (0x1)
-#define CODEC_F00_05_MFG                                   (0x2)
-#define CODEC_F00_05_IS_UNSOL(f00_05)                      RT_BOOL((f00_05) & RT_BIT(8))
-#define CODEC_F00_05_GROUP(f00_05)                         ((f00_05) & 0xff)
-/* Audio Function Group capabilities (7.3.4.5). */
-#define CODEC_MAKE_F00_08(BeepGen, InputDelay, OutputDelay) ((((BeepGen) & 0x1) << 16)| (((InputDelay) & 0xF) << 8) | ((OutputDelay) & 0xF))
-#define CODEC_F00_08_BEEP_GEN(f00_08)                      ((f00_08) & RT_BIT(16)
-
-/* Converter Stream, Channel (7.3.3.11). */
-#define CODEC_F00_06_GET_STREAM_ID(cmd)                    (((cmd) >> 4) & 0x0F)
-#define CODEC_F00_06_GET_CHANNEL_ID(cmd)                   (((cmd) & 0x0F))
-
-/* Widget Capabilities (7.3.4.6). */
-#define CODEC_MAKE_F00_09(type, delay, chan_ext) \
-    ( (((type)     & 0xF) << 20)            \
-    | (((delay)    & 0xF) << 16)           \
-    | (((chan_ext) & 0xF) << 13))
-/* note: types 0x8-0xe are reserved */
-#define CODEC_F00_09_TYPE_AUDIO_OUTPUT                     (0x0)
-#define CODEC_F00_09_TYPE_AUDIO_INPUT                      (0x1)
-#define CODEC_F00_09_TYPE_AUDIO_MIXER                      (0x2)
-#define CODEC_F00_09_TYPE_AUDIO_SELECTOR                   (0x3)
-#define CODEC_F00_09_TYPE_PIN_COMPLEX                      (0x4)
-#define CODEC_F00_09_TYPE_POWER_WIDGET                     (0x5)
-#define CODEC_F00_09_TYPE_VOLUME_KNOB                      (0x6)
-#define CODEC_F00_09_TYPE_BEEP_GEN                         (0x7)
-#define CODEC_F00_09_TYPE_VENDOR_DEFINED                   (0xF)
-
-#define CODEC_F00_09_CAP_CP                                RT_BIT(12)
-#define CODEC_F00_09_CAP_L_R_SWAP                          RT_BIT(11)
-#define CODEC_F00_09_CAP_POWER_CTRL                        RT_BIT(10)
-#define CODEC_F00_09_CAP_DIGITAL                           RT_BIT(9)
-#define CODEC_F00_09_CAP_CONNECTION_LIST                   RT_BIT(8)
-#define CODEC_F00_09_CAP_UNSOL                             RT_BIT(7)
-#define CODEC_F00_09_CAP_PROC_WIDGET                       RT_BIT(6)
-#define CODEC_F00_09_CAP_STRIPE                            RT_BIT(5)
-#define CODEC_F00_09_CAP_FMT_OVERRIDE                      RT_BIT(4)
-#define CODEC_F00_09_CAP_AMP_FMT_OVERRIDE                  RT_BIT(3)
-#define CODEC_F00_09_CAP_OUT_AMP_PRESENT                   RT_BIT(2)
-#define CODEC_F00_09_CAP_IN_AMP_PRESENT                    RT_BIT(1)
-#define CODEC_F00_09_CAP_STEREO                            RT_BIT(0)
-
-#define CODEC_F00_09_TYPE(f00_09)                          (((f00_09) >> 20) & 0xF)
-
-#define CODEC_F00_09_IS_CAP_CP(f00_09)                     RT_BOOL((f00_09) & RT_BIT(12))
-#define CODEC_F00_09_IS_CAP_L_R_SWAP(f00_09)               RT_BOOL((f00_09) & RT_BIT(11))
-#define CODEC_F00_09_IS_CAP_POWER_CTRL(f00_09)             RT_BOOL((f00_09) & RT_BIT(10))
-#define CODEC_F00_09_IS_CAP_DIGITAL(f00_09)                RT_BOOL((f00_09) & RT_BIT(9))
-#define CODEC_F00_09_IS_CAP_CONNECTION_LIST(f00_09)        RT_BOOL((f00_09) & RT_BIT(8))
-#define CODEC_F00_09_IS_CAP_UNSOL(f00_09)                  RT_BOOL((f00_09) & RT_BIT(7))
-#define CODEC_F00_09_IS_CAP_PROC_WIDGET(f00_09)            RT_BOOL((f00_09) & RT_BIT(6))
-#define CODEC_F00_09_IS_CAP_STRIPE(f00_09)                 RT_BOOL((f00_09) & RT_BIT(5))
-#define CODEC_F00_09_IS_CAP_FMT_OVERRIDE(f00_09)           RT_BOOL((f00_09) & RT_BIT(4))
-#define CODEC_F00_09_IS_CAP_AMP_OVERRIDE(f00_09)           RT_BOOL((f00_09) & RT_BIT(3))
-#define CODEC_F00_09_IS_CAP_OUT_AMP_PRESENT(f00_09)        RT_BOOL((f00_09) & RT_BIT(2))
-#define CODEC_F00_09_IS_CAP_IN_AMP_PRESENT(f00_09)         RT_BOOL((f00_09) & RT_BIT(1))
-#define CODEC_F00_09_IS_CAP_LSB(f00_09)                    RT_BOOL((f00_09) & RT_BIT(0))
-
-/* Supported PCM size, rates (7.3.4.7) */
-#define CODEC_F00_0A_32_BIT                                RT_BIT(19)
-#define CODEC_F00_0A_24_BIT                                RT_BIT(18)
-#define CODEC_F00_0A_16_BIT                                RT_BIT(17)
-#define CODEC_F00_0A_8_BIT                                 RT_BIT(16)
-
-#define CODEC_F00_0A_48KHZ_MULT_8X                         RT_BIT(11)
-#define CODEC_F00_0A_48KHZ_MULT_4X                         RT_BIT(10)
-#define CODEC_F00_0A_44_1KHZ_MULT_4X                       RT_BIT(9)
-#define CODEC_F00_0A_48KHZ_MULT_2X                         RT_BIT(8)
-#define CODEC_F00_0A_44_1KHZ_MULT_2X                       RT_BIT(7)
-#define CODEC_F00_0A_48KHZ                                 RT_BIT(6)
-#define CODEC_F00_0A_44_1KHZ                               RT_BIT(5)
-/* 2/3 * 48kHz */
-#define CODEC_F00_0A_48KHZ_2_3X                            RT_BIT(4)
-/* 1/2 * 44.1kHz */
-#define CODEC_F00_0A_44_1KHZ_1_2X                          RT_BIT(3)
-/* 1/3 * 48kHz */
-#define CODEC_F00_0A_48KHZ_1_3X                            RT_BIT(2)
-/* 1/4 * 44.1kHz */
-#define CODEC_F00_0A_44_1KHZ_1_4X                          RT_BIT(1)
-/* 1/6 * 48kHz */
-#define CODEC_F00_0A_48KHZ_1_6X                            RT_BIT(0)
-
-/* Supported streams formats (7.3.4.8) */
-#define CODEC_F00_0B_AC3                                   RT_BIT(2)
-#define CODEC_F00_0B_FLOAT32                               RT_BIT(1)
-#define CODEC_F00_0B_PCM                                   RT_BIT(0)
-
-/* Pin Capabilities (7.3.4.9)*/
-#define CODEC_MAKE_F00_0C(vref_ctrl) (((vref_ctrl) & 0xFF) << 8)
-#define CODEC_F00_0C_CAP_HBR                               RT_BIT(27)
-#define CODEC_F00_0C_CAP_DP                                RT_BIT(24)
-#define CODEC_F00_0C_CAP_EAPD                              RT_BIT(16)
-#define CODEC_F00_0C_CAP_HDMI                              RT_BIT(7)
-#define CODEC_F00_0C_CAP_BALANCED_IO                       RT_BIT(6)
-#define CODEC_F00_0C_CAP_INPUT                             RT_BIT(5)
-#define CODEC_F00_0C_CAP_OUTPUT                            RT_BIT(4)
-#define CODEC_F00_0C_CAP_HEADPHONE_AMP                     RT_BIT(3)
-#define CODEC_F00_0C_CAP_PRESENCE_DETECT                   RT_BIT(2)
-#define CODEC_F00_0C_CAP_TRIGGER_REQUIRED                  RT_BIT(1)
-#define CODEC_F00_0C_CAP_IMPENDANCE_SENSE                  RT_BIT(0)
-
-#define CODEC_F00_0C_IS_CAP_HBR(f00_0c)                    ((f00_0c) & RT_BIT(27))
-#define CODEC_F00_0C_IS_CAP_DP(f00_0c)                     ((f00_0c) & RT_BIT(24))
-#define CODEC_F00_0C_IS_CAP_EAPD(f00_0c)                   ((f00_0c) & RT_BIT(16))
-#define CODEC_F00_0C_IS_CAP_HDMI(f00_0c)                   ((f00_0c) & RT_BIT(7))
-#define CODEC_F00_0C_IS_CAP_BALANCED_IO(f00_0c)            ((f00_0c) & RT_BIT(6))
-#define CODEC_F00_0C_IS_CAP_INPUT(f00_0c)                  ((f00_0c) & RT_BIT(5))
-#define CODEC_F00_0C_IS_CAP_OUTPUT(f00_0c)                 ((f00_0c) & RT_BIT(4))
-#define CODEC_F00_0C_IS_CAP_HP(f00_0c)                     ((f00_0c) & RT_BIT(3))
-#define CODEC_F00_0C_IS_CAP_PRESENCE_DETECT(f00_0c)        ((f00_0c) & RT_BIT(2))
-#define CODEC_F00_0C_IS_CAP_TRIGGER_REQUIRED(f00_0c)       ((f00_0c) & RT_BIT(1))
-#define CODEC_F00_0C_IS_CAP_IMPENDANCE_SENSE(f00_0c)       ((f00_0c) & RT_BIT(0))
-
-/* Input Amplifier capabilities (7.3.4.10). */
-#define CODEC_MAKE_F00_0D(mute_cap, step_size, num_steps, offset) \
-        (  (((mute_cap)  & UINT32_C(0x1))  << 31) \
-         | (((step_size) & UINT32_C(0xFF)) << 16) \
-         | (((num_steps) & UINT32_C(0xFF)) << 8) \
-         |  ((offset)    & UINT32_C(0xFF)))
-
-#define CODEC_F00_0D_CAP_MUTE                              RT_BIT(7)
-
-#define CODEC_F00_0D_IS_CAP_MUTE(f00_0d)                   ( ( f00_0d) & RT_BIT(31))
-#define CODEC_F00_0D_STEP_SIZE(f00_0d)                     ((( f00_0d) & (0x7F << 16)) >> 16)
-#define CODEC_F00_0D_NUM_STEPS(f00_0d)                     ((((f00_0d) & (0x7F << 8)) >> 8) + 1)
-#define CODEC_F00_0D_OFFSET(f00_0d)                        (  (f00_0d) & 0x7F)
-
-/** Indicates that the amplifier can be muted. */
-#define CODEC_AMP_CAP_MUTE                                 0x1
-/** The amplifier's maximum number of steps. We want
- *  a ~90dB dynamic range, so 64 steps with 1.25dB each
- *  should do the trick.
- *
- *  As we want to map our range to [0..128] values we can avoid
- *  multiplication and simply doing a shift later.
- *
- *  Produces -96dB to +0dB.
- *  "0" indicates a step of 0.25dB, "127" indicates a step of 32dB.
- */
-#define CODEC_AMP_NUM_STEPS                                0x7F
-/** The initial gain offset (and when doing a node reset). */
-#define CODEC_AMP_OFF_INITIAL                              0x7F
-/** The amplifier's gain step size. */
-#define CODEC_AMP_STEP_SIZE                                0x2
-
-/* Output Amplifier capabilities (7.3.4.10) */
-#define CODEC_MAKE_F00_12                                  CODEC_MAKE_F00_0D
-
-#define CODEC_F00_12_IS_CAP_MUTE(f00_12)                   CODEC_F00_0D_IS_CAP_MUTE(f00_12)
-#define CODEC_F00_12_STEP_SIZE(f00_12)                     CODEC_F00_0D_STEP_SIZE(f00_12)
-#define CODEC_F00_12_NUM_STEPS(f00_12)                     CODEC_F00_0D_NUM_STEPS(f00_12)
-#define CODEC_F00_12_OFFSET(f00_12)                        CODEC_F00_0D_OFFSET(f00_12)
-
-/* Connection list lenght (7.3.4.11). */
-#define CODEC_MAKE_F00_0E(long_form, length)    \
-    (  (((long_form) & 0x1) << 7)               \
-     | ((length) & 0x7F))
-/* Indicates short-form NIDs. */
-#define CODEC_F00_0E_LIST_NID_SHORT                        0
-/* Indicates long-form NIDs. */
-#define CODEC_F00_0E_LIST_NID_LONG                         1
-#define CODEC_F00_0E_IS_LONG(f00_0e)                       RT_BOOL((f00_0e) & RT_BIT(7))
-#define CODEC_F00_0E_COUNT(f00_0e)                         ((f00_0e) & 0x7F)
-/* Supported Power States (7.3.4.12) */
-#define CODEC_F00_0F_EPSS                                  RT_BIT(31)
-#define CODEC_F00_0F_CLKSTOP                               RT_BIT(30)
-#define CODEC_F00_0F_S3D3                                  RT_BIT(29)
-#define CODEC_F00_0F_D3COLD                                RT_BIT(4)
-#define CODEC_F00_0F_D3                                    RT_BIT(3)
-#define CODEC_F00_0F_D2                                    RT_BIT(2)
-#define CODEC_F00_0F_D1                                    RT_BIT(1)
-#define CODEC_F00_0F_D0                                    RT_BIT(0)
-
-/* Processing capabilities 7.3.4.13 */
-#define CODEC_MAKE_F00_10(num, benign)                     ((((num) & 0xFF) << 8) | ((benign) & 0x1))
-#define CODEC_F00_10_NUM(f00_10)                           (((f00_10) & (0xFF << 8)) >> 8)
-#define CODEC_F00_10_BENING(f00_10)                        ((f00_10) & 0x1)
-
-/* GPIO count (7.3.4.14). */
-#define CODEC_MAKE_F00_11(wake, unsol, numgpi, numgpo, numgpio) \
-    (  (((wake)   & UINT32_C(0x1))  << 31) \
-     | (((unsol)  & UINT32_C(0x1))  << 30) \
-     | (((numgpi) & UINT32_C(0xFF)) << 16) \
-     | (((numgpo) & UINT32_C(0xFF)) << 8) \
-     | ((numgpio) & UINT32_C(0xFF)))
-
-/* Processing States (7.3.3.4). */
-#define CODEC_F03_OFF                                      (0)
-#define CODEC_F03_ON                                       RT_BIT(0)
-#define CODEC_F03_BENING                                   RT_BIT(1)
-/* Power States (7.3.3.10). */
-#define CODEC_MAKE_F05(reset, stopok, error, act, set) \
-    (  (((reset)  & 0x1) << 10) \
-     | (((stopok) & 0x1) << 9) \
-     | (((error)  & 0x1) << 8) \
-     | (((act)    & 0xF) << 4) \
-     | ((set)     & 0xF))
-#define CODEC_F05_D3COLD                                   (4)
-#define CODEC_F05_D3                                       (3)
-#define CODEC_F05_D2                                       (2)
-#define CODEC_F05_D1                                       (1)
-#define CODEC_F05_D0                                       (0)
-
-#define CODEC_F05_IS_RESET(value)                          (((value) & RT_BIT(10)) != 0)
-#define CODEC_F05_IS_STOPOK(value)                         (((value) & RT_BIT(9)) != 0)
-#define CODEC_F05_IS_ERROR(value)                          (((value) & RT_BIT(8)) != 0)
-#define CODEC_F05_ACT(value)                               (((value) & 0xF0) >> 4)
-#define CODEC_F05_SET(value)                               (((value) & 0xF))
-
-#define CODEC_F05_GE(p0, p1)                               ((p0) <= (p1))
-#define CODEC_F05_LE(p0, p1)                               ((p0) >= (p1))
-
-/* Converter Stream, Channel (7.3.3.11). */
-#define CODEC_MAKE_F06(stream, channel) \
-    (  (((stream)  & 0xF) << 4)         \
-     |  ((channel) & 0xF))
-#define CODEC_F06_STREAM(value)                            ((value) & 0xF0)
-#define CODEC_F06_CHANNEL(value)                           ((value) & 0xF)
-
-/* Pin Widged Control (7.3.3.13). */
-#define CODEC_F07_VREF_HIZ                                 (0)
-#define CODEC_F07_VREF_50                                  (0x1)
-#define CODEC_F07_VREF_GROUND                              (0x2)
-#define CODEC_F07_VREF_80                                  (0x4)
-#define CODEC_F07_VREF_100                                 (0x5)
-#define CODEC_F07_IN_ENABLE                                RT_BIT(5)
-#define CODEC_F07_OUT_ENABLE                               RT_BIT(6)
-#define CODEC_F07_OUT_H_ENABLE                             RT_BIT(7)
-
-/* Volume Knob Control (7.3.3.29). */
-#define CODEC_F0F_IS_DIRECT                                RT_BIT(7)
-#define CODEC_F0F_VOLUME                                   (0x7F)
-
-/* Unsolicited enabled (7.3.3.14). */
-#define CODEC_MAKE_F08(enable, tag) ((((enable) & 1) << 7) | ((tag) & 0x3F))
-
-/* Converter formats (7.3.3.8) and (3.7.1). */
-/* This is the same format as SDnFMT. */
-#define CODEC_MAKE_A                                       HDA_SDFMT_MAKE
-
-#define CODEC_A_TYPE                                       HDA_SDFMT_TYPE
-#define CODEC_A_TYPE_PCM                                   HDA_SDFMT_TYPE_PCM
-#define CODEC_A_TYPE_NON_PCM                               HDA_SDFMT_TYPE_NON_PCM
-
-#define CODEC_A_BASE                                       HDA_SDFMT_BASE
-#define CODEC_A_BASE_48KHZ                                 HDA_SDFMT_BASE_48KHZ
-#define CODEC_A_BASE_44KHZ                                 HDA_SDFMT_BASE_44KHZ
-
-/* Pin Sense (7.3.3.15). */
-#define CODEC_MAKE_F09_ANALOG(fPresent, impedance)  \
-(  (((fPresent) & 0x1) << 31)                       \
- | (((impedance) & UINT32_C(0x7FFFFFFF))))
-#define CODEC_F09_ANALOG_NA    UINT32_C(0x7FFFFFFF)
-#define CODEC_MAKE_F09_DIGITAL(fPresent, fELDValid) \
-(   (((fPresent)  & UINT32_C(0x1)) << 31)                      \
-  | (((fELDValid) & UINT32_C(0x1)) << 30))
-
-#define CODEC_MAKE_F0C(lrswap, eapd, btl) ((((lrswap) & 1) << 2) | (((eapd) & 1) << 1) | ((btl) & 1))
-#define CODEC_FOC_IS_LRSWAP(f0c)                           RT_BOOL((f0c) & RT_BIT(2))
-#define CODEC_FOC_IS_EAPD(f0c)                             RT_BOOL((f0c) & RT_BIT(1))
-#define CODEC_FOC_IS_BTL(f0c)                              RT_BOOL((f0c) & RT_BIT(0))
-/* HDA spec 7.3.3.31 defines layout of configuration registers/verbs (0xF1C) */
-/* Configuration's port connection */
-#define CODEC_F1C_PORT_MASK                                (0x3)
-#define CODEC_F1C_PORT_SHIFT                               (30)
-
-#define CODEC_F1C_PORT_COMPLEX                             (0x0)
-#define CODEC_F1C_PORT_NO_PHYS                             (0x1)
-#define CODEC_F1C_PORT_FIXED                               (0x2)
-#define CODEC_F1C_BOTH                                     (0x3)
-
-/* Configuration default: connection */
-#define CODEC_F1C_PORT_MASK                                (0x3)
-#define CODEC_F1C_PORT_SHIFT                               (30)
-
-/* Connected to a jack (1/8", ATAPI, ...). */
-#define CODEC_F1C_PORT_COMPLEX                             (0x0)
-/* No physical connection. */
-#define CODEC_F1C_PORT_NO_PHYS                             (0x1)
-/* Fixed function device (integrated speaker, integrated mic, ...). */
-#define CODEC_F1C_PORT_FIXED                               (0x2)
-/* Both, a jack and an internal device are attached. */
-#define CODEC_F1C_BOTH                                     (0x3)
-
-/* Configuration default: Location */
-#define CODEC_F1C_LOCATION_MASK                            (0x3F)
-#define CODEC_F1C_LOCATION_SHIFT                           (24)
-
-/* [4:5] bits of location region means chassis attachment */
-#define CODEC_F1C_LOCATION_PRIMARY_CHASSIS                 (0)
-#define CODEC_F1C_LOCATION_INTERNAL                        RT_BIT(4)
-#define CODEC_F1C_LOCATION_SECONDRARY_CHASSIS              RT_BIT(5)
-#define CODEC_F1C_LOCATION_OTHER                           RT_BIT(5)
-
-/* [0:3] bits of location region means geometry location attachment */
-#define CODEC_F1C_LOCATION_NA                              (0)
-#define CODEC_F1C_LOCATION_REAR                            (0x1)
-#define CODEC_F1C_LOCATION_FRONT                           (0x2)
-#define CODEC_F1C_LOCATION_LEFT                            (0x3)
-#define CODEC_F1C_LOCATION_RIGTH                           (0x4)
-#define CODEC_F1C_LOCATION_TOP                             (0x5)
-#define CODEC_F1C_LOCATION_BOTTOM                          (0x6)
-#define CODEC_F1C_LOCATION_SPECIAL_0                       (0x7)
-#define CODEC_F1C_LOCATION_SPECIAL_1                       (0x8)
-#define CODEC_F1C_LOCATION_SPECIAL_2                       (0x9)
-
-/* Configuration default: Device type */
-#define CODEC_F1C_DEVICE_MASK                              (0xF)
-#define CODEC_F1C_DEVICE_SHIFT                             (20)
-#define CODEC_F1C_DEVICE_LINE_OUT                          (0)
-#define CODEC_F1C_DEVICE_SPEAKER                           (0x1)
-#define CODEC_F1C_DEVICE_HP                                (0x2)
-#define CODEC_F1C_DEVICE_CD                                (0x3)
-#define CODEC_F1C_DEVICE_SPDIF_OUT                         (0x4)
-#define CODEC_F1C_DEVICE_DIGITAL_OTHER_OUT                 (0x5)
-#define CODEC_F1C_DEVICE_MODEM_LINE_SIDE                   (0x6)
-#define CODEC_F1C_DEVICE_MODEM_HANDSET_SIDE                (0x7)
-#define CODEC_F1C_DEVICE_LINE_IN                           (0x8)
-#define CODEC_F1C_DEVICE_AUX                               (0x9)
-#define CODEC_F1C_DEVICE_MIC                               (0xA)
-#define CODEC_F1C_DEVICE_PHONE                             (0xB)
-#define CODEC_F1C_DEVICE_SPDIF_IN                          (0xC)
-#define CODEC_F1C_DEVICE_RESERVED                          (0xE)
-#define CODEC_F1C_DEVICE_OTHER                             (0xF)
-
-/* Configuration default: Connection type */
-#define CODEC_F1C_CONNECTION_TYPE_MASK                     (0xF)
-#define CODEC_F1C_CONNECTION_TYPE_SHIFT                    (16)
-
-#define CODEC_F1C_CONNECTION_TYPE_UNKNOWN                  (0)
-#define CODEC_F1C_CONNECTION_TYPE_1_8INCHES                (0x1)
-#define CODEC_F1C_CONNECTION_TYPE_1_4INCHES                (0x2)
-#define CODEC_F1C_CONNECTION_TYPE_ATAPI                    (0x3)
-#define CODEC_F1C_CONNECTION_TYPE_RCA                      (0x4)
-#define CODEC_F1C_CONNECTION_TYPE_OPTICAL                  (0x5)
-#define CODEC_F1C_CONNECTION_TYPE_OTHER_DIGITAL            (0x6)
-#define CODEC_F1C_CONNECTION_TYPE_ANALOG                   (0x7)
-#define CODEC_F1C_CONNECTION_TYPE_DIN                      (0x8)
-#define CODEC_F1C_CONNECTION_TYPE_XLR                      (0x9)
-#define CODEC_F1C_CONNECTION_TYPE_RJ_11                    (0xA)
-#define CODEC_F1C_CONNECTION_TYPE_COMBO                    (0xB)
-#define CODEC_F1C_CONNECTION_TYPE_OTHER                    (0xF)
-
-/* Configuration's color */
-#define CODEC_F1C_COLOR_MASK                               (0xF)
-#define CODEC_F1C_COLOR_SHIFT                              (12)
-#define CODEC_F1C_COLOR_UNKNOWN                            (0)
-#define CODEC_F1C_COLOR_BLACK                              (0x1)
-#define CODEC_F1C_COLOR_GREY                               (0x2)
-#define CODEC_F1C_COLOR_BLUE                               (0x3)
-#define CODEC_F1C_COLOR_GREEN                              (0x4)
-#define CODEC_F1C_COLOR_RED                                (0x5)
-#define CODEC_F1C_COLOR_ORANGE                             (0x6)
-#define CODEC_F1C_COLOR_YELLOW                             (0x7)
-#define CODEC_F1C_COLOR_PURPLE                             (0x8)
-#define CODEC_F1C_COLOR_PINK                               (0x9)
-#define CODEC_F1C_COLOR_RESERVED_0                         (0xA)
-#define CODEC_F1C_COLOR_RESERVED_1                         (0xB)
-#define CODEC_F1C_COLOR_RESERVED_2                         (0xC)
-#define CODEC_F1C_COLOR_RESERVED_3                         (0xD)
-#define CODEC_F1C_COLOR_WHITE                              (0xE)
-#define CODEC_F1C_COLOR_OTHER                              (0xF)
-
-/* Configuration's misc */
-#define CODEC_F1C_MISC_MASK                                (0xF)
-#define CODEC_F1C_MISC_SHIFT                               (8)
-#define CODEC_F1C_MISC_NONE                                0
-#define CODEC_F1C_MISC_JACK_NO_PRESENCE_DETECT             RT_BIT(0)
-#define CODEC_F1C_MISC_RESERVED_0                          RT_BIT(1)
-#define CODEC_F1C_MISC_RESERVED_1                          RT_BIT(2)
-#define CODEC_F1C_MISC_RESERVED_2                          RT_BIT(3)
-
-/* Configuration default: Association */
-#define CODEC_F1C_ASSOCIATION_MASK                         (0xF)
-#define CODEC_F1C_ASSOCIATION_SHIFT                        (4)
-
-/** Reserved; don't use. */
-#define CODEC_F1C_ASSOCIATION_INVALID                      0x0
-#define CODEC_F1C_ASSOCIATION_GROUP_0                      0x1
-#define CODEC_F1C_ASSOCIATION_GROUP_1                      0x2
-#define CODEC_F1C_ASSOCIATION_GROUP_2                      0x3
-#define CODEC_F1C_ASSOCIATION_GROUP_3                      0x4
-#define CODEC_F1C_ASSOCIATION_GROUP_4                      0x5
-#define CODEC_F1C_ASSOCIATION_GROUP_5                      0x6
-#define CODEC_F1C_ASSOCIATION_GROUP_6                      0x7
-#define CODEC_F1C_ASSOCIATION_GROUP_7                      0x8
-/* Note: Windows OSes will treat group 15 (0xF) as single PIN devices.
- *       The sequence number associated with that group then will be ignored. */
-#define CODEC_F1C_ASSOCIATION_GROUP_15                     0xF
-
-/* Configuration default: Association Sequence. */
-#define CODEC_F1C_SEQ_MASK                                 (0xF)
-#define CODEC_F1C_SEQ_SHIFT                                (0)
-
-/* Implementation identification (7.3.3.30). */
-#define CODEC_MAKE_F20(bmid, bsku, aid)     \
-    (  (((bmid) & 0xFFFF) << 16)            \
-     | (((bsku) & 0xFF) << 8)               \
-     | (((aid) & 0xFF))                     \
-    )
-
-/* Macro definition helping in filling the configuration registers. */
-#define CODEC_MAKE_F1C(port_connectivity, location, device, connection_type, color, misc, association, sequence)    \
-    (  (((port_connectivity) & 0xF) << CODEC_F1C_PORT_SHIFT)            \
-     | (((location)          & 0xF) << CODEC_F1C_LOCATION_SHIFT)        \
-     | (((device)            & 0xF) << CODEC_F1C_DEVICE_SHIFT)          \
-     | (((connection_type)   & 0xF) << CODEC_F1C_CONNECTION_TYPE_SHIFT) \
-     | (((color)             & 0xF) << CODEC_F1C_COLOR_SHIFT)           \
-     | (((misc)              & 0xF) << CODEC_F1C_MISC_SHIFT)            \
-     | (((association)       & 0xF) << CODEC_F1C_ASSOCIATION_SHIFT)     \
-     | (((sequence)          & 0xF)))
-
-
-/*********************************************************************************************************************************
-*   Structures and Typedefs                                                                                                      *
-*********************************************************************************************************************************/
-/** The F00 parameter length (in dwords). */
-#define CODECNODE_F00_PARAM_LENGTH  20
-/** The F02 parameter length (in dwords). */
-#define CODECNODE_F02_PARAM_LENGTH  16
-
-/**
- * Common (or core) codec node structure.
- */
-typedef struct CODECCOMMONNODE
-{
-    /** The node's ID. */
-    uint8_t         uID;
-    /** The node's name. */
-    char const     *pszName;
-    /** The SDn ID this node is assigned to.
-     *  0 means not assigned, 1 is SDn0. */
-    uint8_t         uSD;
-    /** The SDn's channel to use.
-     *  Only valid if a valid SDn ID is set. */
-    uint8_t         uChannel;
-    /* PRM 5.3.6 */
-    uint32_t au32F00_param[CODECNODE_F00_PARAM_LENGTH];
-    uint32_t au32F02_param[CODECNODE_F02_PARAM_LENGTH];
-} CODECCOMMONNODE;
-typedef CODECCOMMONNODE *PCODECCOMMONNODE;
-AssertCompile(CODECNODE_F00_PARAM_LENGTH == 20);  /* saved state */
-AssertCompile(CODECNODE_F02_PARAM_LENGTH == 16); /* saved state */
-
-/**
- * Compile time assertion on the expected node size.
- */
-#define AssertNodeSize(a_Node, a_cParams) \
-    AssertCompile((a_cParams) <= (60 + 6)); /* the max size - saved state */ \
-    AssertCompile(   sizeof(a_Node) - sizeof(CODECCOMMONNODE)  \
-                  == (((a_cParams) * sizeof(uint32_t) + sizeof(void *) - 1) & ~(sizeof(void *) - 1)) )
-
-typedef struct ROOTCODECNODE
-{
-    CODECCOMMONNODE node;
-} ROOTCODECNODE, *PROOTCODECNODE;
-AssertNodeSize(ROOTCODECNODE, 0);
-
-#define AMPLIFIER_SIZE 60
-typedef uint32_t AMPLIFIER[AMPLIFIER_SIZE];
+
+
 #define AMPLIFIER_IN    0
 #define AMPLIFIER_OUT   1
@@ -592,197 +54,4 @@
 #define AMPLIFIER_RIGHT 0
 #define AMPLIFIER_REGISTER(amp, inout, side, index) ((amp)[30*(inout) + 15*(side) + (index)])
-typedef struct DACNODE
-{
-    CODECCOMMONNODE node;
-    uint32_t    u32F0d_param;
-    uint32_t    u32F04_param;
-    uint32_t    u32F05_param;
-    uint32_t    u32F06_param;
-    uint32_t    u32F0c_param;
-
-    uint32_t    u32A_param;
-    AMPLIFIER   B_params;
-
-} DACNODE, *PDACNODE;
-AssertNodeSize(DACNODE, 6 + 60);
-
-typedef struct ADCNODE
-{
-    CODECCOMMONNODE node;
-    uint32_t    u32F01_param;
-    uint32_t    u32F03_param;
-    uint32_t    u32F05_param;
-    uint32_t    u32F06_param;
-    uint32_t    u32F09_param;
-
-    uint32_t    u32A_param;
-    AMPLIFIER   B_params;
-} ADCNODE, *PADCNODE;
-AssertNodeSize(DACNODE, 6 + 60);
-
-typedef struct SPDIFOUTNODE
-{
-    CODECCOMMONNODE node;
-    uint32_t    u32F05_param;
-    uint32_t    u32F06_param;
-    uint32_t    u32F09_param;
-    uint32_t    u32F0d_param;
-
-    uint32_t    u32A_param;
-    AMPLIFIER   B_params;
-} SPDIFOUTNODE, *PSPDIFOUTNODE;
-AssertNodeSize(SPDIFOUTNODE, 5 + 60);
-
-typedef struct SPDIFINNODE
-{
-    CODECCOMMONNODE node;
-    uint32_t    u32F05_param;
-    uint32_t    u32F06_param;
-    uint32_t    u32F09_param;
-    uint32_t    u32F0d_param;
-
-    uint32_t    u32A_param;
-    AMPLIFIER   B_params;
-} SPDIFINNODE, *PSPDIFINNODE;
-AssertNodeSize(SPDIFINNODE, 5 + 60);
-
-typedef struct AFGCODECNODE
-{
-    CODECCOMMONNODE node;
-    uint32_t  u32F05_param;
-    uint32_t  u32F08_param;
-    uint32_t  u32F17_param;
-    uint32_t  u32F20_param;
-} AFGCODECNODE, *PAFGCODECNODE;
-AssertNodeSize(AFGCODECNODE, 4);
-
-typedef struct PORTNODE
-{
-    CODECCOMMONNODE node;
-    uint32_t u32F01_param;
-    uint32_t u32F07_param;
-    uint32_t u32F08_param;
-    uint32_t u32F09_param;
-    uint32_t u32F1c_param;
-    AMPLIFIER   B_params;
-} PORTNODE, *PPORTNODE;
-AssertNodeSize(PORTNODE, 5 + 60);
-
-typedef struct DIGOUTNODE
-{
-    CODECCOMMONNODE node;
-    uint32_t u32F01_param;
-    uint32_t u32F05_param;
-    uint32_t u32F07_param;
-    uint32_t u32F08_param;
-    uint32_t u32F09_param;
-    uint32_t u32F1c_param;
-} DIGOUTNODE, *PDIGOUTNODE;
-AssertNodeSize(DIGOUTNODE, 6);
-
-typedef struct DIGINNODE
-{
-    CODECCOMMONNODE node;
-    uint32_t u32F05_param;
-    uint32_t u32F07_param;
-    uint32_t u32F08_param;
-    uint32_t u32F09_param;
-    uint32_t u32F0c_param;
-    uint32_t u32F1c_param;
-    uint32_t u32F1e_param;
-} DIGINNODE, *PDIGINNODE;
-AssertNodeSize(DIGINNODE, 7);
-
-typedef struct ADCMUXNODE
-{
-    CODECCOMMONNODE node;
-    uint32_t    u32F01_param;
-
-    uint32_t    u32A_param;
-    AMPLIFIER   B_params;
-} ADCMUXNODE, *PADCMUXNODE;
-AssertNodeSize(ADCMUXNODE, 2 + 60);
-
-typedef struct PCBEEPNODE
-{
-    CODECCOMMONNODE node;
-    uint32_t    u32F07_param;
-    uint32_t    u32F0a_param;
-
-    uint32_t    u32A_param;
-    AMPLIFIER   B_params;
-    uint32_t    u32F1c_param;
-} PCBEEPNODE, *PPCBEEPNODE;
-AssertNodeSize(PCBEEPNODE, 3 + 60 + 1);
-
-typedef struct CDNODE
-{
-    CODECCOMMONNODE node;
-    uint32_t u32F07_param;
-    uint32_t u32F1c_param;
-} CDNODE, *PCDNODE;
-AssertNodeSize(CDNODE, 2);
-
-typedef struct VOLUMEKNOBNODE
-{
-    CODECCOMMONNODE node;
-    uint32_t    u32F08_param;
-    uint32_t    u32F0f_param;
-} VOLUMEKNOBNODE, *PVOLUMEKNOBNODE;
-AssertNodeSize(VOLUMEKNOBNODE, 2);
-
-typedef struct ADCVOLNODE
-{
-    CODECCOMMONNODE node;
-    uint32_t    u32F0c_param;
-    uint32_t    u32F01_param;
-    uint32_t    u32A_params;
-    AMPLIFIER   B_params;
-} ADCVOLNODE, *PADCVOLNODE;
-AssertNodeSize(ADCVOLNODE, 3 + 60);
-
-typedef struct RESNODE
-{
-    CODECCOMMONNODE node;
-    uint32_t    u32F05_param;
-    uint32_t    u32F06_param;
-    uint32_t    u32F07_param;
-    uint32_t    u32F1c_param;
-
-    uint32_t    u32A_param;
-} RESNODE, *PRESNODE;
-AssertNodeSize(RESNODE, 5);
-
-/**
- * Used for the saved state.
- */
-typedef struct CODECSAVEDSTATENODE
-{
-    CODECCOMMONNODE Core;
-    uint32_t        au32Params[60 + 6];
-} CODECSAVEDSTATENODE;
-AssertNodeSize(CODECSAVEDSTATENODE, 60 + 6);
-
-typedef union CODECNODE
-{
-    CODECCOMMONNODE node;
-    ROOTCODECNODE   root;
-    AFGCODECNODE    afg;
-    DACNODE         dac;
-    ADCNODE         adc;
-    SPDIFOUTNODE    spdifout;
-    SPDIFINNODE     spdifin;
-    PORTNODE        port;
-    DIGOUTNODE      digout;
-    DIGINNODE       digin;
-    ADCMUXNODE      adcmux;
-    PCBEEPNODE      pcbeep;
-    CDNODE          cdnode;
-    VOLUMEKNOBNODE  volumeKnob;
-    ADCVOLNODE      adcvol;
-    RESNODE         reserved;
-    CODECSAVEDSTATENODE SavedState;
-} CODECNODE, *PCODECNODE;
-AssertNodeSize(CODECNODE, 60 + 6);
 
 
@@ -845,5 +114,7 @@
 static uint8_t const g_abStac9220Reserveds[]  = { STAC9220_NID_SPDIF_IN, STAC9221_NID_ADAT_OUT, STAC9221_NID_I2S_OUT, STAC9221_NID_PIN_I2S_OUT, 0 };
 
-/** SSM description of a CODECNODE. */
+#ifdef IN_RING3
+
+/** SSM description of CODECCOMMONNODE. */
 static SSMFIELD const g_aCodecNodeFields[] =
 {
@@ -856,5 +127,5 @@
 };
 
-/** Backward compatibility with v1 of the CODECNODE. */
+/** Backward compatibility with v1 of CODECCOMMONNODE. */
 static SSMFIELD const g_aCodecNodeFieldsV1[] =
 {
@@ -868,5 +139,5 @@
 };
 
-
+#endif /* IN_RING3 */
 
 #if 0 /* unused */
@@ -876,5 +147,5 @@
     for (uint8_t i = 1; i < pThis->cTotalNodes; i++)
     {
-        PCODECNODE pNode = &pThis->paNodes[i];
+        PCODECNODE pNode = &pThis->aNodes[i];
         AMPLIFIER *pAmp = &pNode->dac.B_params;
 
@@ -886,34 +157,13 @@
 }
 #endif
-
-/**
- * Resets the codec with all its connected nodes.
- *
- * @param   pThis               HDA codec to reset.
- */
-static DECLCALLBACK(void) stac9220Reset(PHDACODEC pThis)
-{
-    AssertPtrReturnVoid(pThis->paNodes);
-    AssertPtrReturnVoid(pThis->pfnNodeReset);
-
-    LogRel(("HDA: Codec reset\n"));
-
-    pThis->fInReset = true;
-
-    for (uint8_t i = 0; i < pThis->cTotalNodes; i++)
-        pThis->pfnNodeReset(pThis, i, &pThis->paNodes[i]);
-
-    pThis->fInReset = false;
-}
 
 /**
  * Resets a single node of the codec.
  *
- * @returns IPRT status code.
  * @param   pThis               HDA codec of node to reset.
  * @param   uNID                Node ID to set node to.
  * @param   pNode               Node to reset.
  */
-static DECLCALLBACK(int) stac9220ResetNode(PHDACODEC pThis, uint8_t uNID, PCODECNODE pNode)
+static void stac9220NodeReset(PHDACODEC pThis, uint8_t uNID, PCODECNODE pNode)
 {
     LogFlowFunc(("NID=0x%x (%RU8)\n", uNID, uNID));
@@ -1062,5 +312,5 @@
 
             /* Use a fixed format from AFG. */
-            pNode->spdifout.node.au32F00_param[0xA] = pThis->paNodes[STAC9220_NID_AFG].node.au32F00_param[0xA];
+            pNode->spdifout.node.au32F00_param[0xA] = pThis->aNodes[STAC9220_NID_AFG].node.au32F00_param[0xA];
             pNode->spdifout.node.au32F00_param[0xB] = CODEC_F00_0B_PCM;
             break;
@@ -1080,5 +330,5 @@
 
             /* Use a fixed format from AFG. */
-            pNode->spdifin.node.au32F00_param[0xA] = pThis->paNodes[STAC9220_NID_AFG].node.au32F00_param[0xA];
+            pNode->spdifin.node.au32F00_param[0xA] = pThis->aNodes[STAC9220_NID_AFG].node.au32F00_param[0xA];
             pNode->spdifin.node.au32F00_param[0xB] = CODEC_F00_0B_PCM;
 
@@ -1475,15 +725,27 @@
             break;
     }
-
-    return VINF_SUCCESS;
+}
+
+/**
+ * Resets the codec with all its connected nodes.
+ *
+ * @param   pThis               HDA codec to reset.
+ */
+static DECLCALLBACK(void) stac9220Reset(PHDACODEC pThis)
+{
+    AssertPtrReturnVoid(pThis->aNodes);
+
+    LogRel(("HDA: Codec reset\n"));
+
+    pThis->fInReset = true;
+
+    for (uint8_t i = 0; i < pThis->cTotalNodes; i++)
+        stac9220NodeReset(pThis, i, &pThis->aNodes[i]);
+
+    pThis->fInReset = false;
 }
 
 static int stac9220Construct(PHDACODEC pThis)
 {
-    unconst(pThis->cTotalNodes) = STAC9221_NUM_NODES;
-
-    pThis->pfnReset     = stac9220Reset;
-    pThis->pfnNodeReset = stac9220ResetNode;
-
     pThis->u16VendorId  = 0x8384; /* SigmaTel */
     /*
@@ -1496,11 +758,7 @@
     pThis->u8AssemblyId = 0x80;
 
-    pThis->paNodes = (PCODECNODE)RTMemAllocZ(sizeof(CODECNODE) * pThis->cTotalNodes);
-    if (!pThis->paNodes)
-        return VERR_NO_MEMORY;
-
     pThis->fInReset = false;
 
-#define STAC9220WIDGET(type) pThis->au8##type##s = g_abStac9220##type##s
+#define STAC9220WIDGET(type) memcpy(&pThis->au8##type##s, &g_abStac9220##type##s, sizeof(uint8_t) * RT_ELEMENTS(g_abStac9220##type##s));
     STAC9220WIDGET(Port);
     STAC9220WIDGET(Dac);
@@ -1518,6 +776,9 @@
 #undef STAC9220WIDGET
 
-    unconst(pThis->u8AdcVolsLineIn) = STAC9220_NID_AMP_ADC0;
-    unconst(pThis->u8DacLineOut)    = STAC9220_NID_DAC1;
+    pThis->cTotalNodes = STAC9221_NUM_NODES;
+    Assert(pThis->cTotalNodes <= CODEC_NODES_MAX);
+
+    pThis->u8AdcVolsLineIn = STAC9220_NID_AMP_ADC0;
+    pThis->u8DacLineOut    = STAC9220_NID_DAC1;
 
     /*
@@ -1528,12 +789,16 @@
      *       initialize the node default configuration values then!
      */
-    AssertPtr(pThis->paNodes);
-    AssertPtr(pThis->pfnNodeReset);
-
     for (uint8_t i = 0; i < pThis->cTotalNodes; i++)
-    {
-        int rc2 = stac9220ResetNode(pThis, i, &pThis->paNodes[i]);
-        AssertRC(rc2);
-    }
+        stac9220NodeReset(pThis, i, &pThis->aNodes[i]);
+
+    /* Common root node initializers. */
+    pThis->aNodes[STAC9220_NID_ROOT].root.node.au32F00_param[0] = CODEC_MAKE_F00_00(pThis->u16VendorId, pThis->u16DeviceId);
+    pThis->aNodes[STAC9220_NID_ROOT].root.node.au32F00_param[4] = CODEC_MAKE_F00_04(0x1, 0x1);
+
+    /* Common AFG node initializers. */
+    pThis->aNodes[STAC9220_NID_AFG].afg.node.au32F00_param[0x4] = CODEC_MAKE_F00_04(0x2, pThis->cTotalNodes - 2);
+    pThis->aNodes[STAC9220_NID_AFG].afg.node.au32F00_param[0x5] = CODEC_MAKE_F00_05(1, CODEC_F00_05_AFG);
+    pThis->aNodes[STAC9220_NID_AFG].afg.node.au32F00_param[0xA] = CODEC_F00_0A_44_1KHZ | CODEC_F00_0A_16_BIT;
+    pThis->aNodes[STAC9220_NID_AFG].afg.u32F20_param = CODEC_MAKE_F20(pThis->u16VendorId, pThis->u8BSKU, pThis->u8AssemblyId);
 
     return VINF_SUCCESS;
@@ -1581,9 +846,10 @@
 DECLISNODEOFTYPE(Reserved)
 
+#ifdef IN_RING3
 
 /*
  * Misc helpers.
  */
-static int hdaCodecToAudVolume(PHDACODEC pThis, PCODECNODE pNode, AMPLIFIER *pAmp, PDMAUDIOMIXERCTL enmMixerCtl)
+static int hdaR3CodecToAudVolume(PHDACODECR3 pThisCC, PCODECNODE pNode, AMPLIFIER *pAmp, PDMAUDIOMIXERCTL enmMixerCtl)
 {
     RT_NOREF(pNode);
@@ -1631,6 +897,8 @@
              DrvAudioHlpAudMixerCtlToStr(enmMixerCtl), lVol, rVol, RT_BOOL(iMute) ? "Muted" : "Unmuted"));
 
-    return pThis->pfnCbMixerSetVolume(pThis->pDevIns, enmMixerCtl, &Vol);
-}
+    return pThisCC->pfnCbMixerSetVolume(pThisCC->pDevIns, enmMixerCtl, &Vol);
+}
+
+#endif /* IN_RING3 */
 
 DECLINLINE(void) hdaCodecSetRegister(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset, uint32_t mask)
@@ -1685,5 +953,5 @@
     uint8_t u8Index = CODEC_GET_AMP_DIRECTION(cmd) == AMPLIFIER_OUT ? 0 : CODEC_GET_AMP_INDEX(cmd);
 
-    PCODECNODE pNode = &pThis->paNodes[CODEC_NID(cmd)];
+    PCODECNODE pNode = &pThis->aNodes[CODEC_NID(cmd)];
     if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
         *pResp = AMPLIFIER_REGISTER(pNode->dac.B_params,
@@ -1722,10 +990,12 @@
 }
 
+#ifdef IN_RING3
+
 /* 3-- */
-static DECLCALLBACK(int) vrbProcSetAmplifier(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    *pResp = 0;
-
-    PCODECNODE pNode      = &pThis->paNodes[CODEC_NID(cmd)];
+static DECLCALLBACK(int) vrbProcR3SetAmplifier(PHDACODEC pThis, PHDACODECR3 pThisCC, uint32_t cmd, uint64_t *pResp)
+{
+    *pResp = 0;
+
+    PCODECNODE pNode      = &pThis->aNodes[CODEC_NID(cmd)];
     AMPLIFIER *pAmplifier = NULL;
     if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
@@ -1770,5 +1040,5 @@
     //    if (CODEC_NID(cmd) == pThis->u8AdcVolsLineIn)
     //    {
-            hdaCodecToAudVolume(pThis, pNode, pAmplifier, PDMAUDIOMIXERCTL_LINE_IN);
+            hdaR3CodecToAudVolume(pThisCC, pNode, pAmplifier, PDMAUDIOMIXERCTL_LINE_IN);
     //    }
     }
@@ -1781,9 +1051,11 @@
 
         if (CODEC_NID(cmd) == pThis->u8DacLineOut)
-            hdaCodecToAudVolume(pThis, pNode, pAmplifier, PDMAUDIOMIXERCTL_FRONT);
-    }
-
-    return VINF_SUCCESS;
-}
+            hdaR3CodecToAudVolume(pThisCC, pNode, pAmplifier, PDMAUDIOMIXERCTL_FRONT);
+    }
+
+    return VINF_SUCCESS;
+}
+
+#endif /* IN_RING3 */
 
 static DECLCALLBACK(int) vrbProcGetParameter(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
@@ -1798,5 +1070,5 @@
     }
 
-    *pResp = pThis->paNodes[CODEC_NID(cmd)].node.au32F00_param[cmd & CODEC_VERB_8BIT_DATA];
+    *pResp = pThis->aNodes[CODEC_NID(cmd)].node.au32F00_param[cmd & CODEC_VERB_8BIT_DATA];
     return VINF_SUCCESS;
 }
@@ -1808,13 +1080,13 @@
 
     if (hdaCodecIsAdcMuxNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].adcmux.u32F01_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].adcmux.u32F01_param;
     else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].digout.u32F01_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].digout.u32F01_param;
     else if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].port.u32F01_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].port.u32F01_param;
     else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].adc.u32F01_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].adc.u32F01_param;
     else if (hdaCodecIsAdcVolNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].adcvol.u32F01_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].adcvol.u32F01_param;
     else
         LogRel2(("HDA: Warning: Unhandled get connection select control command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
@@ -1830,13 +1102,13 @@
     uint32_t *pu32Reg = NULL;
     if (hdaCodecIsAdcMuxNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].adcmux.u32F01_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].adcmux.u32F01_param;
     else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digout.u32F01_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].digout.u32F01_param;
     else if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].port.u32F01_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].port.u32F01_param;
     else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].adc.u32F01_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].adc.u32F01_param;
     else if (hdaCodecIsAdcVolNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].adcvol.u32F01_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].adcvol.u32F01_param;
     else
         LogRel2(("HDA: Warning: Unhandled set connection select control command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
@@ -1854,15 +1126,15 @@
 
     if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].port.u32F07_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].port.u32F07_param;
     else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].digout.u32F07_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].digout.u32F07_param;
     else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F07_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].digin.u32F07_param;
     else if (hdaCodecIsCdNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].cdnode.u32F07_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].cdnode.u32F07_param;
     else if (hdaCodecIsPcbeepNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].pcbeep.u32F07_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].pcbeep.u32F07_param;
     else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].reserved.u32F07_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].reserved.u32F07_param;
     else
         LogRel2(("HDA: Warning: Unhandled get pin control command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
@@ -1878,16 +1150,16 @@
     uint32_t *pu32Reg = NULL;
     if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].port.u32F07_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].port.u32F07_param;
     else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F07_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].digin.u32F07_param;
     else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digout.u32F07_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].digout.u32F07_param;
     else if (hdaCodecIsCdNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].cdnode.u32F07_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].cdnode.u32F07_param;
     else if (hdaCodecIsPcbeepNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].pcbeep.u32F07_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].pcbeep.u32F07_param;
     else if (   hdaCodecIsReservedNode(pThis, CODEC_NID(cmd))
              && CODEC_NID(cmd) == 0x1b)
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].reserved.u32F07_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].reserved.u32F07_param;
     else
         LogRel2(("HDA: Warning: Unhandled set pin control command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
@@ -1905,15 +1177,15 @@
 
     if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].port.u32F08_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].port.u32F08_param;
     else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F08_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].digin.u32F08_param;
     else if ((cmd) == STAC9220_NID_AFG)
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].afg.u32F08_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].afg.u32F08_param;
     else if (hdaCodecIsVolKnobNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].volumeKnob.u32F08_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].volumeKnob.u32F08_param;
     else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].digout.u32F08_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].digout.u32F08_param;
     else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F08_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].digin.u32F08_param;
     else
         LogRel2(("HDA: Warning: Unhandled get unsolicited enabled command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
@@ -1929,15 +1201,15 @@
     uint32_t *pu32Reg = NULL;
     if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].port.u32F08_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].port.u32F08_param;
     else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F08_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].digin.u32F08_param;
     else if (CODEC_NID(cmd) == STAC9220_NID_AFG)
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].afg.u32F08_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].afg.u32F08_param;
     else if (hdaCodecIsVolKnobNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].volumeKnob.u32F08_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].volumeKnob.u32F08_param;
     else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F08_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].digin.u32F08_param;
     else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digout.u32F08_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].digout.u32F08_param;
     else
         LogRel2(("HDA: Warning: Unhandled set unsolicited enabled command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
@@ -1955,7 +1227,7 @@
 
     if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].port.u32F09_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].port.u32F09_param;
     else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F09_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].digin.u32F09_param;
     else
     {
@@ -1974,7 +1246,7 @@
     uint32_t *pu32Reg = NULL;
     if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].port.u32F09_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].port.u32F09_param;
     else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F09_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].digin.u32F09_param;
     else
         LogRel2(("HDA: Warning: Unhandled set pin sense command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
@@ -1996,5 +1268,5 @@
         return VINF_SUCCESS;
     }
-    *pResp = pThis->paNodes[CODEC_NID(cmd)].node.au32F02_param[cmd & CODEC_VERB_8BIT_DATA];
+    *pResp = pThis->aNodes[CODEC_NID(cmd)].node.au32F02_param[cmd & CODEC_VERB_8BIT_DATA];
     return VINF_SUCCESS;
 }
@@ -2006,5 +1278,5 @@
 
     if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].adc.u32F03_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].adc.u32F03_param;
 
     return VINF_SUCCESS;
@@ -2017,5 +1289,5 @@
 
     if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
-        hdaCodecSetRegisterU8(&pThis->paNodes[CODEC_NID(cmd)].adc.u32F03_param, cmd, 0);
+        hdaCodecSetRegisterU8(&pThis->aNodes[CODEC_NID(cmd)].adc.u32F03_param, cmd, 0);
     return VINF_SUCCESS;
 }
@@ -2027,7 +1299,7 @@
 
     if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F0d_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].spdifout.u32F0d_param;
     else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F0d_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].spdifin.u32F0d_param;
 
     return VINF_SUCCESS;
@@ -2039,7 +1311,7 @@
 
     if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
-        hdaCodecSetRegisterU8(&pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F0d_param, cmd, u8Offset);
+        hdaCodecSetRegisterU8(&pThis->aNodes[CODEC_NID(cmd)].spdifout.u32F0d_param, cmd, u8Offset);
     else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
-        hdaCodecSetRegisterU8(&pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F0d_param, cmd, u8Offset);
+        hdaCodecSetRegisterU8(&pThis->aNodes[CODEC_NID(cmd)].spdifin.u32F0d_param, cmd, u8Offset);
     return VINF_SUCCESS;
 }
@@ -2068,5 +1340,5 @@
     }
     if (CODEC_NID(cmd) == STAC9220_NID_AFG)
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].afg.u32F20_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].afg.u32F20_param;
     else
         *pResp = 0;
@@ -2085,5 +1357,5 @@
     uint32_t *pu32Reg;
     if (CODEC_NID(cmd) == STAC9220_NID_AFG)
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].afg.u32F20_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].afg.u32F20_param;
     else
         AssertFailedReturn(VINF_SUCCESS);
@@ -2123,11 +1395,14 @@
 {
     Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) == STAC9220_NID_AFG);
-
-    if (   CODEC_NID(cmd) == STAC9220_NID_AFG
-        && pThis->pfnReset)
-    {
-        pThis->pfnReset(pThis);
-    }
+
+    if (pThis->enmType == CODEC_TYPE_STAC9220)
+    {
+        Assert(CODEC_NID(cmd) == STAC9220_NID_AFG);
+
+        if (CODEC_NID(cmd) == STAC9220_NID_AFG)
+            stac9220Reset(pThis);
+    }
+    else
+        AssertFailedReturn(VERR_NOT_IMPLEMENTED);
 
     *pResp = 0;
@@ -2141,19 +1416,19 @@
 
     if (CODEC_NID(cmd) == STAC9220_NID_AFG)
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].afg.u32F05_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].afg.u32F05_param;
     else if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].dac.u32F05_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].dac.u32F05_param;
     else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].adc.u32F05_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].adc.u32F05_param;
     else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F05_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].digin.u32F05_param;
     else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].digout.u32F05_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].digout.u32F05_param;
     else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F05_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].spdifout.u32F05_param;
     else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F05_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].spdifin.u32F05_param;
     else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].reserved.u32F05_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].reserved.u32F05_param;
     else
         LogRel2(("HDA: Warning: Unhandled get power state command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
@@ -2172,19 +1447,19 @@
     uint32_t *pu32Reg = NULL;
     if (CODEC_NID(cmd) == STAC9220_NID_AFG)
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].afg.u32F05_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].afg.u32F05_param;
     else if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].dac.u32F05_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].dac.u32F05_param;
     else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F05_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].digin.u32F05_param;
     else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digout.u32F05_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].digout.u32F05_param;
     else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].adc.u32F05_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].adc.u32F05_param;
     else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F05_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].spdifout.u32F05_param;
     else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F05_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].spdifin.u32F05_param;
     else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].reserved.u32F05_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].reserved.u32F05_param;
     else
     {
@@ -2205,6 +1480,6 @@
              CODEC_NID(cmd), uPwrCmd, fReset, fStopOk, fError, uPwrAct, uPwrSet));
     LogFunc(("AFG: Act=D%RU8, Set=D%RU8\n",
-            CODEC_F05_ACT(pThis->paNodes[STAC9220_NID_AFG].afg.u32F05_param),
-            CODEC_F05_SET(pThis->paNodes[STAC9220_NID_AFG].afg.u32F05_param)));
+            CODEC_F05_ACT(pThis->aNodes[STAC9220_NID_AFG].afg.u32F05_param),
+            CODEC_F05_SET(pThis->aNodes[STAC9220_NID_AFG].afg.u32F05_param)));
 #endif
 
@@ -2212,5 +1487,5 @@
         *pu32Reg = CODEC_MAKE_F05(fReset, fStopOk, 0, uPwrCmd /* PS-Act */, uPwrCmd /* PS-Set */);
 
-    const uint8_t uAFGPwrAct = CODEC_F05_ACT(pThis->paNodes[STAC9220_NID_AFG].afg.u32F05_param);
+    const uint8_t uAFGPwrAct = CODEC_F05_ACT(pThis->aNodes[STAC9220_NID_AFG].afg.u32F05_param);
     if (uAFGPwrAct == CODEC_F05_D0) /* Only propagate power state if AFG is on (D0). */
     {
@@ -2223,9 +1498,9 @@
             while (*(++pu8NodeIndex)) \
             { \
-                pThis->paNodes[*pu8NodeIndex]._aMember.u32F05_param = \
+                pThis->aNodes[*pu8NodeIndex]._aMember.u32F05_param = \
                     CODEC_MAKE_F05(fReset, fStopOk, 0, uAFGPwrAct, uPwrCmd); \
                 LogFunc(("\t[NID0x%02x]: Act=D%RU8, Set=D%RU8\n", *pu8NodeIndex, \
-                         CODEC_F05_ACT(pThis->paNodes[*pu8NodeIndex]._aMember.u32F05_param), \
-                         CODEC_F05_SET(pThis->paNodes[*pu8NodeIndex]._aMember.u32F05_param))); \
+                         CODEC_F05_ACT(pThis->aNodes[*pu8NodeIndex]._aMember.u32F05_param), \
+                         CODEC_F05_SET(pThis->aNodes[*pu8NodeIndex]._aMember.u32F05_param))); \
             } \
         }
@@ -2280,17 +1555,17 @@
     uint32_t *pu32Reg;
     if (CODEC_NID(cmd) == 1 /* AFG */)
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].afg.u32F05_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].afg.u32F05_param;
     else if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].dac.u32F05_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].dac.u32F05_param;
     else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F05_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].digin.u32F05_param;
     else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].adc.u32F05_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].adc.u32F05_param;
     else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F05_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].spdifout.u32F05_param;
     else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F05_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].spdifin.u32F05_param;
     else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].reserved.u32F05_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].reserved.u32F05_param;
     else
         AssertFailedReturn(VINF_SUCCESS);
@@ -2305,5 +1580,5 @@
          */
         *pu32Reg = CODEC_MAKE_F05(fReset, fStopOk, 0,
-                                  CODEC_F05_ACT(pThis->paNodes[1].afg.u32F05_param),
+                                  CODEC_F05_ACT(pThis->aNodes[1].afg.u32F05_param),
                                   CODEC_F05_SET(cmd));
     }
@@ -2311,5 +1586,5 @@
     /* Propagate next power state only if AFG is on or verb modifies AFG power state */
     if (   CODEC_NID(cmd) == 1 /* AFG */
-        || !CODEC_F05_ACT(pThis->paNodes[1].afg.u32F05_param))
+        || !CODEC_F05_ACT(pThis->aNodes[1].afg.u32F05_param))
     {
         *pu32Reg = CODEC_MAKE_F05(fReset, fStopOk, 0, CODEC_F05_SET(cmd), CODEC_F05_SET(cmd));
@@ -2320,13 +1595,13 @@
             const uint8_t *pu8NodeIndex = &pThis->au8Dacs[0];
             while (*(++pu8NodeIndex))
-                codecPropogatePowerState(&pThis->paNodes[*pu8NodeIndex].dac.u32F05_param);
+                codecPropogatePowerState(&pThis->aNodes[*pu8NodeIndex].dac.u32F05_param);
 
             pu8NodeIndex = &pThis->au8Adcs[0];
             while (*(++pu8NodeIndex))
-                codecPropogatePowerState(&pThis->paNodes[*pu8NodeIndex].adc.u32F05_param);
+                codecPropogatePowerState(&pThis->aNodes[*pu8NodeIndex].adc.u32F05_param);
 
             pu8NodeIndex = &pThis->au8DigInPins[0];
             while (*(++pu8NodeIndex))
-                codecPropogatePowerState(&pThis->paNodes[*pu8NodeIndex].digin.u32F05_param);
+                codecPropogatePowerState(&pThis->aNodes[*pu8NodeIndex].digin.u32F05_param);
         }
     }
@@ -2341,13 +1616,13 @@
 
     if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].dac.u32F06_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].dac.u32F06_param;
     else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].adc.u32F06_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].adc.u32F06_param;
     else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F06_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].spdifin.u32F06_param;
     else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F06_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].spdifout.u32F06_param;
     else if (CODEC_NID(cmd) == STAC9221_NID_I2S_OUT)
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].reserved.u32F06_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].reserved.u32F06_param;
     else
         LogRel2(("HDA: Warning: Unhandled get stream ID command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
@@ -2359,6 +1634,8 @@
 }
 
+#ifdef IN_RING3
+
 /* 706 */
-static DECLCALLBACK(int) vrbProcSetStreamId(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+static DECLCALLBACK(int) vrbProcR3SetStreamId(PHDACODEC pThis, PHDACODECR3 pThisCC, uint32_t cmd, uint64_t *pResp)
 {
     *pResp = 0;
@@ -2377,20 +1654,20 @@
     if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
     {
-        pu32Addr = &pThis->paNodes[CODEC_NID(cmd)].dac.u32F06_param;
+        pu32Addr = &pThis->aNodes[CODEC_NID(cmd)].dac.u32F06_param;
         enmDir = PDMAUDIODIR_OUT;
     }
     else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
     {
-        pu32Addr = &pThis->paNodes[CODEC_NID(cmd)].adc.u32F06_param;
+        pu32Addr = &pThis->aNodes[CODEC_NID(cmd)].adc.u32F06_param;
         enmDir = PDMAUDIODIR_IN;
     }
     else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
     {
-        pu32Addr = &pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F06_param;
+        pu32Addr = &pThis->aNodes[CODEC_NID(cmd)].spdifout.u32F06_param;
         enmDir = PDMAUDIODIR_OUT;
     }
     else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
     {
-        pu32Addr = &pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F06_param;
+        pu32Addr = &pThis->aNodes[CODEC_NID(cmd)].spdifin.u32F06_param;
         enmDir = PDMAUDIODIR_IN;
     }
@@ -2404,6 +1681,6 @@
     if (enmDir != PDMAUDIODIR_UNKNOWN)
     {
-        pThis->paNodes[CODEC_NID(cmd)].node.uSD      = uSD;
-        pThis->paNodes[CODEC_NID(cmd)].node.uChannel = uChannel;
+        pThis->aNodes[CODEC_NID(cmd)].node.uSD      = uSD;
+        pThis->aNodes[CODEC_NID(cmd)].node.uChannel = uChannel;
 
         if (enmDir == PDMAUDIODIR_OUT)
@@ -2412,15 +1689,15 @@
 
             /* Propagate to the controller. */
-            pThis->pfnCbMixerControl(pThis->pDevIns, PDMAUDIOMIXERCTL_FRONT,      uSD, uChannel);
+            pThisCC->pfnCbMixerControl(pThisCC->pDevIns, PDMAUDIOMIXERCTL_FRONT,      uSD, uChannel);
 #ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
-            pThis->pfnCbMixerControl(pThis->pDevIns, PDMAUDIOMIXERCTL_CENTER_LFE, uSD, uChannel);
-            pThis->pfnCbMixerControl(pThis->pDevIns, PDMAUDIOMIXERCTL_REAR,       uSD, uChannel);
+            pThisCC->pfnCbMixerControl(pThisCC->pDevIns, PDMAUDIOMIXERCTL_CENTER_LFE, uSD, uChannel);
+            pThisCC->pfnCbMixerControl(pThisCC->pDevIns, PDMAUDIOMIXERCTL_REAR,       uSD, uChannel);
 #endif
         }
         else if (enmDir == PDMAUDIODIR_IN)
         {
-            pThis->pfnCbMixerControl(pThis->pDevIns, PDMAUDIOMIXERCTL_LINE_IN,    uSD, uChannel);
+            pThisCC->pfnCbMixerControl(pThisCC->pDevIns, PDMAUDIOMIXERCTL_LINE_IN,    uSD, uChannel);
 #ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
-            pThis->pfnCbMixerControl(pThis->pDevIns, PDMAUDIOMIXERCTL_MIC_IN,     uSD, uChannel);
+            pThisCC->pfnCbMixerControl(pThisCC->pDevIns, PDMAUDIOMIXERCTL_MIC_IN,     uSD, uChannel);
 #endif
         }
@@ -2433,4 +1710,6 @@
 }
 
+#endif /* IN_RING3 */
+
 /* A0 */
 static DECLCALLBACK(int) vrbProcGetConverterFormat(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
@@ -2439,13 +1718,13 @@
 
     if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].dac.u32A_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].dac.u32A_param;
     else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].adc.u32A_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].adc.u32A_param;
     else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifout.u32A_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].spdifout.u32A_param;
     else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifin.u32A_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].spdifin.u32A_param;
     else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].reserved.u32A_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].reserved.u32A_param;
     else
         LogRel2(("HDA: Warning: Unhandled get converter format command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
@@ -2460,11 +1739,11 @@
 
     if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
-        hdaCodecSetRegisterU16(&pThis->paNodes[CODEC_NID(cmd)].dac.u32A_param, cmd, 0);
+        hdaCodecSetRegisterU16(&pThis->aNodes[CODEC_NID(cmd)].dac.u32A_param, cmd, 0);
     else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
-        hdaCodecSetRegisterU16(&pThis->paNodes[CODEC_NID(cmd)].adc.u32A_param, cmd, 0);
+        hdaCodecSetRegisterU16(&pThis->aNodes[CODEC_NID(cmd)].adc.u32A_param, cmd, 0);
     else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
-        hdaCodecSetRegisterU16(&pThis->paNodes[CODEC_NID(cmd)].spdifout.u32A_param, cmd, 0);
+        hdaCodecSetRegisterU16(&pThis->aNodes[CODEC_NID(cmd)].spdifout.u32A_param, cmd, 0);
     else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
-        hdaCodecSetRegisterU16(&pThis->paNodes[CODEC_NID(cmd)].spdifin.u32A_param, cmd, 0);
+        hdaCodecSetRegisterU16(&pThis->aNodes[CODEC_NID(cmd)].spdifin.u32A_param, cmd, 0);
     else
         LogRel2(("HDA: Warning: Unhandled set converter format command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
@@ -2479,9 +1758,9 @@
 
     if (hdaCodecIsAdcVolNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].adcvol.u32F0c_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].adcvol.u32F0c_param;
     else if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].dac.u32F0c_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].dac.u32F0c_param;
     else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F0c_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].digin.u32F0c_param;
     else
         LogRel2(("HDA: Warning: Unhandled get EAPD/BTL enabled command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
@@ -2497,9 +1776,9 @@
     uint32_t *pu32Reg = NULL;
     if (hdaCodecIsAdcVolNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].adcvol.u32F0c_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].adcvol.u32F0c_param;
     else if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].dac.u32F0c_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].dac.u32F0c_param;
     else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F0c_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].digin.u32F0c_param;
     else
         LogRel2(("HDA: Warning: Unhandled set EAPD/BTL enabled command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
@@ -2517,5 +1796,5 @@
 
     if (hdaCodecIsVolKnobNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].volumeKnob.u32F0f_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].volumeKnob.u32F0f_param;
     else
         LogRel2(("HDA: Warning: Unhandled get volume knob control command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
@@ -2531,5 +1810,5 @@
     uint32_t *pu32Reg = NULL;
     if (hdaCodecIsVolKnobNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].volumeKnob.u32F0f_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].volumeKnob.u32F0f_param;
     else
         LogRel2(("HDA: Warning: Unhandled set volume knob control command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
@@ -2580,5 +1859,5 @@
     /* Note: this is true for ALC885. */
     if (CODEC_NID(cmd) == STAC9220_NID_AFG)
-        *pResp = pThis->paNodes[1].afg.u32F17_param;
+        *pResp = pThis->aNodes[1].afg.u32F17_param;
     else
         LogRel2(("HDA: Warning: Unhandled get GPIO direction command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
@@ -2594,5 +1873,5 @@
     uint32_t *pu32Reg = NULL;
     if (CODEC_NID(cmd) == STAC9220_NID_AFG)
-        pu32Reg = &pThis->paNodes[1].afg.u32F17_param;
+        pu32Reg = &pThis->aNodes[1].afg.u32F17_param;
     else
         LogRel2(("HDA: Warning: Unhandled set GPIO direction command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
@@ -2610,15 +1889,15 @@
 
     if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].port.u32F1c_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].port.u32F1c_param;
     else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].digout.u32F1c_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].digout.u32F1c_param;
     else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F1c_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].digin.u32F1c_param;
     else if (hdaCodecIsPcbeepNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].pcbeep.u32F1c_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].pcbeep.u32F1c_param;
     else if (hdaCodecIsCdNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].cdnode.u32F1c_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].cdnode.u32F1c_param;
     else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].reserved.u32F1c_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].reserved.u32F1c_param;
     else
         LogRel2(("HDA: Warning: Unhandled get config command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
@@ -2631,15 +1910,15 @@
     uint32_t *pu32Reg = NULL;
     if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].port.u32F1c_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].port.u32F1c_param;
     else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F1c_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].digin.u32F1c_param;
     else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digout.u32F1c_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].digout.u32F1c_param;
     else if (hdaCodecIsCdNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].cdnode.u32F1c_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].cdnode.u32F1c_param;
     else if (hdaCodecIsPcbeepNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].pcbeep.u32F1c_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].pcbeep.u32F1c_param;
     else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].reserved.u32F1c_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].reserved.u32F1c_param;
     else
         LogRel2(("HDA: Warning: Unhandled set config command (%RU8) for NID0x%02x: 0x%x\n", u8Offset, CODEC_NID(cmd), cmd));
@@ -2685,5 +1964,5 @@
 
     if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].dac.u32F04_param;
+        *pResp = pThis->aNodes[CODEC_NID(cmd)].dac.u32F04_param;
     else
         LogRel2(("HDA: Warning: Unhandled get SDI select command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
@@ -2699,5 +1978,5 @@
     uint32_t *pu32Reg = NULL;
     if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].dac.u32F04_param;
+        pu32Reg = &pThis->aNodes[CODEC_NID(cmd)].dac.u32F04_param;
     else
         LogRel2(("HDA: Warning: Unhandled set SDI select command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
@@ -2709,10 +1988,26 @@
 }
 
+#ifdef IN_RING3
+
 /**
- * HDA codec verb map.
+ * HDA codec verb map for ring-3.
+ */
+static const CODECVERBR3 g_aCodecVerbsR3[] =
+{
+   /* Verb        Verb mask            Callback                        Name
+    * ---------- --------------------- ----------------------------------------------------------
+    */
+   { 0x00070600, CODEC_VERB_8BIT_CMD , vrbProcR3SetStreamId          , "SetStreamId           " },
+   { 0x00030000, CODEC_VERB_16BIT_CMD, vrbProcR3SetAmplifier         , "SetAmplifier          " }
+};
+
+#endif /* IN_RING3 */
+
+/**
+ * HDA codec verb map for ring-0.
  * @todo Any reason not to use binary search here?
  *      bird: because you'd need to sort the entries first...
  */
-static const CODECVERB g_aCodecVerbs[] =
+static const CODECVERBR0 g_aCodecVerbsR0[] =
 {
     /* Verb        Verb mask            Callback                        Name
@@ -2723,5 +2018,4 @@
     { 0x00070100, CODEC_VERB_8BIT_CMD , vrbProcSetConSelectCtrl       , "SetConSelectCtrl      " },
     { 0x000F0600, CODEC_VERB_8BIT_CMD , vrbProcGetStreamId            , "GetStreamId           " },
-    { 0x00070600, CODEC_VERB_8BIT_CMD , vrbProcSetStreamId            , "SetStreamId           " },
     { 0x000F0700, CODEC_VERB_8BIT_CMD , vrbProcGetPinCtrl             , "GetPinCtrl            " },
     { 0x00070700, CODEC_VERB_8BIT_CMD , vrbProcSetPinCtrl             , "SetPinCtrl            " },
@@ -2762,5 +2056,4 @@
     { 0x00020000, CODEC_VERB_16BIT_CMD, vrbProcSetConverterFormat     , "SetConverterFormat    " },
     { 0x000B0000, CODEC_VERB_16BIT_CMD, vrbProcGetAmplifier           , "GetAmplifier          " },
-    { 0x00030000, CODEC_VERB_16BIT_CMD, vrbProcSetAmplifier           , "SetAmplifier          " },
     { 0x000F0400, CODEC_VERB_8BIT_CMD , vrbProcGetSDISelect           , "GetSDISelect          " },
     { 0x00070400, CODEC_VERB_8BIT_CMD , vrbProcSetSDISelect           , "SetSDISelect          " }
@@ -2768,4 +2061,5 @@
 };
 
+#if defined(IN_RING3) && defined(DEBUG)
 
 /**
@@ -2954,5 +2248,5 @@
         for (uint8_t i = 0; i < pInfo->pThis->cTotalNodes; i++)
         {
-            const PCODECNODE pSubNode = &pInfo->pThis->paNodes[i];
+            const PCODECNODE pSubNode = &pInfo->pThis->aNodes[i];
             if (pSubNode->node.uID == pNode->node.uID)
                 continue;
@@ -2974,7 +2268,8 @@
 }
 
-static DECLCALLBACK(void) codecDbgListNodes(PHDACODEC pThis, PCDBGFINFOHLP pHlp, const char *pszArgs)
-{
-    RT_NOREF(pszArgs);
+static DECLCALLBACK(void) codecR3DbgListNodes(PHDACODEC pThis, PHDACODECR3 pThisCC, PCDBGFINFOHLP pHlp, const char *pszArgs)
+{
+    RT_NOREF(pThisCC, pszArgs);
+
     pHlp->pfnPrintf(pHlp, "HDA LINK / INPUTS\n");
 
@@ -2989,5 +2284,5 @@
         for (uint8_t i = 0; i < pThis->cTotalNodes; i++)
         {
-            PCODECNODE pNode = &pThis->paNodes[i];
+            PCODECNODE pNode = &pThis->aNodes[i];
 
             /* Start with all nodes which have connection entries set. */
@@ -2998,18 +2293,17 @@
 }
 
-#ifdef DEBUG
-
-static DECLCALLBACK(void) codecDbgSelector(PHDACODEC pThis, PCDBGFINFOHLP pHlp, const char *pszArgs)
-{
-    RT_NOREF(pThis, pHlp, pszArgs);
-}
-
-#endif /* DEBUG */
-
-static DECLCALLBACK(int) codecLookup(PHDACODEC pThis, uint32_t cmd, uint64_t *puResp)
-{
-    AssertPtrReturn(pThis,  VERR_INVALID_POINTER);
+static DECLCALLBACK(void) codecR3DbgSelector(PHDACODEC pThis, PHDACODECR3 pThisCC, PCDBGFINFOHLP pHlp, const char *pszArgs)
+{
+    RT_NOREF(pThis, pThisCC, pHlp, pszArgs);
+}
+
+#endif /* IN_RING3 && DEBUG */
+
+static DECLCALLBACK(int) codecR3Lookup(PHDACODEC pThis, PHDACODECR3 pThisCC, uint32_t cmd, uint64_t *puResp)
+{
+    AssertPtrReturn(pThisCC,  VERR_INVALID_POINTER);
     AssertPtrReturn(puResp, VERR_INVALID_POINTER);
-    STAM_COUNTER_INC(&pThis->StatLookups);
+
+    STAM_COUNTER_INC(&pThisCC->StatLookupsR3);
 
     if (CODEC_CAD(cmd) != pThis->id)
@@ -3029,12 +2323,16 @@
 
     /** @todo r=andy Implement a binary search here. */
-    for (size_t i = 0; i < pThis->cVerbs; i++)
-    {
-        if ((CODEC_VERBDATA(cmd) & pThis->paVerbs[i].mask) == pThis->paVerbs[i].verb)
-        {
-            int rc2 = pThis->paVerbs[i].pfn(pThis, cmd, puResp);
+    for (size_t i = 0; i < pThisCC->cVerbs; i++)
+    {
+        PCODECVERBR3 pVerb = &pThisCC->aVerbs[i];
+
+        if ((CODEC_VERBDATA(cmd) & pVerb->mask) == pThisCC->aVerbs[i].verb)
+        {
+            AssertPtrReturn(pVerb->pfn, VERR_NOT_IMPLEMENTED); /* Paranoia. */
+
+            int rc2 = pVerb->pfn(pThis, pThisCC, cmd, puResp);
             AssertRC(rc2);
             Log3Func(("[NID0x%02x] (0x%x) %s: 0x%x -> 0x%x\n",
-                      CODEC_NID(cmd), pThis->paVerbs[i].verb, pThis->paVerbs[i].pszName, CODEC_VERB_PAYLOAD8(cmd), *puResp));
+                      CODEC_NID(cmd), pVerb->verb, pVerb->pszName, CODEC_VERB_PAYLOAD8(cmd), *puResp));
             return rc2;
         }
@@ -3046,11 +2344,57 @@
 }
 
+static DECLCALLBACK(int) codecR0Lookup(PHDACODEC pThis, PHDACODECR0 pThisCC, uint32_t cmd, uint64_t *puResp)
+{
+    AssertPtrReturn(pThis,  VERR_INVALID_POINTER);
+    AssertPtrReturn(puResp, VERR_INVALID_POINTER);
+
+    STAM_COUNTER_INC(&pThisCC->StatLookupsR0);
+
+    if (CODEC_CAD(cmd) != pThis->id)
+    {
+        *puResp = 0;
+        AssertMsgFailed(("Unknown codec address 0x%x\n", CODEC_CAD(cmd)));
+        return VERR_INVALID_PARAMETER;
+    }
+
+    if (   CODEC_VERBDATA(cmd) == 0
+        || CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        *puResp = 0;
+        AssertMsgFailed(("[NID0x%02x] Unknown / invalid node or data (0x%x)\n", CODEC_NID(cmd), CODEC_VERBDATA(cmd)));
+        return VERR_INVALID_PARAMETER;
+    }
+
+    /** @todo r=andy Implement a binary search here. */
+    for (size_t i = 0; i < pThisCC->cVerbs; i++)
+    {
+        PCODECVERBR0 pVerb = &pThisCC->aVerbs[i];
+
+        if ((CODEC_VERBDATA(cmd) & pVerb->mask) == pThisCC->aVerbs[i].verb)
+        {
+            AssertPtrReturn(pVerb->pfn, VERR_NOT_IMPLEMENTED); /* Paranoia. */
+
+            int rc2 = pVerb->pfn(pThis, cmd, puResp);
+            AssertRC(rc2);
+            Log3Func(("[NID0x%02x] (0x%x) %s: 0x%x -> 0x%x\n",
+                      CODEC_NID(cmd), pVerb->verb, pVerb->pszName, CODEC_VERB_PAYLOAD8(cmd), *puResp));
+            return rc2;
+        }
+    }
+
+    *puResp = 0;
+    LogFunc(("[NID0x%02x] Callback for %x not found\n", CODEC_NID(cmd), CODEC_VERBDATA(cmd)));
+    return VERR_NOT_FOUND;
+}
+
 /*
  * APIs exposed to DevHDA.
  */
 
-int hdaCodecAddStream(PHDACODEC pThis, PDMAUDIOMIXERCTL enmMixerCtl, PPDMAUDIOSTREAMCFG pCfg)
-{
-    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
+#ifdef IN_RING3
+
+int hdaR3CodecAddStream(PHDACODECR3 pThisCC, PDMAUDIOMIXERCTL enmMixerCtl, PPDMAUDIOSTREAMCFG pCfg)
+{
+    AssertPtrReturn(pThisCC, VERR_INVALID_POINTER);
     AssertPtrReturn(pCfg,  VERR_INVALID_POINTER);
 
@@ -3074,5 +2418,5 @@
 
         default:
-            AssertMsgFailed(("Mixer control %d not implemented\n", enmMixerCtl));
+            AssertMsgFailed(("Mixer control %#x not implemented\n", enmMixerCtl));
             rc = VERR_NOT_IMPLEMENTED;
             break;
@@ -3080,5 +2424,5 @@
 
     if (RT_SUCCESS(rc))
-        rc = pThis->pfnCbMixerAddStream(pThis->pDevIns, enmMixerCtl, pCfg);
+        rc = pThisCC->pfnCbMixerAddStream(pThisCC->pDevIns, enmMixerCtl, pCfg);
 
     LogFlowFuncLeaveRC(rc);
@@ -3086,9 +2430,9 @@
 }
 
-int hdaCodecRemoveStream(PHDACODEC pThis, PDMAUDIOMIXERCTL enmMixerCtl)
-{
-    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
-
-    int rc = pThis->pfnCbMixerRemoveStream(pThis->pDevIns, enmMixerCtl);
+int hdaR3CodecRemoveStream(PHDACODECR3 pThisCC, PDMAUDIOMIXERCTL enmMixerCtl)
+{
+    AssertPtrReturn(pThisCC, VERR_INVALID_POINTER);
+
+    int rc = pThisCC->pfnCbMixerRemoveStream(pThisCC->pDevIns, enmMixerCtl);
 
     LogFlowFuncLeaveRC(rc);
@@ -3103,10 +2447,10 @@
     pHlp->pfnSSMPutU32(pSSM, pThis->cTotalNodes);
     for (unsigned idxNode = 0; idxNode < pThis->cTotalNodes; ++idxNode)
-        pHlp->pfnSSMPutStructEx(pSSM, &pThis->paNodes[idxNode].SavedState, sizeof(pThis->paNodes[idxNode].SavedState),
+        pHlp->pfnSSMPutStructEx(pSSM, &pThis->aNodes[idxNode].SavedState, sizeof(pThis->aNodes[idxNode].SavedState),
                                 0 /*fFlags*/, g_aCodecNodeFields, NULL /*pvUser*/);
     return VINF_SUCCESS;
 }
 
-int hdaCodecLoadState(PPDMDEVINS pDevIns, PHDACODEC pThis, PSSMHANDLE pSSM, uint32_t uVersion)
+int hdaR3CodecLoadState(PPDMDEVINS pDevIns, PHDACODEC pThis, PHDACODECR3 pThisCC, PSSMHANDLE pSSM, uint32_t uVersion)
 {
     PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
@@ -3142,10 +2486,10 @@
     for (unsigned idxNode = 0; idxNode < pThis->cTotalNodes; ++idxNode)
     {
-        uint8_t idOld = pThis->paNodes[idxNode].SavedState.Core.uID;
-        int rc = pHlp->pfnSSMGetStructEx(pSSM, &pThis->paNodes[idxNode].SavedState, sizeof(pThis->paNodes[idxNode].SavedState),
+        uint8_t idOld = pThis->aNodes[idxNode].SavedState.Core.uID;
+        int rc = pHlp->pfnSSMGetStructEx(pSSM, &pThis->aNodes[idxNode].SavedState, sizeof(pThis->aNodes[idxNode].SavedState),
                                          fFlags, pFields, NULL);
         AssertRCReturn(rc, rc);
-        AssertLogRelMsgReturn(idOld == pThis->paNodes[idxNode].SavedState.Core.uID,
-                              ("loaded %#x, expected %#x\n", pThis->paNodes[idxNode].SavedState.Core.uID, idOld),
+        AssertLogRelMsgReturn(idOld == pThis->aNodes[idxNode].SavedState.Core.uID,
+                              ("loaded %#x, expected %#x\n", pThis->aNodes[idxNode].SavedState.Core.uID, idOld),
                               VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
     }
@@ -3157,15 +2501,15 @@
     if (hdaCodecIsDacNode(pThis, pThis->u8DacLineOut))
     {
-        pNode = &pThis->paNodes[pThis->u8DacLineOut];
-        hdaCodecToAudVolume(pThis, pNode, &pNode->dac.B_params, PDMAUDIOMIXERCTL_FRONT);
+        pNode = &pThis->aNodes[pThis->u8DacLineOut];
+        hdaR3CodecToAudVolume(pThisCC, pNode, &pNode->dac.B_params, PDMAUDIOMIXERCTL_FRONT);
     }
     else if (hdaCodecIsSpdifOutNode(pThis, pThis->u8DacLineOut))
     {
-        pNode = &pThis->paNodes[pThis->u8DacLineOut];
-        hdaCodecToAudVolume(pThis, pNode, &pNode->spdifout.B_params, PDMAUDIOMIXERCTL_FRONT);
-    }
-
-    pNode = &pThis->paNodes[pThis->u8AdcVolsLineIn];
-    hdaCodecToAudVolume(pThis, pNode, &pNode->adcvol.B_params, PDMAUDIOMIXERCTL_LINE_IN);
+        pNode = &pThis->aNodes[pThis->u8DacLineOut];
+        hdaR3CodecToAudVolume(pThisCC, pNode, &pNode->spdifout.B_params, PDMAUDIOMIXERCTL_FRONT);
+    }
+
+    pNode = &pThis->aNodes[pThis->u8AdcVolsLineIn];
+    hdaR3CodecToAudVolume(pThisCC, pNode, &pNode->adcvol.B_params, PDMAUDIOMIXERCTL_LINE_IN);
 
     LogFlowFuncLeaveRC(VINF_SUCCESS);
@@ -3174,11 +2518,11 @@
 
 /**
- * Powers off the codec.
+ * Powers off the codec (ring-3).
  *
  * @param   pThis           Codec to power off.
  */
-void hdaCodecPowerOff(PHDACODEC pThis)
-{
-    if (!pThis)
+void hdaR3CodecPowerOff(PHDACODECR3 pThisCC)
+{
+    if (!pThisCC)
         return;
 
@@ -3187,73 +2531,78 @@
     LogRel2(("HDA: Powering off codec ...\n"));
 
-    int rc2 = hdaCodecRemoveStream(pThis, PDMAUDIOMIXERCTL_FRONT);
+    int rc2 = hdaR3CodecRemoveStream(pThisCC, PDMAUDIOMIXERCTL_FRONT);
     AssertRC(rc2);
 #ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
-    rc2 = hdaCodecRemoveStream(pThis, PDMAUDIOMIXERCTL_CENTER_LFE);
+    rc2 = hdaR3CodecRemoveStream(pThisCC, PDMAUDIOMIXERCTL_CENTER_LFE);
     AssertRC(rc2);
-    rc2 = hdaCodecRemoveStream(pThis, PDMAUDIOMIXERCTL_REAR);
+    rc2 = hdaR3CodecRemoveStream(pThisCC, PDMAUDIOMIXERCTL_REAR);
     AssertRC(rc2);
 #endif
 
 #ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
-    rc2 = hdaCodecRemoveStream(pThis, PDMAUDIOMIXERCTL_MIC_IN);
+    rc2 = hdaR3CodecRemoveStream(pThisCC, PDMAUDIOMIXERCTL_MIC_IN);
     AssertRC(rc2);
 #endif
-    rc2 = hdaCodecRemoveStream(pThis, PDMAUDIOMIXERCTL_LINE_IN);
+    rc2 = hdaR3CodecRemoveStream(pThisCC, PDMAUDIOMIXERCTL_LINE_IN);
     AssertRC(rc2);
 }
 
-void hdaCodecDestruct(PHDACODEC pThis)
-{
-    if (!pThis)
-        return;
-
-    LogFlowFuncEnter();
-
-    if (pThis->paNodes)
-    {
-        RTMemFree(pThis->paNodes);
-        pThis->paNodes = NULL;
-    }
-}
-
-int hdaCodecConstruct(PPDMDEVINS pDevIns, PHDACODEC pThis,
-                      uint16_t uLUN, PCFGMNODE pCfg)
+/**
+ * Constructs a codec (ring-3).
+ *
+ * @returns VBox status code.
+ * @param   pDevIns             Associated device instance.
+ * @param   pThis               Shared codec data beteen r0/r3.
+ * @param   pThisCC             Context-specific codec data (ring-3).
+ * @param   uLUN                Device LUN to assign.
+ * @param   pCfg                CFGM node to use for configuration.
+ */
+int hdaR3CodecConstruct(PPDMDEVINS pDevIns, PHDACODEC pThis, PHDACODECR3 pThisCC,
+                        uint16_t uLUN, PCFGMNODE pCfg)
 {
     AssertPtrReturn(pDevIns, VERR_INVALID_POINTER);
     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
+    AssertPtrReturn(pThisCC, VERR_INVALID_POINTER);
     AssertPtrReturn(pCfg,    VERR_INVALID_POINTER);
 
     pThis->id      = uLUN;
-    pThis->paVerbs = &g_aCodecVerbs[0];
-    pThis->cVerbs  = RT_ELEMENTS(g_aCodecVerbs);
+    pThis->enmType = CODEC_TYPE_STAC9220; /** @todo Make this dynamic. */
+
+    int rc;
+
+    switch (pThis->enmType)
+    {
+        case CODEC_TYPE_STAC9220:
+        {
+            rc = stac9220Construct(pThis);
+            AssertRCReturn(rc, rc);
+            break;
+        }
+
+        default:
+            AssertFailedReturn(VERR_NOT_IMPLEMENTED);
+            break;
+    }
+
+    memcpy(&pThisCC->aVerbs, &g_aCodecVerbsR3, sizeof(CODECVERBR3) * RT_ELEMENTS(g_aCodecVerbsR3));
+    pThisCC->cVerbs = RT_ELEMENTS(g_aCodecVerbsR3);
 
 #ifdef DEBUG
-    pThis->pfnDbgSelector  = codecDbgSelector;
+    pThisCC->pfnDbgSelector  = codecR3DbgSelector;
+    pThisCC->pfnDbgListNodes = codecR3DbgListNodes;
 #endif
-    pThis->pfnDbgListNodes = codecDbgListNodes;
-    pThis->pfnLookup       = codecLookup;
-
-    int rc = stac9220Construct(pThis);
-    AssertRCReturn(rc, rc);
-
-    /* Common root node initializers. */
-    pThis->paNodes[STAC9220_NID_ROOT].root.node.au32F00_param[0] = CODEC_MAKE_F00_00(pThis->u16VendorId, pThis->u16DeviceId);
-    pThis->paNodes[STAC9220_NID_ROOT].root.node.au32F00_param[4] = CODEC_MAKE_F00_04(0x1, 0x1);
-
-    /* Common AFG node initializers. */
-    pThis->paNodes[STAC9220_NID_AFG].afg.node.au32F00_param[0x4] = CODEC_MAKE_F00_04(0x2, pThis->cTotalNodes - 2);
-    pThis->paNodes[STAC9220_NID_AFG].afg.node.au32F00_param[0x5] = CODEC_MAKE_F00_05(1, CODEC_F00_05_AFG);
-    pThis->paNodes[STAC9220_NID_AFG].afg.node.au32F00_param[0xA] = CODEC_F00_0A_44_1KHZ | CODEC_F00_0A_16_BIT;
-    pThis->paNodes[STAC9220_NID_AFG].afg.u32F20_param = CODEC_MAKE_F20(pThis->u16VendorId, pThis->u8BSKU, pThis->u8AssemblyId);
+    pThisCC->pfnLookup       = codecR3Lookup;
 
     /*
      * Set initial volume.
      */
-    PCODECNODE pNode = &pThis->paNodes[pThis->u8DacLineOut];
-    hdaCodecToAudVolume(pThis, pNode, &pNode->dac.B_params, PDMAUDIOMIXERCTL_FRONT);
-
-    pNode = &pThis->paNodes[pThis->u8AdcVolsLineIn];
-    hdaCodecToAudVolume(pThis, pNode, &pNode->adcvol.B_params, PDMAUDIOMIXERCTL_LINE_IN);
+    PCODECNODE pNode = &pThis->aNodes[pThis->u8DacLineOut];
+    rc = hdaR3CodecToAudVolume(pThisCC, pNode, &pNode->dac.B_params, PDMAUDIOMIXERCTL_FRONT);
+    AssertRCReturn(rc, rc);
+
+    pNode = &pThis->aNodes[pThis->u8AdcVolsLineIn];
+    rc = hdaR3CodecToAudVolume(pThisCC, pNode, &pNode->adcvol.B_params, PDMAUDIOMIXERCTL_LINE_IN);
+    AssertRCReturn(rc, rc);
+
 #ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
 # error "Implement mic-in support!"
@@ -3264,9 +2613,77 @@
      */
 #ifdef VBOX_WITH_STATISTICS
-    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatLookups, STAMTYPE_COUNTER, "Codec/Lookups", STAMUNIT_OCCURENCES, "Number of codecLookup calls");
+    PDMDevHlpSTAMRegister(pDevIns, &pThisCC->StatLookupsR3, STAMTYPE_COUNTER, "Codec/LookupsR3", STAMUNIT_OCCURENCES, "Number of R3 codecLookup calls");
 #endif
 
-    LogFlowFuncLeaveRC(rc);
     return rc;
 }
 
+#else /* RING0 */
+
+/**
+ * Constructs a codec (ring-0).
+ *
+ * @returns VBox status code.
+ * @param   pDevIns             Associated device instance.
+ * @param   pThis               Shared codec data beteen r0/r3.
+ * @param   pThisCC             Context-specific codec data (ring-0).
+ */
+int hdaR0CodecConstruct(PPDMDEVINS pDevIns, PHDACODEC pThis, PHDACODECR0 pThisCC)
+{
+    AssertPtrReturn(pDevIns, VERR_INVALID_POINTER);
+    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
+    AssertPtrReturn(pThisCC, VERR_INVALID_POINTER);
+
+    memcpy(&pThisCC->aVerbs, &g_aCodecVerbsR0, sizeof(CODECVERBR0) * RT_ELEMENTS(g_aCodecVerbsR0));
+    pThisCC->cVerbs = RT_ELEMENTS(g_aCodecVerbsR0);
+
+    pThisCC->pfnLookup = codecR0Lookup;
+
+    /* Note: Everything else is done in the R3 part. */
+
+    /*
+     * Statistics
+     */
+#ifdef VBOX_WITH_STATISTICS
+    /** @todo */
+#endif
+
+    return VINF_SUCCESS;
+}
+
+#endif /* IN_RING3 */
+
+/**
+ * Destructs a codec.
+ *
+ * @param   pThis           Codec to destruct.
+ */
+void hdaCodecDestruct(PHDACODEC pThis)
+{
+    if (!pThis)
+        return;
+
+    /* Nothing to do here atm. */
+
+    LogFlowFuncEnter();
+}
+
+/**
+ * Resets a codec.
+ *
+ * @param   pThis           Codec to reset.
+ */
+void hdaCodecReset(PHDACODEC pThis)
+{
+    switch (pThis->enmType)
+    {
+        case CODEC_TYPE_STAC9220:
+            stac9220Reset(pThis);
+            break;
+
+        default:
+            AssertFailed();
+            break;
+    }
+}
+
Index: /trunk/src/VBox/Devices/Audio/HDACodec.h
===================================================================
--- /trunk/src/VBox/Devices/Audio/HDACodec.h	(revision 87798)
+++ /trunk/src/VBox/Devices/Audio/HDACodec.h	(revision 87799)
@@ -30,81 +30,888 @@
 /** Pointer to a ring-3 HDA device state.  */
 typedef struct HDASTATER3 *PHDASTATER3;
-/** The ICH HDA (Intel) codec state. */
+/** The ICH HDA (Intel) common codec state. */
 typedef struct HDACODEC *PHDACODEC;
+/** The ICH HDA (Intel) ring-0 state. */
+typedef struct HDACODECR0 *PHDACODECR0;
+/** The ICH HDA (Intel) ring-3 state. */
+typedef struct HDACODECR3 *PHDACODECR3;
 /** The HDA host driver backend. */
 typedef struct HDADRIVER *PHDADRIVER;
 
 /**
+ * Enumeration specifying the codec type to use.
+ */
+typedef enum CODEC_TYPE
+{
+    /** Invalid, do not use. */
+    CODEC_TYPE_INVALID = 0,
+    /** SigmaTel 9220 (922x). */
+    CODEC_TYPE_STAC9220,
+    /** Hack to blow the type up to 32-bit. */
+    CODEC_TYPE__32BIT_HACK = 0x7fffffff
+} CODEC_TYPE;
+
+/**
  * Verb processor method.
  */
-typedef DECLCALLBACKTYPE(int, FNHDACODECVERBPROCESSOR,(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp));
-typedef FNHDACODECVERBPROCESSOR *PFNHDACODECVERBPROCESSOR;
+typedef DECLCALLBACKTYPE(int, FNHDACODECVERBPROCESSORR0,(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp));
+typedef FNHDACODECVERBPROCESSORR0 *PFNHDACODECVERBPROCESSORR0;
+typedef DECLCALLBACKTYPE(int, FNHDACODECVERBPROCESSORR3,(PHDACODEC pThis, PHDACODECR3 pThisCC, uint32_t cmd, uint64_t *pResp));
+typedef FNHDACODECVERBPROCESSORR3 *PFNHDACODECVERBPROCESSORR3;
+
+/* PRM 5.3.1 */
+/** Codec address mask. */
+#define CODEC_CAD_MASK                                     0xF0000000
+/** Codec address shift. */
+#define CODEC_CAD_SHIFT                                    28
+#define CODEC_DIRECT_MASK                                  RT_BIT(27)
+/** Node ID mask. */
+#define CODEC_NID_MASK                                     0x07F00000
+/** Node ID shift. */
+#define CODEC_NID_SHIFT                                    20
+#define CODEC_VERBDATA_MASK                                0x000FFFFF
+#define CODEC_VERB_4BIT_CMD                                0x000FFFF0
+#define CODEC_VERB_4BIT_DATA                               0x0000000F
+#define CODEC_VERB_8BIT_CMD                                0x000FFF00
+#define CODEC_VERB_8BIT_DATA                               0x000000FF
+#define CODEC_VERB_16BIT_CMD                               0x000F0000
+#define CODEC_VERB_16BIT_DATA                              0x0000FFFF
+
+#define CODEC_CAD(cmd)                                     (((cmd) & CODEC_CAD_MASK) >> CODEC_CAD_SHIFT)
+#define CODEC_DIRECT(cmd)                                  ((cmd) & CODEC_DIRECT_MASK)
+#define CODEC_NID(cmd)                                     ((((cmd) & CODEC_NID_MASK)) >> CODEC_NID_SHIFT)
+#define CODEC_VERBDATA(cmd)                                ((cmd) & CODEC_VERBDATA_MASK)
+#define CODEC_VERB_CMD(cmd, mask, x)                       (((cmd) & (mask)) >> (x))
+#define CODEC_VERB_CMD4(cmd)                               (CODEC_VERB_CMD((cmd), CODEC_VERB_4BIT_CMD, 4))
+#define CODEC_VERB_CMD8(cmd)                               (CODEC_VERB_CMD((cmd), CODEC_VERB_8BIT_CMD, 8))
+#define CODEC_VERB_CMD16(cmd)                              (CODEC_VERB_CMD((cmd), CODEC_VERB_16BIT_CMD, 16))
+#define CODEC_VERB_PAYLOAD4(cmd)                           ((cmd) & CODEC_VERB_4BIT_DATA)
+#define CODEC_VERB_PAYLOAD8(cmd)                           ((cmd) & CODEC_VERB_8BIT_DATA)
+#define CODEC_VERB_PAYLOAD16(cmd)                          ((cmd) & CODEC_VERB_16BIT_DATA)
+
+#define CODEC_VERB_GET_AMP_DIRECTION                       RT_BIT(15)
+#define CODEC_VERB_GET_AMP_SIDE                            RT_BIT(13)
+#define CODEC_VERB_GET_AMP_INDEX                           0x7
+
+/* HDA spec 7.3.3.7 NoteA */
+#define CODEC_GET_AMP_DIRECTION(cmd)                       (((cmd) & CODEC_VERB_GET_AMP_DIRECTION) >> 15)
+#define CODEC_GET_AMP_SIDE(cmd)                            (((cmd) & CODEC_VERB_GET_AMP_SIDE) >> 13)
+#define CODEC_GET_AMP_INDEX(cmd)                           (CODEC_GET_AMP_DIRECTION(cmd) ? 0 : ((cmd) & CODEC_VERB_GET_AMP_INDEX))
+
+/* HDA spec 7.3.3.7 NoteC */
+#define CODEC_VERB_SET_AMP_OUT_DIRECTION                   RT_BIT(15)
+#define CODEC_VERB_SET_AMP_IN_DIRECTION                    RT_BIT(14)
+#define CODEC_VERB_SET_AMP_LEFT_SIDE                       RT_BIT(13)
+#define CODEC_VERB_SET_AMP_RIGHT_SIDE                      RT_BIT(12)
+#define CODEC_VERB_SET_AMP_INDEX                           (0x7 << 8)
+#define CODEC_VERB_SET_AMP_MUTE                            RT_BIT(7)
+/** Note: 7-bit value [6:0]. */
+#define CODEC_VERB_SET_AMP_GAIN                            0x7F
+
+#define CODEC_SET_AMP_IS_OUT_DIRECTION(cmd)                (((cmd) & CODEC_VERB_SET_AMP_OUT_DIRECTION) != 0)
+#define CODEC_SET_AMP_IS_IN_DIRECTION(cmd)                 (((cmd) & CODEC_VERB_SET_AMP_IN_DIRECTION) != 0)
+#define CODEC_SET_AMP_IS_LEFT_SIDE(cmd)                    (((cmd) & CODEC_VERB_SET_AMP_LEFT_SIDE) != 0)
+#define CODEC_SET_AMP_IS_RIGHT_SIDE(cmd)                   (((cmd) & CODEC_VERB_SET_AMP_RIGHT_SIDE) != 0)
+#define CODEC_SET_AMP_INDEX(cmd)                           (((cmd) & CODEC_VERB_SET_AMP_INDEX) >> 7)
+#define CODEC_SET_AMP_MUTE(cmd)                            ((cmd) & CODEC_VERB_SET_AMP_MUTE)
+#define CODEC_SET_AMP_GAIN(cmd)                            ((cmd) & CODEC_VERB_SET_AMP_GAIN)
+
+/* HDA spec 7.3.3.1 defines layout of configuration registers/verbs (0xF00) */
+/* VendorID (7.3.4.1) */
+#define CODEC_MAKE_F00_00(vendorID, deviceID)              (((vendorID) << 16) | (deviceID))
+#define CODEC_F00_00_VENDORID(f00_00)                      (((f00_00) >> 16) & 0xFFFF)
+#define CODEC_F00_00_DEVICEID(f00_00)                      ((f00_00) & 0xFFFF)
+
+/** RevisionID (7.3.4.2). */
+#define CODEC_MAKE_F00_02(majRev, minRev, venFix, venProg, stepFix, stepProg) \
+    (  (((majRev)   & 0xF) << 20) \
+     | (((minRev)   & 0xF) << 16) \
+     | (((venFix)   & 0xF) << 12) \
+     | (((venProg)  & 0xF) << 8)  \
+     | (((stepFix)  & 0xF) << 4)  \
+     |  ((stepProg) & 0xF))
+
+/** Subordinate node count (7.3.4.3). */
+#define CODEC_MAKE_F00_04(startNodeNumber, totalNodeNumber) ((((startNodeNumber) & 0xFF) << 16)|((totalNodeNumber) & 0xFF))
+#define CODEC_F00_04_TO_START_NODE_NUMBER(f00_04)          (((f00_04) >> 16) & 0xFF)
+#define CODEC_F00_04_TO_NODE_COUNT(f00_04)                 ((f00_04) & 0xFF)
+/*
+ * Function Group Type  (7.3.4.4)
+ * 0 & [0x3-0x7f] are reserved types
+ * [0x80 - 0xff] are vendor defined function groups
+ */
+#define CODEC_MAKE_F00_05(UnSol, NodeType)                 (((UnSol) << 8)|(NodeType))
+#define CODEC_F00_05_UNSOL                                 RT_BIT(8)
+#define CODEC_F00_05_AFG                                   (0x1)
+#define CODEC_F00_05_MFG                                   (0x2)
+#define CODEC_F00_05_IS_UNSOL(f00_05)                      RT_BOOL((f00_05) & RT_BIT(8))
+#define CODEC_F00_05_GROUP(f00_05)                         ((f00_05) & 0xff)
+/* Audio Function Group capabilities (7.3.4.5). */
+#define CODEC_MAKE_F00_08(BeepGen, InputDelay, OutputDelay) ((((BeepGen) & 0x1) << 16)| (((InputDelay) & 0xF) << 8) | ((OutputDelay) & 0xF))
+#define CODEC_F00_08_BEEP_GEN(f00_08)                      ((f00_08) & RT_BIT(16)
+
+/* Converter Stream, Channel (7.3.3.11). */
+#define CODEC_F00_06_GET_STREAM_ID(cmd)                    (((cmd) >> 4) & 0x0F)
+#define CODEC_F00_06_GET_CHANNEL_ID(cmd)                   (((cmd) & 0x0F))
+
+/* Widget Capabilities (7.3.4.6). */
+#define CODEC_MAKE_F00_09(type, delay, chan_ext) \
+    ( (((type)     & 0xF) << 20)            \
+    | (((delay)    & 0xF) << 16)           \
+    | (((chan_ext) & 0xF) << 13))
+/* note: types 0x8-0xe are reserved */
+#define CODEC_F00_09_TYPE_AUDIO_OUTPUT                     (0x0)
+#define CODEC_F00_09_TYPE_AUDIO_INPUT                      (0x1)
+#define CODEC_F00_09_TYPE_AUDIO_MIXER                      (0x2)
+#define CODEC_F00_09_TYPE_AUDIO_SELECTOR                   (0x3)
+#define CODEC_F00_09_TYPE_PIN_COMPLEX                      (0x4)
+#define CODEC_F00_09_TYPE_POWER_WIDGET                     (0x5)
+#define CODEC_F00_09_TYPE_VOLUME_KNOB                      (0x6)
+#define CODEC_F00_09_TYPE_BEEP_GEN                         (0x7)
+#define CODEC_F00_09_TYPE_VENDOR_DEFINED                   (0xF)
+
+#define CODEC_F00_09_CAP_CP                                RT_BIT(12)
+#define CODEC_F00_09_CAP_L_R_SWAP                          RT_BIT(11)
+#define CODEC_F00_09_CAP_POWER_CTRL                        RT_BIT(10)
+#define CODEC_F00_09_CAP_DIGITAL                           RT_BIT(9)
+#define CODEC_F00_09_CAP_CONNECTION_LIST                   RT_BIT(8)
+#define CODEC_F00_09_CAP_UNSOL                             RT_BIT(7)
+#define CODEC_F00_09_CAP_PROC_WIDGET                       RT_BIT(6)
+#define CODEC_F00_09_CAP_STRIPE                            RT_BIT(5)
+#define CODEC_F00_09_CAP_FMT_OVERRIDE                      RT_BIT(4)
+#define CODEC_F00_09_CAP_AMP_FMT_OVERRIDE                  RT_BIT(3)
+#define CODEC_F00_09_CAP_OUT_AMP_PRESENT                   RT_BIT(2)
+#define CODEC_F00_09_CAP_IN_AMP_PRESENT                    RT_BIT(1)
+#define CODEC_F00_09_CAP_STEREO                            RT_BIT(0)
+
+#define CODEC_F00_09_TYPE(f00_09)                          (((f00_09) >> 20) & 0xF)
+
+#define CODEC_F00_09_IS_CAP_CP(f00_09)                     RT_BOOL((f00_09) & RT_BIT(12))
+#define CODEC_F00_09_IS_CAP_L_R_SWAP(f00_09)               RT_BOOL((f00_09) & RT_BIT(11))
+#define CODEC_F00_09_IS_CAP_POWER_CTRL(f00_09)             RT_BOOL((f00_09) & RT_BIT(10))
+#define CODEC_F00_09_IS_CAP_DIGITAL(f00_09)                RT_BOOL((f00_09) & RT_BIT(9))
+#define CODEC_F00_09_IS_CAP_CONNECTION_LIST(f00_09)        RT_BOOL((f00_09) & RT_BIT(8))
+#define CODEC_F00_09_IS_CAP_UNSOL(f00_09)                  RT_BOOL((f00_09) & RT_BIT(7))
+#define CODEC_F00_09_IS_CAP_PROC_WIDGET(f00_09)            RT_BOOL((f00_09) & RT_BIT(6))
+#define CODEC_F00_09_IS_CAP_STRIPE(f00_09)                 RT_BOOL((f00_09) & RT_BIT(5))
+#define CODEC_F00_09_IS_CAP_FMT_OVERRIDE(f00_09)           RT_BOOL((f00_09) & RT_BIT(4))
+#define CODEC_F00_09_IS_CAP_AMP_OVERRIDE(f00_09)           RT_BOOL((f00_09) & RT_BIT(3))
+#define CODEC_F00_09_IS_CAP_OUT_AMP_PRESENT(f00_09)        RT_BOOL((f00_09) & RT_BIT(2))
+#define CODEC_F00_09_IS_CAP_IN_AMP_PRESENT(f00_09)         RT_BOOL((f00_09) & RT_BIT(1))
+#define CODEC_F00_09_IS_CAP_LSB(f00_09)                    RT_BOOL((f00_09) & RT_BIT(0))
+
+/* Supported PCM size, rates (7.3.4.7) */
+#define CODEC_F00_0A_32_BIT                                RT_BIT(19)
+#define CODEC_F00_0A_24_BIT                                RT_BIT(18)
+#define CODEC_F00_0A_16_BIT                                RT_BIT(17)
+#define CODEC_F00_0A_8_BIT                                 RT_BIT(16)
+
+#define CODEC_F00_0A_48KHZ_MULT_8X                         RT_BIT(11)
+#define CODEC_F00_0A_48KHZ_MULT_4X                         RT_BIT(10)
+#define CODEC_F00_0A_44_1KHZ_MULT_4X                       RT_BIT(9)
+#define CODEC_F00_0A_48KHZ_MULT_2X                         RT_BIT(8)
+#define CODEC_F00_0A_44_1KHZ_MULT_2X                       RT_BIT(7)
+#define CODEC_F00_0A_48KHZ                                 RT_BIT(6)
+#define CODEC_F00_0A_44_1KHZ                               RT_BIT(5)
+/* 2/3 * 48kHz */
+#define CODEC_F00_0A_48KHZ_2_3X                            RT_BIT(4)
+/* 1/2 * 44.1kHz */
+#define CODEC_F00_0A_44_1KHZ_1_2X                          RT_BIT(3)
+/* 1/3 * 48kHz */
+#define CODEC_F00_0A_48KHZ_1_3X                            RT_BIT(2)
+/* 1/4 * 44.1kHz */
+#define CODEC_F00_0A_44_1KHZ_1_4X                          RT_BIT(1)
+/* 1/6 * 48kHz */
+#define CODEC_F00_0A_48KHZ_1_6X                            RT_BIT(0)
+
+/* Supported streams formats (7.3.4.8) */
+#define CODEC_F00_0B_AC3                                   RT_BIT(2)
+#define CODEC_F00_0B_FLOAT32                               RT_BIT(1)
+#define CODEC_F00_0B_PCM                                   RT_BIT(0)
+
+/* Pin Capabilities (7.3.4.9)*/
+#define CODEC_MAKE_F00_0C(vref_ctrl) (((vref_ctrl) & 0xFF) << 8)
+#define CODEC_F00_0C_CAP_HBR                               RT_BIT(27)
+#define CODEC_F00_0C_CAP_DP                                RT_BIT(24)
+#define CODEC_F00_0C_CAP_EAPD                              RT_BIT(16)
+#define CODEC_F00_0C_CAP_HDMI                              RT_BIT(7)
+#define CODEC_F00_0C_CAP_BALANCED_IO                       RT_BIT(6)
+#define CODEC_F00_0C_CAP_INPUT                             RT_BIT(5)
+#define CODEC_F00_0C_CAP_OUTPUT                            RT_BIT(4)
+#define CODEC_F00_0C_CAP_HEADPHONE_AMP                     RT_BIT(3)
+#define CODEC_F00_0C_CAP_PRESENCE_DETECT                   RT_BIT(2)
+#define CODEC_F00_0C_CAP_TRIGGER_REQUIRED                  RT_BIT(1)
+#define CODEC_F00_0C_CAP_IMPENDANCE_SENSE                  RT_BIT(0)
+
+#define CODEC_F00_0C_IS_CAP_HBR(f00_0c)                    ((f00_0c) & RT_BIT(27))
+#define CODEC_F00_0C_IS_CAP_DP(f00_0c)                     ((f00_0c) & RT_BIT(24))
+#define CODEC_F00_0C_IS_CAP_EAPD(f00_0c)                   ((f00_0c) & RT_BIT(16))
+#define CODEC_F00_0C_IS_CAP_HDMI(f00_0c)                   ((f00_0c) & RT_BIT(7))
+#define CODEC_F00_0C_IS_CAP_BALANCED_IO(f00_0c)            ((f00_0c) & RT_BIT(6))
+#define CODEC_F00_0C_IS_CAP_INPUT(f00_0c)                  ((f00_0c) & RT_BIT(5))
+#define CODEC_F00_0C_IS_CAP_OUTPUT(f00_0c)                 ((f00_0c) & RT_BIT(4))
+#define CODEC_F00_0C_IS_CAP_HP(f00_0c)                     ((f00_0c) & RT_BIT(3))
+#define CODEC_F00_0C_IS_CAP_PRESENCE_DETECT(f00_0c)        ((f00_0c) & RT_BIT(2))
+#define CODEC_F00_0C_IS_CAP_TRIGGER_REQUIRED(f00_0c)       ((f00_0c) & RT_BIT(1))
+#define CODEC_F00_0C_IS_CAP_IMPENDANCE_SENSE(f00_0c)       ((f00_0c) & RT_BIT(0))
+
+/* Input Amplifier capabilities (7.3.4.10). */
+#define CODEC_MAKE_F00_0D(mute_cap, step_size, num_steps, offset) \
+        (  (((mute_cap)  & UINT32_C(0x1))  << 31) \
+         | (((step_size) & UINT32_C(0xFF)) << 16) \
+         | (((num_steps) & UINT32_C(0xFF)) << 8) \
+         |  ((offset)    & UINT32_C(0xFF)))
+
+#define CODEC_F00_0D_CAP_MUTE                              RT_BIT(7)
+
+#define CODEC_F00_0D_IS_CAP_MUTE(f00_0d)                   ( ( f00_0d) & RT_BIT(31))
+#define CODEC_F00_0D_STEP_SIZE(f00_0d)                     ((( f00_0d) & (0x7F << 16)) >> 16)
+#define CODEC_F00_0D_NUM_STEPS(f00_0d)                     ((((f00_0d) & (0x7F << 8)) >> 8) + 1)
+#define CODEC_F00_0D_OFFSET(f00_0d)                        (  (f00_0d) & 0x7F)
+
+/** Indicates that the amplifier can be muted. */
+#define CODEC_AMP_CAP_MUTE                                 0x1
+/** The amplifier's maximum number of steps. We want
+ *  a ~90dB dynamic range, so 64 steps with 1.25dB each
+ *  should do the trick.
+ *
+ *  As we want to map our range to [0..128] values we can avoid
+ *  multiplication and simply doing a shift later.
+ *
+ *  Produces -96dB to +0dB.
+ *  "0" indicates a step of 0.25dB, "127" indicates a step of 32dB.
+ */
+#define CODEC_AMP_NUM_STEPS                                0x7F
+/** The initial gain offset (and when doing a node reset). */
+#define CODEC_AMP_OFF_INITIAL                              0x7F
+/** The amplifier's gain step size. */
+#define CODEC_AMP_STEP_SIZE                                0x2
+
+/* Output Amplifier capabilities (7.3.4.10) */
+#define CODEC_MAKE_F00_12                                  CODEC_MAKE_F00_0D
+
+#define CODEC_F00_12_IS_CAP_MUTE(f00_12)                   CODEC_F00_0D_IS_CAP_MUTE(f00_12)
+#define CODEC_F00_12_STEP_SIZE(f00_12)                     CODEC_F00_0D_STEP_SIZE(f00_12)
+#define CODEC_F00_12_NUM_STEPS(f00_12)                     CODEC_F00_0D_NUM_STEPS(f00_12)
+#define CODEC_F00_12_OFFSET(f00_12)                        CODEC_F00_0D_OFFSET(f00_12)
+
+/* Connection list lenght (7.3.4.11). */
+#define CODEC_MAKE_F00_0E(long_form, length)    \
+    (  (((long_form) & 0x1) << 7)               \
+     | ((length) & 0x7F))
+/* Indicates short-form NIDs. */
+#define CODEC_F00_0E_LIST_NID_SHORT                        0
+/* Indicates long-form NIDs. */
+#define CODEC_F00_0E_LIST_NID_LONG                         1
+#define CODEC_F00_0E_IS_LONG(f00_0e)                       RT_BOOL((f00_0e) & RT_BIT(7))
+#define CODEC_F00_0E_COUNT(f00_0e)                         ((f00_0e) & 0x7F)
+/* Supported Power States (7.3.4.12) */
+#define CODEC_F00_0F_EPSS                                  RT_BIT(31)
+#define CODEC_F00_0F_CLKSTOP                               RT_BIT(30)
+#define CODEC_F00_0F_S3D3                                  RT_BIT(29)
+#define CODEC_F00_0F_D3COLD                                RT_BIT(4)
+#define CODEC_F00_0F_D3                                    RT_BIT(3)
+#define CODEC_F00_0F_D2                                    RT_BIT(2)
+#define CODEC_F00_0F_D1                                    RT_BIT(1)
+#define CODEC_F00_0F_D0                                    RT_BIT(0)
+
+/* Processing capabilities 7.3.4.13 */
+#define CODEC_MAKE_F00_10(num, benign)                     ((((num) & 0xFF) << 8) | ((benign) & 0x1))
+#define CODEC_F00_10_NUM(f00_10)                           (((f00_10) & (0xFF << 8)) >> 8)
+#define CODEC_F00_10_BENING(f00_10)                        ((f00_10) & 0x1)
+
+/* GPIO count (7.3.4.14). */
+#define CODEC_MAKE_F00_11(wake, unsol, numgpi, numgpo, numgpio) \
+    (  (((wake)   & UINT32_C(0x1))  << 31) \
+     | (((unsol)  & UINT32_C(0x1))  << 30) \
+     | (((numgpi) & UINT32_C(0xFF)) << 16) \
+     | (((numgpo) & UINT32_C(0xFF)) << 8) \
+     | ((numgpio) & UINT32_C(0xFF)))
+
+/* Processing States (7.3.3.4). */
+#define CODEC_F03_OFF                                      (0)
+#define CODEC_F03_ON                                       RT_BIT(0)
+#define CODEC_F03_BENING                                   RT_BIT(1)
+/* Power States (7.3.3.10). */
+#define CODEC_MAKE_F05(reset, stopok, error, act, set) \
+    (  (((reset)  & 0x1) << 10) \
+     | (((stopok) & 0x1) << 9) \
+     | (((error)  & 0x1) << 8) \
+     | (((act)    & 0xF) << 4) \
+     | ((set)     & 0xF))
+#define CODEC_F05_D3COLD                                   (4)
+#define CODEC_F05_D3                                       (3)
+#define CODEC_F05_D2                                       (2)
+#define CODEC_F05_D1                                       (1)
+#define CODEC_F05_D0                                       (0)
+
+#define CODEC_F05_IS_RESET(value)                          (((value) & RT_BIT(10)) != 0)
+#define CODEC_F05_IS_STOPOK(value)                         (((value) & RT_BIT(9)) != 0)
+#define CODEC_F05_IS_ERROR(value)                          (((value) & RT_BIT(8)) != 0)
+#define CODEC_F05_ACT(value)                               (((value) & 0xF0) >> 4)
+#define CODEC_F05_SET(value)                               (((value) & 0xF))
+
+#define CODEC_F05_GE(p0, p1)                               ((p0) <= (p1))
+#define CODEC_F05_LE(p0, p1)                               ((p0) >= (p1))
+
+/* Converter Stream, Channel (7.3.3.11). */
+#define CODEC_MAKE_F06(stream, channel) \
+    (  (((stream)  & 0xF) << 4)         \
+     |  ((channel) & 0xF))
+#define CODEC_F06_STREAM(value)                            ((value) & 0xF0)
+#define CODEC_F06_CHANNEL(value)                           ((value) & 0xF)
+
+/* Pin Widged Control (7.3.3.13). */
+#define CODEC_F07_VREF_HIZ                                 (0)
+#define CODEC_F07_VREF_50                                  (0x1)
+#define CODEC_F07_VREF_GROUND                              (0x2)
+#define CODEC_F07_VREF_80                                  (0x4)
+#define CODEC_F07_VREF_100                                 (0x5)
+#define CODEC_F07_IN_ENABLE                                RT_BIT(5)
+#define CODEC_F07_OUT_ENABLE                               RT_BIT(6)
+#define CODEC_F07_OUT_H_ENABLE                             RT_BIT(7)
+
+/* Volume Knob Control (7.3.3.29). */
+#define CODEC_F0F_IS_DIRECT                                RT_BIT(7)
+#define CODEC_F0F_VOLUME                                   (0x7F)
+
+/* Unsolicited enabled (7.3.3.14). */
+#define CODEC_MAKE_F08(enable, tag) ((((enable) & 1) << 7) | ((tag) & 0x3F))
+
+/* Converter formats (7.3.3.8) and (3.7.1). */
+/* This is the same format as SDnFMT. */
+#define CODEC_MAKE_A                                       HDA_SDFMT_MAKE
+
+#define CODEC_A_TYPE                                       HDA_SDFMT_TYPE
+#define CODEC_A_TYPE_PCM                                   HDA_SDFMT_TYPE_PCM
+#define CODEC_A_TYPE_NON_PCM                               HDA_SDFMT_TYPE_NON_PCM
+
+#define CODEC_A_BASE                                       HDA_SDFMT_BASE
+#define CODEC_A_BASE_48KHZ                                 HDA_SDFMT_BASE_48KHZ
+#define CODEC_A_BASE_44KHZ                                 HDA_SDFMT_BASE_44KHZ
+
+/* Pin Sense (7.3.3.15). */
+#define CODEC_MAKE_F09_ANALOG(fPresent, impedance)  \
+(  (((fPresent) & 0x1) << 31)                       \
+ | (((impedance) & UINT32_C(0x7FFFFFFF))))
+#define CODEC_F09_ANALOG_NA    UINT32_C(0x7FFFFFFF)
+#define CODEC_MAKE_F09_DIGITAL(fPresent, fELDValid) \
+(   (((fPresent)  & UINT32_C(0x1)) << 31)                      \
+  | (((fELDValid) & UINT32_C(0x1)) << 30))
+
+#define CODEC_MAKE_F0C(lrswap, eapd, btl) ((((lrswap) & 1) << 2) | (((eapd) & 1) << 1) | ((btl) & 1))
+#define CODEC_FOC_IS_LRSWAP(f0c)                           RT_BOOL((f0c) & RT_BIT(2))
+#define CODEC_FOC_IS_EAPD(f0c)                             RT_BOOL((f0c) & RT_BIT(1))
+#define CODEC_FOC_IS_BTL(f0c)                              RT_BOOL((f0c) & RT_BIT(0))
+/* HDA spec 7.3.3.31 defines layout of configuration registers/verbs (0xF1C) */
+/* Configuration's port connection */
+#define CODEC_F1C_PORT_MASK                                (0x3)
+#define CODEC_F1C_PORT_SHIFT                               (30)
+
+#define CODEC_F1C_PORT_COMPLEX                             (0x0)
+#define CODEC_F1C_PORT_NO_PHYS                             (0x1)
+#define CODEC_F1C_PORT_FIXED                               (0x2)
+#define CODEC_F1C_BOTH                                     (0x3)
+
+/* Configuration default: connection */
+#define CODEC_F1C_PORT_MASK                                (0x3)
+#define CODEC_F1C_PORT_SHIFT                               (30)
+
+/* Connected to a jack (1/8", ATAPI, ...). */
+#define CODEC_F1C_PORT_COMPLEX                             (0x0)
+/* No physical connection. */
+#define CODEC_F1C_PORT_NO_PHYS                             (0x1)
+/* Fixed function device (integrated speaker, integrated mic, ...). */
+#define CODEC_F1C_PORT_FIXED                               (0x2)
+/* Both, a jack and an internal device are attached. */
+#define CODEC_F1C_BOTH                                     (0x3)
+
+/* Configuration default: Location */
+#define CODEC_F1C_LOCATION_MASK                            (0x3F)
+#define CODEC_F1C_LOCATION_SHIFT                           (24)
+
+/* [4:5] bits of location region means chassis attachment */
+#define CODEC_F1C_LOCATION_PRIMARY_CHASSIS                 (0)
+#define CODEC_F1C_LOCATION_INTERNAL                        RT_BIT(4)
+#define CODEC_F1C_LOCATION_SECONDRARY_CHASSIS              RT_BIT(5)
+#define CODEC_F1C_LOCATION_OTHER                           RT_BIT(5)
+
+/* [0:3] bits of location region means geometry location attachment */
+#define CODEC_F1C_LOCATION_NA                              (0)
+#define CODEC_F1C_LOCATION_REAR                            (0x1)
+#define CODEC_F1C_LOCATION_FRONT                           (0x2)
+#define CODEC_F1C_LOCATION_LEFT                            (0x3)
+#define CODEC_F1C_LOCATION_RIGTH                           (0x4)
+#define CODEC_F1C_LOCATION_TOP                             (0x5)
+#define CODEC_F1C_LOCATION_BOTTOM                          (0x6)
+#define CODEC_F1C_LOCATION_SPECIAL_0                       (0x7)
+#define CODEC_F1C_LOCATION_SPECIAL_1                       (0x8)
+#define CODEC_F1C_LOCATION_SPECIAL_2                       (0x9)
+
+/* Configuration default: Device type */
+#define CODEC_F1C_DEVICE_MASK                              (0xF)
+#define CODEC_F1C_DEVICE_SHIFT                             (20)
+#define CODEC_F1C_DEVICE_LINE_OUT                          (0)
+#define CODEC_F1C_DEVICE_SPEAKER                           (0x1)
+#define CODEC_F1C_DEVICE_HP                                (0x2)
+#define CODEC_F1C_DEVICE_CD                                (0x3)
+#define CODEC_F1C_DEVICE_SPDIF_OUT                         (0x4)
+#define CODEC_F1C_DEVICE_DIGITAL_OTHER_OUT                 (0x5)
+#define CODEC_F1C_DEVICE_MODEM_LINE_SIDE                   (0x6)
+#define CODEC_F1C_DEVICE_MODEM_HANDSET_SIDE                (0x7)
+#define CODEC_F1C_DEVICE_LINE_IN                           (0x8)
+#define CODEC_F1C_DEVICE_AUX                               (0x9)
+#define CODEC_F1C_DEVICE_MIC                               (0xA)
+#define CODEC_F1C_DEVICE_PHONE                             (0xB)
+#define CODEC_F1C_DEVICE_SPDIF_IN                          (0xC)
+#define CODEC_F1C_DEVICE_RESERVED                          (0xE)
+#define CODEC_F1C_DEVICE_OTHER                             (0xF)
+
+/* Configuration default: Connection type */
+#define CODEC_F1C_CONNECTION_TYPE_MASK                     (0xF)
+#define CODEC_F1C_CONNECTION_TYPE_SHIFT                    (16)
+
+#define CODEC_F1C_CONNECTION_TYPE_UNKNOWN                  (0)
+#define CODEC_F1C_CONNECTION_TYPE_1_8INCHES                (0x1)
+#define CODEC_F1C_CONNECTION_TYPE_1_4INCHES                (0x2)
+#define CODEC_F1C_CONNECTION_TYPE_ATAPI                    (0x3)
+#define CODEC_F1C_CONNECTION_TYPE_RCA                      (0x4)
+#define CODEC_F1C_CONNECTION_TYPE_OPTICAL                  (0x5)
+#define CODEC_F1C_CONNECTION_TYPE_OTHER_DIGITAL            (0x6)
+#define CODEC_F1C_CONNECTION_TYPE_ANALOG                   (0x7)
+#define CODEC_F1C_CONNECTION_TYPE_DIN                      (0x8)
+#define CODEC_F1C_CONNECTION_TYPE_XLR                      (0x9)
+#define CODEC_F1C_CONNECTION_TYPE_RJ_11                    (0xA)
+#define CODEC_F1C_CONNECTION_TYPE_COMBO                    (0xB)
+#define CODEC_F1C_CONNECTION_TYPE_OTHER                    (0xF)
+
+/* Configuration's color */
+#define CODEC_F1C_COLOR_MASK                               (0xF)
+#define CODEC_F1C_COLOR_SHIFT                              (12)
+#define CODEC_F1C_COLOR_UNKNOWN                            (0)
+#define CODEC_F1C_COLOR_BLACK                              (0x1)
+#define CODEC_F1C_COLOR_GREY                               (0x2)
+#define CODEC_F1C_COLOR_BLUE                               (0x3)
+#define CODEC_F1C_COLOR_GREEN                              (0x4)
+#define CODEC_F1C_COLOR_RED                                (0x5)
+#define CODEC_F1C_COLOR_ORANGE                             (0x6)
+#define CODEC_F1C_COLOR_YELLOW                             (0x7)
+#define CODEC_F1C_COLOR_PURPLE                             (0x8)
+#define CODEC_F1C_COLOR_PINK                               (0x9)
+#define CODEC_F1C_COLOR_RESERVED_0                         (0xA)
+#define CODEC_F1C_COLOR_RESERVED_1                         (0xB)
+#define CODEC_F1C_COLOR_RESERVED_2                         (0xC)
+#define CODEC_F1C_COLOR_RESERVED_3                         (0xD)
+#define CODEC_F1C_COLOR_WHITE                              (0xE)
+#define CODEC_F1C_COLOR_OTHER                              (0xF)
+
+/* Configuration's misc */
+#define CODEC_F1C_MISC_MASK                                (0xF)
+#define CODEC_F1C_MISC_SHIFT                               (8)
+#define CODEC_F1C_MISC_NONE                                0
+#define CODEC_F1C_MISC_JACK_NO_PRESENCE_DETECT             RT_BIT(0)
+#define CODEC_F1C_MISC_RESERVED_0                          RT_BIT(1)
+#define CODEC_F1C_MISC_RESERVED_1                          RT_BIT(2)
+#define CODEC_F1C_MISC_RESERVED_2                          RT_BIT(3)
+
+/* Configuration default: Association */
+#define CODEC_F1C_ASSOCIATION_MASK                         (0xF)
+#define CODEC_F1C_ASSOCIATION_SHIFT                        (4)
+
+/** Reserved; don't use. */
+#define CODEC_F1C_ASSOCIATION_INVALID                      0x0
+#define CODEC_F1C_ASSOCIATION_GROUP_0                      0x1
+#define CODEC_F1C_ASSOCIATION_GROUP_1                      0x2
+#define CODEC_F1C_ASSOCIATION_GROUP_2                      0x3
+#define CODEC_F1C_ASSOCIATION_GROUP_3                      0x4
+#define CODEC_F1C_ASSOCIATION_GROUP_4                      0x5
+#define CODEC_F1C_ASSOCIATION_GROUP_5                      0x6
+#define CODEC_F1C_ASSOCIATION_GROUP_6                      0x7
+#define CODEC_F1C_ASSOCIATION_GROUP_7                      0x8
+/* Note: Windows OSes will treat group 15 (0xF) as single PIN devices.
+ *       The sequence number associated with that group then will be ignored. */
+#define CODEC_F1C_ASSOCIATION_GROUP_15                     0xF
+
+/* Configuration default: Association Sequence. */
+#define CODEC_F1C_SEQ_MASK                                 (0xF)
+#define CODEC_F1C_SEQ_SHIFT                                (0)
+
+/* Implementation identification (7.3.3.30). */
+#define CODEC_MAKE_F20(bmid, bsku, aid)     \
+    (  (((bmid) & 0xFFFF) << 16)            \
+     | (((bsku) & 0xFF) << 8)               \
+     | (((aid) & 0xFF))                     \
+    )
+
+/* Macro definition helping in filling the configuration registers. */
+#define CODEC_MAKE_F1C(port_connectivity, location, device, connection_type, color, misc, association, sequence)    \
+    (  (((port_connectivity) & 0xF) << CODEC_F1C_PORT_SHIFT)            \
+     | (((location)          & 0xF) << CODEC_F1C_LOCATION_SHIFT)        \
+     | (((device)            & 0xF) << CODEC_F1C_DEVICE_SHIFT)          \
+     | (((connection_type)   & 0xF) << CODEC_F1C_CONNECTION_TYPE_SHIFT) \
+     | (((color)             & 0xF) << CODEC_F1C_COLOR_SHIFT)           \
+     | (((misc)              & 0xF) << CODEC_F1C_MISC_SHIFT)            \
+     | (((association)       & 0xF) << CODEC_F1C_ASSOCIATION_SHIFT)     \
+     | (((sequence)          & 0xF)))
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+/** The F00 parameter length (in dwords). */
+#define CODECNODE_F00_PARAM_LENGTH  20
+/** The F02 parameter length (in dwords). */
+#define CODECNODE_F02_PARAM_LENGTH  16
 
 /* PRM 5.3.1 */
 #define CODEC_RESPONSE_UNSOLICITED RT_BIT_64(34)
 
-typedef struct CODECVERB
+/**
+ * Structure for maintaining a codec verb implementation (ring-0).
+ */
+typedef struct CODECVERBR0
 {
     /** Verb. */
-    uint32_t                 verb;
+    uint32_t                   verb;
     /** Verb mask. */
-    uint32_t                 mask;
+    uint32_t                   mask;
     /** Function pointer for implementation callback. */
-    PFNHDACODECVERBPROCESSOR pfn;
+    PFNHDACODECVERBPROCESSORR0 pfn;
     /** Friendly name, for debugging. */
-    const char              *pszName;
-} CODECVERB;
-
-union CODECNODE;
-typedef union CODECNODE CODECNODE, *PCODECNODE;
+    const char                *pszName;
+} CODECVERBR0;
+/** Ponter to a  codec verb implementation (ring-0). */
+typedef CODECVERBR0 *PCODECVERBR0;
 
 /**
- * HDA codec state.
+ * Structure for maintaining a codec verb implementation (ring-3).
+ */
+typedef struct CODECVERBR3
+{
+    /** Verb. */
+    uint32_t                   verb;
+    /** Verb mask. */
+    uint32_t                   mask;
+    /** Function pointer for implementation callback. */
+    PFNHDACODECVERBPROCESSORR3 pfn;
+    /** Friendly name, for debugging. */
+    const char                *pszName;
+} CODECVERBR3;
+/** Ponter to a  codec verb implementation (ring-3). */
+typedef CODECVERBR3 *PCODECVERBR3;
+
+#define AMPLIFIER_SIZE 60
+
+typedef uint32_t AMPLIFIER[AMPLIFIER_SIZE];
+
+/**
+ * Common (or core) codec node structure.
+ */
+typedef struct CODECCOMMONNODE
+{
+    /** The node's ID. */
+    uint8_t         uID;
+    /** The node's name. */
+    /** The SDn ID this node is assigned to.
+     *  0 means not assigned, 1 is SDn0. */
+    uint8_t         uSD;
+    /** The SDn's channel to use.
+     *  Only valid if a valid SDn ID is set. */
+    uint8_t         uChannel;
+    /* PRM 5.3.6 */
+    uint32_t        au32F00_param[CODECNODE_F00_PARAM_LENGTH];
+    uint32_t        au32F02_param[CODECNODE_F02_PARAM_LENGTH];
+} CODECCOMMONNODE;
+typedef CODECCOMMONNODE *PCODECCOMMONNODE;
+AssertCompile(CODECNODE_F00_PARAM_LENGTH == 20);  /* saved state */
+AssertCompile(CODECNODE_F02_PARAM_LENGTH == 16); /* saved state */
+
+/**
+ * Compile time assertion on the expected node size.
+ */
+#define AssertNodeSize(a_Node, a_cParams) \
+    AssertCompile((a_cParams) <= (60 + 6)); /* the max size - saved state */ \
+    AssertCompile(   sizeof(a_Node) - sizeof(CODECCOMMONNODE)  \
+                  == ((a_cParams) * sizeof(uint32_t)) )
+
+typedef struct ROOTCODECNODE
+{
+    CODECCOMMONNODE node;
+} ROOTCODECNODE, *PROOTCODECNODE;
+AssertNodeSize(ROOTCODECNODE, 0);
+
+typedef struct DACNODE
+{
+    CODECCOMMONNODE node;
+    uint32_t    u32F0d_param;
+    uint32_t    u32F04_param;
+    uint32_t    u32F05_param;
+    uint32_t    u32F06_param;
+    uint32_t    u32F0c_param;
+
+    uint32_t    u32A_param;
+    AMPLIFIER   B_params;
+
+} DACNODE, *PDACNODE;
+AssertNodeSize(DACNODE, 6 + 60);
+
+typedef struct ADCNODE
+{
+    CODECCOMMONNODE node;
+    uint32_t    u32F01_param;
+    uint32_t    u32F03_param;
+    uint32_t    u32F05_param;
+    uint32_t    u32F06_param;
+    uint32_t    u32F09_param;
+
+    uint32_t    u32A_param;
+    AMPLIFIER   B_params;
+} ADCNODE, *PADCNODE;
+AssertNodeSize(DACNODE, 6 + 60);
+
+typedef struct SPDIFOUTNODE
+{
+    CODECCOMMONNODE node;
+    uint32_t    u32F05_param;
+    uint32_t    u32F06_param;
+    uint32_t    u32F09_param;
+    uint32_t    u32F0d_param;
+
+    uint32_t    u32A_param;
+    AMPLIFIER   B_params;
+} SPDIFOUTNODE, *PSPDIFOUTNODE;
+AssertNodeSize(SPDIFOUTNODE, 5 + 60);
+
+typedef struct SPDIFINNODE
+{
+    CODECCOMMONNODE node;
+    uint32_t    u32F05_param;
+    uint32_t    u32F06_param;
+    uint32_t    u32F09_param;
+    uint32_t    u32F0d_param;
+
+    uint32_t    u32A_param;
+    AMPLIFIER   B_params;
+} SPDIFINNODE, *PSPDIFINNODE;
+AssertNodeSize(SPDIFINNODE, 5 + 60);
+
+typedef struct AFGCODECNODE
+{
+    CODECCOMMONNODE node;
+    uint32_t  u32F05_param;
+    uint32_t  u32F08_param;
+    uint32_t  u32F17_param;
+    uint32_t  u32F20_param;
+} AFGCODECNODE, *PAFGCODECNODE;
+AssertNodeSize(AFGCODECNODE, 4);
+
+typedef struct PORTNODE
+{
+    CODECCOMMONNODE node;
+    uint32_t u32F01_param;
+    uint32_t u32F07_param;
+    uint32_t u32F08_param;
+    uint32_t u32F09_param;
+    uint32_t u32F1c_param;
+    AMPLIFIER   B_params;
+} PORTNODE, *PPORTNODE;
+AssertNodeSize(PORTNODE, 5 + 60);
+
+typedef struct DIGOUTNODE
+{
+    CODECCOMMONNODE node;
+    uint32_t u32F01_param;
+    uint32_t u32F05_param;
+    uint32_t u32F07_param;
+    uint32_t u32F08_param;
+    uint32_t u32F09_param;
+    uint32_t u32F1c_param;
+} DIGOUTNODE, *PDIGOUTNODE;
+AssertNodeSize(DIGOUTNODE, 6);
+
+typedef struct DIGINNODE
+{
+    CODECCOMMONNODE node;
+    uint32_t u32F05_param;
+    uint32_t u32F07_param;
+    uint32_t u32F08_param;
+    uint32_t u32F09_param;
+    uint32_t u32F0c_param;
+    uint32_t u32F1c_param;
+    uint32_t u32F1e_param;
+} DIGINNODE, *PDIGINNODE;
+AssertNodeSize(DIGINNODE, 7);
+
+typedef struct ADCMUXNODE
+{
+    CODECCOMMONNODE node;
+    uint32_t    u32F01_param;
+
+    uint32_t    u32A_param;
+    AMPLIFIER   B_params;
+} ADCMUXNODE, *PADCMUXNODE;
+AssertNodeSize(ADCMUXNODE, 2 + 60);
+
+typedef struct PCBEEPNODE
+{
+    CODECCOMMONNODE node;
+    uint32_t    u32F07_param;
+    uint32_t    u32F0a_param;
+
+    uint32_t    u32A_param;
+    AMPLIFIER   B_params;
+    uint32_t    u32F1c_param;
+} PCBEEPNODE, *PPCBEEPNODE;
+AssertNodeSize(PCBEEPNODE, 3 + 60 + 1);
+
+typedef struct CDNODE
+{
+    CODECCOMMONNODE node;
+    uint32_t u32F07_param;
+    uint32_t u32F1c_param;
+} CDNODE, *PCDNODE;
+AssertNodeSize(CDNODE, 2);
+
+typedef struct VOLUMEKNOBNODE
+{
+    CODECCOMMONNODE node;
+    uint32_t    u32F08_param;
+    uint32_t    u32F0f_param;
+} VOLUMEKNOBNODE, *PVOLUMEKNOBNODE;
+AssertNodeSize(VOLUMEKNOBNODE, 2);
+
+typedef struct ADCVOLNODE
+{
+    CODECCOMMONNODE node;
+    uint32_t    u32F0c_param;
+    uint32_t    u32F01_param;
+    uint32_t    u32A_params;
+    AMPLIFIER   B_params;
+} ADCVOLNODE, *PADCVOLNODE;
+AssertNodeSize(ADCVOLNODE, 3 + 60);
+
+typedef struct RESNODE
+{
+    CODECCOMMONNODE node;
+    uint32_t    u32F05_param;
+    uint32_t    u32F06_param;
+    uint32_t    u32F07_param;
+    uint32_t    u32F1c_param;
+
+    uint32_t    u32A_param;
+} RESNODE, *PRESNODE;
+AssertNodeSize(RESNODE, 5);
+
+/**
+ * Used for the saved state.
+ */
+typedef struct CODECSAVEDSTATENODE
+{
+    CODECCOMMONNODE Core;
+    uint32_t        au32Params[60 + 6];
+} CODECSAVEDSTATENODE;
+AssertNodeSize(CODECSAVEDSTATENODE, 60 + 6);
+
+typedef union CODECNODE
+{
+    CODECCOMMONNODE node;
+    ROOTCODECNODE   root;
+    AFGCODECNODE    afg;
+    DACNODE         dac;
+    ADCNODE         adc;
+    SPDIFOUTNODE    spdifout;
+    SPDIFINNODE     spdifin;
+    PORTNODE        port;
+    DIGOUTNODE      digout;
+    DIGINNODE       digin;
+    ADCMUXNODE      adcmux;
+    PCBEEPNODE      pcbeep;
+    CDNODE          cdnode;
+    VOLUMEKNOBNODE  volumeKnob;
+    ADCVOLNODE      adcvol;
+    RESNODE         reserved;
+    CODECSAVEDSTATENODE SavedState;
+} CODECNODE, *PCODECNODE;
+AssertNodeSize(CODECNODE, 60 + 6);
+
+#define CODEC_VERBS_MAX     64
+#define CODEC_NODES_MAX     32
+
+/**
+ * HDA codec state (shared).
  */
 typedef struct HDACODEC
 {
-    uint16_t                id;
-    uint16_t                u16VendorId;
-    uint16_t                u16DeviceId;
-    uint8_t                 u8BSKU;
-    uint8_t                 u8AssemblyId;
-
-    /** List of assigned HDA drivers to this codec.
-     * A driver only can be assigned to one codec at a time. */
-    RTLISTANCHOR            lstDrv;
-
-    CODECVERB const        *paVerbs;
+    /** Codec implementation type. */
+    CODEC_TYPE enmType;
+    /** Codec ID. */
+    uint16_t   id;
+    uint16_t   u16VendorId;
+    uint16_t   u16DeviceId;
+    uint8_t    u8BSKU;
+    uint8_t    u8AssemblyId;
+
+    CODECNODE  aNodes[CODEC_NODES_MAX];
+    size_t     cNodes;
+
+    bool       fInReset;
+    uint8_t    abPadding1[3];
+
+    uint8_t    cTotalNodes;
+    uint8_t    u8AdcVolsLineIn;
+    uint8_t    u8DacLineOut;
+    uint8_t    bPadding2;
+
+    uint8_t    au8Ports[CODEC_NODES_MAX];
+    uint8_t    au8Dacs[CODEC_NODES_MAX];
+    uint8_t    au8AdcVols[CODEC_NODES_MAX];
+    uint8_t    au8Adcs[CODEC_NODES_MAX];
+    uint8_t    au8AdcMuxs[CODEC_NODES_MAX];
+    uint8_t    au8Pcbeeps[CODEC_NODES_MAX];
+    uint8_t    au8SpdifIns[CODEC_NODES_MAX];
+    uint8_t    au8SpdifOuts[CODEC_NODES_MAX];
+    uint8_t    au8DigInPins[CODEC_NODES_MAX];
+    uint8_t    au8DigOutPins[CODEC_NODES_MAX];
+    uint8_t    au8Cds[CODEC_NODES_MAX];
+    uint8_t    au8VolKnobs[CODEC_NODES_MAX];
+    uint8_t    au8Reserveds[CODEC_NODES_MAX];
+} HDACODEC;
+
+/**
+ * HDA codec state (ring-0).
+ */
+typedef struct HDACODECR0
+{
+    CODECVERBR0             aVerbs[CODEC_VERBS_MAX];
     size_t                  cVerbs;
-
-    PCODECNODE              paNodes;
-
-    bool                    fInReset;
-    uint8_t                 abPadding1[3];
-
-    const uint8_t           cTotalNodes;
-    const uint8_t           u8AdcVolsLineIn;
-    const uint8_t           u8DacLineOut;
-    uint8_t                 bPadding2;
-    const uint8_t          *au8Ports;
-    const uint8_t          *au8Dacs;
-    const uint8_t          *au8AdcVols;
-    const uint8_t          *au8Adcs;
-    const uint8_t          *au8AdcMuxs;
-    const uint8_t          *au8Pcbeeps;
-    const uint8_t          *au8SpdifIns;
-    const uint8_t          *au8SpdifOuts;
-    const uint8_t          *au8DigInPins;
-    const uint8_t          *au8DigOutPins;
-    const uint8_t          *au8Cds;
-    const uint8_t          *au8VolKnobs;
-    const uint8_t          *au8Reserveds;
 
     /** @name Public codec functions.
      *  @{  */
-    DECLR3CALLBACKMEMBER(int,  pfnLookup, (PHDACODEC pThis, uint32_t uVerb, uint64_t *puResp));
-    DECLR3CALLBACKMEMBER(void, pfnReset, (PHDACODEC pThis));
-    DECLR3CALLBACKMEMBER(int,  pfnNodeReset, (PHDACODEC pThis, uint8_t, PCODECNODE));
-    DECLR3CALLBACKMEMBER(void, pfnDbgListNodes, (PHDACODEC pThis, PCDBGFINFOHLP pHlp, const char *pszArgs));
-    DECLR3CALLBACKMEMBER(void, pfnDbgSelector, (PHDACODEC pThis, PCDBGFINFOHLP pHlp, const char *pszArgs));
+    DECLCALLBACKMEMBER(void, pfnReset, (PHDACODEC pThis, PHDACODECR0 pThisCC));
+    DECLCALLBACKMEMBER(int,  pfnNodeReset, (PHDACODEC pThis, uint8_t nID, PCODECNODE pNode));
+    DECLCALLBACKMEMBER(int,  pfnLookup, (PHDACODEC pThis, PHDACODECR0 pThisCC, uint32_t uVerb, uint64_t *puResp));
+    /** @} */
+
+#ifdef VBOX_WITH_STATISTICS
+    STAMCOUNTER StatLookupsR0;
+#endif
+
+} HDACODECR0;
+
+int hdaR0CodecConstruct(PPDMDEVINS pDevIns, PHDACODEC pThis, PHDACODECR0 pThisCC);
+
+/**
+ * HDA codec state (ring-3).
+ */
+typedef struct HDACODECR3
+{
+    CODECVERBR3             aVerbs[CODEC_VERBS_MAX];
+    size_t                  cVerbs;
+
+    /** @name Public codec functions.
+     *  @{  */
+    DECLCALLBACKMEMBER(int,  pfnLookup, (PHDACODEC pThis, PHDACODECR3 pThisCC, uint32_t uVerb, uint64_t *puResp));
+    DECLCALLBACKMEMBER(void, pfnDbgListNodes, (PHDACODEC pThis, PHDACODECR3 pThisCC, PCDBGFINFOHLP pHlp, const char *pszArgs));
+    DECLCALLBACKMEMBER(void, pfnDbgSelector, (PHDACODEC pThis, PHDACODECR3 pThisCC, PCDBGFINFOHLP pHlp, const char *pszArgs));
     /** @} */
 
@@ -160,15 +967,19 @@
 
 #ifdef VBOX_WITH_STATISTICS
-    STAMCOUNTER             StatLookups;
+    STAMCOUNTER StatLookupsR0;
+    STAMCOUNTER StatLookupsR3;
 #endif
-} HDACODEC;
-
-int hdaCodecConstruct(PPDMDEVINS pDevIns, PHDACODEC pThis, uint16_t uLUN, PCFGMNODE pCfg);
+
+} HDACODECR3;
+
+int hdaR3CodecConstruct(PPDMDEVINS pDevIns, PHDACODEC pThis, PHDACODECR3 pThisCC, uint16_t uLUN, PCFGMNODE pCfg);
+void hdaR3CodecPowerOff(PHDACODECR3 pThisCC);
+int hdaR3CodecLoadState(PPDMDEVINS pDevIns, PHDACODEC pThis, PHDACODECR3 pThisCC, PSSMHANDLE pSSM, uint32_t uVersion);
+int hdaR3CodecAddStream(PHDACODECR3 pThisCC, PDMAUDIOMIXERCTL enmMixerCtl, PPDMAUDIOSTREAMCFG pCfg);
+int hdaR3CodecRemoveStream(PHDACODECR3 pThisCC, PDMAUDIOMIXERCTL enmMixerCtl);
+
+int hdaCodecSaveState(PPDMDEVINS pDevIns, PHDACODEC pThis, PSSMHANDLE pSSM);
 void hdaCodecDestruct(PHDACODEC pThis);
-void hdaCodecPowerOff(PHDACODEC pThis);
-int hdaCodecSaveState(PPDMDEVINS pDevIns, PHDACODEC pThis, PSSMHANDLE pSSM);
-int hdaCodecLoadState(PPDMDEVINS pDevIns, PHDACODEC pThis, PSSMHANDLE pSSM, uint32_t uVersion);
-int hdaCodecAddStream(PHDACODEC pThis, PDMAUDIOMIXERCTL enmMixerCtl, PPDMAUDIOSTREAMCFG pCfg);
-int hdaCodecRemoveStream(PHDACODEC pThis, PDMAUDIOMIXERCTL enmMixerCtl);
+void hdaCodecReset(PHDACODEC pThis);
 
 /** @name DevHDA saved state versions
