VirtualBox

Changeset 60941 in vbox for trunk/src/VBox/Devices/Audio


Ignore:
Timestamp:
May 12, 2016 1:12:20 PM (9 years ago)
Author:
vboxsync
Message:

Audio/HDA:

  • Lowered timer to 100Hz and start/stop it only if needed. Should improve overall performance.
  • More work on dynamic stream assignments (SDI/SDO select) by the guest -- should make more Linux guests compatible with HDA.
Location:
trunk/src/VBox/Devices/Audio
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/AudioMixer.cpp

    r60934 r60941  
    312312    }
    313313
    314     LogFlowFunc(("Sink=%s, Cmd=%ld, rc=%Rrc\n", pSink->pszName, enmCmd, rc));
     314    LogFlowFunc(("%s: enmCmd=%ld, rc=%Rrc\n", pSink->pszName, enmCmd, rc));
    315315    return rc;
    316316}
     
    342342
    343343    RTMemFree(pSink);
     344}
     345
     346/**
     347 * Returns the sink's mixing direction.
     348 *
     349 * @returns Mixing direction.
     350 * @param   pSink           Sink to return direction for.
     351 *
     352 * @remark
     353 */
     354AUDMIXSINKDIR AudioMixerSinkGetDir(PAUDMIXSINK pSink)
     355{
     356    AssertPtrReturn(pSink, AUDMIXSINKDIR_UNKNOWN);
     357    return pSink->enmDir;
    344358}
    345359
     
    519533void AudioMixerSinkTimerUpdate(PAUDMIXSINK pSink, uint64_t cTicksPerSec, uint64_t cTicksElapsed, uint32_t *pcbData)
    520534{
     535    AssertPtrReturnVoid(pSink);
     536    /* pcbData is optional. */
     537
    521538    uint32_t cSamplesMin  = (uint32_t)((2 * cTicksElapsed * pSink->PCMProps.uHz + cTicksPerSec) / cTicksPerSec / 2);
    522539    uint32_t cbSamplesMin = cSamplesMin << pSink->PCMProps.cShift;
  • trunk/src/VBox/Devices/Audio/AudioMixer.h

    r60934 r60941  
    156156int AudioMixerSinkCtl(PAUDMIXSINK pSink, AUDMIXSINKCMD enmCmd);
    157157void AudioMixerSinkDestroy(PAUDMIXSINK pSink);
     158AUDMIXSINKDIR AudioMixerSinkGetDir(PAUDMIXSINK pSink);
    158159PAUDMIXSTREAM AudioMixerSinkGetStream(PAUDMIXSINK pSink, uint8_t uIndex);
    159160uint8_t AudioMixerSinkGetStreamCount(PAUDMIXSINK pSink);
  • trunk/src/VBox/Devices/Audio/DevIchHda.cpp

    r60925 r60941  
    629629
    630630/**
     631 * Structure defining an HDA mixer sink.
     632 * Its purpose is to know which audio mixer sink is bound to
     633 * which SDn (SDI/SDO) device stream.
     634 *
     635 * This is needed in order to handle interleaved streams
     636 * (that is, multiple channels in one stream) or non-interleaved
     637 * streams (each channel has a dedicated stream).
     638 *
     639 * This is only known to the actual device emulation level.
     640 */
     641typedef struct HDAMIXERSINK
     642{
     643    /** SDn ID this sink is assigned to. 0 if not assigned. */
     644    uint8_t                uSD;
     645    /** Channel ID of SDn ID. Only valid if SDn ID is valid. */
     646    uint8_t                uChannel;
     647    uint8_t                Padding[3];
     648    /** Pointer to the actual audio mixer sink. */
     649    R3PTRTYPE(PAUDMIXSINK) pMixSink;
     650} HDAMIXERSINK, *PHDAMIXERSINK;
     651
     652/**
    631653 * Structure for keeping a HDA stream state.
    632654 *
     
    637659{
    638660    /** Stream descriptor number (SDn). */
    639     uint8_t                 u8SD;
    640     uint8_t                 Padding0[7];
     661    uint8_t                  u8SD;
     662    uint8_t                  Padding0[7];
    641663    /** DMA base address (SDnBDPU - SDnBDPL). */
    642     uint64_t                u64BDLBase;
     664    uint64_t                 u64BDLBase;
    643665    /** Cyclic Buffer Length (SDnCBL).
    644666     *  Represents the size of the ring buffer. */
    645     uint32_t                u32CBL;
     667    uint32_t                 u32CBL;
    646668    /** Format (SDnFMT). */
    647     uint16_t                u16FMT;
     669    uint16_t                 u16FMT;
    648670    /** FIFO Size (FIFOS).
    649671     *  Maximum number of bytes that may have been DMA'd into
     
    651673     *
    652674     *  Must be a power of two. */
    653     uint16_t                u16FIFOS;
     675    uint16_t                 u16FIFOS;
    654676    /** Last Valid Index (SDnLVI). */
    655     uint16_t                u16LVI;
    656     uint16_t                Padding1[3];
    657     /** Pointer to mixer sink this stream is attached to. */
    658     R3PTRTYPE(PAUDMIXSINK)  pSink;
     677    uint16_t                 u16LVI;
     678    uint16_t                 Padding1[3];
     679    /** Pointer to HDA sink this stream is attached to. */
     680    R3PTRTYPE(PHDAMIXERSINK) pMixSink;
    659681    /** Internal state of this stream. */
    660     HDASTREAMSTATE          State;
     682    HDASTREAMSTATE           State;
    661683} HDASTREAM, *PHDASTREAM;
    662684
    663685/**
    664  * Structure for mapping a stream tag to
    665  * an internal stream state.
     686 * Structure for mapping a stream tag to an HDA stream.
    666687 */
    667688typedef struct HDATAG
    668689{
    669     /** Own Tag. */
     690    /** Own stream tag. */
    670691    uint8_t               uTag;
    671692    uint8_t               Padding[7];
     
    785806    /** Flag whether the RC part is enabled. */
    786807    bool                               fRCEnabled;
     808    /** Number of active (running) SDn streams. */
     809    uint8_t                            cStreamsActive;
    787810#ifndef VBOX_WITH_AUDIO_CALLBACKS
    788811    /** The timer for pumping data thru the attached LUN drivers. */
     
    807830    /** The device' software mixer. */
    808831    R3PTRTYPE(PAUDIOMIXER)             pMixer;
    809     /** Audio sink for PCM output. */
    810     R3PTRTYPE(PAUDMIXSINK)             pSinkFront;
     832    /** HDA sink for (front) output. */
     833    HDAMIXERSINK                       SinkFront;
    811834#ifdef VBOX_WITH_HDA_51_SURROUND
    812     R3PTRTYPE(PAUDMIXSINK)             pSinkCenterLFE;
    813     R3PTRTYPE(PAUDMIXSINK)             pSinkRear;
    814 #endif
    815     /** Audio mixer sink for line input. */
    816     R3PTRTYPE(PAUDMIXSINK)             pSinkLineIn;
     835    /** HDA sink for center / LFE output. */
     836    HDAMIXERSINK                       SinkCenterLFE;
     837    /** HDA sink for rear output. */
     838    HDAMIXERSINK                       SinkRear;
     839#endif
     840    /** HDA mixer sink for line input. */
     841    HDAMIXERSINK                       SinkLineIn;
    817842#ifdef VBOX_WITH_HDA_MIC_IN
    818843    /** Audio mixer sink for microphone input. */
    819     R3PTRTYPE(PAUDMIXSINK)             pSinkMicIn;
     844    HDAMIXERSINK                       SinkMicIn;
    820845#endif
    821846    uint64_t                           u64BaseTS;
     
    898923#ifdef IN_RING3
    899924static void hdaStreamDestroy(PHDASTREAM pStrmSt);
     925static int hdaStreamSetActive(PHDASTATE pThis, PHDASTREAM pStream, bool fActive);
    900926static int hdaStreamStart(PHDASTREAM pStrmSt);
    901927static int hdaStreamStop(PHDASTREAM pStrmSt);
     
    919945static int           hdaProcessInterrupt(PHDASTATE pThis);
    920946
     947/*
     948 * Timer routines.
     949 */
     950#ifndef VBOX_WITH_AUDIO_CALLBACKS
     951static void hdaTimerMaybeStart(PHDASTATE pThis);
     952static void hdaTimerMaybeStop(PHDASTATE pThis);
     953static DECLCALLBACK(void) hdaTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser);
     954#endif
    921955
    922956/*********************************************************************************************************************************
     
    12511285}
    12521286
     1287/**
     1288 * Returns the HDA stream of specified stream descriptor number.
     1289 *
     1290 * @return  Pointer to HDA stream, or NULL if none found.
     1291 */
    12531292DECLINLINE(PHDASTREAM) hdaStreamFromSD(PHDASTATE pThis, uint8_t uSD)
    12541293{
    12551294    AssertPtrReturn(pThis, NULL);
    12561295    AssertReturn(uSD <= HDA_MAX_STREAMS, NULL);
     1296
     1297    if (uSD >= HDA_MAX_STREAMS)
     1298        return NULL;
     1299
    12571300    return &pThis->aStreams[uSD];
     1301}
     1302
     1303/**
     1304 * Returns the HDA stream of specified HDA sink.
     1305 *
     1306 * @return  Pointer to HDA stream, or NULL if none found.
     1307 */
     1308DECLINLINE(PHDASTREAM) hdaGetStreamFromSink(PHDASTATE pThis, PHDAMIXERSINK pSink)
     1309{
     1310    AssertPtrReturn(pThis, NULL);
     1311    AssertPtrReturn(pSink, NULL);
     1312
     1313    /** @todo Do something with the channel mapping here? */
     1314    return hdaStreamFromSD(pThis, pSink->uSD);
    12581315}
    12591316
     
    15561613    {
    15571614        pStrmSt->u8SD           = uSD;
    1558         pStrmSt->pSink          = NULL;
     1615        pStrmSt->pMixSink       = NULL;
    15591616
    15601617        pStrmSt->State.fActive  = false;
     
    16851742}
    16861743
     1744static int hdaStreamSetActive(PHDASTATE pThis, PHDASTREAM pStream, bool fActive)
     1745{
     1746    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
     1747    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     1748
     1749    AUDMIXSINKCMD enmCmd = fActive
     1750                         ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE;
     1751
     1752    /* First, enable or disable the stream's sink, if any. */
     1753    AssertPtr(pStream->pMixSink);
     1754    if (pStream->pMixSink->pMixSink)
     1755        AudioMixerSinkCtl(pStream->pMixSink->pMixSink, enmCmd);
     1756
     1757    /* Second, see if we need to start or stop the timer. */
     1758    if (!fActive)
     1759    {
     1760        if (pThis->cStreamsActive) /* Disable can be called mupltiple times. */
     1761            pThis->cStreamsActive--;
     1762
     1763#ifndef VBOX_WITH_AUDIO_CALLBACKS
     1764        hdaTimerMaybeStop(pThis);
     1765#endif
     1766    }
     1767    else
     1768    {
     1769        pThis->cStreamsActive++;
     1770#ifndef VBOX_WITH_AUDIO_CALLBACKS
     1771        hdaTimerMaybeStart(pThis);
     1772#endif
     1773    }
     1774
     1775    LogFlowFunc(("u8Strm=%RU8, fActive=%RTbool, cStreamsActive=%RU8\n", pStream->u8SD, fActive, pThis->cStreamsActive));
     1776
     1777    return VINF_SUCCESS;
     1778}
     1779
     1780static void hdaStreamAssignToSink(PHDASTREAM pStrmSt, PHDAMIXERSINK pMixSink)
     1781{
     1782    AssertPtrReturnVoid(pStrmSt);
     1783
     1784    int rc2 = RTSemMutexRequest(pStrmSt->State.hMtx, RT_INDEFINITE_WAIT);
     1785    if (RT_SUCCESS(rc2))
     1786    {
     1787        pStrmSt->pMixSink = pMixSink;
     1788
     1789        rc2 = RTSemMutexRelease(pStrmSt->State.hMtx);
     1790        AssertRC(rc2);
     1791    }
     1792}
     1793
    16871794static int hdaStreamStart(PHDASTREAM pStrmSt)
    16881795{
     
    21502257     */
    21512258    uint8_t uTag = (u32Value >> HDA_SDCTL_NUM_SHIFT) & HDA_SDCTL_NUM_MASK;
    2152 
    2153     /* Tag 0 is reserved for software / invalid, just skip. */
    2154     if (   !uTag
    2155         || (uTag > HDA_MAX_TAGS))
     2259    if (uTag > HDA_MAX_TAGS)
    21562260    {
    21572261        LogFunc(("[SD%RU8]: Warning: Invalid stream tag %RU8 specified!\n", uSD, uTag));
     
    21632267    AssertPtr(pTag);
    21642268
    2165     if (pTag->uTag)
    2166         LogFunc(("[SD%RU8]: Warning: Tag %RU8 already assigned to %RU8 (pStrm=%p)\n", uSD, uTag, pTag->uTag, pTag->pStrm));
     2269    LogFunc(("[SD%RU8]: Using stream tag=%RU8\n", uSD, uTag));
    21672270
    21682271    /* Assign new values. */
    21692272    pTag->uTag  = uTag;
    21702273    pTag->pStrm = hdaStreamFromSD(pThis, uSD);
    2171 
    2172     LogFunc(("[SD%RU8]: Using stream tag=%RU8\n", uSD, uTag));
    21732274
    21742275    PHDASTREAM pStrmSt = pTag->pStrm;
     
    22142315            LogFunc(("[SD%RU8]: fRun=%RTbool\n", pStrmSt->u8SD, fRun));
    22152316
    2216             AUDMIXSINKCMD enmCmd = fRun
    2217                                  ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE;
    2218 
    2219             if (hdaGetDirFromSD(uSD) == PDMAUDIODIR_IN)
    2220             {
    2221 # ifdef VBOX_WITH_HDA_MIC_IN
    2222                 AudioMixerSinkCtl(pThis->pSinkMicIn,  enmCmd);
    2223 # endif
    2224                 AudioMixerSinkCtl(pThis->pSinkLineIn, enmCmd);
    2225             }
    2226             else
    2227             {
    2228                 AudioMixerSinkCtl(pThis->pSinkFront,     enmCmd);
    2229 # ifdef VBOX_WITH_HDA_51_SURROUND
    2230                 AudioMixerSinkCtl(pThis->pSinkCenterLFE, enmCmd);
    2231                 AudioMixerSinkCtl(pThis->pSinkRear,      enmCmd);
    2232 # endif
    2233             }
     2317            hdaStreamSetActive(pThis, pStrmSt, fRun);
    22342318
    22352319            if (fRun)
     
    26302714{
    26312715#ifdef IN_RING3
    2632     if (HDA_REG_IND(pThis, iReg) == u32Value) /* Value already set? */
    2633         return VINF_SUCCESS;
    2634 
    26352716    PDMAUDIOSTREAMCFG strmCfg;
    26362717    RT_ZERO(strmCfg);
     
    33333414        }
    33343415
    3335         rc = AudioMixerSinkRead(pStrmSt->pSink, AUDMIXOP_BLEND, pBDLE->State.au8FIFO, cbBuf, &cbRead);
     3416        AssertPtr(pStrmSt->pMixSink);
     3417        AssertPtr(pStrmSt->pMixSink->pMixSink);
     3418        rc = AudioMixerSinkRead(pStrmSt->pMixSink->pMixSink, AUDMIXOP_BLEND, pBDLE->State.au8FIFO, cbBuf, &cbRead);
    33363419        if (RT_FAILURE(rc))
    33373420            break;
     
    34813564             * Write data to according mixer sinks.
    34823565             */
    3483             rc2 = AudioMixerSinkWrite(pThis->pSinkFront,    AUDMIXOP_COPY, pvDataFront,     cbDataFront,
     3566            rc2 = AudioMixerSinkWrite(pThis->SinkFront.pMixSink, AUDMIXOP_COPY, pvDataFront,     cbDataFront,
    34843567                                      NULL /* pcbWritten */);
    34853568            AssertRC(rc2);
    34863569#ifdef VBOX_WITH_HDA_51_SURROUND
    3487             rc2 = AudioMixerSinkWrite(pThis->pSinkCenterLFE, AUDMIXOP_COPY, pvDataCenterLFE, cbDataCenterLFE,
     3570            rc2 = AudioMixerSinkWrite(pThis->SinkCenterLFE,      AUDMIXOP_COPY, pvDataCenterLFE, cbDataCenterLFE,
    34883571                                      NULL /* pcbWritten */);
    34893572            AssertRC(rc2);
    3490             rc2 = AudioMixerSinkWrite(pThis->pSinkRear,      AUDMIXOP_COPY, pvDataRear,      cbDataRear,
     3573            rc2 = AudioMixerSinkWrite(pThis->SinkRear,           AUDMIXOP_COPY, pvDataRear,      cbDataRear,
    34913574                                      NULL /* pcbWritten */);
    34923575            AssertRC(rc2);
     
    35453628 * Returns NULL if no sink is found.
    35463629 *
    3547  * @return  PAUDMIXSINK
     3630 * @return  PHDAMIXERSINK
    35483631 * @param   pThis               HDA state.
    35493632 * @param   enmMixerCtl         Mixer control to get the corresponding sink for.
    35503633 */
    3551 static PAUDMIXSINK hdaMixerControlToSink(PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl)
    3552 {
    3553     PAUDMIXSINK pSink;
     3634static PHDAMIXERSINK hdaMixerControlToSink(PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl)
     3635{
     3636    PHDAMIXERSINK pSink;
    35543637
    35553638    switch (enmMixerCtl)
     
    35583641            /* Fall through is intentional. */
    35593642        case PDMAUDIOMIXERCTL_FRONT:
    3560             pSink = pThis->pSinkFront;
     3643            pSink = &pThis->SinkFront;
    35613644            break;
    35623645#ifdef VBOX_WITH_HDA_51_SURROUND
    35633646        case PDMAUDIOMIXERCTL_CENTER_LFE:
    3564             pSink = pThis->pSinkCenterLFE;
     3647            pSink = &pThis->SinkCenterLFE;
    35653648            break;
    35663649        case PDMAUDIOMIXERCTL_REAR:
    3567             pSink = pThis->pSinkRear;
     3650            pSink = &pThis->SinkRear;
    35683651            break;
    35693652#endif
    35703653        case PDMAUDIOMIXERCTL_LINE_IN:
    3571             pSink = pThis->pSinkLineIn;
     3654            pSink = &pThis->SinkLineIn;
    35723655            break;
    35733656#ifdef VBOX_WITH_HDA_MIC_IN
    35743657        case PDMAUDIOMIXERCTL_MIC_IN:
    3575             pSink = pThis->pSinkMicIn;
     3658            pSink = &pThis->SinkMicIn;
    35763659            break;
    35773660#endif
     
    35853668}
    35863669
    3587 static DECLCALLBACK(int) hdaMixerAddStream(PHDASTATE pThis, PAUDMIXSINK pSink, PPDMAUDIOSTREAMCFG pCfg)
     3670static DECLCALLBACK(int) hdaMixerAddStream(PHDASTATE pThis, PHDAMIXERSINK pSink, PPDMAUDIOSTREAMCFG pCfg)
    35883671{
    35893672    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     
    35913674    AssertPtrReturn(pCfg,  VERR_INVALID_POINTER);
    35923675
    3593     LogFunc(("Sink=%s, Stream=%s\n", pSink->pszName, pCfg->szName));
    3594 
    3595     int rc = VINF_SUCCESS;
     3676    LogFunc(("Sink=%s, Stream=%s\n", pSink->pMixSink->pszName, pCfg->szName));
     3677
     3678    /* Update the sink's format. */
     3679    PDMPCMPROPS PCMProps;
     3680    int rc = DrvAudioStreamCfgToProps(pCfg, &PCMProps);
     3681    if (RT_SUCCESS(rc))
     3682        rc = AudioMixerSinkSetFormat(pSink->pMixSink, &PCMProps);
    35963683
    35973684    PHDADRIVER pDrv;
     
    36433730        if (RT_SUCCESS(rc2))
    36443731        {
     3732            AudioMixerSinkRemoveStream(pSink->pMixSink, pStream->pMixStrm);
     3733
     3734            AudioMixerStreamDestroy(pStream->pMixStrm);
     3735            pStream->pMixStrm = NULL;
     3736
    36453737            PAUDMIXSTREAM pMixStrm;
    36463738            rc2 = AudioMixerStreamCreate(pDrv->pConnector, pCfg, 0 /* fFlags */, &pMixStrm);
    36473739            if (RT_SUCCESS(rc2))
    36483740            {
    3649                 rc2 = AudioMixerSinkAddStream(pSink, pMixStrm);
     3741                rc2 = AudioMixerSinkAddStream(pSink->pMixSink, pMixStrm);
    36503742                LogFlowFunc(("LUN#%RU8: Added \"%s\" to sink, rc=%Rrc\n", pDrv->uLUN, pCfg->szName , rc2));
    36513743            }
     
    36803772    int rc;
    36813773
    3682     PAUDMIXSINK pSink = hdaMixerControlToSink(pThis, enmMixerCtl);
     3774    PHDAMIXERSINK pSink = hdaMixerControlToSink(pThis, enmMixerCtl);
    36833775    if (pSink)
    36843776    {
     
    36883780        rc = VERR_NOT_FOUND;
    36893781
    3690     LogFlowFunc(("Sink=%s, enmMixerCtl=%ld, rc=%Rrc\n", pSink->pszName, enmMixerCtl, rc));
     3782    LogFlowFunc(("Sink=%s, enmMixerCtl=%ld, rc=%Rrc\n", pSink->pMixSink->pszName, enmMixerCtl, rc));
    36913783    return rc;
    36923784}
     
    37053797    int rc;
    37063798
    3707     PAUDMIXSINK pSink = hdaMixerControlToSink(pThis, enmMixerCtl);
     3799    PHDAMIXERSINK pSink = hdaMixerControlToSink(pThis, enmMixerCtl);
    37083800    if (pSink)
    37093801    {
    3710         AudioMixerSinkRemoveAllStreams(pSink);
     3802        PHDADRIVER pDrv;
     3803        RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
     3804        {
     3805            PAUDMIXSTREAM pMixStream;
     3806            switch (enmMixerCtl)
     3807            {
     3808                /*
     3809                 * Input.
     3810                 */
     3811                case PDMAUDIOMIXERCTL_LINE_IN:
     3812                    pMixStream = pDrv->LineIn.pMixStrm;
     3813                    pDrv->LineIn.pMixStrm = NULL;
     3814                    break;
     3815#ifdef VBOX_WITH_HDA_MIC_IN
     3816                case PDMAUDIOMIXERCTL_MIC_IN:
     3817                    pMixStream = pDrv->MicIn.pMixStrm;
     3818                    pDrv->MicIn.pMixStrm = NULL;
     3819                    break;
     3820#endif
     3821                /*
     3822                 * Output.
     3823                 */
     3824                case PDMAUDIOMIXERCTL_FRONT:
     3825                    pMixStream = pDrv->Front.pMixStrm;
     3826                    pDrv->Front.pMixStrm = NULL;
     3827                    break;
     3828#ifdef VBOX_WITH_HDA_51_SURROUND
     3829                case PDMAUDIOMIXERCTL_CENTER_LFE:
     3830                    pMixStream = pDrv->CenterLFE.pMixStrm;
     3831                    pDrv->CenterLFE.pMixStrm = NULL;
     3832                    break;
     3833                case PDMAUDIOMIXERCTL_REAR:
     3834                    pMixStream = pDrv->Rear.pMixStrm;
     3835                    pDrv->Rear.pMixStrm = NULL;
     3836                    break;
     3837#endif
     3838                default:
     3839                    AssertMsgFailed(("Mixer control %ld not implemented\n", enmMixerCtl));
     3840                    break;
     3841            }
     3842
     3843            AudioMixerSinkRemoveStream(pSink->pMixSink, pMixStream);
     3844            AudioMixerStreamDestroy(pMixStream);
     3845        }
     3846
     3847        AudioMixerSinkRemoveAllStreams(pSink->pMixSink);
    37113848        rc = VINF_SUCCESS;
    37123849    }
     
    37153852
    37163853    LogFlowFunc(("enmMixerCtl=%ld, rc=%Rrc\n", enmMixerCtl, rc));
     3854    return rc;
     3855}
     3856
     3857/**
     3858 * Sets a SDn stream number and channel to a particular mixer control.
     3859 *
     3860 * @returns IPRT status code.
     3861 * @param   pThis               HDA State.
     3862 * @param   enmMixerCtl         Mixer control to set SD stream number and channel for.
     3863 * @param   uSD                 SD stream number (number + 1) to set. Set to 0 for unassign.
     3864 * @param   uChannel            Channel to set. Only valid if a valid SD stream number is specified.
     3865 */
     3866static DECLCALLBACK(int) hdaMixerSetStream(PHDASTATE pThis,
     3867                                           PDMAUDIOMIXERCTL enmMixerCtl, uint8_t uSD, uint8_t uChannel)
     3868{
     3869    LogFlowFunc(("enmMixerCtl=%RU32, uSD=%RU8, uChannel=%RU8\n", enmMixerCtl, uSD, uChannel));
     3870
     3871    if (uSD == 0) /* Stream number 0 is reserved. */
     3872    {
     3873        LogFlowFunc(("Invalid SDn (%RU8) number for mixer control %ld, ignoring\n", uSD, enmMixerCtl));
     3874        return VINF_SUCCESS;
     3875    }
     3876    /* uChannel is optional. */
     3877
     3878    /* SDn0 starts as 1. */
     3879    Assert(uSD);
     3880    uSD--;
     3881
     3882    int rc;
     3883
     3884    PHDAMIXERSINK pSink = hdaMixerControlToSink(pThis, enmMixerCtl);
     3885    if (pSink)
     3886    {
     3887        if (   (uSD < HDA_MAX_SDI)
     3888            && AudioMixerSinkGetDir(pSink->pMixSink) == AUDMIXSINKDIR_OUTPUT)
     3889        {
     3890            uSD += HDA_MAX_SDI;
     3891        }
     3892
     3893        LogFlowFunc(("%s: Setting to stream ID=%RU8, channel=%RU8, enmMixerCtl=%RU32\n",
     3894                     pSink->pMixSink->pszName, uSD, uChannel, enmMixerCtl));
     3895
     3896        Assert(uSD < HDA_MAX_STREAMS);
     3897
     3898        PHDASTREAM pStream = hdaStreamFromSD(pThis, pSink->uSD);
     3899        if (pStream)
     3900        {
     3901            pSink->uSD      = uSD;
     3902            pSink->uChannel = uChannel;
     3903
     3904            /* Make sure that the stream also has this sink set. */
     3905            hdaStreamAssignToSink(pStream, pSink);
     3906
     3907            rc = VINF_SUCCESS;
     3908        }
     3909        else
     3910        {
     3911            LogRel(("HDA: Guest wanted to assign invalid stream ID=%RU8 (channel %RU8) to mixer control %RU32, skipping\n",
     3912                    uSD, uChannel, enmMixerCtl));
     3913            rc = VERR_INVALID_PARAMETER;
     3914        }
     3915    }
     3916    else
     3917        rc = VERR_NOT_FOUND;
     3918
     3919    LogFlowFuncLeaveRC(rc);
    37173920    return rc;
    37183921}
     
    37313934    int rc;
    37323935
    3733     PAUDMIXSINK pSink = hdaMixerControlToSink(pThis, enmMixerCtl);
     3936    PHDAMIXERSINK pSink = hdaMixerControlToSink(pThis, enmMixerCtl);
    37343937    if (pSink)
    37353938    {
    37363939        /* Set the volume.
    37373940         * We assume that the codec already converted it to the correct range. */
    3738         rc = AudioMixerSinkSetVolume(pSink, pVol);
     3941        rc = AudioMixerSinkSetVolume(pSink->pMixSink, pVol);
    37393942    }
    37403943    else
     
    37463949
    37473950#ifndef VBOX_WITH_AUDIO_CALLBACKS
     3951
     3952static void hdaTimerMaybeStart(PHDASTATE pThis)
     3953{
     3954    if (pThis->cStreamsActive == 0) /* Only start the timer if there are no active streams. */
     3955        return;
     3956
     3957    if (!pThis->pTimer)
     3958        return;
     3959
     3960    LogFlowFuncEnter();
     3961
     3962    /* Fire off timer. */
     3963    TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->cTimerTicks);
     3964}
     3965
     3966static void hdaTimerMaybeStop(PHDASTATE pThis)
     3967{
     3968    if (pThis->cStreamsActive) /* Some streams still active? Bail out. */
     3969        return;
     3970
     3971    if (!pThis->pTimer)
     3972        return;
     3973
     3974    LogFlowFuncEnter();
     3975
     3976    int rc2 = TMTimerStop(pThis->pTimer);
     3977    AssertRC(rc2);
     3978}
    37483979
    37493980static DECLCALLBACK(void) hdaTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
     
    37643995    pThis->uTimerTS = cTicksNow;
    37653996
    3766     /*
    3767      * Calculate the codec's (fixed) sampling rate.
    3768      */
    3769     AssertPtr(pThis->pCodec);
    3770 
    3771     /* Since the codec always runs at a fixed delivery rate (48 kHz), calculate the sample processing rate based
    3772      * on the clock ticks elapsed (the clock itself runs at 24 Mhz).
    3773      * A stream itself can have a higher or lower delivery rate, which in turn then results in more or less
    3774      * stream samples per frame. */
    3775     uint32_t cCodecSamplesMin  = (int)((2 * cTicksElapsed * 48000 /* Hz */ + cTicksPerSec) / cTicksPerSec / 2);
    3776     /* We always use 32-bit as containers to make sure all data is being pumped if we need to. */
    3777     uint32_t cbCodecSamplesMin = cCodecSamplesMin << 1;
    3778 
    3779 #if 0
    3780     /*
    3781      * Process all driver nodes.
    3782      */
    3783     PHDADRIVER pDrv;
    3784     RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
    3785     {
    3786         uint32_t cbIn = 0;
    3787         uint32_t cbOut = 0;
    3788 
    3789         rc = pDrv->pConnector->pfnQueryStatus(pDrv->pConnector, &cbIn, &cbOut, NULL /* pcSamplesLive */);
    3790         if (RT_SUCCESS(rc))
    3791             rc = pDrv->pConnector->pfnPlayOut(pDrv->pConnector, NULL /* pcSamplesPlayed */);
    3792 
    3793 #ifdef DEBUG_TIMER
    3794         LogFlowFunc(("LUN#%RU8: rc=%Rrc, cbIn=%RU32, cbOut=%RU32\n", pDrv->uLUN, rc, cbIn, cbOut));
    3795 #endif
    3796         /* If we there was an error handling (available) output or there simply is no output available,
    3797          * then calculate the minimum data rate which must be processed by the device emulation in order
    3798          * to function correctly.
    3799          *
    3800          * This is not the optimal solution, but as we have to deal with this on a timer-based approach
    3801          * (until we have the audio callbacks) we need to have device' DMA engines running. */
    3802         if (!AudioMixerStreamIsValid(pDrv->Front.pMixStrm))
    3803         {
    3804             /* Use the codec's (fixed) sampling rate. */
    3805             cbOut = RT_MAX(cbOut, cbCodecSamplesMin);
    3806             continue;
    3807         }
    3808 
    3809         const bool fIsActiveOut = pDrv->pConnector->pfnIsActiveOut(pDrv->pConnector, pDrv->Front.pMixStrm->InOut.pOut);
    3810         if (   RT_FAILURE(rc)
    3811             || !fIsActiveOut)
    3812         {
    3813             uint32_t cSamplesMin  = (int)((2 * cTicksElapsed * pDrv->Front.pMixStrm->InOut.pOut->Props.uHz + cTicksPerSec) / cTicksPerSec / 2);
    3814             uint32_t cbSamplesMin = AUDIOMIXBUF_S2B(&pDrv->Front.pMixStrm->InOut.pOut->MixBuf, cSamplesMin);
    3815 
    3816 #ifdef DEBUG_TIMER
    3817             LogFlowFunc(("\trc=%Rrc, cSamplesMin=%RU32, cbSamplesMin=%RU32\n", rc, cSamplesMin, cbSamplesMin));
    3818 #endif
    3819             cbOut = RT_MAX(cbOut, cbSamplesMin);
    3820         }
    3821 
    3822         cbOutMin = RT_MIN(cbOutMin, cbOut);
    3823         cbInMax  = RT_MAX(cbInMax, cbIn);
    3824     }
    3825 #else
    3826     AudioMixerSinkUpdate(pThis->pSinkFront);
    3827     cbOutMin = _4K; //cbCodecSamplesMin;
    3828     cbInMax  = _4K;
    3829 #endif
    3830 
    3831 #ifdef DEBUG_TIMER
    3832     LogFlowFunc(("cbInMax=%RU32, cbOutMin=%RU32\n", cbInMax, cbOutMin));
    3833 #endif
    3834 
    3835     if (cbOutMin == UINT32_MAX)
    3836         cbOutMin = 0;
    3837 
    3838     /** @todo Determine the streams to be handled. */
    3839     PHDASTREAM pStreamLineIn  = &pThis->aStreams[0];
     3997    PHDASTREAM pStreamLineIn  = hdaGetStreamFromSink(pThis, &pThis->SinkLineIn);
    38403998#ifdef VBOX_WITH_HDA_MIC_IN
    3841     /** @todo Anything to do for mic-in? */
    3842 #endif
    3843     PHDASTREAM pStreamOut     = &pThis->aStreams[4];
    3844 
    3845     /* Do the actual device transfers. */
    3846     hdaTransfer(pThis, pStreamOut,     cbOutMin /* cbToProcess */, NULL /* pcbProcessed */);
    3847     hdaTransfer(pThis, pStreamLineIn,  cbInMax  /* cbToProcess */, NULL /* pcbProcessed */);
     3999    PHDASTREAM pStreamMicIn   = hdaGetStreamFromSink(pThis, &pThis->SinkMicIn);
     4000#endif
     4001    PHDASTREAM pStreamFront   = hdaGetStreamFromSink(pThis, &pThis->SinkFront);
     4002
     4003    uint32_t cbLineIn;
     4004    AudioMixerSinkTimerUpdate(pThis->SinkLineIn.pMixSink, cTicksPerSec, cTicksElapsed, &cbLineIn);
     4005    if (cbLineIn)
     4006        hdaTransfer(pThis, pStreamLineIn, cbLineIn, NULL); /** @todo Add rc! */
     4007
     4008#ifdef VBOX_WITH_HDA_MIC_IN
     4009    uint32_t cbMicIn;
     4010    AudioMixerSinkTimerUpdate(pThis->SinkMicIn.pMixSink , cTicksPerSec, cTicksElapsed, &cbMicIn);
     4011#endif
     4012
     4013    uint32_t cbOut;
     4014    AudioMixerSinkTimerUpdate(pThis->SinkFront.pMixSink, cTicksPerSec, cTicksElapsed, &cbOut);
     4015    if (cbOut)
     4016        hdaTransfer(pThis, pStreamFront, cbOut, NULL);  /** @todo Add rc! */
    38484017
    38494018    /* Kick the timer again. */
     
    39114080    /* pcbProcessed is optional. */
    39124081
    3913     // 44100 / 200 Hz Timer = cbToProcess = 220,8
    3914     cbToProcess = 440; // FIFO SIZE
    3915 
    39164082    if (ASMAtomicReadBool(&pThis->fInReset)) /* HDA controller in reset mode? Bail out. */
    39174083    {
     
    39754141    Assert(pStream->State.fInReset == false);
    39764142
    3977 //    uint32_t cbLeft  = cbToProcess;
    39784143    uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStream->u8SD);
    39794144    Assert(u32LPIB <= pStream->u32CBL);
     
    40394204
    40404205        /* Set the FIFORDY bit on the stream while doing the transfer. */
    4041     //    HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
     4206        HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
    40424207
    40434208        uint32_t cbProcessed;
     
    40484213
    40494214        /* Remove the FIFORDY bit again. */
    4050     //    HDA_STREAM_REG(pThis, STS, pStream->u8SD) &= ~HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
     4215        HDA_STREAM_REG(pThis, STS, pStream->u8SD) &= ~HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
    40514216
    40524217        if (RT_FAILURE(rc))
     
    48545019
    48555020# ifdef VBOX_WITH_HDA_MIC_IN
    4856         AudioMixerSinkCtl(pThis->pSinkMicIn,     enmCmdMicIn);
     5021        AudioMixerSinkCtl(pThis->SinkMicIn.pMixSink,     enmCmdMicIn);
    48575022# endif
    4858         AudioMixerSinkCtl(pThis->pSinkLineIn,    enmCmdLineIn);
    4859         AudioMixerSinkCtl(pThis->pSinkFront,     enmCmdOut);
     5023        AudioMixerSinkCtl(pThis->SinkLineIn.pMixSink,    enmCmdLineIn);
     5024        AudioMixerSinkCtl(pThis->SinkFront.pMixSink,     enmCmdOut);
    48605025# ifdef VBOX_WITH_HDA_51_SURROUND
    4861         AudioMixerSinkCtl(pThis->pSinkCenterLFE, enmCmdOut);
    4862         AudioMixerSinkCtl(pThis->pSinkRear,      enmCmdOut);
     5026        AudioMixerSinkCtl(pThis->SinkCenterLFE.pMixSink, enmCmdOut);
     5027        AudioMixerSinkCtl(pThis->SinkRear.pMixSink,      enmCmdOut);
    48635028# endif
    48645029    }
     
    51775342     * Stop the timer, if any.
    51785343     */
    5179     int rc2;
    5180     if (pThis->pTimer)
    5181     {
    5182         rc2 = TMTimerStop(pThis->pTimer);
    5183         AssertRC(rc2);
    5184     }
     5344    hdaTimerMaybeStop(pThis);
    51855345# endif
    51865346
     
    52055365     * Stop any audio currently playing and/or recording.
    52065366     */
    5207     AudioMixerSinkCtl(pThis->pSinkFront,     AUDMIXSINKCMD_DISABLE);
     5367    AudioMixerSinkCtl(pThis->SinkFront.pMixSink,     AUDMIXSINKCMD_DISABLE);
    52085368# ifdef VBOX_WITH_HDA_MIC_IN
    5209     AudioMixerSinkCtl(pThis->pSinkMicIn,     AUDMIXSINKCMD_DISABLE);
     5369    AudioMixerSinkCtl(pThis->SinkMicIn.pMixSink,     AUDMIXSINKCMD_DISABLE);
    52105370# endif
    5211     AudioMixerSinkCtl(pThis->pSinkLineIn,    AUDMIXSINKCMD_DISABLE);
     5371    AudioMixerSinkCtl(pThis->SinkLineIn.pMixSink,    AUDMIXSINKCMD_DISABLE);
    52125372# ifdef VBOX_WITH_HDA_51_SURROUND
    5213     AudioMixerSinkCtl(pThis->pSinkCenterLFE, AUDMIXSINKCMD_DISABLE);
    5214     AudioMixerSinkCtl(pThis->pSinkRear,      AUDMIXSINKCMD_DISABLE);
     5373    AudioMixerSinkCtl(pThis->SinkCenterLFE.pMixSink, AUDMIXSINKCMD_DISABLE);
     5374    AudioMixerSinkCtl(pThis->SinkRear.pMixSink,      AUDMIXSINKCMD_DISABLE);
    52155375# endif
     5376
     5377    /*
     5378     * Set some sensible defaults for which HDA sinks
     5379     * are connected to which stream number.
     5380     *
     5381     * We use SD0 for input and SD4 for output by default.
     5382     * These stream numbers can be changed by the guest dynamically lateron.
     5383     */
     5384#ifdef VBOX_WITH_HDA_MIC_IN
     5385    hdaMixerSetStream(pThis, PDMAUDIOMIXERCTL_MIC_IN    , 1 /* SD0 */, 0 /* Channel */);
     5386#endif
     5387    hdaMixerSetStream(pThis, PDMAUDIOMIXERCTL_LINE_IN   , 1 /* SD0 */, 0 /* Channel */);
     5388
     5389    hdaMixerSetStream(pThis, PDMAUDIOMIXERCTL_FRONT     , 5 /* SD4 */, 0 /* Channel */);
     5390#ifdef VBOX_WITH_HDA_51_SURROUND
     5391    hdaMixerSetStream(pThis, PDMAUDIOMIXERCTL_CENTER_LFE, 5 /* SD4 */, 0 /* Channel */);
     5392    hdaMixerSetStream(pThis, PDMAUDIOMIXERCTL_REAR      , 5 /* SD4 */, 0 /* Channel */);
     5393#endif
    52165394
    52175395    pThis->cbCorbBuf = 256 * sizeof(uint32_t); /** @todo Use a define here. */
     
    52445422
    52455423# ifndef VBOX_WITH_AUDIO_CALLBACKS
    5246     /*
    5247      * Start timer again, if any.
    5248      */
    5249     if (pThis->pTimer)
    5250     {
    5251         LogFunc(("Restarting timer\n"));
    5252         rc2 = TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->cTimerTicks);
    5253         AssertRC(rc2);
    5254     }
     5424    hdaTimerMaybeStart(pThis);
    52555425# endif
    52565426
     
    54055575    LogRel2(("HDA: Powering off ...\n"));
    54065576
     5577    /* Ditto goes for the codec, which in turn uses the mixer. */
     5578    hdaCodecPowerOff(pThis->pCodec);
     5579
    54075580    /**
    54085581     * Note: Destroy the mixer while powering off and *not* in hdaDestruct,
     
    54155588        pThis->pMixer = NULL;
    54165589    }
    5417 
    5418     /* Ditto goes for the codec, which in turn uses the mixer. */
    5419     hdaCodecPowerOff(pThis->pCodec);
    54205590}
    54215591
     
    55085678#ifndef VBOX_WITH_AUDIO_CALLBACKS
    55095679    uint16_t uTimerHz;
    5510     rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, 200 /* Hz */);
     5680    rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, 100 /* Hz */);
    55115681    if (RT_FAILURE(rc))
    55125682        return PDMDEV_SET_ERROR(pDevIns, rc,
     
    56755845#ifdef VBOX_WITH_HDA_51_SURROUND
    56765846            rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Front",
    5677                                       AUDMIXSINKDIR_OUTPUT, &pThis->pSinkFront);
     5847                                      AUDMIXSINKDIR_OUTPUT, &pThis->SinkFront.pMixSink);
    56785848            AssertRC(rc);
    56795849            rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Center / Subwoofer",
    5680                                       AUDMIXSINKDIR_OUTPUT, &pThis->pSinkCenterLFE);
     5850                                      AUDMIXSINKDIR_OUTPUT, &pThis->SinkCenterLFE.pMixSink);
    56815851            AssertRC(rc);
    56825852            rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Rear",
    5683                                       AUDMIXSINKDIR_OUTPUT, &pThis->pSinkRear);
     5853                                      AUDMIXSINKDIR_OUTPUT, &pThis->SinkRear.pMixSink);
    56845854            AssertRC(rc);
    56855855#else
    56865856            rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] PCM Output",
    5687                                       AUDMIXSINKDIR_OUTPUT, &pThis->pSinkFront);
     5857                                      AUDMIXSINKDIR_OUTPUT, &pThis->SinkFront.pMixSink);
    56885858            AssertRC(rc);
    56895859#endif
     
    56925862             */
    56935863            rc = AudioMixerCreateSink(pThis->pMixer, "[Recording] Line In",
    5694                                       AUDMIXSINKDIR_INPUT, &pThis->pSinkLineIn);
     5864                                      AUDMIXSINKDIR_INPUT, &pThis->SinkLineIn.pMixSink);
    56955865            AssertRC(rc);
    56965866#ifdef VBOX_WITH_HDA_MIC_IN
    56975867            rc = AudioMixerCreateSink(pThis->pMixer, "[Recording] Microphone In",
    5698                                       AUDMIXSINKDIR_INPUT, &pThis->pSinkMicIn);
     5868                                      AUDMIXSINKDIR_INPUT, &pThis->SinkMicIn.pMixSink);
    56995869            AssertRC(rc);
    57005870#endif
     
    57165886        pThis->pCodec->pfnMixerAddStream    = hdaMixerAddStream;
    57175887        pThis->pCodec->pfnMixerRemoveStream = hdaMixerRemoveStream;
     5888        pThis->pCodec->pfnMixerSetStream    = hdaMixerSetStream;
    57185889        pThis->pCodec->pfnMixerSetVolume    = hdaMixerSetVolume;
    57195890        pThis->pCodec->pfnReset             = hdaCodecReset;
     
    57445915            AssertRC(rc);
    57455916        }
    5746 
    5747         /*
    5748          * As we don't have any dynamic stream <-> mixer sink mapping (yet),
    5749          * hard-wire the associations here.
    5750          */
    5751 #ifdef VBOX_WITH_HDA_51_SURROUND
    5752 # error "Implement me!" /** @todo */
    5753 #else
    5754         /* Same goes for the input sink. */
    5755         for (uint8_t i = 0; i < HDA_MAX_SDI; i++)
    5756             pThis->aStreams[i].pSink = pThis->pSinkLineIn;
    5757 # ifdef VBOX_WITH_HDA_MIC_IN
    5758 #  error "Implement me!" /** @todo */
    5759 # endif
    5760         /* Assign all output streams to the one-and-only output sink. */
    5761         for (uint8_t i = HDA_MAX_SDI; i < HDA_MAX_SDO; i++)
    5762             pThis->aStreams[i].pSink = pThis->pSinkFront;
    5763 #endif /* VBOX_WITH_HDA_51_SURROUND */
    57645917
    57655918        /*
     
    59696122            LogFunc(("Timer ticks=%RU64 (%RU16 Hz)\n", pThis->cTimerTicks, uTimerHz));
    59706123
    5971             /* Fire off timer. */
    5972             TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->cTimerTicks);
     6124            hdaTimerMaybeStart(pThis);
    59736125        }
    59746126    }
  • trunk/src/VBox/Devices/Audio/DevIchHdaCodec.cpp

    r60925 r60941  
    550550typedef struct CODECCOMMONNODE
    551551{
    552     /** Node id - 7 bit format */
    553     uint8_t         id;
    554     /** The node name. */
     552    /** The node's ID. */
     553    uint8_t         uID;
     554    /** The node's name. */
    555555    char const     *pszName;
     556    /** The SDn ID this node is assigned to.
     557     *  0 means not assigned, 1 is SDn0. */
     558    uint8_t         uSD;
     559    /** The SDn's channel to use.
     560     *  Only valid if a valid SDn ID is set. */
     561    uint8_t         uChannel;
    556562    /* PRM 5.3.6 */
    557563    uint32_t au32F00_param[CODECNODE_F00_PARAM_LENGTH];
     
    839845static SSMFIELD const g_aCodecNodeFields[] =
    840846{
    841     SSMFIELD_ENTRY(     CODECSAVEDSTATENODE, Core.id),
     847    SSMFIELD_ENTRY(     CODECSAVEDSTATENODE, Core.uID),
    842848    SSMFIELD_ENTRY_PAD_HC_AUTO(3, 3),
    843849    SSMFIELD_ENTRY(     CODECSAVEDSTATENODE, Core.au32F00_param),
     
    850856static SSMFIELD const g_aCodecNodeFieldsV1[] =
    851857{
    852     SSMFIELD_ENTRY(     CODECSAVEDSTATENODE, Core.id),
     858    SSMFIELD_ENTRY(     CODECSAVEDSTATENODE, Core.uID),
    853859    SSMFIELD_ENTRY_PAD_HC_AUTO(3, 7),
    854860    SSMFIELD_ENTRY_OLD_HCPTR(Core.name),
     
    890896
    891897    /* Set common parameters across all nodes. */
    892     pNode->node.id = uNID;
     898    pNode->node.uID = uNID;
     899    pNode->node.uSD = 0;
    893900
    894901    switch (uNID)
     
    20512058        && pThis->pfnCodecNodeReset)
    20522059    {
    2053         uint8_t i;
    20542060        LogFunc(("Entering reset ...\n"));
    20552061
    2056         //pThis->fInReset = true;
    2057 
    2058         for (i = 0; i < pThis->cTotalNodes; ++i)
     2062        pThis->fInReset = true;
     2063
     2064        for (uint8_t i = 0; i < pThis->cTotalNodes; ++i)
    20592065            pThis->pfnCodecNodeReset(pThis, i, &pThis->paNodes[i]);
    20602066
    2061         //pThis->fInReset = false;
     2067        pThis->fInReset = false;
    20622068
    20632069        LogFunc(("Exited reset\n"));
     
    22742280    *pResp = 0;
    22752281
     2282    bool fIsOut;
     2283
    22762284    if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
    22772285        *pResp = pThis->paNodes[CODEC_NID(cmd)].dac.u32F06_param;
     
    22872295        LogRel2(("HDA: Warning: Unhandled get stream ID command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
    22882296
    2289     /*LogFlowFunc(("[NID0x%02x] Stream ID is 0x%x\n",
    2290                  CODEC_NID(cmd), CODEC_F00_06_GET_STREAM_ID(*pResp)));*/
     2297    LogFlowFunc(("[NID0x%02x] Stream ID=%RU8, channel=%RU8\n",
     2298                 CODEC_NID(cmd), CODEC_F00_06_GET_STREAM_ID(cmd), CODEC_F00_06_GET_CHANNEL_ID(cmd)));
    22912299
    22922300    return VINF_SUCCESS;
     
    22982306    *pResp = 0;
    22992307
     2308    PDMAUDIODIR enmDir;
     2309
    23002310    uint32_t *pu32Addr = NULL;
    23012311    if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
     2312    {
    23022313        pu32Addr = &pThis->paNodes[CODEC_NID(cmd)].dac.u32F06_param;
     2314        enmDir = PDMAUDIODIR_OUT;
     2315    }
    23032316    else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
     2317    {
    23042318        pu32Addr = &pThis->paNodes[CODEC_NID(cmd)].adc.u32F06_param;
     2319        enmDir = PDMAUDIODIR_IN;
     2320    }
    23052321    else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
     2322    {
    23062323        pu32Addr = &pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F06_param;
     2324        enmDir = PDMAUDIODIR_OUT;
     2325    }
    23072326    else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
     2327    {
    23082328        pu32Addr = &pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F06_param;
    2309     else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
    2310         pu32Addr = &pThis->paNodes[CODEC_NID(cmd)].reserved.u32F06_param;
     2329        enmDir = PDMAUDIODIR_IN;
     2330    }
    23112331    else
     2332    {
     2333        enmDir = PDMAUDIODIR_UNKNOWN;
    23122334        LogRel2(("HDA: Warning: Unhandled set stream ID command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd));
    2313 
    2314 /*    LogFlowFunc(("[NID0x%02x] Setting new stream ID to 0x%x\n",
    2315                  CODEC_NID(cmd), CODEC_F00_06_GET_STREAM_ID(cmd)));*/
     2335    }
     2336
     2337    /* Do we (re-)assign our input/output SDn (SDI/SDO) IDs? */
     2338    if (enmDir != PDMAUDIODIR_UNKNOWN)
     2339    {
     2340        uint8_t uSD      = CODEC_F00_06_GET_STREAM_ID(cmd);
     2341        uint8_t uChannel = CODEC_F00_06_GET_CHANNEL_ID(cmd);
     2342
     2343        LogFlowFunc(("[NID0x%02x] Setting to stream ID=%RU8, channel=%RU8, enmDir=%RU32\n",
     2344                     CODEC_NID(cmd), uSD, uChannel, enmDir));
     2345
     2346        pThis->paNodes[CODEC_NID(cmd)].node.uSD      = uSD;
     2347        pThis->paNodes[CODEC_NID(cmd)].node.uChannel = uChannel;
     2348
     2349        if (enmDir == PDMAUDIODIR_OUT)
     2350        {
     2351            /** @todo Check if non-interleaved streams need a different channel / SDn? */
     2352
     2353            /* Propagate to the controller. */
     2354            pThis->pfnMixerSetStream(pThis->pHDAState, PDMAUDIOMIXERCTL_FRONT,      uSD, uChannel);
     2355#ifdef VBOX_WITH_HDA_51_SURROUND
     2356            pThis->pfnMixerSetStream(pThis->pHDAState, PDMAUDIOMIXERCTL_CENTER_LFE, uSD, uChannel);
     2357            pThis->pfnMixerSetStream(pThis->pHDAState, PDMAUDIOMIXERCTL_REAR,       uSD, uChannel);
     2358#endif
     2359        }
     2360        else if (enmDir == PDMAUDIODIR_IN)
     2361        {
     2362            pThis->pfnMixerSetStream(pThis->pHDAState, PDMAUDIOMIXERCTL_LINE_IN,    uSD, uChannel);
     2363#ifdef VBOX_WITH_HDA_MIC_IN
     2364            pThis->pfnMixerSetStream(pThis->pHDAState, PDMAUDIOMIXERCTL_MIC_IN,     uSD, uChannel);
     2365#endif
     2366        }
     2367    }
    23162368
    23172369    if (pu32Addr)
     
    27562808static void codecDbgPrintNode(PCODECDBGINFO pInfo, PCODECNODE pNode, bool fRecursive)
    27572809{
    2758     codecDbgPrintf(pInfo, "Node 0x%02x (%02RU8): ", pNode->node.id, pNode->node.id);
    2759 
    2760     if (pNode->node.id == STAC9220_NID_ROOT)
     2810    codecDbgPrintf(pInfo, "Node 0x%02x (%02RU8): ", pNode->node.uID, pNode->node.uID);
     2811
     2812    if (pNode->node.uID == STAC9220_NID_ROOT)
    27612813    {
    27622814        CODECDBG_PRINT("ROOT\n");
    27632815    }
    2764     else if (pNode->node.id == STAC9220_NID_AFG)
     2816    else if (pNode->node.uID == STAC9220_NID_AFG)
    27652817    {
    27662818        CODECDBG_PRINT("AFG\n");
     
    27702822        CODECDBG_UNINDENT
    27712823    }
    2772     else if (hdaCodecIsPortNode(pInfo->pThis, pNode->node.id))
     2824    else if (hdaCodecIsPortNode(pInfo->pThis, pNode->node.uID))
    27732825    {
    27742826        CODECDBG_PRINT("PORT\n");
    27752827    }
    2776     else if (hdaCodecIsDacNode(pInfo->pThis, pNode->node.id))
     2828    else if (hdaCodecIsDacNode(pInfo->pThis, pNode->node.uID))
    27772829    {
    27782830        CODECDBG_PRINT("DAC\n");
     
    27842836        CODECDBG_UNINDENT
    27852837    }
    2786     else if (hdaCodecIsAdcVolNode(pInfo->pThis, pNode->node.id))
     2838    else if (hdaCodecIsAdcVolNode(pInfo->pThis, pNode->node.uID))
    27872839    {
    27882840        CODECDBG_PRINT("ADC VOLUME\n");
     
    27932845        CODECDBG_UNINDENT
    27942846    }
    2795     else if (hdaCodecIsAdcNode(pInfo->pThis, pNode->node.id))
     2847    else if (hdaCodecIsAdcNode(pInfo->pThis, pNode->node.uID))
    27962848    {
    27972849        CODECDBG_PRINT("ADC\n");
     
    28032855        CODECDBG_UNINDENT
    28042856    }
    2805     else if (hdaCodecIsAdcMuxNode(pInfo->pThis, pNode->node.id))
     2857    else if (hdaCodecIsAdcMuxNode(pInfo->pThis, pNode->node.uID))
    28062858    {
    28072859        CODECDBG_PRINT("ADC MUX\n");
     
    28122864        CODECDBG_UNINDENT
    28132865    }
    2814     else if (hdaCodecIsPcbeepNode(pInfo->pThis, pNode->node.id))
     2866    else if (hdaCodecIsPcbeepNode(pInfo->pThis, pNode->node.uID))
    28152867    {
    28162868        CODECDBG_PRINT("PC BEEP\n");
    28172869    }
    2818     else if (hdaCodecIsSpdifOutNode(pInfo->pThis, pNode->node.id))
     2870    else if (hdaCodecIsSpdifOutNode(pInfo->pThis, pNode->node.uID))
    28192871    {
    28202872        CODECDBG_PRINT("SPDIF OUT\n");
    28212873    }
    2822     else if (hdaCodecIsSpdifInNode(pInfo->pThis, pNode->node.id))
     2874    else if (hdaCodecIsSpdifInNode(pInfo->pThis, pNode->node.uID))
    28232875    {
    28242876        CODECDBG_PRINT("SPDIF IN\n");
    28252877    }
    2826     else if (hdaCodecIsDigInPinNode(pInfo->pThis, pNode->node.id))
     2878    else if (hdaCodecIsDigInPinNode(pInfo->pThis, pNode->node.uID))
    28272879    {
    28282880        CODECDBG_PRINT("DIGITAL IN PIN\n");
    28292881    }
    2830     else if (hdaCodecIsDigOutPinNode(pInfo->pThis, pNode->node.id))
     2882    else if (hdaCodecIsDigOutPinNode(pInfo->pThis, pNode->node.uID))
    28312883    {
    28322884        CODECDBG_PRINT("DIGITAL OUT PIN\n");
    28332885    }
    2834     else if (hdaCodecIsCdNode(pInfo->pThis, pNode->node.id))
     2886    else if (hdaCodecIsCdNode(pInfo->pThis, pNode->node.uID))
    28352887    {
    28362888        CODECDBG_PRINT("CD\n");
    28372889    }
    2838     else if (hdaCodecIsVolKnobNode(pInfo->pThis, pNode->node.id))
     2890    else if (hdaCodecIsVolKnobNode(pInfo->pThis, pNode->node.uID))
    28392891    {
    28402892        CODECDBG_PRINT("VOLUME KNOB\n");
    28412893    }
    2842     else if (hdaCodecIsReservedNode(pInfo->pThis, pNode->node.id))
     2894    else if (hdaCodecIsReservedNode(pInfo->pThis, pNode->node.uID))
    28432895    {
    28442896        CODECDBG_PRINT("RESERVED\n");
    28452897    }
    28462898    else
    2847         CODECDBG_PRINT("UNKNOWN TYPE 0x%x\n", pNode->node.id);
     2899        CODECDBG_PRINT("UNKNOWN TYPE 0x%x\n", pNode->node.uID);
    28482900
    28492901    if (fRecursive)
     
    28532905        {                                                                          \
    28542906            const uint8_t uID = RT_BYTE##_aEntry(_aNode->node.au32F02_param[0x0]); \
    2855             if (pNode->node.id == uID)                                             \
     2907            if (pNode->node.uID == uID)                                             \
    28562908                codecDbgPrintNode(pInfo, _aNode, false /* fRecursive */);          \
    28572909        }
     
    28612913        {
    28622914            const PCODECNODE pSubNode = &pInfo->pThis->paNodes[i];
    2863             if (pSubNode->node.id == pNode->node.id)
     2915            if (pSubNode->node.uID == pNode->node.uID)
    28642916                continue;
    28652917
     
    30523104    for (unsigned idxNode = 0; idxNode < pThis->cTotalNodes; ++idxNode)
    30533105    {
    3054         uint8_t idOld = pThis->paNodes[idxNode].SavedState.Core.id;
     3106        uint8_t idOld = pThis->paNodes[idxNode].SavedState.Core.uID;
    30553107        int rc = SSMR3GetStructEx(pSSM, &pThis->paNodes[idxNode].SavedState,
    30563108                                  sizeof(pThis->paNodes[idxNode].SavedState),
     
    30583110        if (RT_FAILURE(rc))
    30593111            return rc;
    3060         AssertLogRelMsgReturn(idOld == pThis->paNodes[idxNode].SavedState.Core.id,
    3061                               ("loaded %#x, expected %#x\n", pThis->paNodes[idxNode].SavedState.Core.id, idOld),
     3112        AssertLogRelMsgReturn(idOld == pThis->paNodes[idxNode].SavedState.Core.uID,
     3113                              ("loaded %#x, expected %#x\n", pThis->paNodes[idxNode].SavedState.Core.uID, idOld),
    30623114                              VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
    30633115    }
  • trunk/src/VBox/Devices/Audio/DevIchHdaCodec.h

    r60925 r60941  
    9797    DECLR3CALLBACKMEMBER(int, pfnMixerAddStream, (PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl, PPDMAUDIOSTREAMCFG pCfg));
    9898    DECLR3CALLBACKMEMBER(int, pfnMixerRemoveStream, (PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl));
     99    DECLR3CALLBACKMEMBER(int, pfnMixerSetStream, (PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl, uint8_t uSD, uint8_t uChannel));
    99100    DECLR3CALLBACKMEMBER(int, pfnMixerSetVolume, (PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl, PPDMAUDIOVOLUME pVol));
    100101    /** Callbacks by codec implementation. */
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette