VirtualBox

Changeset 70132 in vbox for trunk


Ignore:
Timestamp:
Dec 14, 2017 3:40:51 PM (7 years ago)
Author:
vboxsync
Message:

Audio/HDA: Implemented crude support for macOS guests. See notes for more to-dos.

Location:
trunk/src/VBox/Devices/Audio
Files:
4 edited

Legend:

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

    r70121 r70132  
    13761376        hdaStreamAsyncIOEnable(pStream, false /* fEnable */);
    13771377# endif
     1378        /* Make sure to remove the run bit before doing the actual stream reset. */
     1379        HDA_STREAM_REG(pThis, CTL, uSD) &= ~HDA_SDCTL_RUN;
     1380
    13781381        hdaStreamReset(pThis, pStream, pStream->u8SD);
    13791382
     
    14451448    }
    14461449
    1447     DEVHDA_UNLOCK_BOTH(pThis);
    1448 
    14491450    int rc2 = hdaRegWriteU24(pThis, iReg, u32Value);
    14501451    AssertRC(rc2);
     1452
     1453    DEVHDA_UNLOCK_BOTH(pThis);
    14511454
    14521455    return VINF_SUCCESS; /* Always return success to the MMIO handler. */
     
    18161819    if (rc == VERR_NOT_SUPPORTED)
    18171820    {
    1818         LogRel2(("HDA: Unsupported channel count (%RU8), falling back to stereo channels\n", pCfg->Props.cChannels));
     1821        LogRel(("HDA: Warning: Unsupported channel count (%RU8), falling back to stereo channels (2)\n", pCfg->Props.cChannels));
    18191822
    18201823        /* Fall back to 2 channels (see below in fUseFront block). */
  • trunk/src/VBox/Devices/Audio/DevHDACommon.cpp

    r70121 r70132  
    362362        /* Sanity checks. */
    363363        Assert(cbChunk <= pBDLE->Desc.u32BufSize - pBDLE->State.u32BufOff);
    364         Assert(cbChunk % HDA_FRAME_SIZE == 0);
     364        Assert(cbChunk % pStream->State.cbFrameSize == 0);
    365365        Assert((cbChunk >> 1) >= 1);
    366366
  • trunk/src/VBox/Devices/Audio/HDAStream.cpp

    r70125 r70132  
    180180    pStream->u32CBL     = HDA_STREAM_REG(pThis, CBL, pStream->u8SD);
    181181    pStream->u16FIFOS   = HDA_STREAM_REG(pThis, FIFOS, pStream->u8SD) + 1;
    182 
    183     /* Make sure to also update the stream's DMA counter (based on its current LPIB value). */
    184     hdaStreamSetPosition(pStream, HDA_STREAM_REG(pThis, LPIB, pStream->u8SD));
    185182
    186183    PPDMAUDIOSTREAMCFG pCfg = &pStream->State.Cfg;
     
    218215            break;
    219216    }
     217
     218    /* Set the stream's frame size. */
     219    pStream->State.cbFrameSize = pCfg->Props.cChannels * (pCfg->Props.cBits / 8 /* To bytes */);
    220220
    221221    /*
     
    231231
    232232    LogFunc(("[SD%RU8] DMA @ 0x%x (%RU32 bytes), LVI=%RU16, FIFOS=%RU16, Hz=%RU32, rc=%Rrc\n",
    233              pStream->u8SD, pStream->u64BDLBase, pStream->u32CBL, pStream->u16LVI, pStream->u16FIFOS, 
     233             pStream->u8SD, pStream->u64BDLBase, pStream->u32CBL, pStream->u16LVI, pStream->u16FIFOS,
    234234             pStream->State.Cfg.Props.uHz, rc));
    235235
     
    251251        pStream->State.cbTransferSize = pStream->u32CBL / cFragments;
    252252        Assert(pStream->State.cbTransferSize);
    253         Assert(pStream->State.cbTransferSize % HDA_FRAME_SIZE == 0);
     253        Assert(pStream->State.cbTransferSize % pStream->State.cbFrameSize == 0);
    254254
    255255        /* Calculate the bytes we need to transfer to / from the stream's DMA per iteration.
    256256         * This is bound to the device's Hz rate and thus to the (virtual) timing the device expects. */
    257         pStream->State.cbTransferChunk = (pStream->State.Cfg.Props.uHz / pThis->u16TimerHz) * HDA_FRAME_SIZE;
     257        pStream->State.cbTransferChunk = (pStream->State.Cfg.Props.uHz / pThis->u16TimerHz) * pStream->State.cbFrameSize;
    258258        Assert(pStream->State.cbTransferChunk);
    259         Assert(pStream->State.cbTransferChunk % HDA_FRAME_SIZE == 0);
     259        Assert(pStream->State.cbTransferChunk % pStream->State.cbFrameSize == 0);
    260260
    261261        /* Make sure that the transfer chunk does not exceed the overall transfer size. */
     
    303303#ifdef VBOX_WITH_INTEL_HDA
    304304                /* Intel ICH / PCH: 1 frame. */
    305                 if (BDLE.Desc.u32BufSize == 1 * HDA_FRAME_SIZE)
     305                if (BDLE.Desc.u32BufSize == 1 * pStream->State.cbFrameSize)
    306306                {
    307307                    cfPosAdjust = 1;
    308308                }
    309309                /* Intel Baytrail / Braswell: 32 frames. */
    310                 else if (BDLE.Desc.u32BufSize == 32 * HDA_FRAME_SIZE)
     310                else if (BDLE.Desc.u32BufSize == 32 * pStream->State.cbFrameSize)
    311311                {
    312312                    cfPosAdjust = 32;
     
    328328
    329329        LogFunc(("[SD%RU8] cfPosAdjust=%RU32\n", pStream->u8SD, cfPosAdjust));
     330
     331        /* Make sure to also update the stream's DMA counter (based on its current LPIB value). */
     332        hdaStreamSetPosition(pStream, HDA_STREAM_REG(pThis, LPIB, pStream->u8SD));
    330333
    331334#ifdef LOG_ENABLED
     
    492495    AssertPtrReturnVoid(pStream);
    493496
    494     Assert(u32LPIB % HDA_FRAME_SIZE == 0);
     497    Assert(u32LPIB % pStream->State.cbFrameSize == 0);
    495498
    496499    Log3Func(("[SD%RU8] LPIB=%RU32 (DMA Position Buffer Enabled: %RTbool)\n",
     
    811814    uint32_t cbProcessed = 0;
    812815    uint32_t cbLeft      = cbToProcess;
    813     Assert(cbLeft % HDA_FRAME_SIZE == 0);
     816    Assert(cbLeft % pStream->State.cbFrameSize == 0);
    814817
    815818    uint8_t abChunk[HDA_FIFO_MAX + 1];
     
    825828         * make sure that we process them first as a whole. */
    826829        if (pStream->State.cPosAdjustFramesLeft)
    827             cbChunk = RT_MIN(cbChunk, uint32_t(pStream->State.cPosAdjustFramesLeft * HDA_FRAME_SIZE));
     830            cbChunk = RT_MIN(cbChunk, uint32_t(pStream->State.cPosAdjustFramesLeft * pStream->State.cbFrameSize));
    828831
    829832        Log3Func(("[SD%RU8] cbChunk=%RU32, cPosAdjustFramesLeft=%RU16\n",
     
    843846            uint32_t cbDMAToWrite = cbChunk;
    844847
     848            /** @todo Do we need interleaving streams support here as well?
     849             *        Never saw anything else besides mono/stereo mics (yet). */
    845850            while (cbDMAToWrite)
    846851            {
     
    893898                }
    894899
     900#ifndef VBOX_WITH_HDA_AUDIO_INTERLEAVING_STREAMS_SUPPORT
     901                /**
     902                 * The following code extracts the required audio stream (channel) data
     903                 * of non-interleaved  *and* interleaved audio streams.
     904                 *
     905                 * We by default only support 2 channels with 16-bit samples (HDA_FRAME_SIZE),
     906                 * but an HDA audio stream can have interleaved audio data of multiple audio
     907                 * channels in such a single stream ("AA,AA,AA vs. AA,BB,AA,BB").
     908                 *
     909                 * So take this into account by just handling the first channel in such a stream ("A")
     910                 * and just discard the other channel's data.
     911                 */
    895912                while (cbDMALeft)
    896913                {
    897914                    void *pvBuf; size_t cbBuf;
    898                     RTCircBufAcquireWriteBlock(pCircBuf, cbDMALeft, &pvBuf, &cbBuf);
     915                    RTCircBufAcquireWriteBlock(pCircBuf, HDA_FRAME_SIZE, &pvBuf, &cbBuf);
    899916
    900917                    if (cbBuf)
     
    903920                    RTCircBufReleaseWriteBlock(pCircBuf, cbBuf);
    904921
    905                     cbDMALeft    -= (uint32_t)cbBuf;
    906                     cbDMAWritten += (uint32_t)cbBuf;
     922                    cbDMALeft    -= (uint32_t)pStream->State.cbFrameSize;
     923                    cbDMAWritten += (uint32_t)pStream->State.cbFrameSize;
    907924                }
     925#else
     926                /** @todo This needs making use of HDAStreamMap + HDAStreamChannel. */
     927# error "Implement reading interleaving streams support here."
     928#endif
    908929            }
    909930            else
     
    918939        if (cbDMA)
    919940        {
    920             Assert(cbDMA % HDA_FRAME_SIZE == 0);
     941            Assert(cbDMA % pStream->State.cbFrameSize == 0);
    921942
    922943            /* We always increment the position of DMA buffer counter because we're always reading
     
    9851006
    9861007        /* Do the position adjustment accounting. */
    987         pStream->State.cPosAdjustFramesLeft -= RT_MIN(pStream->State.cPosAdjustFramesLeft, cbDMA / HDA_FRAME_SIZE);
     1008        pStream->State.cPosAdjustFramesLeft -= RT_MIN(pStream->State.cPosAdjustFramesLeft, cbDMA / pStream->State.cbFrameSize);
    9881009
    9891010        if (RT_FAILURE(rc))
     
    9951016
    9961017    /* Sanity. */
    997     Assert(cbProcessed % HDA_FRAME_SIZE == 0);
     1018    Assert(cbProcessed % pStream->State.cbFrameSize == 0);
    9981019    Assert(cbProcessed == cbToProcess);
    9991020    Assert(cbLeft      == 0);
     
    10031024    if (pStream->State.cPosAdjustFramesLeft == 0)
    10041025    {
    1005         hdaStreamPeriodInc(pPeriod, RT_MIN(cbProcessed / HDA_FRAME_SIZE, hdaStreamPeriodGetRemainingFrames(pPeriod)));
     1026        hdaStreamPeriodInc(pPeriod, RT_MIN(cbProcessed / pStream->State.cbFrameSize, hdaStreamPeriodGetRemainingFrames(pPeriod)));
    10061027
    10071028        pStream->State.cbTransferProcessed += cbProcessed;
     
    10321053        const bool fWalClkSet = hdaWalClkSet(pThis,
    10331054                                               hdaWalClkGetCurrent(pThis)
    1034                                              + hdaStreamPeriodFramesToWalClk(pPeriod, pStream->State.cbTransferProcessed / HDA_FRAME_SIZE),
     1055                                             + hdaStreamPeriodFramesToWalClk(pPeriod, pStream->State.cbTransferProcessed / pStream->State.cbFrameSize),
    10351056                                             false /* fForce */);
    10361057        RT_NOREF(fWalClkSet);
     
    10781099        tsTransferNext = tsNow + (cbTransferNext * pStream->State.cTicksPerByte);
    10791100
    1080         /** 
     1101        /**
    10811102         * If the current transfer is complete, reset our counter.
    1082          * 
     1103         *
    10831104         * This can happen for examlpe if the guest OS (like macOS) sets up
    10841105         * big BDLEs without IOC bits set (but for the last one) and the
    1085          * transfer is complete before we reach such a BDL entry. 
    1086          */ 
     1106         * transfer is complete before we reach such a BDL entry.
     1107         */
    10871108        if (fTransferComplete)
    10881109            pStream->State.cbTransferProcessed = 0;
  • trunk/src/VBox/Devices/Audio/HDAStream.h

    r70013 r70132  
    148148     *  BDLE interrupt-on-completion (IOC) bits set. */
    149149    uint8_t                 cTransferPendingInterrupts;
    150     uint8_t                 Padding1[4];
     150    /** The stream's current audio frame size (in bytes). */
     151    uint32_t                cbFrameSize;
    151152    /** How many audio data frames are left to be processed
    152153     *  for the position adjustment handling.
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