VirtualBox

Changeset 67400 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jun 14, 2017 1:03:01 PM (8 years ago)
Author:
vboxsync
Message:

Audio/DevHDA: Forward ported / integrated wall clock handling + stream period code.

Location:
trunk/src/VBox/Devices
Files:
3 edited

Legend:

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

    r67387 r67400  
    4747#include "AudioMixer.h"
    4848#include "HDACodec.h"
     49#include "HDAStreamPeriod.h"
    4950#include "DevHDACommon.h"
    5051#include "DrvAudio.h"
     
    570571     *  Used to calculate the time actually elapsed between two transfers. */
    571572    uint64_t                uTimerTS;
     573    /** The stream's period. Need for timing. */
     574    HDASTREAMPERIOD         Period;
    572575    /** The stream's current configuration.
    573576     *  Should match SDFMT. */
     
    700703    uint8_t               Padding[7];
    701704    /** Pointer to associated stream. */
    702     R3PTRTYPE(PHDASTREAM) pStrm;
     705    R3PTRTYPE(PHDASTREAM) pStream;
    703706} HDATAG, *PHDATAG;
    704707
     
    884887    HDAMIXERSINK                       SinkMicIn;
    885888#endif
     889    /** The controller's base time stamp which the WALCLK register
     890     *  derives its current value from. */
    886891    uint64_t                           u64BaseTS;
     892    /** Last updated WALCLK counter. */
     893    uint64_t                           u64WalClk;
    887894    /** Response Interrupt Count (RINTCNT). */
    888895    uint8_t                            u8RespIntCnt;
     
    10411048/** @} */
    10421049
     1050/** @name Wall clock (WALCLK) functions.
     1051 * @{
     1052 */
     1053uint64_t          hdaWalClkGetCurrent(PHDASTATE pThis);
     1054#ifdef IN_RING3
     1055bool              hdaWalClkSet(PHDASTATE pThis, uint64_t u64WalClk, bool fForce);
     1056#endif
     1057/** @} */
    10431058
    10441059/*********************************************************************************************************************************
     
    22052220}
    22062221
     2222/**
     2223 * Retrieves the currently set value for the wall clock.
     2224 *
     2225 * @return  IPRT status code.
     2226 * @return  Currently set wall clock value.
     2227 * @param   pThis               HDA state.
     2228 *
     2229 * @remark  Operation is atomic.
     2230 */
     2231uint64_t hdaWalClkGetCurrent(PHDASTATE pThis)
     2232{
     2233    return ASMAtomicReadU64(&pThis->u64WalClk);
     2234}
     2235
     2236#ifdef IN_RING3
     2237/**
     2238 * Returns the current maximum value the wall clock counter can be set to.
     2239 * This maximum value depends on all currently handled HDA streams and their own current timing.
     2240 *
     2241 * @return  Current maximum value the wall clock counter can be set to.
     2242 * @param   pThis               HDA state.
     2243 *
     2244 * @remark  Does not actually set the wall clock counter.
     2245 */
     2246uint64_t hdaWalClkGetMax(PHDASTATE pThis)
     2247{
     2248    const uint64_t u64WalClkCur       = ASMAtomicReadU64(&pThis->u64WalClk);
     2249    const uint64_t u64FrontAbsWalClk  = hdaStreamPeriodGetAbsElapsedWalClk(&hdaSinkGetStream(pThis, &pThis->SinkFront)->State.Period);
     2250#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
     2251# error "Implement me!"
     2252#endif
     2253    const uint64_t u64LineInAbsWalClk = hdaStreamPeriodGetAbsElapsedWalClk(&hdaSinkGetStream(pThis, &pThis->SinkLineIn)->State.Period);
     2254#ifdef VBOX_WITH_HDA_MIC_IN
     2255    const uint64_t u64MicInAbsWalClk  = hdaStreamPeriodGetAbsElapsedWalClk(&hdaSinkGetStream(pThis, &pThis->SinkMicIn)->State.Period);
     2256#endif
     2257
     2258    uint64_t u64WalClkNew = RT_MAX(u64WalClkCur, u64FrontAbsWalClk);
     2259#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
     2260# error "Implement me!"
     2261#endif
     2262             u64WalClkNew = RT_MAX(u64WalClkNew, u64LineInAbsWalClk);
     2263#ifdef VBOX_WITH_HDA_MIC_IN
     2264             u64WalClkNew = RT_MAX(u64WalClkNew, u64MicInAbsWalClk);
     2265#endif
     2266
     2267    Log3Func(("%RU64 -> Front=%RU64, LineIn=%RU64 -> %RU64\n",
     2268              u64WalClkCur, u64FrontAbsWalClk, u64LineInAbsWalClk, u64WalClkNew));
     2269
     2270    return u64WalClkNew;
     2271}
     2272
     2273/**
     2274 * Sets the actual WALCLK register to the specified wall clock value.
     2275 * The specified wall clock value only will be set (unless fForce is set to \c @true) if all
     2276 * handled HDA streams have passed (in time) that value. This guarantees that the WALCLK
     2277 * register stays in sync with all handled HDA streams.
     2278 *
     2279 * @return  \c @true if the WALCLK register has been updated, \c @false if not.
     2280 * @param   pThis               HDA state.
     2281 * @param   u64WalClk           Wall clock value to set WALCLK register to.
     2282 * @param   fForce              Whether to force setting the wall clock value or not.
     2283 */
     2284bool hdaWalClkSet(PHDASTATE pThis, uint64_t u64WalClk, bool fForce)
     2285{
     2286    const bool     fFrontPassed       = hdaStreamPeriodHasPassedAbsWalClk (&hdaSinkGetStream(pThis, &pThis->SinkFront)->State.Period,
     2287                                                                           u64WalClk);
     2288    const uint64_t u64FrontAbsWalClk  = hdaStreamPeriodGetAbsElapsedWalClk(&hdaSinkGetStream(pThis, &pThis->SinkFront)->State.Period);
     2289#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
     2290# error "Implement me!"
     2291#endif
     2292
     2293    const bool     fLineInPassed      = hdaStreamPeriodHasPassedAbsWalClk (&hdaSinkGetStream(pThis, &pThis->SinkLineIn)->State.Period, u64WalClk);
     2294    const uint64_t u64LineInAbsWalClk = hdaStreamPeriodGetAbsElapsedWalClk(&hdaSinkGetStream(pThis, &pThis->SinkLineIn)->State.Period);
     2295#ifdef VBOX_WITH_HDA_MIC_IN
     2296    const bool     fMicInPassed       = hdaStreamPeriodHasPassedAbsWalClk (&hdaSinkGetStream(pThis, &pThis->SinkMicIn)->State.Period,  u64WalClk);
     2297    const uint64_t u64MicInAbsWalClk  = hdaStreamPeriodGetAbsElapsedWalClk(&hdaSinkGetStream(pThis, &pThis->SinkMicIn)->State.Period);
     2298#endif
     2299
     2300#ifdef VBOX_STRICT
     2301    const uint64_t u64WalClkCur = ASMAtomicReadU64(&pThis->u64WalClk);
     2302#endif
     2303          uint64_t u64WalClkSet = u64WalClk;
     2304
     2305    /* Only drive the WALCLK register forward if all (active) stream periods have passed
     2306     * the specified point in time given by u64WalClk. */
     2307    if (  (   fFrontPassed
     2308#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
     2309# error "Implement me!"
     2310#endif
     2311           && fLineInPassed
     2312#ifdef VBOX_WITH_HDA_MIC_IN
     2313           && fMicInPassed
     2314#endif
     2315          )
     2316       || fForce)
     2317    {
     2318        if (!fForce)
     2319        {
     2320            /* Get the maximum value of all periods we need to handle.
     2321             * Not the most elegant solution, but works for now ... */
     2322            u64WalClk = RT_MAX(u64WalClkSet, u64FrontAbsWalClk);
     2323#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
     2324# error "Implement me!"
     2325#endif
     2326            u64WalClk = RT_MAX(u64WalClkSet, u64LineInAbsWalClk);
     2327#ifdef VBOX_WITH_HDA_MIC_IN
     2328            u64WalClk = RT_MAX(u64WalClkSet, u64MicInAbsWalClk);
     2329#endif
     2330            AssertMsg(u64WalClkSet > u64WalClkCur,
     2331                      ("Setting WALCLK to a stale or backward value (%RU64 -> %RU64) isn't a good idea really. "
     2332                       "Good luck with stuck audio stuff.\n", u64WalClkCur, u64WalClkSet));
     2333        }
     2334
     2335        /* Set the new WALCLK value. */
     2336        ASMAtomicWriteU64(&pThis->u64WalClk, u64WalClkSet);
     2337    }
     2338
     2339    const uint64_t u64WalClkNew = hdaWalClkGetCurrent(pThis);
     2340
     2341    Log3Func(("Cur: %RU64, New: %RU64 (force %RTbool) -> %RU64 %s\n",
     2342              u64WalClkCur, u64WalClk, fForce,
     2343              u64WalClkNew, u64WalClkNew == u64WalClk ? "[OK]" : "[DELAYED]"));
     2344
     2345    return (u64WalClkNew == u64WalClk);
     2346}
     2347#endif /* IN_RING3 */
     2348
    22072349static int hdaRegReadWALCLK(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
    22082350{
    2209     RT_NOREF_PV(iReg);
    2210 
    2211     /* HDA spec (1a): 3.3.16 WALCLK counter ticks with 24Mhz bitclock rate. */
    2212     *pu32Value = (uint32_t)ASMMultU64ByU32DivByU32(PDMDevHlpTMTimeVirtGetNano(pThis->CTX_SUFF(pDevIns))
    2213                                                    - pThis->u64BaseTS, 24, 1000);
    2214     LogFlowFunc(("%RU32\n", *pu32Value));
     2351#ifdef IN_RING3
     2352    RT_NOREF(iReg);
     2353
     2354    *pu32Value = RT_LO_U32(ASMAtomicReadU64(&pThis->u64WalClk));
     2355
     2356    Log3Func(("%RU32 (max @ %RU64)\n",*pu32Value, hdaWalClkGetMax(pThis)));
     2357
    22152358    return VINF_SUCCESS;
     2359#else
     2360    RT_NOREF(pThis, iReg, pu32Value);
     2361    return VINF_IOM_R3_MMIO_WRITE;
     2362#endif
    22162363}
    22172364
     
    23522499
    23532500    /* Assign new values. */
    2354     pTag->uTag  = uTag;
    2355     pTag->pStrm = hdaStreamGetFromSD(pThis, uSD);
    2356 
    2357     PHDASTREAM pStream = pTag->pStrm;
     2501    pTag->uTag    = uTag;
     2502    pTag->pStream = hdaStreamGetFromSD(pThis, uSD);
     2503
     2504    PHDASTREAM pStream = pTag->pStream;
    23582505    AssertPtr(pStream);
    23592506
     
    31293276 * Registers access handlers for a stream's BDLE DMA accesses.
    31303277 *
    3131  * @returns @true if registration was successful, @false if not.
     3278 * @returns \c @true if registration was successful, \c @false if not.
    31323279 * @param   pThis               HDA state.
    31333280 * @param   pStream             HDA stream to register BDLE access handlers for.
  • trunk/src/VBox/Devices/Audio/HDAStreamPeriod.cpp

    r67358 r67400  
    9999    pPeriod->u8SD              = u8SD;
    100100    pPeriod->u64StartWalClk    = 0;
    101     pPeriod->u32Hz             = pStreamCfg->uHz;
     101    pPeriod->u32Hz             = pStreamCfg->Props.uHz;
    102102    pPeriod->u64DurationWalClk = hdaStreamPeriodFramesToWalClk(pPeriod, framesToTransfer);
    103103    pPeriod->u64ElapsedWalClk  = 0;
  • trunk/src/VBox/Devices/Makefile.kmk

    r66125 r67400  
    55
    66#
    7 # Copyright (C) 2006-2016 Oracle Corporation
     7# Copyright (C) 2006-2017 Oracle Corporation
    88#
    99# This file is part of VirtualBox Open Source Edition (OSE), as
     
    597597        Audio/DevHDA.cpp \
    598598        Audio/HDACodec.cpp \
     599        Audio/HDAStreamPeriod.cpp \
    599600        Audio/AudioMixBuffer.cpp \
    600601        Audio/AudioMixer.cpp \
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