- Timestamp:
- May 10, 2016 1:27:44 PM (9 years ago)
- Location:
- trunk
- Files:
-
- 21 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmm/pdmaudioifs.h
r60368 r60925 28 28 29 29 #include <VBox/types.h> 30 #include <iprt/circbuf.h> 30 31 #include <iprt/critsect.h> 31 32 #include <iprt/list.h> … … 52 53 typedef enum PDMAUDIOFMT 53 54 { 54 AUD_FMT_INVALID,55 AUD_FMT_U8,56 AUD_FMT_S8,57 AUD_FMT_U16,58 AUD_FMT_S16,59 AUD_FMT_U32,60 AUD_FMT_S32,55 PDMAUDIOFMT_INVALID, 56 PDMAUDIOFMT_U8, 57 PDMAUDIOFMT_S8, 58 PDMAUDIOFMT_U16, 59 PDMAUDIOFMT_S16, 60 PDMAUDIOFMT_U32, 61 PDMAUDIOFMT_S32, 61 62 /** Hack to blow the type up to 32-bit. */ 62 AUD_FMT_32BIT_HACK = 0x7fffffff63 PDMAUDIOFMT_32BIT_HACK = 0x7fffffff 63 64 } PDMAUDIOFMT; 64 65 … … 152 153 153 154 /** 155 * Audio stream (data) layout. 156 */ 157 typedef enum PDMAUDIOSTREAMLAYOUT 158 { 159 /** Unknown access type; do not use. */ 160 PDMAUDIOSTREAMLAYOUT_UNKNOWN = 0, 161 /** Non-interleaved access, that is, consecutive 162 * access to the data. */ 163 PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED, 164 /** Interleaved access, where the data can be 165 * mixed together with data of other audio streams. */ 166 PDMAUDIOSTREAMLAYOUT_INTERLEAVED 167 } PDMAUDIOSTREAMLAYOUT, *PPDMAUDIOSTREAMLAYOUT; 168 169 /** No stream channel data flags defined. */ 170 #define PDMAUDIOSTREAMCHANNELDATA_FLAG_NONE 0 171 172 /** 173 * Structure for keeping a stream channel data block around. 174 */ 175 typedef struct PDMAUDIOSTREAMCHANNELDATA 176 { 177 /** Circular buffer for the channel data. */ 178 PRTCIRCBUF pCircBuf; 179 size_t cbAcq; 180 /** Channel data flags. */ 181 uint32_t fFlags; 182 } PDMAUDIOSTREAMCHANNELDATA, *PPDMAUDIOSTREAMCHANNELDATA; 183 184 /** 185 * Structure for a single channel of an audio stream. 186 * An audio stream consists of one or multiple channels, 187 * depending on the configuration. 188 */ 189 typedef struct PDMAUDIOSTREAMCHANNEL 190 { 191 /** Channel ID. */ 192 uint8_t uChannel; 193 /** Step size (in bytes) to the channel's next frame. */ 194 size_t cbStep; 195 /** Frame size (in bytes) of this channel. */ 196 size_t cbFrame; 197 /** Offset (in bytes) to first sample in the data block. */ 198 size_t cbFirst; 199 /** Currente offset (in bytes) in the data stream. */ 200 size_t cbOff; 201 /** Associated data buffer. */ 202 PDMAUDIOSTREAMCHANNELDATA Data; 203 } PDMAUDIOSTREAMCHANNEL, *PPDMAUDIOSTREAMCHANNEL; 204 205 /** 154 206 * Structure for keeping an audio stream configuration. 155 207 */ … … 157 209 { 158 210 /** Friendly name of the stream. */ 159 c onst char *pszName;211 char szName[64]; 160 212 /** Direction of the stream. */ 161 213 PDMAUDIODIR enmDir; … … 169 221 /** Frequency in Hertz (Hz). */ 170 222 uint32_t uHz; 171 /** Number of channels (2 for stereo, 1 for mono). */223 /** Number of audio channels (2 for stereo, 1 for mono). */ 172 224 uint8_t cChannels; 173 225 /** Audio format. */ … … 337 389 */ 338 390 int64_t iFreqRatio; 339 /* For quickly converting samples <-> bytes and 340 * vice versa. */ 391 /** For quickly converting samples <-> bytes and vice versa. */ 341 392 uint8_t cShift; 342 393 } PDMAUDIOMIXBUF; … … 347 398 /** No flags being set. */ 348 399 #define PDMAUDIOSTRMSTS_FLAG_NONE 0 400 /** Whether this stream has been initialized by the 401 * backend or not. */ 402 #define PDMAUDIOSTRMSTS_FLAG_INITIALIZED RT_BIT_32(0) 349 403 /** Whether this stream is enabled or disabled. */ 350 #define PDMAUDIOSTRMSTS_FLAG_ENABLED RT_BIT_32( 0)404 #define PDMAUDIOSTRMSTS_FLAG_ENABLED RT_BIT_32(1) 351 405 /** Whether this stream has been paused or not. This also implies 352 406 * that this is an enabled stream! */ 353 #define PDMAUDIOSTRMSTS_FLAG_PAUSED RT_BIT_32( 1)407 #define PDMAUDIOSTRMSTS_FLAG_PAUSED RT_BIT_32(2) 354 408 /** Whether this stream was marked as being disabled 355 409 * but there are still associated guest output streams 356 410 * which rely on its data. */ 357 #define PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE RT_BIT_32( 2)411 #define PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE RT_BIT_32(3) 358 412 /** Validation mask. */ 359 #define PDMAUDIOSTRMSTS_VALID_MASK UINT32_C(0x0000000 7)413 #define PDMAUDIOSTRMSTS_VALID_MASK UINT32_C(0x0000000F) 360 414 361 415 /** … … 418 472 bool fEmpty; 419 473 /** Name of this stream. */ 420 char *pszName;474 char szName[64]; 421 475 /** Number of references to this stream. Only can be 422 476 * destroyed if the reference count is reaching 0. */ 423 uint 8_tcRefs;477 uint32_t cRefs; 424 478 } PDMAUDIOGSTSTRMSTATE, *PPDMAUDIOGSTSTRMSTATE; 425 479 … … 515 569 /** 516 570 * Audio connector interface (up). 571 ** @todo Get rid of the separate XXXIn and XXXOut methods and unify the In/Out structs with a union, 572 ** so that we only have one guest and one host stream ultimately. 517 573 */ 518 574 typedef struct PDMIAUDIOCONNECTOR 519 575 { 520 576 DECLR3CALLBACKMEMBER(int, pfnQueryStatus, (PPDMIAUDIOCONNECTOR pInterface, uint32_t *pcbAvailIn, uint32_t *pcbFreeOut, uint32_t *pcSamplesLive)); 577 578 /** 579 * Adds a reference to the specified input stream. 580 * 581 * @returns New reference count. 582 * @param pInterface Pointer to the interface structure containing the called function pointer. 583 * @param pGstStrmIn Pointer to guest input stream adding the reference to. 584 */ 585 DECLR3CALLBACKMEMBER(uint32_t, pfnAddRefIn, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMIN pGstStrmIn)); 586 587 /** 588 * Adds a reference to the specified output stream. 589 * 590 * @returns New reference count. 591 * @param pInterface Pointer to the interface structure containing the called function pointer. 592 * @param pGstStrmOut Pointer to guest output stream adding the reference to. 593 */ 594 DECLR3CALLBACKMEMBER(uint32_t, pfnAddRefOut, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMOUT pGstStrmOut)); 595 596 /** 597 * Releases a reference from the input specified stream. 598 * 599 * @returns New reference count. 600 * @param pInterface Pointer to the interface structure containing the called function pointer. 601 * @param pGstStrmIn Pointer to guest input stream releasing a reference from. 602 */ 603 DECLR3CALLBACKMEMBER(uint32_t, pfnReleaseIn, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMIN pGstStrmIn)); 604 605 /** 606 * Releases a reference from the output specified stream. 607 * 608 * @returns New reference count. 609 * @param pInterface Pointer to the interface structure containing the called function pointer. 610 * @param pGstStrmOut Pointer to guest output stream releasing a reference from. 611 */ 612 DECLR3CALLBACKMEMBER(uint32_t, pfnReleaseOut, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMOUT pGstStrmOut)); 521 613 522 614 /** … … 552 644 * @param pCfg Where to store the host audio backend configuration data. 553 645 */ 554 DECLR3CALLBACKMEMBER(int, pfnGetConfig uration, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOBACKENDCFG pCfg));646 DECLR3CALLBACKMEMBER(int, pfnGetConfig, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOBACKENDCFG pCfg)); 555 647 556 648 /** … … 616 708 * @param pInterface Pointer to the interface structure containing the called function pointer. 617 709 * @param pszName Friendly name of this input stream. 618 * @param pCfg Pointer to PDMAUDIOSTREAMCFG to use.619 710 * @param ppGstStrmIn Pointer where to return the guest guest input stream on success. 620 711 */ 621 DECLR3CALLBACKMEMBER(int, pfnCreateIn, (PPDMIAUDIOCONNECTOR pInterface, const char *pszName,622 PPDMAUDIO STREAMCFG pCfg, PPDMAUDIOGSTSTRMIN *ppGstStrmIn));712 DECLR3CALLBACKMEMBER(int, pfnCreateIn, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAMCFG pCfg, 713 PPDMAUDIOGSTSTRMIN *ppGstStrmIn)); 623 714 /** 624 715 * Creates a guest output stream. … … 626 717 * @returns VBox status code. 627 718 * @param pInterface Pointer to the interface structure containing the called function pointer. 628 * @param pszName Friendly name of this output stream.629 719 * @param pCfg Pointer to PDMAUDIOSTREAMCFG to use. 630 720 * @param ppGstStrmOut Pointer where to return the guest guest input stream on success. 631 721 */ 632 DECLR3CALLBACKMEMBER(int, pfnCreateOut, (PPDMIAUDIOCONNECTOR pInterface, const char *pszName, 633 PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOGSTSTRMOUT *ppGstStrmOut)); 634 722 DECLR3CALLBACKMEMBER(int, pfnCreateOut, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAMCFG pCfg, 723 PPDMAUDIOGSTSTRMOUT *ppGstStrmOut)); 635 724 /** 636 725 * Destroys a guest input stream. … … 666 755 667 756 /** PDMIAUDIOCONNECTOR interface ID. */ 668 #define PDMIAUDIOCONNECTOR_IID " f0ef4012-ae89-4528-9dad-4ef496894df8"757 #define PDMIAUDIOCONNECTOR_IID "5bba362c-092a-493b-854b-5d0ad3acecc4" 669 758 670 759 -
trunk/src/VBox/Devices/Audio/AudioMixBuffer.cpp
r60353 r60925 19 19 #include <VBox/log.h> 20 20 21 #if 021 #if 1 22 22 /* 23 23 * DEBUG_DUMP_PCM_DATA enables dumping the raw PCM data … … 230 230 uint32_t AudioMixBufAvail(PPDMAUDIOMIXBUF pMixBuf) 231 231 { 232 AssertPtrReturn(pMixBuf, true);232 AssertPtrReturn(pMixBuf, 0); 233 233 234 234 uint32_t cAvail; 235 if (pMixBuf->pParent) /* Child*/235 if (pMixBuf->pParent) /* Is this a child buffer? */ 236 236 cAvail = pMixBuf->cMixed; 237 237 else … … 975 975 static int audioMixBufMixTo(PPDMAUDIOMIXBUF pDst, PPDMAUDIOMIXBUF pSrc, uint32_t cSamples, uint32_t *pcProcessed) 976 976 { 977 AssertPtrReturn(pDst, VERR_INVALID_POINTER);978 AssertPtrReturn(pSrc, VERR_INVALID_POINTER);977 AssertPtrReturn(pDst, VERR_INVALID_POINTER); 978 AssertPtrReturn(pSrc, VERR_INVALID_POINTER); 979 979 AssertReturn(cSamples, VERR_INVALID_PARAMETER); 980 980 /* pcProcessed is optional. */ … … 1021 1021 1022 1022 Assert(offWrite + cToWrite <= pDst->cSamples); 1023 Assert(offRead + cToRead<= pSrc->cSamples);1023 Assert(offRead + cToRead <= pSrc->cSamples); 1024 1024 1025 1025 AUDMIXBUF_LOG(("\t%RU32Hz -> %RU32Hz\n", AUDMIXBUF_FMT_SAMPLE_FREQ(pSrc->AudioFmt), AUDMIXBUF_FMT_SAMPLE_FREQ(pDst->AudioFmt))); … … 1046 1046 1047 1047 pSrc->cMixed += cWrittenTotal; 1048 1048 1049 pDst->cProcessed += cWrittenTotal; 1050 1051 #if 0 1052 /** 1053 * Note: pDst->cProcessed can be bigger than pDst->cSamples if there 1054 * was a wrap-around. In that case samples were lost, 1055 * e.g. not consumed (yet). 1056 * 1057 * So adjust the current read/write offset to match the current 1058 * position, minus the dropped samples. */ 1059 if (pDst->cProcessed > pDst->cSamples) 1060 { 1061 LogFlowFunc(("%s: %RU32 / %RU32\n", pDst->pszName, pDst->cProcessed, pDst->cSamples)); 1062 pSrc->cMixed = pDst->cSamples; 1063 pDst->offReadWrite = 0; 1064 pDst->cProcessed = pDst->cSamples; 1065 } 1066 #endif 1067 1049 1068 #ifdef DEBUG 1050 1069 s_cSamplesMixedTotal += cWrittenTotal; … … 1135 1154 1136 1155 AUDMIXBUF_LOG(("********************************************\n")); 1137 AUDMIXBUF_LOG(("[PARENT] %s : offReadWrite=%RU32, cProcessed=%RU32, cMixed=%RU32 (BpS=%RU32)\n",1138 pParent->pszName, 1156 AUDMIXBUF_LOG(("[PARENT] %s (%RU32): offReadWrite=%RU32, cProcessed=%RU32, cMixed=%RU32 (BpS=%RU32)\n", 1157 pParent->pszName, pParent->cSamples, 1139 1158 pParent->offReadWrite, pParent->cProcessed, pParent->cMixed, 1140 1159 AUDIOMIXBUF_S2B(pParent, 1))); 1141 1160 1161 size_t cChildren = 0; 1162 1142 1163 PPDMAUDIOMIXBUF pIter; 1143 1164 RTListForEach(&pParent->lstBuffers, pIter, PDMAUDIOMIXBUF, Node) 1144 1165 { 1145 AUDMIXBUF_LOG(("\t[CHILD] %s : offReadWrite=%RU32, cProcessed=%RU32, cMixed=%RU32 (BpS=%RU32)\n",1146 pIter->pszName, 1166 AUDMIXBUF_LOG(("\t[CHILD] %s (%RU32): offReadWrite=%RU32, cProcessed=%RU32, cMixed=%RU32 (BpS=%RU32)\n", 1167 pIter->pszName, pIter->cSamples, 1147 1168 pIter->offReadWrite, pIter->cProcessed, pIter->cMixed, 1148 1169 AUDIOMIXBUF_S2B(pIter, 1))); 1149 } 1150 AUDMIXBUF_LOG(("Total samples mixed: %RU64\n", s_cSamplesMixedTotal)); 1170 cChildren++; 1171 } 1172 AUDMIXBUF_LOG(("Children: %zu - Total samples mixed: %RU64\n", cChildren, s_cSamplesMixedTotal)); 1151 1173 AUDMIXBUF_LOG(("********************************************\n")); 1152 1174 } -
trunk/src/VBox/Devices/Audio/AudioMixer.cpp
r60353 r60925 4 4 * emulations to achieve proper multiplexing from/to attached 5 5 * devices LUNs. 6 * 7 * This mixer acts as a layer between the audio connector interface and 8 * the actual device emulation, providing mechanisms for audio sources (input) and 9 * audio sinks (output). 10 * 11 * As audio driver instances are handled as LUNs on the device level, this 12 * audio mixer then can take care of e.g. mixing various inputs/outputs to/from 13 * a specific source/sink. 14 * 15 * How and which audio streams are connected to sinks/sources depends on how 16 * the audio mixer has been set up. 17 * 18 * A sink can connect multiple output streams together, whereas a source 19 * does this with input streams. Each sink / source consists of one or more 20 * so-called mixer streams, which then in turn have pointers to the actual 21 * PDM audio input/output streams. 6 22 */ 7 23 … … 32 48 #include <iprt/string.h> 33 49 34 static int audioMixerUpdateSinkVolume(PAUDMIXSINK pSink, const PPDMAUDIOVOLUME pVolMaster); 35 36 37 int AudioMixerAddSink(PAUDIOMIXER pMixer, const char *pszName, AUDMIXSINKDIR enmDir, PAUDMIXSINK *ppSink) 50 static void audioMixerSinkDestroyInternal(PAUDMIXSINK pSink); 51 static int audioMixerSinkUpdateVolume(PAUDMIXSINK pSink, const PPDMAUDIOVOLUME pVolMaster); 52 static void audioMixerSinkRemoveStreamInternal(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream); 53 54 static void audioMixerStreamDestroyInternal(PAUDMIXSTREAM pStream); 55 static void audioMixerStreamFree(PAUDMIXSTREAM pStream); 56 57 int AudioMixerCreateSink(PAUDIOMIXER pMixer, const char *pszName, AUDMIXSINKDIR enmDir, PAUDMIXSINK *ppSink) 38 58 { 39 59 AssertPtrReturn(pMixer, VERR_INVALID_POINTER); 40 60 AssertPtrReturn(pszName, VERR_INVALID_POINTER); 41 /* *ppSink is optional. */61 /* ppSink is optional. */ 42 62 43 63 int rc = VINF_SUCCESS; … … 80 100 } 81 101 82 int AudioMixerAddStreamIn(PAUDMIXSINK pSink, PPDMIAUDIOCONNECTOR pConnector, PPDMAUDIOGSTSTRMIN pStream,83 uint32_t uFlags, PAUDMIXSTREAM *ppStream)84 {85 AssertPtrReturn(pSink, VERR_INVALID_POINTER);86 AssertPtrReturn(pStream, VERR_INVALID_POINTER);87 /** @todo Add flag validation. */88 /* ppStream is optional. */89 90 int rc;91 92 if (pSink->cStreams == UINT8_MAX) /* 255 streams per sink max. */93 return VERR_TOO_MUCH_DATA;94 95 PAUDMIXSTREAM pMixStream96 = (PAUDMIXSTREAM)RTMemAllocZ(sizeof(AUDMIXSTREAM));97 if (pMixStream)98 {99 pMixStream->pConn = pConnector;100 pMixStream->pIn = pStream;101 /** @todo Process flags. */102 103 RTListAppend(&pSink->lstStreams, &pMixStream->Node);104 pSink->cStreams++;105 106 LogFlowFunc(("%s: pStream=%p, cStreams=%RU8\n",107 pSink->pszName, pMixStream, pSink->cStreams));108 109 /* Increase the stream's reference count to let others know110 * we're reyling on it to be around now. */111 pStream->State.cRefs++;112 113 if (ppStream)114 *ppStream = pMixStream;115 116 rc = VINF_SUCCESS;117 }118 else119 rc = VERR_NO_MEMORY;120 121 return rc;122 }123 124 int AudioMixerAddStreamOut(PAUDMIXSINK pSink, PPDMIAUDIOCONNECTOR pConnector, PPDMAUDIOGSTSTRMOUT pStream,125 uint32_t uFlags, PAUDMIXSTREAM *ppStream)126 {127 AssertPtrReturn(pSink, VERR_INVALID_POINTER);128 AssertPtrReturn(pStream, VERR_INVALID_POINTER);129 /** @todo Add flag validation. */130 /* ppStream is optional. */131 132 int rc;133 134 if (pSink->cStreams == UINT8_MAX) /* 255 streams per sink max. */135 return VERR_TOO_MUCH_DATA;136 137 PAUDMIXSTREAM pMixStream138 = (PAUDMIXSTREAM)RTMemAllocZ(sizeof(AUDMIXSTREAM));139 if (pMixStream)140 {141 pMixStream->pConn = pConnector;142 pMixStream->pOut = pStream;143 /** @todo Process flags. */144 145 RTListAppend(&pSink->lstStreams, &pMixStream->Node);146 pSink->cStreams++;147 148 LogFlowFunc(("%s: pStream=%p, cStreams=%RU8\n",149 pSink->pszName, pMixStream, pSink->cStreams));150 151 /* Increase the stream's reference count to let others know152 * we're reyling on it to be around now. */153 pStream->State.cRefs++;154 155 if (ppStream)156 *ppStream = pMixStream;157 158 rc = VINF_SUCCESS;159 }160 else161 rc = VERR_NO_MEMORY;162 163 return rc;164 }165 166 int AudioMixerControlStream(PAUDIOMIXER pMixer, PAUDMIXSTREAM pHandle)167 {168 return VERR_NOT_IMPLEMENTED;169 }170 171 102 int AudioMixerCreate(const char *pszName, uint32_t uFlags, PAUDIOMIXER *ppMixer) 172 103 { … … 207 138 } 208 139 140 void AudioMixerDebug(PAUDIOMIXER pMixer, PCDBGFINFOHLP pHlp, const char *pszArgs) 141 { 142 PAUDMIXSINK pSink; 143 unsigned iSink = 0; 144 145 pHlp->pfnPrintf(pHlp, "[Master] %s: lVol=%u, rVol=%u, fMuted=%RTbool\n", pMixer->pszName, 146 pMixer->VolMaster.uLeft, pMixer->VolMaster.uRight, pMixer->VolMaster.fMuted); 147 148 RTListForEach(&pMixer->lstSinks, pSink, AUDMIXSINK, Node) 149 { 150 pHlp->pfnPrintf(pHlp, "[Sink %u] %s: lVol=%u, rVol=%u, fMuted=%RTbool\n", iSink, pSink->pszName, 151 pSink->Volume.uLeft, pSink->Volume.uRight, pSink->Volume.fMuted); 152 ++iSink; 153 } 154 } 155 209 156 void AudioMixerDestroy(PAUDIOMIXER pMixer) 210 157 { … … 216 163 PAUDMIXSINK pSink, pSinkNext; 217 164 RTListForEachSafe(&pMixer->lstSinks, pSink, pSinkNext, AUDMIXSINK, Node) 218 AudioMixerRemoveSink(pMixer, pSink); 219 220 Assert(pMixer->cSinks == 0); 165 audioMixerSinkDestroyInternal(pSink); 221 166 222 167 if (pMixer->pszName) … … 227 172 228 173 RTMemFree(pMixer); 229 } 230 231 static void audioMixerDestroySink(PAUDMIXSINK pSink) 174 pMixer = NULL; 175 } 176 177 int AudioMixerGetDeviceFormat(PAUDIOMIXER pMixer, PPDMAUDIOSTREAMCFG pCfg) 178 { 179 AssertPtrReturn(pMixer, VERR_INVALID_POINTER); 180 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 181 182 /** @todo Perform a deep copy, if needed. */ 183 *pCfg = pMixer->devFmt; 184 185 return VINF_SUCCESS; 186 } 187 188 void AudioMixerInvalidate(PAUDIOMIXER pMixer) 189 { 190 AssertPtrReturnVoid(pMixer); 191 192 LogFlowFunc(("%s: Invalidating ...\n", pMixer->pszName)); 193 194 /* Propagate new master volume to all connected sinks. */ 195 PAUDMIXSINK pSink; 196 RTListForEach(&pMixer->lstSinks, pSink, AUDMIXSINK, Node) 197 { 198 int rc2 = audioMixerSinkUpdateVolume(pSink, &pMixer->VolMaster); 199 AssertRC(rc2); 200 } 201 } 202 203 void AudioMixerRemoveSink(PAUDIOMIXER pMixer, PAUDMIXSINK pSink) 204 { 205 AssertPtrReturnVoid(pMixer); 206 if (!pSink) 207 return; 208 209 /** @todo Check if pSink is part of pMixer. */ 210 211 AudioMixerSinkRemoveAllStreams(pSink); 212 213 Assert(pSink->cStreams == 0); 214 215 RTListNodeRemove(&pSink->Node); 216 217 Assert(pMixer->cSinks); 218 pMixer->cSinks--; 219 220 LogFlowFunc(("%s: pSink=%s, cSinks=%RU8\n", 221 pMixer->pszName, pSink->pszName, pMixer->cSinks)); 222 } 223 224 int AudioMixerSetDeviceFormat(PAUDIOMIXER pMixer, PPDMAUDIOSTREAMCFG pCfg) 225 { 226 AssertPtrReturn(pMixer, VERR_INVALID_POINTER); 227 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 228 229 /** @todo Perform a deep copy, if needed. */ 230 pMixer->devFmt = *pCfg; 231 232 return VINF_SUCCESS; 233 } 234 235 /** 236 * Sets the mixer's master volume. 237 * 238 * @returns IPRT status code. 239 * @param pMixer Mixer to set master volume for. 240 * @param pVol Volume to set. 241 */ 242 int AudioMixerSetMasterVolume(PAUDIOMIXER pMixer, PPDMAUDIOVOLUME pVol) 243 { 244 AssertPtrReturn(pMixer, VERR_INVALID_POINTER); 245 AssertPtrReturn(pVol, VERR_INVALID_POINTER); 246 247 pMixer->VolMaster = *pVol; 248 249 LogFlowFunc(("%s: lVol=%RU32, rVol=%RU32 => fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n", 250 pMixer->pszName, pVol->uLeft, pVol->uRight, 251 pMixer->VolMaster.fMuted, pMixer->VolMaster.uLeft, pMixer->VolMaster.uRight)); 252 253 AudioMixerInvalidate(pMixer); 254 return VINF_SUCCESS; 255 } 256 257 /***************************************************************************** 258 * Mixer Sink implementation. 259 *****************************************************************************/ 260 261 int AudioMixerSinkAddStream(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream) 262 { 263 AssertPtrReturn(pSink, VERR_INVALID_POINTER); 264 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 265 266 if (pSink->cStreams == UINT8_MAX) /* 255 streams per sink max. */ 267 return VERR_NO_MORE_HANDLES; 268 269 /** @todo Check if stream already is assigned to (another) sink. */ 270 271 RTListAppend(&pSink->lstStreams, &pStream->Node); 272 pSink->cStreams++; 273 274 LogFlowFunc(("%s: cStreams=%RU8\n", pSink->pszName, pSink->cStreams)); 275 276 return VINF_SUCCESS; 277 } 278 279 static PDMAUDIOSTREAMCMD audioMixerSinkToStreamCmd(AUDMIXSINKCMD enmCmd) 280 { 281 switch (enmCmd) 282 { 283 case AUDMIXSINKCMD_ENABLE: return PDMAUDIOSTREAMCMD_ENABLE; 284 case AUDMIXSINKCMD_DISABLE: return PDMAUDIOSTREAMCMD_DISABLE; 285 case AUDMIXSINKCMD_PAUSE: return PDMAUDIOSTREAMCMD_PAUSE; 286 case AUDMIXSINKCMD_RESUME: return PDMAUDIOSTREAMCMD_RESUME; 287 default: break; 288 } 289 290 AssertMsgFailed(("Unsupported sink command %ld\n", enmCmd)); 291 return PDMAUDIOSTREAMCMD_UNKNOWN; 292 } 293 294 int AudioMixerSinkCtl(PAUDMIXSINK pSink, AUDMIXSINKCMD enmCmd) 295 { 296 AssertPtrReturn(pSink, VERR_INVALID_POINTER); 297 298 PDMAUDIOSTREAMCMD enmCmdStream = audioMixerSinkToStreamCmd(enmCmd); 299 if (enmCmdStream == PDMAUDIOSTREAMCMD_UNKNOWN) 300 return VERR_NOT_SUPPORTED; 301 302 int rc = VINF_SUCCESS; 303 304 PAUDMIXSTREAM pStream; 305 RTListForEach(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node) 306 { 307 int rc2 = AudioMixerStreamCtl(pStream, enmCmdStream, AUDMIXSTRMCTL_FLAG_NONE); 308 if (RT_SUCCESS(rc)) 309 rc = rc2; 310 /* Keep going. Flag? */ 311 } 312 313 LogFlowFunc(("Sink=%s, Cmd=%ld, rc=%Rrc\n", pSink->pszName, enmCmd, rc)); 314 return rc; 315 } 316 317 void AudioMixerSinkDestroy(PAUDMIXSINK pSink) 318 { 319 audioMixerSinkDestroyInternal(pSink); 320 } 321 322 static void audioMixerSinkDestroyInternal(PAUDMIXSINK pSink) 232 323 { 233 324 AssertPtrReturnVoid(pSink); … … 235 326 return; 236 327 328 LogFunc(("%s\n", pSink->pszName)); 329 330 PAUDMIXSTREAM pStream, pStreamNext; 331 RTListForEachSafe(&pSink->lstStreams, pStream, pStreamNext, AUDMIXSTREAM, Node) 332 { 333 audioMixerSinkRemoveStreamInternal(pSink, pStream); 334 audioMixerStreamDestroyInternal(pStream); 335 } 336 337 Assert(pSink->cStreams == 0); 338 237 339 if (pSink->pszName) 238 340 RTStrFree(pSink->pszName); … … 241 343 } 242 344 243 static void audioMixerDestroyStream(PAUDMIXSTREAM pStream) 244 { 245 AssertPtrReturnVoid(pStream); 246 if (!pStream) 247 return; 248 249 RTMemFree(pStream); 250 } 251 252 int AudioMixerGetDeviceFormat(PAUDIOMIXER pMixer, PPDMAUDIOSTREAMCFG pCfg) 253 { 254 AssertPtrReturn(pMixer, VERR_INVALID_POINTER); 255 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 256 257 /** @todo Perform a deep copy, if needed. */ 258 *pCfg = pMixer->devFmt; 259 260 return VINF_SUCCESS; 261 } 262 263 uint32_t AudioMixerGetStreamCount(PAUDIOMIXER pMixer) 264 { 265 AssertPtrReturn(pMixer, 0); 266 267 uint32_t cStreams = 0; 268 269 PAUDMIXSINK pSink; 270 RTListForEach(&pMixer->lstSinks, pSink, AUDMIXSINK, Node) 271 cStreams += pSink->cStreams; 272 273 return cStreams; 274 } 275 276 void AudioMixerInvalidate(PAUDIOMIXER pMixer) 277 { 278 AssertPtrReturnVoid(pMixer); 279 280 LogFlowFunc(("%s: Invalidating ...\n", pMixer->pszName)); 281 282 /* Propagate new master volume to all connected sinks. */ 283 PAUDMIXSINK pSink; 284 RTListForEach(&pMixer->lstSinks, pSink, AUDMIXSINK, Node) 285 { 286 int rc2 = audioMixerUpdateSinkVolume(pSink, &pMixer->VolMaster); 287 AssertRC(rc2); 288 } 289 } 290 291 int AudioMixerProcessSinkIn(PAUDMIXSINK pSink, AUDMIXOP enmOp, void *pvBuf, uint32_t cbBuf, uint32_t *pcbProcessed) 345 PAUDMIXSTREAM AudioMixerSinkGetStream(PAUDMIXSINK pSink, uint8_t uIndex) 346 { 347 AssertPtrReturn(pSink, NULL); 348 AssertMsgReturn(uIndex < pSink->cStreams, 349 ("Index %RU8 exceeds stream count (%RU8)", uIndex, pSink->cStreams), NULL); 350 351 /* Slow lookup, d'oh. */ 352 PAUDMIXSTREAM pStream = RTListGetFirst(&pSink->lstStreams, AUDMIXSTREAM, Node); 353 while (uIndex) 354 { 355 pStream = RTListGetNext(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node); 356 uIndex--; 357 } 358 359 AssertPtr(pStream); 360 return pStream; 361 } 362 363 uint8_t AudioMixerSinkGetStreamCount(PAUDMIXSINK pSink) 364 { 365 if (!pSink) 366 return 0; 367 368 return pSink->cStreams; 369 } 370 371 int AudioMixerSinkRead(PAUDMIXSINK pSink, AUDMIXOP enmOp, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead) 292 372 { 293 373 AssertPtrReturn(pSink, VERR_INVALID_POINTER); 294 374 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 295 AssertReturn(cbBuf, VERR_INVALID_PARAMETER);296 /* pcb Processed is optional. */375 AssertReturn(cbBuf, VERR_INVALID_PARAMETER); 376 /* pcbRead is optional. */ 297 377 298 378 /** @todo Handle mixing operation enmOp! */ … … 303 383 304 384 int rc = VERR_NOT_FOUND; 305 uint32_t cbProcessed = 0; 306 307 LogFlowFunc(("%s: pvBuf=%p, cbBuf=%zu\n", pSink->pszName, pvBuf, cbBuf)); 385 uint32_t cbRead = 0; 308 386 309 387 PAUDMIXSTREAM pStream; 310 388 RTListForEach(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node) 311 389 { 312 if (!pStream->pConn->pfnIsActiveIn(pStream->pConn, pStream-> pIn))390 if (!pStream->pConn->pfnIsActiveIn(pStream->pConn, pStream->InOut.pIn)) 313 391 continue; 314 392 … … 318 396 while (cbToRead) 319 397 { 320 uint32_t cbRead ;398 uint32_t cbReadStrm; 321 399 AssertPtr(pStream->pConn); 322 rc = pStream->pConn->pfnRead(pStream->pConn, pStream-> pIn,323 (uint8_t *)pvMixBuf + cbTotalRead, cbToRead, &cbRead );400 rc = pStream->pConn->pfnRead(pStream->pConn, pStream->InOut.pIn, 401 (uint8_t *)pvMixBuf + cbTotalRead, cbToRead, &cbReadStrm); 324 402 if ( RT_FAILURE(rc) 325 || !cbRead )403 || !cbReadStrm) 326 404 break; 327 405 328 406 /** @todo Right now we only handle one stream (the last one added in fact). */ 329 407 330 AssertBreakStmt(cbRead <= cbToRead, rc = VERR_BUFFER_OVERFLOW);331 cbToRead -= cbRead;332 cbTotalRead += cbRead ;408 AssertBreakStmt(cbReadStrm <= cbToRead, rc = VERR_BUFFER_OVERFLOW); 409 cbToRead -= cbReadStrm; 410 cbTotalRead += cbReadStrm; 333 411 } 334 412 … … 336 414 continue; 337 415 338 cb Processed = RT_MAX(cbProcessed, cbTotalRead);416 cbRead = RT_MAX(cbRead, cbTotalRead); 339 417 } 340 418 341 419 if (RT_SUCCESS(rc)) 342 420 { 343 memcpy(pvBuf, pvMixBuf, cb Processed); /* @todo Use an intermediate mixing buffer per sink! */344 345 if (pcb Processed)346 *pcb Processed = cbProcessed;421 memcpy(pvBuf, pvMixBuf, cbRead); /* @todo Use an intermediate mixing buffer per sink! */ 422 423 if (pcbRead) 424 *pcbRead = cbRead; 347 425 } 348 426 349 427 RTMemFree(pvMixBuf); 350 428 351 Log FlowFunc(("cbProcessed=%RU32, rc=%Rrc\n", cbProcessed, rc));429 Log3Func(("%s: cbRead=%RU32, rc=%Rrc\n", pSink->pszName, cbRead, rc)); 352 430 return rc; 353 431 } 354 432 355 int AudioMixerProcessSinkOut(PAUDMIXSINK pSink, AUDMIXOP enmOp, const void *pvBuf, uint32_t cbBuf, uint32_t *pcbProcessed) 356 { 357 return VERR_NOT_IMPLEMENTED; 358 } 359 360 void AudioMixerRemoveSink(PAUDIOMIXER pMixer, PAUDMIXSINK pSink) 361 { 362 AssertPtrReturnVoid(pMixer); 363 if (!pSink) 364 return; 365 366 PAUDMIXSTREAM pStream, pStreamNext; 367 RTListForEachSafe(&pSink->lstStreams, pStream, pStreamNext, AUDMIXSTREAM, Node) 368 AudioMixerRemoveStream(pSink, pStream); 369 370 Assert(pSink->cStreams == 0); 371 372 RTListNodeRemove(&pSink->Node); 373 Assert(pMixer->cSinks); 374 pMixer->cSinks--; 375 376 LogFlowFunc(("%s: pSink=%s, cSinks=%RU8\n", 377 pMixer->pszName, pSink->pszName, pMixer->cSinks)); 378 379 audioMixerDestroySink(pSink); 380 } 381 382 void AudioMixerRemoveStream(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream) 433 static void audioMixerSinkRemoveStreamInternal(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream) 383 434 { 384 435 AssertPtrReturnVoid(pSink); … … 386 437 return; 387 438 439 /** @todo Check if pStream is part of pSink. */ 440 388 441 Assert(pSink->cStreams); 389 RTListNodeRemove(&pStream->Node);390 pSink->cStreams--;391 442 392 443 #ifdef DEBUG 393 444 const char *pszStream = pSink->enmDir == AUDMIXSINKDIR_INPUT 394 ? pStream-> pIn->MixBuf.pszName : pStream->pOut->MixBuf.pszName;395 396 LogFlowFunc(("%s: pStream=%s, cStreams=%RU8\n",445 ? pStream->InOut.pIn->MixBuf.pszName : pStream->InOut.pOut->MixBuf.pszName; 446 447 LogFlowFunc(("%s: (Stream = %s), cStreams=%RU8\n", 397 448 pSink->pszName, pszStream ? pszStream : "<Unnamed>", pSink->cStreams)); 398 449 #endif 399 450 400 /* Decrease the reference count again. */ 401 switch (pSink->enmDir) 402 { 403 case AUDMIXSINKDIR_INPUT: 404 { 405 Assert(pStream->pIn->State.cRefs); 406 pStream->pIn->State.cRefs--; 407 break; 408 } 409 410 case AUDMIXSINKDIR_OUTPUT: 411 { 412 Assert(pStream->pOut->State.cRefs); 413 pStream->pOut->State.cRefs--; 414 break; 415 } 416 417 default: 418 AssertMsgFailed(("Not implemented\n")); 419 break; 420 } 421 422 audioMixerDestroyStream(pStream); 423 } 424 425 int AudioMixerSetDeviceFormat(PAUDIOMIXER pMixer, PPDMAUDIOSTREAMCFG pCfg) 426 { 427 AssertPtrReturn(pMixer, VERR_INVALID_POINTER); 428 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 429 430 /** @todo Perform a deep copy, if needed. */ 431 pMixer->devFmt = *pCfg; 451 /* Remove stream from sink. */ 452 RTListNodeRemove(&pStream->Node); 453 454 Assert(pSink->cStreams); 455 pSink->cStreams--; 456 } 457 458 void AudioMixerSinkRemoveStream(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream) 459 { 460 audioMixerSinkRemoveStreamInternal(pSink, pStream); 461 } 462 463 /** 464 * Removes all attached streams from a given sink. 465 * 466 * @param pSink Sink to remove attached streams from. 467 */ 468 void AudioMixerSinkRemoveAllStreams(PAUDMIXSINK pSink) 469 { 470 if (!pSink) 471 return; 472 473 LogFunc(("%s\n", pSink->pszName)); 474 475 PAUDMIXSTREAM pStream, pStreamNext; 476 RTListForEachSafe(&pSink->lstStreams, pStream, pStreamNext, AUDMIXSTREAM, Node) 477 audioMixerSinkRemoveStreamInternal(pSink, pStream); 478 479 Assert(pSink->cStreams == 0); 480 } 481 482 int AudioMixerSinkSetFormat(PAUDMIXSINK pSink, PPDMPCMPROPS pPCMProps) 483 { 484 AssertPtrReturn(pSink, VERR_INVALID_POINTER); 485 AssertPtrReturn(pPCMProps, VERR_INVALID_POINTER); 486 487 memcpy(&pSink->PCMProps, pPCMProps, sizeof(PDMPCMPROPS)); 488 489 PAUDMIXSTREAM pStream; 490 RTListForEach(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node) 491 { 492 /** @todo Invalidate mix buffers! */ 493 } 432 494 433 495 return VINF_SUCCESS; 434 496 } 435 497 436 static int audioMixerUpdateSinkVolume(PAUDMIXSINK pSink, const PPDMAUDIOVOLUME pVolMaster) 498 /** 499 * Set the volume of an individual sink. 500 * 501 * @returns IPRT status code. 502 * @param pSink Sink to set volume for. 503 * @param pVol Volume to set. 504 */ 505 int AudioMixerSinkSetVolume(PAUDMIXSINK pSink, PPDMAUDIOVOLUME pVol) 506 { 507 AssertPtrReturn(pSink, VERR_INVALID_POINTER); 508 AssertPtrReturn(pVol, VERR_INVALID_POINTER); 509 AssertPtr(pSink->pParent); 510 511 LogFlowFunc(("%s: fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n", pSink->pszName, pVol->fMuted, pVol->uLeft, pVol->uRight)); 512 513 pSink->Volume = *pVol; 514 515 return audioMixerSinkUpdateVolume(pSink, &pSink->pParent->VolMaster); 516 } 517 518 int AudioMixerSinkUpdate(PAUDMIXSINK pSink) 519 { 520 AssertPtrReturn(pSink, VERR_INVALID_POINTER); 521 522 PAUDMIXSTREAM pStream; 523 RTListForEach(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node) 524 { 525 uint32_t cbIn, cbOut; 526 uint32_t cSamplesLive; 527 int rc2 = pStream->pConn->pfnQueryStatus(pStream->pConn, 528 &cbIn, &cbOut, &cSamplesLive); 529 #ifdef DEBUG 530 if ( cbIn 531 || cbOut 532 || cSamplesLive) 533 { 534 Log3Func(("cbIn=%RU32, cbOut=%RU32, cSamplesLive=%RU32, rc2=%Rrc\n", cbIn, cbOut, cSamplesLive, rc2)); 535 } 536 #endif 537 if (pSink->enmDir == AUDMIXSINKDIR_OUTPUT) 538 { 539 rc2 = pStream->pConn->pfnPlayOut(pStream->pConn, NULL /* pcSamplesPlayed */); 540 if (RT_FAILURE(rc2)) 541 Log3Func(("rc2=%Rrc\n", rc2)); 542 } 543 else if (pSink->enmDir == AUDMIXSINKDIR_INPUT) 544 { 545 //int rc2 = pStream->pConn->pfnCaptureIn(pStream->pConn, NULL /* pcSamplesCaptured */); 546 //Log3Func(("rc2=%Rrc\n", rc2)); 547 } 548 else 549 AssertMsgFailed(("Direction not implemented\n")); 550 } 551 552 return VINF_SUCCESS; 553 } 554 555 static int audioMixerSinkUpdateVolume(PAUDMIXSINK pSink, const PPDMAUDIOVOLUME pVolMaster) 437 556 { 438 557 AssertPtrReturn(pSink, VERR_INVALID_POINTER); … … 461 580 { 462 581 if (fOut) 463 AudioMixBufSetVolume(&pStream-> pOut->MixBuf, &volSink);582 AudioMixBufSetVolume(&pStream->InOut.pOut->MixBuf, &volSink); 464 583 else 465 AudioMixBufSetVolume(&pStream-> pIn->MixBuf, &volSink);584 AudioMixBufSetVolume(&pStream->InOut.pIn->MixBuf, &volSink); 466 585 } 467 586 … … 469 588 } 470 589 471 /** Set the master volume of the mixer. */ 472 int AudioMixerSetMasterVolume(PAUDIOMIXER pMixer, PPDMAUDIOVOLUME pVol) 473 { 474 AssertPtrReturn(pMixer, VERR_INVALID_POINTER); 475 AssertPtrReturn(pVol, VERR_INVALID_POINTER); 476 477 pMixer->VolMaster = *pVol; 478 479 LogFlowFunc(("%s: lVol=%RU32, rVol=%RU32 => fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n", 480 pMixer->pszName, pVol->uLeft, pVol->uRight, 481 pMixer->VolMaster.fMuted, pMixer->VolMaster.uLeft, pMixer->VolMaster.uRight)); 482 483 AudioMixerInvalidate(pMixer); 590 int AudioMixerSinkWrite(PAUDMIXSINK pSink, AUDMIXOP enmOp, const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten) 591 { 592 AssertPtrReturn(pSink, VERR_INVALID_POINTER); 593 /* pcbWritten is optional. */ 594 595 if (!pvBuf || !cbBuf) 596 { 597 if (pcbWritten) 598 *pcbWritten = 0; 599 return VINF_SUCCESS; 600 } 601 602 uint32_t cbProcessed = 0; 603 604 PAUDMIXSTREAM pStream; 605 RTListForEach(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node) 606 { 607 int rc2 = pStream->pConn->pfnWrite(pStream->pConn, pStream->InOut.pOut, pvBuf, cbBuf, &cbProcessed); 608 if ( RT_FAILURE(rc2) 609 || cbProcessed < cbBuf) 610 { 611 LogFlowFunc(("rc=%Rrc, cbBuf=%RU32, cbProcessed=%RU32\n", rc2, cbBuf, cbProcessed)); 612 } 613 } 614 615 if (pcbWritten) 616 *pcbWritten = cbBuf; /* Always report back a complete write for now. */ 617 484 618 return VINF_SUCCESS; 485 619 } 486 620 487 /** Set the volume of an individual sink. */ 488 int AudioMixerSetSinkVolume(PAUDMIXSINK pSink, PPDMAUDIOVOLUME pVol) 489 { 490 AssertPtrReturn(pSink, VERR_INVALID_POINTER); 491 AssertPtrReturn(pVol, VERR_INVALID_POINTER); 492 AssertPtr(pSink->pParent); 493 494 LogFlowFunc(("%s: fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n", pSink->pszName, pVol->fMuted, pVol->uLeft, pVol->uRight)); 495 496 pSink->Volume = *pVol; 497 498 return audioMixerUpdateSinkVolume(pSink, &pSink->pParent->VolMaster); 499 } 500 501 void AudioMixerDebug(PAUDIOMIXER pMixer, PCDBGFINFOHLP pHlp, const char *pszArgs) 502 { 503 PAUDMIXSINK pSink; 504 unsigned iSink = 0; 505 506 pHlp->pfnPrintf(pHlp, "[Master] %s: lVol=%u, rVol=%u, fMuted=%RTbool\n", pMixer->pszName, 507 pMixer->VolMaster.uLeft, pMixer->VolMaster.uRight, pMixer->VolMaster.fMuted); 508 509 RTListForEach(&pMixer->lstSinks, pSink, AUDMIXSINK, Node) 510 { 511 pHlp->pfnPrintf(pHlp, "[Sink %u] %s: lVol=%u, rVol=%u, fMuted=%RTbool\n", iSink, pSink->pszName, 512 pSink->Volume.uLeft, pSink->Volume.uRight, pSink->Volume.fMuted); 513 ++iSink; 514 } 515 } 621 /***************************************************************************** 622 * Mixer Stream implementation. 623 *****************************************************************************/ 624 625 int AudioMixerStreamCtl(PAUDMIXSTREAM pStream, PDMAUDIOSTREAMCMD enmCmd, uint32_t fCtl) 626 { 627 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 628 /** @todo Validate fCtl. */ 629 630 int rc; 631 switch (pStream->enmDir) 632 { 633 case PDMAUDIODIR_IN: 634 { 635 if ( enmCmd == PDMAUDIOSTREAMCMD_ENABLE 636 || enmCmd == PDMAUDIOSTREAMCMD_DISABLE) 637 { 638 rc = pStream->pConn->pfnEnableIn(pStream->pConn, pStream->InOut.pIn, 639 enmCmd == PDMAUDIOSTREAMCMD_ENABLE); 640 } 641 else 642 AssertFailed(); 643 break; 644 } 645 646 case PDMAUDIODIR_OUT: 647 { 648 if ( enmCmd == PDMAUDIOSTREAMCMD_ENABLE 649 || enmCmd == PDMAUDIOSTREAMCMD_DISABLE) 650 { 651 rc = pStream->pConn->pfnEnableOut(pStream->pConn, pStream->InOut.pOut, 652 enmCmd == PDMAUDIOSTREAMCMD_ENABLE); 653 } 654 else 655 AssertFailed(); 656 break; 657 } 658 659 default: 660 AssertMsgFailed(("Not implemented\n")); 661 break; 662 } 663 664 return rc; 665 } 666 667 int AudioMixerStreamCreate(PPDMIAUDIOCONNECTOR pConn, PPDMAUDIOSTREAMCFG pCfg, uint32_t fFlags, PAUDMIXSTREAM *ppStream) 668 { 669 AssertPtrReturn(pConn, VERR_INVALID_POINTER); 670 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 671 /** @todo Validate fFlags. */ 672 /* ppStream is optional. */ 673 674 PAUDMIXSTREAM pMixStream = (PAUDMIXSTREAM)RTMemAllocZ(sizeof(AUDMIXSTREAM)); 675 if (!pMixStream) 676 return VERR_NO_MEMORY; 677 678 pMixStream->pszName = RTStrDup(pCfg->szName); 679 if (!pMixStream->pszName) 680 { 681 RTMemFree(pMixStream); 682 return VERR_NO_MEMORY; 683 } 684 685 int rc; 686 if (pCfg->enmDir == PDMAUDIODIR_IN) 687 { 688 PPDMAUDIOGSTSTRMIN pGstStrm; 689 rc = pConn->pfnCreateIn(pConn, pCfg, &pGstStrm); 690 if (RT_SUCCESS(rc)) 691 { 692 pMixStream->InOut.pIn = pGstStrm; 693 694 /* Increase the stream's reference count to let others know 695 * we're reyling on it to be around now. */ 696 pConn->pfnAddRefIn(pConn, pGstStrm); 697 } 698 } 699 else if (pCfg->enmDir == PDMAUDIODIR_OUT) 700 { 701 PPDMAUDIOGSTSTRMOUT pGstStrm; 702 rc = pConn->pfnCreateOut(pConn, pCfg, &pGstStrm); 703 if (RT_SUCCESS(rc)) 704 { 705 pMixStream->InOut.pOut = pGstStrm; 706 707 /* Increase the stream's reference count to let others know 708 * we're reyling on it to be around now. */ 709 pConn->pfnAddRefOut(pConn, pGstStrm); 710 } 711 } 712 else 713 rc = VERR_NOT_SUPPORTED; 714 715 if (RT_SUCCESS(rc)) 716 { 717 pMixStream->fFlags = fFlags; 718 pMixStream->enmDir = pCfg->enmDir; 719 pMixStream->pConn = pConn; 720 721 if (ppStream) 722 *ppStream = pMixStream; 723 } 724 else if (pMixStream) 725 { 726 RTStrFree(pMixStream->pszName); 727 pMixStream->pszName = NULL; 728 729 RTMemFree(pMixStream); 730 pMixStream = NULL; 731 } 732 733 return rc; 734 } 735 736 static void audioMixerStreamDestroyInternal(PAUDMIXSTREAM pStream) 737 { 738 if (!pStream) 739 return; 740 741 LogFunc(("%s\n", pStream->pszName)); 742 743 if (pStream->pConn) /* Stream has a connector interface present? */ 744 { 745 if ( pStream->enmDir == PDMAUDIODIR_IN 746 && pStream->pConn->pfnDestroyIn) 747 { 748 if (pStream->InOut.pIn) 749 { 750 pStream->pConn->pfnReleaseIn(pStream->pConn, pStream->InOut.pIn); 751 pStream->pConn->pfnDestroyIn(pStream->pConn, pStream->InOut.pIn); 752 } 753 } 754 else if ( pStream->enmDir == PDMAUDIODIR_OUT 755 && pStream->pConn->pfnDestroyOut) 756 { 757 if (pStream->InOut.pOut) 758 { 759 pStream->pConn->pfnReleaseOut(pStream->pConn, pStream->InOut.pOut); 760 pStream->pConn->pfnDestroyOut(pStream->pConn, pStream->InOut.pOut); 761 } 762 } 763 else 764 AssertFailed(); 765 } 766 767 audioMixerStreamFree(pStream); 768 } 769 770 void AudioMixerStreamDestroy(PAUDMIXSTREAM pStream) 771 { 772 audioMixerStreamDestroyInternal(pStream); 773 } 774 775 static void audioMixerStreamFree(PAUDMIXSTREAM pStream) 776 { 777 if (pStream) 778 { 779 LogFunc(("%s\n", pStream->pszName)); 780 781 if (pStream->pszName) 782 { 783 RTStrFree(pStream->pszName); 784 pStream->pszName = NULL; 785 } 786 787 RTMemFree(pStream); 788 pStream = NULL; 789 } 790 } 791 792 bool AudioMixerStreamIsActive(PAUDMIXSTREAM pStream) 793 { 794 if (!pStream) 795 return false; 796 797 bool fIsValid; 798 switch (pStream->enmDir) 799 { 800 case PDMAUDIODIR_IN: 801 { 802 fIsValid = pStream->pConn->pfnIsActiveIn(pStream->pConn, pStream->InOut.pIn); 803 break; 804 } 805 806 case PDMAUDIODIR_OUT: 807 { 808 fIsValid = pStream->pConn->pfnIsActiveOut(pStream->pConn, pStream->InOut.pOut); 809 break; 810 } 811 812 default: 813 fIsValid = false; 814 AssertMsgFailed(("Not implemented\n")); 815 break; 816 } 817 818 return fIsValid; 819 } 820 821 bool AudioMixerStreamIsValid(PAUDMIXSTREAM pStream) 822 { 823 if (!pStream) 824 return false; 825 826 bool fIsValid; 827 switch (pStream->enmDir) 828 { 829 case PDMAUDIODIR_IN: 830 { 831 fIsValid = pStream->pConn->pfnIsValidIn(pStream->pConn, pStream->InOut.pIn); 832 break; 833 } 834 835 case PDMAUDIODIR_OUT: 836 { 837 fIsValid = pStream->pConn->pfnIsValidOut(pStream->pConn, pStream->InOut.pOut); 838 break; 839 } 840 841 default: 842 fIsValid = false; 843 AssertMsgFailed(("Not implemented\n")); 844 break; 845 } 846 847 return fIsValid; 848 } 849 -
trunk/src/VBox/Devices/Audio/AudioMixer.h
r59275 r60925 24 24 #include <VBox/vmm/pdmaudioifs.h> 25 25 26 /** 27 * Structure for maintaining an audio mixer instance. 28 */ 26 29 typedef struct AUDIOMIXER 27 30 { … … 40 43 } AUDIOMIXER, *PAUDIOMIXER; 41 44 45 /** No flags specified. */ 46 #define AUDMIXSTREAM_FLAG_NONE 0 47 48 /** 49 * Structure for maintaining an audio mixer stream. 50 */ 42 51 typedef struct AUDMIXSTREAM 43 52 { 53 /** List node. */ 44 54 RTLISTNODE Node; 55 /** Name of this stream. */ 56 char *pszName; 57 /** Stream flags of type AUDMIXSTREAM_FLAG_. */ 58 uint32_t fFlags; 59 /** Pointer to audio connector being used. */ 45 60 PPDMIAUDIOCONNECTOR pConn; 61 /** Audio direction of this stream. */ 62 PDMAUDIODIR enmDir; 63 /** Union of PDM input/output streams for this stream. */ 46 64 union 47 65 { 48 66 PPDMAUDIOGSTSTRMIN pIn; 49 67 PPDMAUDIOGSTSTRMOUT pOut; 50 } ;68 } InOut; 51 69 } AUDMIXSTREAM, *PAUDMIXSTREAM; 52 70 71 /** 72 * Audio mixer sink direction. 73 */ 53 74 typedef enum AUDMIXSINKDIR 54 75 { … … 60 81 } AUDMIXSINKDIR; 61 82 83 /** 84 * Audio mixer sink command. 85 */ 86 typedef enum AUDMIXSINKCMD 87 { 88 /** Unknown command, do not use. */ 89 AUDMIXSINKCMD_UNKNOWN = 0, 90 /** Enables the sink. */ 91 AUDMIXSINKCMD_ENABLE, 92 /** Disables the sink. */ 93 AUDMIXSINKCMD_DISABLE, 94 /** Pauses the sink. */ 95 AUDMIXSINKCMD_PAUSE, 96 /** Resumes the sink. */ 97 AUDMIXSINKCMD_RESUME, 98 /** Hack to blow the type up to 32-bit. */ 99 AUDMIXSINKCMD_32BIT_HACK = 0x7fffffff 100 } AUDMIXSINKCMD; 101 102 /** 103 * Structure for maintaining an audio mixer sink. 104 */ 62 105 typedef struct AUDMIXSINK 63 106 { 64 107 RTLISTNODE Node; 108 /** Pointer to mixer object this sink is bound to. */ 109 PAUDIOMIXER pParent; 65 110 /** Name of this sink. */ 66 111 char *pszName; … … 68 113 * if this sink handles input or output. */ 69 114 AUDMIXSINKDIR enmDir; 70 /** Pointer to mixer object this sink is bound 71 * to. */ 72 PAUDIOMIXER pParent; 115 /** The sink's PCM format. */ 116 PDMPCMPROPS PCMProps; 73 117 /** Number of streams assigned. */ 74 118 uint8_t cStreams; 75 119 /** List of assigned streams. */ 120 /** @todo Use something faster -- vector maybe? */ 76 121 RTLISTANCHOR lstStreams; 77 122 /** This sink's mixing buffer. */ … … 82 127 } AUDMIXSINK, *PAUDMIXSINK; 83 128 129 /** 130 * Audio mixer operation. 131 */ 84 132 typedef enum AUDMIXOP 85 133 { 86 AUDMIXOP_NONE = 0, 134 /** Invalid operation, do not use. */ 135 AUDMIXOP_INVALID = 0, 87 136 AUDMIXOP_COPY, 88 137 AUDMIXOP_BLEND, … … 91 140 } AUDMIXOP; 92 141 142 /** No flags specified. */ 143 #define AUDMIXSTRMCTL_FLAG_NONE 0 93 144 94 int AudioMixerAddSink(PAUDIOMIXER pMixer, const char *pszName, AUDMIXSINKDIR enmDir, PAUDMIXSINK *ppSink);95 int AudioMixerAddStreamIn(PAUDMIXSINK pSink, PPDMIAUDIOCONNECTOR pConnector, PPDMAUDIOGSTSTRMIN pStream, uint32_t uFlags, PAUDMIXSTREAM *ppStream);96 int AudioMixerAddStreamOut(PAUDMIXSINK pSink, PPDMIAUDIOCONNECTOR pConnector, PPDMAUDIOGSTSTRMOUT pStream, uint32_t uFlags, PAUDMIXSTREAM *ppStream);97 int AudioMixerControlStream(AUDMIXSTREAM pHandle); /** @todo Implement me. */98 145 int AudioMixerCreate(const char *pszName, uint32_t uFlags, PAUDIOMIXER *ppMixer); 146 int AudioMixerCreateSink(PAUDIOMIXER pMixer, const char *pszName, AUDMIXSINKDIR enmDir, PAUDMIXSINK *ppSink); 99 147 void AudioMixerDestroy(PAUDIOMIXER pMixer); 100 148 int AudioMixerGetDeviceFormat(PAUDIOMIXER pMixer, PPDMAUDIOSTREAMCFG pCfg); 101 uint32_t AudioMixerGetStreamCount(PAUDIOMIXER pMixer);102 149 void AudioMixerInvalidate(PAUDIOMIXER pMixer); 103 int AudioMixerProcessSinkIn(PAUDMIXSINK pSink, AUDMIXOP enmOp, void *pvBuf, uint32_t cbBuf, uint32_t *pcbProcessed);104 int AudioMixerProcessSinkOut(PAUDMIXSINK pSink, AUDMIXOP enmOp, const void *pvBuf, uint32_t cbBuf, uint32_t *pcbProcessed);105 150 void AudioMixerRemoveSink(PAUDIOMIXER pMixer, PAUDMIXSINK pSink); 106 void AudioMixerRemoveStream(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream);107 151 int AudioMixerSetDeviceFormat(PAUDIOMIXER pMixer, PPDMAUDIOSTREAMCFG pCfg); 108 152 int AudioMixerSetMasterVolume(PAUDIOMIXER pMixer, PPDMAUDIOVOLUME pVol); 109 int AudioMixerSetSinkVolume(PAUDMIXSINK pSink, PPDMAUDIOVOLUME pVol);110 153 void AudioMixerDebug(PAUDIOMIXER pMixer, PCDBGFINFOHLP pHlp, const char *pszArgs); 154 155 int AudioMixerSinkAddStream(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream); 156 int AudioMixerSinkCtl(PAUDMIXSINK pSink, AUDMIXSINKCMD enmCmd); 157 void AudioMixerSinkDestroy(PAUDMIXSINK pSink); 158 PAUDMIXSTREAM AudioMixerSinkGetStream(PAUDMIXSINK pSink, uint8_t uIndex); 159 uint8_t AudioMixerSinkGetStreamCount(PAUDMIXSINK pSink); 160 int AudioMixerSinkRead(PAUDMIXSINK pSink, AUDMIXOP enmOp, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead); 161 void AudioMixerSinkRemoveStream(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream); 162 void AudioMixerSinkRemoveAllStreams(PAUDMIXSINK pSink); 163 int AudioMixerSinkSetFormat(PAUDMIXSINK pSink, PPDMPCMPROPS pPCMProps); 164 int AudioMixerSinkSetVolume(PAUDMIXSINK pSink, PPDMAUDIOVOLUME pVol); 165 int AudioMixerSinkWrite(PAUDMIXSINK pSink, AUDMIXOP enmOp, const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten); 166 int AudioMixerSinkUpdate(PAUDMIXSINK pSink); 167 168 int AudioMixerStreamCreate(PPDMIAUDIOCONNECTOR pConnector, PPDMAUDIOSTREAMCFG pCfg, uint32_t fFlags, PAUDMIXSTREAM *ppStream); 169 int AudioMixerStreamCtl(PAUDMIXSTREAM pStream, PDMAUDIOSTREAMCMD enmCmd, uint32_t fCtl); 170 void AudioMixerStreamDestroy(PAUDMIXSTREAM pStream); 171 bool AudioMixerStreamIsActive(PAUDMIXSTREAM pStream); 172 bool AudioMixerStreamIsValid(PAUDMIXSTREAM pStream); 111 173 112 174 #endif /* AUDIO_MIXER_H */ -
trunk/src/VBox/Devices/Audio/DevIchAc97.cpp
r60361 r60925 52 52 #define AC97_SSM_VERSION 1 53 53 54 #define AC97_TIMER_HZ 200 55 54 56 #ifdef VBOX 55 57 # define SOFT_VOLUME /** @todo Get rid of this crap. */ … … 58 60 #endif 59 61 62 /** @todo Use AC97_ prefixes! */ 60 63 #define SR_FIFOE RT_BIT(4) /* rwc, FIFO error. */ 61 64 #define SR_BCIS RT_BIT(3) /* rwc, Buffer completion interrupt status. */ … … 113 116 /** @name Buffer Descriptor 114 117 * @{ */ 115 #define BD_IOC RT_BIT(31) /**< Interrupt on Completion */ 116 #define BD_BUP RT_BIT(30) /**< Buffer Underrun Policy */ 118 #define BD_IOC RT_BIT(31) /**< Interrupt on Completion. */ 119 #define BD_BUP RT_BIT(30) /**< Buffer Underrun Policy. */ 120 121 #define BD_MAX_LEN_MASK 0xFFFE 117 122 /** @} */ 118 123 119 #define EACS_VRA 1 120 #define EACS_VRM 8 124 /** @name Extended Audio Status and Control Register 125 * @{ */ 126 #define EACS_VRA 1 /**< Variable Rate Audio (4.2.1.1). */ 127 #define EACS_VRM 8 /**< Variable Rate Mic Audio (4.2.1.1). */ 128 /** @} */ 121 129 122 130 #define VOL_MASK 0x1f … … 193 201 194 202 /** Emits registers for a specific (Native Audio Bus Master BAR) NABMBAR. */ 195 #define AC97_NABMBAR_REGS(prefix, off) \196 enum { \197 prefix ## _BDBAR = off, 198 prefix ## _CIV = off + 4, \199 prefix ## _LVI = off + 5, \200 prefix ## _SR = off + 6, \201 prefix ## _PICB = off + 8, \202 prefix ## _PIV = off + 10, \203 prefix ## _CR = off + 11 \203 #define AC97_NABMBAR_REGS(prefix, off) \ 204 enum { \ 205 prefix ## _BDBAR = off, /* Buffer Descriptor Base Address */ \ 206 prefix ## _CIV = off + 4, /* Current Index Value */ \ 207 prefix ## _LVI = off + 5, /* Last Valid Index */ \ 208 prefix ## _SR = off + 6, /* Status Register */ \ 209 prefix ## _PICB = off + 8, /* Position in Current Buffer */ \ 210 prefix ## _PIV = off + 10, /* Prefetched Index Value */ \ 211 prefix ## _CR = off + 11 /* Control Register */ \ 204 212 } 205 213 … … 264 272 typedef struct AC97STREAMSTATE 265 273 { 266 /* Nothing yet. */ 274 /** Temporary FIFO write buffer. */ 275 R3PTRTYPE(uint8_t *) au8FIFOW; 276 /** Size of the temporary FIFO write buffer. */ 277 uint32_t cbFIFOW; 278 /** Current write offset in FIFO write buffer. */ 279 uint32_t offFIFOW; 280 uint8_t Padding; 267 281 } AC97STREAMSTATE, *PAC97STREAMSTATE; 268 282 … … 286 300 { 287 301 /** PCM line input stream. */ 288 R3PTRTYPE(PPDMAUDIOGSTSTRMIN) 302 R3PTRTYPE(PPDMAUDIOGSTSTRMIN) pStrmIn; 289 303 /** Mixer handle for line input stream. */ 290 R3PTRTYPE(PAUDMIXSTREAM) phStrmIn;304 R3PTRTYPE(PAUDMIXSTREAM) pMixStrm; 291 305 } AC97INPUTSTREAM, *PAC97INPUTSTREAM; 292 306 … … 294 308 { 295 309 /** PCM output stream. */ 296 R3PTRTYPE(PPDMAUDIOGSTSTRMOUT) 310 R3PTRTYPE(PPDMAUDIOGSTSTRMOUT) pStrmOut; 297 311 /** Mixer handle for output stream. */ 298 R3PTRTYPE(PAUDMIXSTREAM) phStrmOut;312 R3PTRTYPE(PAUDMIXSTREAM) pMixStrm; 299 313 } AC97OUTPUTSTREAM, *PAC97OUTPUTSTREAM; 300 314 … … 335 349 /** R3 Pointer to the device instance. */ 336 350 PPDMDEVINSR3 pDevInsR3; 337 /** Global Control (Bus Master Control Register) */351 /** Global Control (Bus Master Control Register). */ 338 352 uint32_t glob_cnt; 339 /** Global Status (Bus Master Control Register) */353 /** Global Status (Bus Master Control Register). */ 340 354 uint32_t glob_sta; 341 /** Codec Access Semaphore Register (Bus Master Control Register) */355 /** Codec Access Semaphore Register (Bus Master Control Register). */ 342 356 uint32_t cas; 343 357 uint32_t last_samp; … … 379 393 /** Base port of the I/O space region. */ 380 394 RTIOPORT IOPortBase[2]; 381 /** Pointer to temporary scratch read/write buffer. */382 R3PTRTYPE(uint8_t *) pvReadWriteBuf;383 /** Size of the temporary scratch read/write buffer. */384 uint32_t cbReadWriteBuf;385 395 /** Codec model. */ 386 396 uint32_t uCodecModel; … … 393 403 #ifndef VBOX_DEVICE_STRUCT_TESTCASE 394 404 405 static void ichac97CloseIn(PAC97STATE pThis, PDMAUDIORECSOURCE enmRecSource); 406 static void ichac97CloseOut(PAC97STATE pThis); 395 407 DECLINLINE(PAC97STREAM) ichac97GetStreamFromID(PAC97STATE pThis, uint32_t uID); 408 static int ichac97StreamInit(PAC97STATE pThis, PAC97STREAM pStream, uint8_t u8Strm); 396 409 static DECLCALLBACK(void) ichac97Reset(PPDMDEVINS pDevIns); 397 410 #ifndef VBOX_WITH_AUDIO_CALLBACKS 398 411 static DECLCALLBACK(void) ichac97Timer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser); 399 412 #endif 400 static int ichac97TransferAudio(PAC97STATE pThis, AC97SOUNDSOURCE enmSrc, uint32_t cbElapsed);413 static int ichac97TransferAudio(PAC97STATE pThis, PAC97STREAM pStream, uint32_t cbElapsed); 401 414 402 415 static void ichac97WarmReset(PAC97STATE pThis) … … 410 423 } 411 424 425 DECLINLINE(PAUDMIXSINK) ichac97IndexToSink(PAC97STATE pThis, uint8_t uIndex) 426 { 427 AssertPtrReturn(pThis, NULL); 428 429 switch (uIndex) 430 { 431 case PI_INDEX: return pThis->pSinkLineIn; break; 432 case PO_INDEX: return pThis->pSinkOutput; break; 433 case MC_INDEX: return pThis->pSinkMicIn; break; 434 default: break; 435 } 436 437 AssertMsgFailed(("Wrong index %RU8\n", uIndex)); 438 return NULL; 439 } 440 412 441 /** Fetches the buffer descriptor at _CIV. */ 413 static void ichac97StreamFetchBDLE(PAC97STATE pThis, PAC97STREAM pStr mSt)442 static void ichac97StreamFetchBDLE(PAC97STATE pThis, PAC97STREAM pStream) 414 443 { 415 444 PPDMDEVINS pDevIns = ICHAC97STATE_2_DEVINS(pThis); 416 PAC97BMREGS pRegs = &pStr mSt->Regs;445 PAC97BMREGS pRegs = &pStream->Regs; 417 446 418 447 uint32_t u32[2]; … … 426 455 pRegs->bd.ctl_len = RT_H2LE_U32(u32[1]); 427 456 #endif 428 pRegs->picb = pRegs->bd.ctl_len & 0xffff;457 pRegs->picb = pRegs->bd.ctl_len & BD_MAX_LEN_MASK; 429 458 LogFlowFunc(("bd %2d addr=%#x ctl=%#06x len=%#x(%d bytes)\n", 430 459 pRegs->civ, pRegs->bd.addr, pRegs->bd.ctl_len >> 16, 431 pRegs->bd.ctl_len & 0xffff, (pRegs->bd.ctl_len & 0xffff) << 1)); 460 pRegs->bd.ctl_len & BD_MAX_LEN_MASK, 461 (pRegs->bd.ctl_len & BD_MAX_LEN_MASK) << 1)); /** @todo r=andy Assumes 16bit samples. */ 432 462 } 433 463 … … 435 465 * Update the BM status register 436 466 */ 437 static void ichac97StreamUpdateStatus(PAC97STATE pThis, PAC97STREAM pStr mSt, uint32_t new_sr)467 static void ichac97StreamUpdateStatus(PAC97STATE pThis, PAC97STREAM pStream, uint32_t new_sr) 438 468 { 439 469 PPDMDEVINS pDevIns = ICHAC97STATE_2_DEVINS(pThis); 440 PAC97BMREGS pRegs = &pStr mSt->Regs;441 442 bool fSignal 443 bool iIrqLevel;470 PAC97BMREGS pRegs = &pStream->Regs; 471 472 bool fSignal = false; 473 int iIRQL; 444 474 445 475 uint32_t new_mask = new_sr & SR_INT_MASK; … … 453 483 if (!new_mask) 454 484 { 455 fSignal 456 iI rqLevel= 0;485 fSignal = true; 486 iIRQL = 0; 457 487 } 458 488 else if ((new_mask & SR_LVBCI) && (pRegs->cr & CR_LVBIE)) 459 489 { 460 fSignal 461 iI rqLevel= 1;490 fSignal = true; 491 iIRQL = 1; 462 492 } 463 493 else if ((new_mask & SR_BCIS) && (pRegs->cr & CR_IOCE)) 464 494 { 465 fSignal 466 iI rqLevel= 1;495 fSignal = true; 496 iIRQL = 1; 467 497 } 468 498 } … … 470 500 pRegs->sr = new_sr; 471 501 472 LogFlowFunc(("IOC%d, LVB%d, sr=%#x, fSignal=%RTbool, iIrqLevel=%d\n",473 pRegs->sr & SR_BCIS, pRegs->sr & SR_LVBCI, pRegs->sr, fSignal, iI rqLevel));502 LogFlowFunc(("IOC%d, LVB%d, sr=%#x, fSignal=%RTbool, IRQL=%d\n", 503 pRegs->sr & SR_BCIS, pRegs->sr & SR_LVBCI, pRegs->sr, fSignal, iIRQL)); 474 504 475 505 if (fSignal) 476 506 { 477 if (iI rqLevel)478 pThis->glob_sta |= masks[pStr mSt->u8Strm];507 if (iIRQL) 508 pThis->glob_sta |= masks[pStream->u8Strm]; 479 509 else 480 pThis->glob_sta &= ~masks[pStr mSt->u8Strm];481 482 LogFlowFunc((" set irq level=%d\n", !!iIrqLevel));483 PDMDevHlpPCISetIrq(pDevIns, 0, !!iIrqLevel);484 } 485 } 486 487 static int ichac97StreamSetActive(PAC97STATE pThis, PAC97STREAM pStr mSt, bool fActive)510 pThis->glob_sta &= ~masks[pStream->u8Strm]; 511 512 LogFlowFunc(("Setting IRQ level=%d\n", iIRQL)); 513 PDMDevHlpPCISetIrq(pDevIns, 0, iIRQL); 514 } 515 } 516 517 static int ichac97StreamSetActive(PAC97STATE pThis, PAC97STREAM pStream, bool fActive) 488 518 { 489 519 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 490 AssertPtrReturn(pStrmSt, VERR_INVALID_POINTER); 491 492 LogFlowFunc(("u8Strm=%RU8, fActive=%RTbool\n", pStrmSt->u8Strm, fActive)); 493 494 int rc = VINF_SUCCESS; 495 496 PAC97DRIVER pDrv; 497 switch (pStrmSt->u8Strm) 498 { 499 case PI_INDEX: 500 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 501 { 502 int rc2 = pDrv->pConnector->pfnEnableIn(pDrv->pConnector, 503 pDrv->LineIn.pStrmIn, fActive); 504 if (RT_SUCCESS(rc)) 505 rc = rc2; 506 } 507 break; 508 509 case PO_INDEX: 510 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 511 { 512 int rc2 = pDrv->pConnector->pfnEnableOut(pDrv->pConnector, 513 pDrv->Out.pStrmOut, fActive); 514 if (RT_SUCCESS(rc)) 515 rc = rc2; 516 } 517 break; 518 519 case MC_INDEX: 520 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 521 { 522 int rc2 = pDrv->pConnector->pfnEnableIn(pDrv->pConnector, 523 pDrv->MicIn.pStrmIn, fActive); 524 if (RT_SUCCESS(rc)) 525 rc = rc2; 526 } 527 break; 528 529 default: 530 AssertMsgFailed(("Wrong index %RU32\n", pStrmSt->u8Strm)); 531 rc = VERR_NOT_SUPPORTED; 532 break; 533 } 534 535 return rc; 536 } 537 538 static void ichac97StreamResetBMRegs(PAC97STATE pThis, PAC97STREAM pStrmSt) 520 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 521 522 LogFlowFunc(("u8Strm=%RU8, fActive=%RTbool\n", pStream->u8Strm, fActive)); 523 524 return AudioMixerSinkCtl(ichac97IndexToSink(pThis, pStream->u8Strm), 525 fActive ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE); 526 } 527 528 static void ichac97StreamResetBMRegs(PAC97STATE pThis, PAC97STREAM pStream) 539 529 { 540 530 AssertPtrReturnVoid(pThis); 541 AssertPtrReturnVoid(pStr mSt);531 AssertPtrReturnVoid(pStream); 542 532 543 533 LogFlowFuncEnter(); 544 534 545 PAC97BMREGS pRegs = &pStr mSt->Regs;535 PAC97BMREGS pRegs = &pStream->Regs; 546 536 547 537 pRegs->bdbar = 0; … … 549 539 pRegs->lvi = 0; 550 540 551 ichac97StreamUpdateStatus(pThis, pStr mSt, SR_DCH); /** @todo Do we need to do that? */541 ichac97StreamUpdateStatus(pThis, pStream, SR_DCH); /** @todo Do we need to do that? */ 552 542 553 543 pRegs->picb = 0; … … 556 546 pRegs->bd_valid = 0; 557 547 558 int rc = ichac97StreamSetActive(pThis, pStr mSt, false /* fActive */);548 int rc = ichac97StreamSetActive(pThis, pStream, false /* fActive */); 559 549 AssertRC(rc); 560 550 561 551 RT_ZERO(pThis->silence); 552 } 553 554 static void ichac97StreamDestroy(PAC97STREAM pStream) 555 { 556 if (pStream->State.au8FIFOW) 557 { 558 Assert(pStream->State.cbFIFOW); 559 RTMemFree(pStream->State.au8FIFOW); 560 pStream->State.au8FIFOW = NULL; 561 } 562 563 pStream->State.cbFIFOW = 0; 564 pStream->State.offFIFOW = 0; 565 } 566 567 static void ichac97StreamsDestroy(PAC97STATE pThis) 568 { 569 LogFlowFuncEnter(); 570 571 ichac97CloseIn(pThis, PDMAUDIORECSOURCE_LINE); 572 ichac97CloseIn(pThis, PDMAUDIORECSOURCE_MIC); 573 ichac97CloseOut(pThis); 574 575 ichac97StreamDestroy(&pThis->StrmStLineIn); 576 ichac97StreamDestroy(&pThis->StrmStMicIn); 577 ichac97StreamDestroy(&pThis->StrmStOut); 578 } 579 580 static int ichac97StreamsInit(PAC97STATE pThis) 581 { 582 LogFlowFuncEnter(); 583 584 ichac97StreamInit(pThis, &pThis->StrmStLineIn, PI_INDEX); 585 ichac97StreamInit(pThis, &pThis->StrmStMicIn, MC_INDEX); 586 ichac97StreamInit(pThis, &pThis->StrmStOut, PO_INDEX); 587 588 return VINF_SUCCESS; 562 589 } 563 590 … … 589 616 } 590 617 591 static DECLCALLBACK(void)ichac97CloseIn(PAC97STATE pThis, PDMAUDIORECSOURCE enmRecSource)592 { 593 NOREF(pThis);594 NOREF(enmRecSource); 618 static void ichac97CloseIn(PAC97STATE pThis, PDMAUDIORECSOURCE enmRecSource) 619 { 620 AssertPtrReturnVoid(pThis); 621 595 622 LogFlowFuncEnter(); 596 }597 598 static DECLCALLBACK(void) ichac97CloseOut(PAC97STATE pThis)599 {600 NOREF(pThis);601 LogFlowFuncEnter();602 }603 604 static int ichac97OpenIn(PAC97STATE pThis,605 const char *pszName, PDMAUDIORECSOURCE enmRecSource,606 PPDMAUDIOSTREAMCFG pCfg)607 {608 AssertPtrReturn(pThis, VERR_INVALID_POINTER);609 AssertPtrReturn(pszName, VERR_INVALID_POINTER);610 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);611 623 612 624 PAUDMIXSINK pSink; … … 621 633 default: 622 634 AssertMsgFailed(("Audio source %ld not supported\n", enmRecSource)); 623 return VERR_NOT_SUPPORTED; 624 } 625 626 int rc = VINF_SUCCESS; 635 return; 636 } 627 637 628 638 PAC97DRIVER pDrv; 629 639 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 630 640 { 631 char *pszDesc;632 if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] %s", pDrv->uLUN, pszName) <= 0)633 {634 rc = VERR_NO_MEMORY;635 break;636 }637 638 641 PAC97INPUTSTREAM pStrmIn; 639 642 if (enmRecSource == PDMAUDIORECSOURCE_MIC) /** @todo Refine this once we have more streams. */ … … 642 645 pStrmIn = &pDrv->LineIn; 643 646 644 int rc2 = pDrv->pConnector->pfnCreateIn(pDrv->pConnector, pszDesc, pCfg, &pStrmIn->pStrmIn); 645 LogFlowFunc(("LUN#%RU8: Created input \"%s\", with rc=%Rrc\n", pDrv->uLUN, pszDesc, rc2)); 646 if (RT_SUCCESS(rc2)) 647 { 648 AudioMixerRemoveStream(pSink, pStrmIn->phStrmIn); 649 rc2 = AudioMixerAddStreamIn(pSink, 650 pDrv->pConnector, pStrmIn->pStrmIn, 651 0 /* uFlags */, &pStrmIn->phStrmIn); 652 } 653 654 if (RT_SUCCESS(rc)) 655 rc = rc2; 656 657 RTStrFree(pszDesc); 658 } 659 660 LogFlowFuncLeaveRC(rc); 661 return rc; 662 } 663 664 static int ichac97OpenOut(PAC97STATE pThis, const char *pszName, PPDMAUDIOSTREAMCFG pCfg) 647 AudioMixerSinkRemoveStream(pSink, pStrmIn->pMixStrm); 648 AudioMixerStreamDestroy(pStrmIn->pMixStrm); 649 pStrmIn->pMixStrm = NULL; 650 } 651 } 652 653 static void ichac97CloseOut(PAC97STATE pThis) 654 { 655 AssertPtrReturnVoid(pThis); 656 657 LogFlowFuncEnter(); 658 659 PAC97DRIVER pDrv; 660 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 661 { 662 AudioMixerSinkRemoveStream(pThis->pSinkOutput, pDrv->Out.pMixStrm); 663 AudioMixerStreamDestroy(pDrv->Out.pMixStrm); 664 pDrv->Out.pMixStrm = NULL; 665 } 666 } 667 668 static int ichac97OpenIn(PAC97STATE pThis, 669 const char *pszName, PDMAUDIORECSOURCE enmRecSource, PPDMAUDIOSTREAMCFG pCfg) 665 670 { 666 671 AssertPtrReturn(pThis, VERR_INVALID_POINTER); … … 668 673 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 669 674 670 int rc = VINF_SUCCESS; 671 char *pszDesc; 675 PAUDMIXSINK pSink; 676 switch (enmRecSource) 677 { 678 case PDMAUDIORECSOURCE_MIC: 679 pSink = pThis->pSinkMicIn; 680 break; 681 case PDMAUDIORECSOURCE_LINE: 682 pSink = pThis->pSinkLineIn; 683 break; 684 default: 685 AssertMsgFailed(("Audio source %ld not supported\n", enmRecSource)); 686 return VERR_NOT_SUPPORTED; 687 } 688 689 /* Update the sink's format. */ 690 PDMPCMPROPS PCMProps; 691 int rc = DrvAudioStreamCfgToProps(pCfg, &PCMProps); 692 if (RT_SUCCESS(rc)) 693 rc = AudioMixerSinkSetFormat(pSink, &PCMProps); 694 695 if (RT_FAILURE(rc)) 696 return rc; 672 697 673 698 PAC97DRIVER pDrv; 674 699 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 675 700 { 676 if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] %s (%RU32Hz, %RU8 %s)", 677 pDrv->uLUN, pszName, pCfg->uHz, pCfg->cChannels, pCfg->cChannels > 1 ? "Channels" : "Channel") <= 0) 678 { 679 rc = VERR_NO_MEMORY; 680 break; 681 } 682 683 int rc2 = pDrv->pConnector->pfnCreateOut(pDrv->pConnector, pszDesc, pCfg, &pDrv->Out.pStrmOut); 684 LogFlowFunc(("LUN#%RU8: Created output \"%s\", with rc=%Rrc\n", pDrv->uLUN, pszDesc, rc2)); 701 if (!RTStrPrintf(pCfg->szName, sizeof(pCfg->szName), "[LUN#%RU8] %s", pDrv->uLUN, pszName)) 702 { 703 rc = VERR_BUFFER_OVERFLOW; 704 break; 705 } 706 707 PAC97INPUTSTREAM pStrmIn; 708 if (enmRecSource == PDMAUDIORECSOURCE_MIC) /** @todo Refine this once we have more streams. */ 709 pStrmIn = &pDrv->MicIn; 710 else 711 pStrmIn = &pDrv->LineIn; 712 713 AudioMixerSinkRemoveStream(pSink, pStrmIn->pMixStrm); 714 715 AudioMixerStreamDestroy(pStrmIn->pMixStrm); 716 pStrmIn->pMixStrm = NULL; 717 718 int rc2 = AudioMixerStreamCreate(pDrv->pConnector, pCfg, 0 /* fFlags */ , &pStrmIn->pMixStrm); 685 719 if (RT_SUCCESS(rc2)) 686 720 { 687 AudioMixerRemoveStream(pThis->pSinkOutput, pDrv->Out.phStrmOut); 688 rc2 = AudioMixerAddStreamOut(pThis->pSinkOutput, 689 pDrv->pConnector, pDrv->Out.pStrmOut, 690 0 /* uFlags */, &pDrv->Out.phStrmOut); 721 rc2 = AudioMixerSinkAddStream(pSink, pStrmIn->pMixStrm); 722 LogFlowFunc(("LUN#%RU8: Created input \"%s\", rc=%Rrc\n", pDrv->uLUN, pCfg->szName, rc2)); 691 723 } 692 724 693 725 if (RT_SUCCESS(rc)) 694 726 rc = rc2; 695 696 RTStrFree(pszDesc);697 727 } 698 728 … … 701 731 } 702 732 703 static int ichac97StreamInitEx(PAC97STATE pThis, PAC97STREAM pStrmSt, uint8_t u8Strm, PPDMAUDIOSTREAMCFG pCfg) 733 static int ichac97OpenOut(PAC97STATE pThis, const char *pszName, PPDMAUDIOSTREAMCFG pCfg) 734 { 735 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 736 AssertPtrReturn(pszName, VERR_INVALID_POINTER); 737 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 738 739 /* Update the sink's format. */ 740 PDMPCMPROPS PCMProps; 741 int rc = DrvAudioStreamCfgToProps(pCfg, &PCMProps); 742 if (RT_SUCCESS(rc)) 743 rc = AudioMixerSinkSetFormat(pThis->pSinkOutput, &PCMProps); 744 745 if (RT_FAILURE(rc)) 746 return rc; 747 748 PAC97DRIVER pDrv; 749 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 750 { 751 if (!RTStrPrintf(pCfg->szName, sizeof(pCfg->szName), "[LUN#%RU8] %s (%RU32Hz, %RU8 %s)", 752 pDrv->uLUN, pszName, pCfg->uHz, pCfg->cChannels, pCfg->cChannels > 1 ? "Channels" : "Channel")) 753 { 754 rc = VERR_BUFFER_OVERFLOW; 755 break; 756 } 757 758 AudioMixerSinkRemoveStream(pThis->pSinkOutput, pDrv->Out.pMixStrm); 759 760 AudioMixerStreamDestroy(pDrv->Out.pMixStrm); 761 pDrv->Out.pMixStrm = NULL; 762 763 int rc2 = AudioMixerStreamCreate(pDrv->pConnector, pCfg, 0 /* fFlags */, &pDrv->Out.pMixStrm); 764 if (RT_SUCCESS(rc2)) 765 { 766 rc2 = AudioMixerSinkAddStream(pThis->pSinkOutput, pDrv->Out.pMixStrm); 767 LogFlowFunc(("LUN#%RU8: Created output \"%s\", rc=%Rrc\n", pDrv->uLUN, pCfg->szName, rc2)); 768 } 769 770 if (RT_SUCCESS(rc)) 771 rc = rc2; 772 } 773 774 LogFlowFuncLeaveRC(rc); 775 return rc; 776 } 777 778 static int ichac97StreamInitEx(PAC97STATE pThis, PAC97STREAM pStream, uint8_t u8Strm, PPDMAUDIOSTREAMCFG pCfg) 704 779 { 705 780 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 706 AssertPtrReturn(pStr mSt, VERR_INVALID_POINTER);781 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 707 782 AssertReturn(u8Strm <= LAST_INDEX, VERR_INVALID_PARAMETER); 708 783 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 709 784 710 pStr mSt->u8Strm = u8Strm;785 pStream->u8Strm = u8Strm; 711 786 712 787 LogFlowFunc(("u8Strm=%RU8, %RU32Hz, %RU8 %s\n", 713 pStr mSt->u8Strm, pCfg->uHz, pCfg->cChannels, pCfg->cChannels > 1 ? "Channels" : "Channel"));788 pStream->u8Strm, pCfg->uHz, pCfg->cChannels, pCfg->cChannels > 1 ? "Channels" : "Channel")); 714 789 715 790 int rc; 716 switch (pStr mSt->u8Strm)791 switch (pStream->u8Strm) 717 792 { 718 793 case PI_INDEX: … … 733 808 } 734 809 810 if (RT_FAILURE(rc)) 811 LogRel2(("AC97: Error opening stream #%RU8, rc=%Rrc\n", pStream->u8Strm, rc)); 812 735 813 LogFlowFuncLeaveRC(rc); 736 814 return rc; 737 815 } 738 816 739 static int ichac97StreamInit(PAC97STATE pThis, PAC97STREAM pStr mSt, uint8_t u8Strm)817 static int ichac97StreamInit(PAC97STATE pThis, PAC97STREAM pStream, uint8_t u8Strm) 740 818 { 741 819 int rc = VINF_SUCCESS; … … 769 847 } 770 848 771 if (RT_FAILURE(rc)) 772 return rc; 773 774 if (streamCfg.uHz) 775 { 776 streamCfg.cChannels = 2; 777 streamCfg.enmFormat = AUD_FMT_S16; 778 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS; 779 780 return ichac97StreamInitEx(pThis, pStrmSt, u8Strm, &streamCfg); 781 } 782 783 /* If no frequency is given, disable the stream. */ 784 return ichac97StreamSetActive(pThis, pStrmSt, false /* fActive */); 785 } 786 787 static int ichac97StreamReInit(PAC97STATE pThis, PAC97STREAM pStrmSt) 788 { 789 return ichac97StreamInit(pThis, pStrmSt, pStrmSt->u8Strm); 790 } 791 792 static void ichac97StreamReset(PAC97STATE pThis, PAC97STREAM pStrmSt) 849 if (RT_SUCCESS(rc)) 850 { 851 pStream->State.cbFIFOW = 256; /** @todo Make FIFOW size configurable. */ 852 pStream->State.offFIFOW = 0; 853 pStream->State.au8FIFOW = (uint8_t *)RTMemAllocZ(pStream->State.cbFIFOW); 854 if (!pStream->State.au8FIFOW) 855 rc = VERR_NO_MEMORY; 856 } 857 858 if (RT_SUCCESS(rc)) 859 { 860 if (streamCfg.uHz) 861 { 862 streamCfg.cChannels = 2; /** @todo Handle mono channels? */ 863 streamCfg.enmFormat = PDMAUDIOFMT_S16; 864 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS; 865 866 rc = ichac97StreamInitEx(pThis, pStream, u8Strm, &streamCfg); 867 } 868 else 869 { 870 /* If no frequency is given, disable the stream. */ 871 rc = ichac97StreamSetActive(pThis, pStream, false /* fActive */); 872 } 873 } 874 875 LogFlowFunc(("Index=%RU8, rc=%Rrc\n", u8Strm, rc)); 876 return rc; 877 } 878 879 static int ichac97StreamReInit(PAC97STATE pThis, PAC97STREAM pStrm) 880 { 881 return ichac97StreamInit(pThis, pStrm, pStrm->u8Strm); 882 } 883 884 static void ichac97StreamReset(PAC97STATE pThis, PAC97STREAM pStrm) 793 885 { 794 886 AssertPtrReturnVoid(pThis); 795 AssertPtrReturnVoid(pStrmSt); 796 797 LogFlowFunc(("uStrm=%RU8\n", pStrmSt->u8Strm)); 887 AssertPtrReturnVoid(pStrm); 888 889 if (pStrm->State.au8FIFOW) 890 { 891 Assert(pStrm->State.cbFIFOW); 892 RT_BZERO(pStrm->State.au8FIFOW, pStrm->State.cbFIFOW); 893 } 894 895 pStrm->State.offFIFOW = 0; 896 897 LogFlowFunc(("uStrm=%RU8\n", pStrm->u8Strm)); 798 898 } 799 899 … … 832 932 833 933 case PDMAUDIOMIXERCTL_FRONT: 834 rc = AudioMixerS etSinkVolume(pThis->pSinkOutput, &vol);934 rc = AudioMixerSinkSetVolume(pThis->pSinkOutput, &vol); 835 935 break; 836 936 837 937 case PDMAUDIOMIXERCTL_MIC_IN: 838 rc = AudioMixerS etSinkVolume(pThis->pSinkMicIn, &vol);938 rc = AudioMixerSinkSetVolume(pThis->pSinkMicIn, &vol); 839 939 break; 840 940 841 941 case PDMAUDIOMIXERCTL_LINE_IN: 842 rc = AudioMixerS etSinkVolume(pThis->pSinkLineIn, &vol);942 rc = AudioMixerSinkSetVolume(pThis->pSinkLineIn, &vol); 843 943 break; 844 944 … … 991 1091 * @return IPRT status code. 992 1092 * @param pThis 993 * @param pStr mSt1093 * @param pStream 994 1094 * @param cbMax 995 1095 * @param pcbWritten 996 1096 */ 997 static int ichac97WriteAudio(PAC97STATE pThis, PAC97STREAM pStr mSt, uint32_t cbMax, uint32_t *pcbWritten)998 { 999 AssertPtrReturn(pThis, 1000 AssertPtrReturn(pStr mSt,VERR_INVALID_POINTER);1001 AssertReturn(cbMax, 1097 static int ichac97WriteAudio(PAC97STATE pThis, PAC97STREAM pStream, uint32_t cbMax, uint32_t *pcbWritten) 1098 { 1099 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1100 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1101 AssertReturn(cbMax, VERR_INVALID_PARAMETER); 1002 1102 /* pcbWritten is optional. */ 1003 1103 1004 1104 PPDMDEVINS pDevIns = ICHAC97STATE_2_DEVINS(pThis); 1005 PAC97BMREGS pRegs = &pStr mSt->Regs;1105 PAC97BMREGS pRegs = &pStream->Regs; 1006 1106 1007 1107 uint32_t addr = pRegs->bd.addr; 1008 1108 uint32_t cbWrittenTotal = 0; 1009 uint32_t cbToRead; 1010 1011 uint32_t cbToWrite = RT_MIN((uint32_t)(pRegs->picb << 1), cbMax); 1109 1110 Log3Func(("PICB=%RU16, cbMax=%RU32\n", pRegs->picb, cbMax)); 1111 1112 uint32_t cbToWrite = RT_MIN((uint32_t)(pRegs->picb << 1), cbMax); /** @todo r=andy Assumes 16bit sample size. */ 1012 1113 if (!cbToWrite) 1013 1114 { … … 1021 1122 LogFlowFunc(("pReg=%p, cbMax=%RU32, cbToWrite=%RU32\n", pRegs, cbMax, cbToWrite)); 1022 1123 1124 Assert(pStream->State.offFIFOW <= pStream->State.cbFIFOW); 1125 uint32_t cbFIFOW = pStream->State.cbFIFOW - pStream->State.offFIFOW; 1126 uint8_t *pu8FIFOW = &pStream->State.au8FIFOW[pStream->State.offFIFOW]; 1127 1128 uint32_t cbToRead; 1023 1129 while (cbToWrite) 1024 1130 { 1025 cbToRead = RT_MIN(cbToWrite, pThis->cbReadWriteBuf); 1026 PDMDevHlpPhysRead(pDevIns, addr, pThis->pvReadWriteBuf, cbToRead); /** @todo Check rc? */ 1027 1131 cbToRead = RT_MIN(cbToWrite, cbFIFOW); 1132 PDMDevHlpPhysRead(pDevIns, addr, pu8FIFOW, cbToRead); /** @todo r=andy Check rc? */ 1133 1134 /* 1135 * Write data to the mixer sink. 1136 */ 1028 1137 uint32_t cbWritten; 1029 1030 /* Just multiplex the output to the connected backends. 1031 * No need to utilize the virtual mixer here (yet). */ 1032 PAC97DRIVER pDrv; 1033 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 1034 { 1035 int rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Out.pStrmOut, 1036 pThis->pvReadWriteBuf, cbToRead, &cbWritten); 1037 LogFlowFunc(("\tLUN#%RU8: rc=%Rrc, cbWritten=%RU32\n", pDrv->uLUN, rc2, cbWritten)); 1038 } 1039 1040 LogFlowFunc(("\tcbToRead=%RU32, cbToWrite=%RU32, cbLeft=%RU32\n", 1041 cbToRead, cbToWrite, cbToWrite - cbWrittenTotal)); 1042 1138 rc = AudioMixerSinkWrite(pThis->pSinkOutput, AUDMIXOP_COPY, pu8FIFOW, cbToRead, &cbWritten); 1139 1140 LogFlowFunc(("\tcbToRead=%RU32, cbToWrite=%RU32, cbWritten=%RU32, cbLeft=%RU32, rc=%Rrc\n", 1141 cbToRead, cbToWrite, cbWritten, cbToWrite - cbWrittenTotal, rc)); 1142 1143 if (RT_FAILURE(rc)) 1144 break; 1145 1146 /* Advance. */ 1043 1147 Assert(cbToWrite >= cbToRead); 1044 1148 cbToWrite -= cbToRead; … … 1047 1151 } 1048 1152 1153 /* Set new buffer descriptor address. */ 1049 1154 pRegs->bd.addr = addr; 1050 1155 … … 1059 1164 } 1060 1165 else 1061 pThis->last_samp = *(uint32_t *)&p This->pvReadWriteBuf[cbToRead - 4];1166 pThis->last_samp = *(uint32_t *)&pStream->State.au8FIFOW[pStream->State.offFIFOW + cbToRead - 4]; 1062 1167 } 1063 1168 … … 1122 1227 } 1123 1228 1124 static int ichac97ReadAudio(PAC97STATE pThis, PAC97STREAM pStr mSt, uint32_t cbMax, uint32_t *pcbRead)1229 static int ichac97ReadAudio(PAC97STATE pThis, PAC97STREAM pStream, uint32_t cbMax, uint32_t *pcbRead) 1125 1230 { 1126 1231 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1127 AssertPtrReturn(pStr mSt, VERR_INVALID_POINTER);1232 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1128 1233 AssertReturn(cbMax, VERR_INVALID_PARAMETER); 1129 1234 /* pcbRead is optional. */ 1130 1235 1131 1236 PPDMDEVINS pDevIns = ICHAC97STATE_2_DEVINS(pThis); 1132 PAC97BMREGS pRegs = &pStr mSt->Regs;1237 PAC97BMREGS pRegs = &pStream->Regs; 1133 1238 1134 1239 /* Select audio sink to process. */ 1135 AssertMsg(pStr mSt->u8Strm != PO_INDEX, ("Can't read from output\n"));1136 PAUDMIXSINK pSink = pStr mSt->u8Strm == MC_INDEX ? pThis->pSinkMicIn : pThis->pSinkLineIn;1240 AssertMsg(pStream->u8Strm != PO_INDEX, ("Can't read from output\n")); 1241 PAUDMIXSINK pSink = pStream->u8Strm == MC_INDEX ? pThis->pSinkMicIn : pThis->pSinkLineIn; 1137 1242 AssertPtr(pSink); 1138 1243 1139 1244 uint32_t cbRead = 0; 1140 1141 uint32_t cbMixBuf = cbMax; 1142 uint32_t cbToRead = RT_MIN((uint32_t)(pRegs->picb << 1), cbMixBuf); 1245 uint32_t cbToRead = RT_MIN((uint32_t)(pRegs->picb << 1), 1246 RT_MIN(pStream->State.cbFIFOW, cbMax)); /** @todo r=andy Assumes 16bit samples. */ 1143 1247 1144 1248 if (!cbToRead) … … 1151 1255 int rc; 1152 1256 1153 uint8_t *pvMixBuf = (uint8_t *)RTMemAlloc(cbMixBuf); 1154 if (pvMixBuf) 1155 { 1156 rc = AudioMixerProcessSinkIn(pSink, AUDMIXOP_BLEND, pvMixBuf, cbToRead, &cbRead); 1157 if ( RT_SUCCESS(rc) 1158 && cbRead) 1159 { 1160 PDMDevHlpPCIPhysWrite(pDevIns, pRegs->bd.addr, pvMixBuf, cbRead); 1161 pRegs->bd.addr += cbRead; 1162 } 1163 1164 RTMemFree(pvMixBuf); 1165 } 1166 else 1167 rc = VERR_NO_MEMORY; 1257 rc = AudioMixerSinkRead(pSink, AUDMIXOP_BLEND, &pStream->State.au8FIFOW[pStream->State.offFIFOW], cbToRead, &cbRead); 1258 if ( RT_SUCCESS(rc) 1259 && cbRead) 1260 { 1261 PDMDevHlpPCIPhysWrite(pDevIns, pRegs->bd.addr, &pStream->State.au8FIFOW[pStream->State.offFIFOW], cbRead); 1262 pRegs->bd.addr += cbRead; 1263 } 1168 1264 1169 1265 if (RT_SUCCESS(rc)) 1170 1266 { 1267 if (!cbRead) 1268 rc = VINF_EOF; 1269 1171 1270 if (pcbRead) 1172 1271 *pcbRead = cbRead; … … 1189 1288 uint32_t cbOutMin = UINT32_MAX; 1190 1289 1191 PAC97DRIVER pDrv;1290 // PAC97DRIVER pDrv; 1192 1291 1193 1292 uint64_t cTicksNow = TMTimerGet(pTimer); … … 1197 1296 pThis->uTimerTS = cTicksNow; 1198 1297 1298 #if 0 1199 1299 /* 1200 1300 * Calculate the mixer's (fixed) sampling rate. … … 1277 1377 if (cbInMax) 1278 1378 ichac97TransferAudio(pThis, PI_INDEX, cbInMax); /** @todo Add rc! */ 1379 #else 1380 AudioMixerSinkUpdate(pThis->pSinkLineIn); 1381 AudioMixerSinkUpdate(pThis->pSinkMicIn); 1382 AudioMixerSinkUpdate(pThis->pSinkOutput); 1383 1384 uint32_t cMixerSamplesMin = (int)((2 * cTicksElapsed * pThis->pSinkOutput->PCMProps.uHz + cTicksPerSec) / cTicksPerSec / 2); 1385 uint32_t cbMixerSamplesMin = cMixerSamplesMin << pThis->pSinkOutput->PCMProps.cShift; 1386 1387 Log3Func(("cMixerSamplesMin=%RU32, cbMixerSamplesMin=%RU32, mixerHz=%RU32\n", 1388 cMixerSamplesMin, cbMixerSamplesMin, pThis->pSinkOutput->PCMProps.uHz)); 1389 1390 //uint32_t cbSamplesElapsed = 5120; //((48000 / AC97_TIMER_HZ) * 20) / 8; 1391 1392 uint32_t cMixerSamplesMinIn = (int)((2 * cTicksElapsed * pThis->pSinkLineIn->PCMProps.uHz + cTicksPerSec) / cTicksPerSec / 2); 1393 uint32_t cbMixerSamplesMinIn = cMixerSamplesMinIn << pThis->pSinkLineIn->PCMProps.cShift; 1394 1395 ichac97TransferAudio(pThis, &pThis->StrmStLineIn, cMixerSamplesMinIn); /** @todo Add rc! */ 1396 ichac97TransferAudio(pThis, &pThis->StrmStOut, cbMixerSamplesMin); /** @todo Add rc! */ 1397 #endif 1279 1398 1280 1399 /* Kick the timer again. */ … … 1288 1407 #endif 1289 1408 1290 static int ichac97TransferAudio(PAC97STATE pThis, AC97SOUNDSOURCE enmSrc, uint32_t cbElapsed) 1291 { 1292 LogFlowFunc(("pThis=%p, enmSrc=%RU32, cbElapsed=%RU32\n", pThis, enmSrc, cbElapsed)); 1293 1294 PAC97STREAM pStrmSt; 1295 switch (enmSrc) 1296 { 1297 case PI_INDEX: pStrmSt = &pThis->StrmStLineIn; break; 1298 case MC_INDEX: pStrmSt = &pThis->StrmStMicIn; break; 1299 case PO_INDEX: pStrmSt = &pThis->StrmStOut; break; 1300 default: 1301 { 1302 AssertMsgFailed(("Unknown source index %ld\n", enmSrc)); 1303 return VERR_NOT_SUPPORTED; 1304 } 1305 } 1306 1307 PAC97BMREGS pRegs = &pStrmSt->Regs; 1409 static int ichac97TransferAudio(PAC97STATE pThis, PAC97STREAM pStream, uint32_t cbElapsed) 1410 { 1411 Log3Func(("SD=%RU8, cbElapsed=%RU32\n", pStream->u8Strm , cbElapsed)); 1412 1413 PAC97BMREGS pRegs = &pStream->Regs; 1308 1414 1309 1415 if (pRegs->sr & SR_DCH) /* Controller halted? */ … … 1311 1417 if (pRegs->cr & CR_RPBM) 1312 1418 { 1313 switch ( enmSrc)1419 switch (pStream->u8Strm) 1314 1420 { 1315 1421 case PO_INDEX: … … 1325 1431 } 1326 1432 1433 /* BCIS flag still set? Skip iteration. */ 1434 if (pRegs->sr & SR_BCIS) 1435 return VINF_SUCCESS; 1436 1327 1437 int rc = VINF_SUCCESS; 1328 1438 uint32_t cbWrittenTotal = 0; 1329 1439 1330 while (cbElapsed >> 1) 1440 while (cbElapsed >> 1) /** @todo r=andy This assumes (hardcodes) 16bit sample size.*/ 1331 1441 { 1332 1442 if (!pRegs->bd_valid) 1333 1443 { 1334 1444 LogFlowFunc(("Invalid buffer descriptor, fetching next one ...\n")); 1335 ichac97StreamFetchBDLE(pThis, pStr mSt);1445 ichac97StreamFetchBDLE(pThis, pStream); 1336 1446 } 1337 1447 … … 1351 1461 pRegs->sr &= ~SR_CELV; 1352 1462 pRegs->civ = pRegs->piv; 1353 pRegs->piv = (pRegs->piv + 1) % 32; 1354 1355 ichac97StreamFetchBDLE(pThis, pStr mSt);1463 pRegs->piv = (pRegs->piv + 1) % 32; /** @todo r=andy Define for max BDLEs? */ 1464 1465 ichac97StreamFetchBDLE(pThis, pStream); 1356 1466 continue; 1357 1467 } 1358 1468 1359 1469 uint32_t cbTransferred; 1360 switch ( enmSrc)1470 switch (pStream->u8Strm) 1361 1471 { 1362 1472 case PO_INDEX: 1363 1473 { 1364 rc = ichac97WriteAudio(pThis, pStr mSt, cbElapsed, &cbTransferred);1474 rc = ichac97WriteAudio(pThis, pStream, cbElapsed, &cbTransferred); 1365 1475 if ( RT_SUCCESS(rc) 1366 1476 && cbTransferred) … … 1370 1480 cbElapsed -= cbTransferred; 1371 1481 Assert((cbTransferred & 1) == 0); /* Else the following shift won't work */ 1372 pRegs->picb -= (cbTransferred >> 1); 1482 pRegs->picb -= (cbTransferred >> 1); /** @todo r=andy Assumes 16bit samples. */ 1373 1483 } 1374 1484 break; … … 1378 1488 case MC_INDEX: 1379 1489 { 1380 rc = ichac97ReadAudio(pThis, pStr mSt, cbElapsed, &cbTransferred);1490 rc = ichac97ReadAudio(pThis, pStream, cbElapsed, &cbTransferred); 1381 1491 if ( RT_SUCCESS(rc) 1382 1492 && cbTransferred) 1383 1493 { 1384 1494 Assert(cbElapsed >= cbTransferred); 1385 cbElapsed -= cbTransferred;1495 cbElapsed -= cbTransferred; 1386 1496 Assert((cbTransferred & 1) == 0); /* Else the following shift won't work */ 1387 pRegs->picb -= (cbTransferred >> 1); 1497 pRegs->picb -= (cbTransferred >> 1); /** @todo r=andy Assumes 16bit samples. */ 1388 1498 } 1389 1499 break; … … 1391 1501 1392 1502 default: 1393 AssertMsgFailed(("S ource %RU32 not supported\n", enmSrc));1503 AssertMsgFailed(("Stream #%RU8 not supported\n", pStream->u8Strm)); 1394 1504 rc = VERR_NOT_SUPPORTED; 1395 1505 break; 1396 1506 } 1397 1507 1398 LogFlowFunc(("pReg->picb=%#x, cbWrittenTotal=%RU32\n", pRegs->picb, cbWrittenTotal)); 1508 Log3Func(("PICB=%RU16 (%#x), cbTransferred=%RU32 (%zu samples), cbWrittenTotal=%RU32\n", 1509 pRegs->picb, pRegs->picb, cbTransferred, (cbTransferred >> 1), cbWrittenTotal)); 1399 1510 1400 1511 if (!pRegs->picb) … … 1409 1520 if (pRegs->civ == pRegs->lvi) 1410 1521 { 1411 Log FlowFunc(("Underrun civ (%RU8) == lvi (%RU8)\n", pRegs->civ, pRegs->lvi));1522 Log3Func(("Underrun civ (%RU8) == lvi (%RU8)\n", pRegs->civ, pRegs->lvi)); 1412 1523 new_sr |= SR_LVBCI | SR_DCH | SR_CELV; 1413 1524 pThis->bup_flag = (pRegs->bd.ctl_len & BD_BUP) ? BUP_LAST : 0; … … 1418 1529 { 1419 1530 pRegs->civ = pRegs->piv; 1420 pRegs->piv = (pRegs->piv + 1) % 32; 1421 ichac97StreamFetchBDLE(pThis, pStr mSt);1531 pRegs->piv = (pRegs->piv + 1) % 32; /** @todo r=andy Define for max BDLEs? */ 1532 ichac97StreamFetchBDLE(pThis, pStream); 1422 1533 } 1423 1534 1424 ichac97StreamUpdateStatus(pThis, pStr mSt, new_sr);1535 ichac97StreamUpdateStatus(pThis, pStream, new_sr); 1425 1536 } 1426 1537 … … 1447 1558 const uint32_t uPortIdx = Port - pThis->IOPortBase[1]; 1448 1559 1449 PAC97STREAM pStr mSt= ichac97GetStreamFromID(pThis, AC97_PORT2IDX(uPortIdx));1450 PAC97BMREGS pRegs = pStrmSt ? &pStrmSt->Regs : NULL;1560 PAC97STREAM pStream = ichac97GetStreamFromID(pThis, AC97_PORT2IDX(uPortIdx)); 1561 PAC97BMREGS pRegs = pStream ? &pStream->Regs : NULL; 1451 1562 1452 1563 switch (cbVal) … … 1519 1630 case PO_PICB: 1520 1631 case MC_PICB: 1521 /* Position in Current Buffer Register*/1632 /* Position in Current Buffer */ 1522 1633 *pu32Val = pRegs->picb; 1523 1634 LogFlowFunc(("PICB[%d] -> %#x\n", AC97_PORT2IDX(uPortIdx), *pu32Val)); … … 1597 1708 const uint32_t uPortIdx = Port - pThis->IOPortBase[1]; 1598 1709 1599 PAC97STREAM pStr mSt= ichac97GetStreamFromID(pThis, AC97_PORT2IDX(uPortIdx));1600 PAC97BMREGS pRegs = pStrmSt ? &pStrmSt->Regs : NULL;1710 PAC97STREAM pStream = ichac97GetStreamFromID(pThis, AC97_PORT2IDX(uPortIdx)); 1711 PAC97BMREGS pRegs = pStream ? &pStream->Regs : NULL; 1601 1712 1602 1713 switch (cbVal) … … 1616 1727 pRegs->piv = (pRegs->piv + 1) % 32; 1617 1728 1618 ichac97StreamFetchBDLE(pThis, pStr mSt);1729 ichac97StreamFetchBDLE(pThis, pStream); 1619 1730 } 1620 1731 pRegs->lvi = u32Val % 32; … … 1628 1739 if (u32Val & CR_RR) /* Busmaster reset */ 1629 1740 { 1630 ichac97StreamResetBMRegs(pThis, pStr mSt);1741 ichac97StreamResetBMRegs(pThis, pStream); 1631 1742 } 1632 1743 else … … 1635 1746 if (!(pRegs->cr & CR_RPBM)) 1636 1747 { 1637 ichac97StreamSetActive(pThis, pStr mSt, false /* fActive */);1748 ichac97StreamSetActive(pThis, pStream, false /* fActive */); 1638 1749 pRegs->sr |= SR_DCH; 1639 1750 } … … 1643 1754 pRegs->piv = (pRegs->piv + 1) % 32; 1644 1755 1645 ichac97StreamFetchBDLE(pThis, pStr mSt);1756 ichac97StreamFetchBDLE(pThis, pStream); 1646 1757 1647 1758 pRegs->sr &= ~SR_DCH; 1648 ichac97StreamSetActive(pThis, pStr mSt, true /* fActive */);1759 ichac97StreamSetActive(pThis, pStream, true /* fActive */); 1649 1760 } 1650 1761 } … … 1657 1768 /* Status Register */ 1658 1769 pRegs->sr |= u32Val & ~(SR_RO_MASK | SR_WCLEAR_MASK); 1659 ichac97StreamUpdateStatus(pThis, pStr mSt, pRegs->sr & ~(u32Val & SR_WCLEAR_MASK));1770 ichac97StreamUpdateStatus(pThis, pStream, pRegs->sr & ~(u32Val & SR_WCLEAR_MASK)); 1660 1771 LogFlowFunc(("SR[%d] <- %#x (sr %#x)\n", AC97_PORT2IDX(uPortIdx), u32Val, pRegs->sr)); 1661 1772 break; … … 1676 1787 /* Status Register */ 1677 1788 pRegs->sr |= u32Val & ~(SR_RO_MASK | SR_WCLEAR_MASK); 1678 ichac97StreamUpdateStatus(pThis, pStr mSt, pRegs->sr & ~(u32Val & SR_WCLEAR_MASK));1789 ichac97StreamUpdateStatus(pThis, pStream, pRegs->sr & ~(u32Val & SR_WCLEAR_MASK)); 1679 1790 LogFlowFunc(("SR[%d] <- %#x (sr %#x)\n", AC97_PORT2IDX(uPortIdx), u32Val, pRegs->sr)); 1680 1791 break; … … 1857 1968 } 1858 1969 else 1859 LogFlowFunc(("Attempt to set front DAC rate to %RU32, but VRA is not set\n", u32Val));1970 AssertMsgFailed(("Attempt to set front DAC rate to %RU32, but VRA is not set\n", u32Val)); 1860 1971 break; 1861 1972 case AC97_MIC_ADC_Rate: … … 1867 1978 } 1868 1979 else 1869 LogFlowFunc(("Attempt to set MIC ADC rate to %RU32, but VRM is not set\n", u32Val));1980 AssertMsgFailed(("Attempt to set MIC ADC rate to %RU32, but VRM is not set\n", u32Val)); 1870 1981 break; 1871 1982 case AC97_PCM_LR_ADC_Rate: … … 1877 1988 } 1878 1989 else 1879 LogFlowFunc(("Attempt to set LR ADC rate to %RU32, but VRA is not set\n", u32Val));1990 AssertMsgFailed(("Attempt to set LR ADC rate to %RU32, but VRA is not set\n", u32Val)); 1880 1991 break; 1881 1992 default: … … 1949 2060 1950 2061 #ifdef IN_RING3 1951 static int ichac97SaveStream(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PAC97STREAM pStr mSt)1952 { 1953 PAC97BMREGS pRegs = &pStr mSt->Regs;2062 static int ichac97SaveStream(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PAC97STREAM pStream) 2063 { 2064 PAC97BMREGS pRegs = &pStream->Regs; 1954 2065 1955 2066 SSMR3PutU32(pSSM, pRegs->bdbar); … … 2006 2117 } 2007 2118 2008 static int ichac97LoadStream(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PAC97STREAM pStr mSt)2009 { 2010 PAC97BMREGS pRegs = &pStr mSt->Regs;2119 static int ichac97LoadStream(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PAC97STREAM pStream) 2120 { 2121 PAC97BMREGS pRegs = &pStream->Regs; 2011 2122 2012 2123 SSMR3GetU32(pSSM, &pRegs->bdbar); … … 2064 2175 ichac97MixerGet(pThis, AC97_Headphone_Volume_Mute)); 2065 2176 2066 int rc; 2067 rc = ichac97StreamInit(pThis, &pThis->StrmStLineIn, PI_INDEX); 2068 AssertRC(rc); 2069 rc = ichac97StreamInit(pThis, &pThis->StrmStMicIn, MC_INDEX); 2070 AssertRC(rc); 2071 rc = ichac97StreamInit(pThis, &pThis->StrmStOut, PO_INDEX); 2177 int rc = ichac97StreamsInit(pThis); 2072 2178 AssertRC(rc); 2073 2179 … … 2101 2207 2102 2208 /** 2209 * Powers off the device. 2210 * 2211 * @param pDevIns Device instance to power off. 2212 */ 2213 static DECLCALLBACK(void) ichac97PowerOff(PPDMDEVINS pDevIns) 2214 { 2215 PAC97STATE pThis = PDMINS_2_DATA(pDevIns, PAC97STATE); 2216 2217 LogRel2(("AC97: Powering off ...\n")); 2218 2219 /** 2220 * Note: Destroy the mixer while powering off and *not* in ichac97Destruct, 2221 * giving the mixer the chance to release any references held to 2222 * PDM audio streams it maintains. 2223 */ 2224 if (pThis->pMixer) 2225 { 2226 AudioMixerDestroy(pThis->pMixer); 2227 pThis->pMixer = NULL; 2228 } 2229 } 2230 2231 2232 /** 2103 2233 * @interface_method_impl{PDMDEVREG,pfnReset} 2104 2234 * … … 2129 2259 * Stop any audio currently playing. 2130 2260 */ 2131 PAC97DRIVER pDrv; 2132 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 2133 { 2134 pDrv->pConnector->pfnEnableIn(pDrv->pConnector, pDrv->LineIn.pStrmIn, false /* Disable */); 2135 /* Ignore rc. */ 2136 pDrv->pConnector->pfnEnableIn(pDrv->pConnector, pDrv->MicIn.pStrmIn, false /* Disable */); 2137 /* Ditto. */ 2138 pDrv->pConnector->pfnEnableOut(pDrv->pConnector, pDrv->Out.pStrmOut, false /* Disable */); 2139 /* Ditto. */ 2140 } 2261 /* 2262 * Stop any audio currently playing and/or recording. 2263 */ 2264 AudioMixerSinkCtl(pThis->pSinkOutput, AUDMIXSINKCMD_DISABLE); 2265 AudioMixerSinkCtl(pThis->pSinkMicIn, AUDMIXSINKCMD_DISABLE); 2266 AudioMixerSinkCtl(pThis->pSinkLineIn, AUDMIXSINKCMD_DISABLE); 2141 2267 2142 2268 /* … … 2169 2295 } 2170 2296 2171 if (pThis->pMixer) 2172 { 2173 AudioMixerDestroy(pThis->pMixer); 2174 pThis->pMixer = NULL; 2175 } 2176 2177 if (pThis->pvReadWriteBuf) 2178 { 2179 RTMemFree(pThis->pvReadWriteBuf); 2180 pThis->pvReadWriteBuf = NULL; 2181 pThis->cbReadWriteBuf = 0; 2182 } 2297 ichac97StreamsDestroy(pThis); 2183 2298 2184 2299 LogFlowFuncLeave(); … … 2319 2434 #define RC_CHECK() if (RT_FAILURE(rc)) { AssertReleaseRC(rc); break; } 2320 2435 2321 int rc = VINF_SUCCESS;2436 int rc; 2322 2437 do 2323 2438 { … … 2379 2494 #ifndef VBOX_WITH_AUDIO_CALLBACKS 2380 2495 uint16_t uTimerHz; 2381 rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, 200 /* Hz*/);2496 rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, AC97_TIMER_HZ /* Default value, if not set. */); 2382 2497 if (RT_FAILURE(rc)) 2383 2498 return PDMDEV_SET_ERROR(pDevIns, rc, … … 2500 2615 streamCfg.uHz = 44100; 2501 2616 streamCfg.cChannels = 2; 2502 streamCfg.enmFormat = AUD_FMT_S16;2617 streamCfg.enmFormat = PDMAUDIOFMT_S16; 2503 2618 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS; 2504 2619 … … 2507 2622 2508 2623 /* Add all required audio sinks. */ 2509 rc = AudioMixerAddSink(pThis->pMixer, "[Playback] PCM Output", AUDMIXSINKDIR_OUTPUT, &pThis->pSinkOutput);2510 AssertRC(rc );2511 2512 rc = AudioMixerAddSink(pThis->pMixer, "[Recording] Line In", AUDMIXSINKDIR_INPUT, &pThis->pSinkLineIn);2513 AssertRC(rc );2514 2515 rc = AudioMixerAddSink(pThis->pMixer, "[Recording] Microphone In", AUDMIXSINKDIR_INPUT, &pThis->pSinkMicIn);2516 AssertRC(rc );2624 int rc2 = AudioMixerCreateSink(pThis->pMixer, "[Playback] PCM Output", AUDMIXSINKDIR_OUTPUT, &pThis->pSinkOutput); 2625 AssertRC(rc2); 2626 2627 rc2 = AudioMixerCreateSink(pThis->pMixer, "[Recording] Line In", AUDMIXSINKDIR_INPUT, &pThis->pSinkLineIn); 2628 AssertRC(rc2); 2629 2630 rc2 = AudioMixerCreateSink(pThis->pMixer, "[Recording] Microphone In", AUDMIXSINKDIR_INPUT, &pThis->pSinkMicIn); 2631 AssertRC(rc2); 2517 2632 } 2518 2633 } … … 2522 2637 if (RT_SUCCESS(rc)) 2523 2638 { 2524 rc = ichac97StreamInit(pThis, &pThis->StrmStLineIn, PI_INDEX); 2525 if (RT_FAILURE(rc)) 2526 return rc; 2527 rc = ichac97StreamInit(pThis, &pThis->StrmStMicIn, MC_INDEX); 2528 if (RT_FAILURE(rc)) 2529 return rc; 2530 rc = ichac97StreamInit(pThis, &pThis->StrmStOut, PO_INDEX); 2531 if (RT_FAILURE(rc)) 2532 return rc; 2639 ichac97StreamsInit(pThis); 2533 2640 2534 2641 PAC97DRIVER pDrv; … … 2545 2652 AssertPtr(pCon); 2546 2653 2547 bool fValidLineIn = pCon->pfnIsValidIn (pCon, pDrv->LineIn.pStrmIn);2548 bool fValidMicIn = pCon->pfnIsValidIn (pCon, pDrv->MicIn.pStrmIn);2549 bool fValidOut = pCon->pfnIsValidOut(pCon, pDrv->Out.pStrmOut);2654 bool fValidLineIn = AudioMixerStreamIsValid(pDrv->LineIn.pMixStrm); 2655 bool fValidMicIn = AudioMixerStreamIsValid(pDrv->MicIn.pMixStrm); 2656 bool fValidOut = AudioMixerStreamIsValid(pDrv->Out.pMixStrm); 2550 2657 2551 2658 if ( !fValidLineIn … … 2555 2662 LogRel(("AC97: Falling back to NULL backend (no sound audible)\n")); 2556 2663 2664 /* Destroy the streams before re-attaching the NULL driver. */ 2665 ichac97StreamsDestroy(pThis); 2666 2557 2667 ichac97Reset(pDevIns); 2558 2668 ichac97Reattach(pThis, pDrv, pDrv->uLUN, "NullAudio"); 2669 2670 ichac97StreamsInit(pThis); 2559 2671 2560 2672 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding", … … 2567 2679 2568 2680 PDMAUDIOBACKENDCFG backendCfg; 2569 int rc2 = pCon->pfnGetConfig uration(pCon, &backendCfg);2681 int rc2 = pCon->pfnGetConfig(pCon, &backendCfg); 2570 2682 if (RT_SUCCESS(rc2)) 2571 2683 { … … 2624 2736 } 2625 2737 } 2626 }2627 2628 if (RT_SUCCESS(rc))2629 {2630 pThis->cbReadWriteBuf = _4K; /** @todo Make this configurable. */2631 pThis->pvReadWriteBuf = (uint8_t *)RTMemAllocZ(pThis->cbReadWriteBuf);2632 if (!pThis->pvReadWriteBuf)2633 rc = VERR_NO_MEMORY;2634 2738 } 2635 2739 … … 2748 2852 NULL, 2749 2853 /* pfnPowerOff */ 2750 NULL,2854 ichac97PowerOff, 2751 2855 /* pfnSoftReset */ 2752 2856 NULL, -
trunk/src/VBox/Devices/Audio/DevIchHda.cpp
r60353 r60925 87 87 #define BIRD_THINKS_CORBRP_IS_MOSTLY_RO 88 88 89 /* Make sure that interleaving streams support is enabled if the 5.1 code 90 * is being used. */ 91 #ifdef VBOX_WITH_HDA_51_SURROUND 89 /* Make sure that interleaving streams support is enabled if the 5.1 code is being used. */ 90 #if defined (VBOX_WITH_HDA_51_SURROUND) && !defined(VBOX_WITH_HDA_INTERLEAVING_STREAMS_SUPPORT) 92 91 # define VBOX_WITH_HDA_INTERLEAVING_STREAMS_SUPPORT 93 92 #endif 94 93 95 94 /** 96 * At the moment we support 4 input + 4 output streams (for 7.1 support) max,97 * which is 12 in total.Bidirectional streams are currently *not* supported.95 * At the moment we support 4 input + 4 output streams max, which is 8 in total. 96 * Bidirectional streams are currently *not* supported. 98 97 * 99 98 * Note: When changing any of those values, be prepared for some saved state … … 143 142 */ 144 143 #define HDA_MAKE_GCAP(oss, iss, bss, bds, b64sup) \ 145 ( (((oss) & 0xF) << 12) \146 | (((iss) & 0xF) << 8) \147 | (((bss) & 0x F) << 3) \148 | (((bds) & 0x3) << 1) \144 ( (((oss) & 0xF) << 12) \ 145 | (((iss) & 0xF) << 8) \ 146 | (((bss) & 0x1F) << 3) \ 147 | (((bds) & 0x3) << 1) \ 149 148 | ((b64sup) & 1)) 150 149 … … 588 587 589 588 /** 589 * Structure for keeping an audio stream data mapping. 590 */ 591 typedef struct HDASTREAMMAPPING 592 { 593 /** The stream's layout. */ 594 PDMAUDIOSTREAMLAYOUT enmLayout; 595 /** Number of audio channels in this stream. */ 596 uint8_t cChannels; 597 /** Array audio channels. */ 598 R3PTRTYPE(PPDMAUDIOSTREAMCHANNEL) paChannels; 599 R3PTRTYPE(PRTCIRCBUF) pCircBuf; 600 } HDASTREAMMAPPING, *PHDASTREAMMAPPING; 601 602 /** 590 603 * Internal state of a HDA stream. 591 604 */ … … 594 607 /** Current BDLE to use. Wraps around to 0 if 595 608 * maximum (cBDLE) is reached. */ 596 uint16_t uCurBDLE;609 uint16_t uCurBDLE; 597 610 /** Stop indicator. */ 598 volatile bool fDoStop;611 volatile bool fDoStop; 599 612 /** Flag indicating whether this stream is in an 600 613 * active (operative) state or not. */ 601 volatile bool fActive;614 volatile bool fActive; 602 615 /** Flag indicating whether this stream currently is 603 616 * in reset mode and therefore not acccessible by the guest. */ 604 volatile bool fInReset;617 volatile bool fInReset; 605 618 /** Unused, padding. */ 606 bool fPadding;619 bool fPadding; 607 620 /** Mutex semaphore handle to serialize access. */ 608 RTSEMMUTEX hMtx;621 RTSEMMUTEX hMtx; 609 622 /** Event signalling that the stream's state has been changed. */ 610 RTSEMEVENT hStateChangedEvent; 623 RTSEMEVENT hStateChangedEvent; 624 /** This stream's data mapping. */ 625 HDASTREAMMAPPING Mapping; 611 626 /** Current BDLE (Buffer Descriptor List Entry). */ 612 HDABDLE BDLE;627 HDABDLE BDLE; 613 628 } HDASTREAMSTATE, *PHDASTREAMSTATE; 614 629 … … 659 674 } HDATAG, *PHDATAG; 660 675 661 typedef struct HDAINPUTSTREAM 662 { 663 /** Pointer to guest input stream. */ 664 R3PTRTYPE(PPDMAUDIOGSTSTRMIN) pGstStrm; 676 /** 677 * Structure defining an HDA mixer stream. 678 * This is being used together with an audio mixer instance. 679 */ 680 typedef struct HDAMIXERSTREAM 681 { 682 union 683 { 684 /** Desired playback destination (for an output stream). */ 685 PDMAUDIOPLAYBACKDEST Dest; 686 /** Desired recording source (for an input stream). */ 687 PDMAUDIORECSOURCE Source; 688 } DestSource; 689 uint8_t Padding1[4]; 665 690 /** Associated mixer handle. */ 666 R3PTRTYPE(PAUDMIXSTREAM) pMixStrm; 667 } HDAINPUTSTREAM, *PHDAINPUTSTREAM; 668 669 typedef struct HDAOUTPUTSTREAM 670 { 671 /** Pointer to guest output stream. */ 672 R3PTRTYPE(PPDMAUDIOGSTSTRMOUT) pGstStrm; 673 /** Associated mixer handle. */ 674 R3PTRTYPE(PAUDMIXSTREAM) pMixStrm; 675 } HDAOUTPUTSTREAM, *PHDAOUTPUTSTREAM; 691 R3PTRTYPE(PAUDMIXSTREAM) pMixStrm; 692 } HDAMIXERSTREAM, *PHDAMIXERSTREAM; 676 693 677 694 /** … … 701 718 /** Audio connector interface to the underlying host backend. */ 702 719 R3PTRTYPE(PPDMIAUDIOCONNECTOR) pConnector; 703 /** Stream for line input. */704 HDA INPUTSTREAM LineIn;720 /** Mixer stream for line input. */ 721 HDAMIXERSTREAM LineIn; 705 722 #ifdef VBOX_WITH_HDA_MIC_IN 706 /** Stream for mic input. */707 HDA INPUTSTREAM MicIn;708 #endif 709 /** Stream for front output. */710 HDA OUTPUTSTREAMFront;723 /** Mixer stream for mic input. */ 724 HDAMIXERSTREAM MicIn; 725 #endif 726 /** Mixer stream for front output. */ 727 HDAMIXERSTREAM Front; 711 728 #ifdef VBOX_WITH_HDA_51_SURROUND 712 /** Stream for center/LFE output. */713 HDA OUTPUTSTREAMCenterLFE;714 /** Stream for rear output. */715 HDA OUTPUTSTREAMRear;729 /** Mixer stream for center/LFE output. */ 730 HDAMIXERSTREAM CenterLFE; 731 /** Mixer stream for rear output. */ 732 HDAMIXERSTREAM Rear; 716 733 #endif 717 734 } HDADRIVER; … … 807 824 /** Padding for alignment. */ 808 825 uint8_t au8Padding2[7]; 809 #ifdef VBOX_WITH_HDA_INTERLEAVING_STREAMS_SUPPORT810 /** Circular buffer for interleaving streams support.811 * This is needed for extracting multiple channels out of a single HDA stream. */812 R3PTRTYPE(PRTCIRCBUF) pCircBuf;813 #endif814 826 } HDASTATE; 815 827 /** Pointer to the ICH Intel HD Audio Controller state. */ … … 853 865 static int hdaRegWriteRIRBSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value); 854 866 static int hdaRegWriteSTATESTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value); 855 static int hdaRegReadOUTPAY(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);856 static int hdaRegWriteOUTPAY(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);857 static int hdaRegReadOUTSTRMPAY(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);858 static int hdaRegWriteOUTSTRMPAY(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);859 867 static int hdaRegWriteIRS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value); 860 868 static int hdaRegReadIRS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value); … … 897 905 898 906 #ifdef IN_RING3 899 static int hdaBDLEFetch(PHDASTATE pThis, PHDABDLE pBDLE, uint64_t u64BaseDMA, uint16_t u16Entry); 900 DECLINLINE(void) hdaStreamUpdateLPIB(PHDASTATE pThis, PHDASTREAM pStrmSt, uint32_t u32LPIB); 907 static int hdaStreamMapInit(PHDASTREAMMAPPING pMapping, PPDMAUDIOSTREAMCFG pCfg); 908 static void hdaStreamMapDestroy(PHDASTREAMMAPPING pMapping); 909 static void hdaStreamMapReset(PHDASTREAMMAPPING pMapping); 910 #endif 911 912 #ifdef IN_RING3 913 static int hdaBDLEFetch(PHDASTATE pThis, PHDABDLE pBDLE, uint64_t u64BaseDMA, uint16_t u16Entry); 914 DECLINLINE(uint32_t) hdaStreamUpdateLPIB(PHDASTATE pThis, PHDASTREAM pStrmSt, uint32_t u32LPIB); 901 915 # ifdef LOG_ENABLED 902 static void 916 static void hdaBDLEDumpAll(PHDASTATE pThis, uint64_t u64BaseDMA, uint16_t cBDLE); 903 917 # endif 904 918 #endif 919 static int hdaProcessInterrupt(PHDASTATE pThis); 905 920 906 921 … … 936 951 { offset + 0xC, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16, hdaRegWriteSDLVI , HDA_REG_IDX_STRM(name, LVI) , #name " Last Valid Index" }, \ 937 952 /* Reserved: FIFO Watermark. ** @todo Document this! */ \ 938 { offset + 0xE, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16, hdaRegWrite SDFIFOW,HDA_REG_IDX_STRM(name, FIFOW), #name " FIFO Watermark" }, \953 { offset + 0xE, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16, hdaRegWriteU16, HDA_REG_IDX_STRM(name, FIFOW), #name " FIFO Watermark" }, \ 939 954 /* Offset 0x90 (SD0) */ \ 940 { offset + 0x10, 0x00002, 0x000000FF, 0x00000000, hdaRegReadU16, hdaRegWrite SDFIFOS,HDA_REG_IDX_STRM(name, FIFOS), #name " FIFO Size" }, \955 { offset + 0x10, 0x00002, 0x000000FF, 0x00000000, hdaRegReadU16, hdaRegWriteU16, HDA_REG_IDX_STRM(name, FIFOS), #name " FIFO Size" }, \ 941 956 /* Offset 0x92 (SD0) */ \ 942 957 { offset + 0x12, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16, hdaRegWriteSDFMT , HDA_REG_IDX_STRM(name, FMT) , #name " Stream Format" }, \ … … 980 995 { 0x00002, 0x00001, 0x000000FF, 0x00000000, hdaRegReadU8 , hdaRegWriteUnimpl , HDA_REG_IDX(VMIN) }, /* Minor Version */ 981 996 { 0x00003, 0x00001, 0x000000FF, 0x00000000, hdaRegReadU8 , hdaRegWriteUnimpl , HDA_REG_IDX(VMAJ) }, /* Major Version */ 982 { 0x00004, 0x00002, 0x0000FFFF, 0x00000000, hdaRegRead OUTPAY , hdaRegWriteOUTPAY, HDA_REG_IDX(OUTPAY) }, /* Output Payload Capabilities */997 { 0x00004, 0x00002, 0x0000FFFF, 0x00000000, hdaRegReadU16 , hdaRegWriteU16 , HDA_REG_IDX(OUTPAY) }, /* Output Payload Capabilities */ 983 998 { 0x00006, 0x00002, 0x0000FFFF, 0x00000000, hdaRegReadU16 , hdaRegWriteUnimpl , HDA_REG_IDX(INPAY) }, /* Input Payload Capabilities */ 984 999 { 0x00008, 0x00004, 0x00000103, 0x00000103, hdaRegReadU32 , hdaRegWriteGCTL , HDA_REG_IDX(GCTL) }, /* Global Control */ … … 986 1001 { 0x0000e, 0x00002, 0x00000007, 0x00000007, hdaRegReadU8 , hdaRegWriteSTATESTS , HDA_REG_IDX(STATESTS) }, /* State Change Status */ 987 1002 { 0x00010, 0x00002, 0xFFFFFFFF, 0x00000000, hdaRegReadUnimpl , hdaRegWriteUnimpl , HDA_REG_IDX(GSTS) }, /* Global Status */ 988 { 0x00018, 0x00002, 0x0000FFFF, 0x00000000, hdaRegRead OUTSTRMPAY , hdaRegWriteOUTSTRMPAY, HDA_REG_IDX(OUTSTRMPAY) }, /* Output Stream Payload Capability */1003 { 0x00018, 0x00002, 0x0000FFFF, 0x00000000, hdaRegReadU16 , hdaRegWriteU16 , HDA_REG_IDX(OUTSTRMPAY) }, /* Output Stream Payload Capability */ 989 1004 { 0x0001A, 0x00002, 0x0000FFFF, 0x00000000, hdaRegReadU16 , hdaRegWriteUnimpl , HDA_REG_IDX(INSTRMPAY) }, /* Input Stream Payload Capability */ 990 1005 { 0x00020, 0x00004, 0xC00000FF, 0xC00000FF, hdaRegReadU32 , hdaRegWriteU32 , HDA_REG_IDX(INTCTL) }, /* Interrupt Control */ 991 1006 { 0x00024, 0x00004, 0xC00000FF, 0x00000000, hdaRegReadINTSTS , hdaRegWriteUnimpl , HDA_REG_IDX(INTSTS) }, /* Interrupt Status */ 992 1007 { 0x00030, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadWALCLK , hdaRegWriteUnimpl , HDA_REG_IDX_LOCAL(WALCLK) }, /* Wall Clock Counter */ 993 { 0x00034, 0x00004, 0x000000FF, 0x000000FF, hdaRegRead SSYNC , hdaRegWriteSSYNC, HDA_REG_IDX(SSYNC) }, /* Stream Synchronization */1008 { 0x00034, 0x00004, 0x000000FF, 0x000000FF, hdaRegReadU32 , hdaRegWriteU32 , HDA_REG_IDX(SSYNC) }, /* Stream Synchronization */ 994 1009 { 0x00040, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteBase , HDA_REG_IDX(CORBLBASE) }, /* CORB Lower Base Address */ 995 1010 { 0x00044, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteBase , HDA_REG_IDX(CORBUBASE) }, /* CORB Upper Base Address */ … … 1011 1026 { 0x00070, 0x00004, 0xFFFFFFFF, 0xFFFFFF81, hdaRegReadU32 , hdaRegWriteBase , HDA_REG_IDX(DPLBASE) }, /* DMA Position Lower Base */ 1012 1027 { 0x00074, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteBase , HDA_REG_IDX(DPUBASE) }, /* DMA Position Upper Base */ 1013 /* 4 Input Stream Descriptors (ISD). */1028 /* 4 Serial Data In (SDI). */ 1014 1029 HDA_REG_MAP_DEF_STREAM(0, SD0), 1015 1030 HDA_REG_MAP_DEF_STREAM(1, SD1), 1016 1031 HDA_REG_MAP_DEF_STREAM(2, SD2), 1017 1032 HDA_REG_MAP_DEF_STREAM(3, SD3), 1018 /* 4 Output Stream Descriptors (OSD). */1033 /* 4 Serial Data Out (SDO). */ 1019 1034 HDA_REG_MAP_DEF_STREAM(4, SD4), 1020 1035 HDA_REG_MAP_DEF_STREAM(5, SD5), … … 1086 1101 1087 1102 #ifdef IN_RING3 1088 DECLINLINE( void) hdaStreamUpdateLPIB(PHDASTATE pThis, PHDASTREAM pStrmSt, uint32_t u32LPIB)1089 { 1090 AssertPtrReturn Void(pThis);1091 AssertPtrReturn Void(pStrmSt);1103 DECLINLINE(uint32_t) hdaStreamUpdateLPIB(PHDASTATE pThis, PHDASTREAM pStrmSt, uint32_t u32LPIB) 1104 { 1105 AssertPtrReturn(pThis, 0); 1106 AssertPtrReturn(pStrmSt, 0); 1092 1107 1093 1108 Assert(u32LPIB <= pStrmSt->u32CBL); … … 1107 1122 AssertRC(rc2); 1108 1123 } 1124 1125 return u32LPIB; 1109 1126 } 1110 1127 #endif … … 1169 1186 * @return IPRT status code. 1170 1187 */ 1171 DECLINLINE(int) hdaStreamGetNextBDLE(PHDASTATE pThis, PHDASTREAM pStr mSt)1188 DECLINLINE(int) hdaStreamGetNextBDLE(PHDASTATE pThis, PHDASTREAM pStream) 1172 1189 { 1173 1190 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1174 AssertPtrReturn(pStr mSt, VERR_INVALID_POINTER);1191 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1175 1192 1176 1193 NOREF(pThis); 1177 1194 1178 Assert(pStrmSt->State.uCurBDLE < pStrmSt->u16LVI + 1); 1195 Assert(pStream->State.uCurBDLE < pStream->u16LVI + 1); 1196 1197 LogFlowFuncEnter(); 1179 1198 1180 1199 #ifdef DEBUG 1181 uint32_t uOldBDLE = pStrmSt->State.uCurBDLE; 1182 #endif 1200 uint32_t uOldBDLE = pStream->State.uCurBDLE; 1201 #endif 1202 1203 PHDABDLE pBDLE = &pStream->State.BDLE; 1183 1204 1184 1205 /* … … 1186 1207 * if we reached the end of the Buffer Descriptor List (BDL). 1187 1208 */ 1188 pStrmSt->State.uCurBDLE++; 1189 if (pStrmSt->State.uCurBDLE == pStrmSt->u16LVI + 1) 1190 { 1191 pStrmSt->State.uCurBDLE = 0; 1192 1193 hdaStreamUpdateLPIB(pThis, pStrmSt, 0); 1194 } 1195 1196 Assert(pStrmSt->State.uCurBDLE < pStrmSt->u16LVI + 1); 1197 1198 int rc = hdaBDLEFetch(pThis, &pStrmSt->State.BDLE, pStrmSt->u64BDLBase, pStrmSt->State.uCurBDLE); 1209 pStream->State.uCurBDLE++; 1210 if (pStream->State.uCurBDLE == pStream->u16LVI + 1) 1211 { 1212 pStream->State.uCurBDLE = 0; 1213 1214 hdaStreamUpdateLPIB(pThis, pStream, 0); 1215 } 1216 1217 Assert(pStream->State.uCurBDLE < pStream->u16LVI + 1); 1218 1219 /* Fetch the next BDLE entry. */ 1220 int rc = hdaBDLEFetch(pThis, pBDLE, pStream->u64BDLBase, pStream->State.uCurBDLE); 1199 1221 1200 1222 #ifdef DEBUG 1201 1223 LogFlowFunc(("[SD%RU8]: uOldBDLE=%RU16, uCurBDLE=%RU16, LVI=%RU32, rc=%Rrc, %R[bdle]\n", 1202 pStrmSt->u8SD, uOldBDLE, pStrmSt->State.uCurBDLE, pStrmSt->u16LVI, rc, &pStrmSt->State.BDLE)); 1203 #endif 1224 pStream->u8SD, uOldBDLE, pStream->State.uCurBDLE, pStream->u16LVI, rc, pBDLE)); 1225 #endif 1226 1204 1227 return rc; 1205 1228 } 1206 1229 #endif /* IN_RING3 */ 1230 1231 /** 1232 * Returns the audio direction of a specified stream descriptor. 1233 * 1234 * The register layout specifies that input streams (SDI) come first, 1235 * followed by the output streams (SDO). So every stream ID below HDA_MAX_SDI 1236 * is an input stream, whereas everything >= HDA_MAX_SDI is an output stream. 1237 * 1238 * Note: SDnFMT register does not provide that information, so we have to judge 1239 * for ourselves. 1240 * 1241 * @return Audio direction. 1242 */ 1243 DECLINLINE(PDMAUDIODIR) hdaGetDirFromSD(uint8_t uSD) 1244 { 1245 AssertReturn(uSD <= HDA_MAX_STREAMS, PDMAUDIODIR_UNKNOWN); 1246 1247 if (uSD < HDA_MAX_SDI) 1248 return PDMAUDIODIR_IN; 1249 1250 return PDMAUDIODIR_OUT; 1251 } 1207 1252 1208 1253 DECLINLINE(PHDASTREAM) hdaStreamFromSD(PHDASTATE pThis, uint8_t uSD) … … 1239 1284 && (SDSTS(pThis, num) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS))) 1240 1285 1241 bool fIrq = false;1286 uint8_t uLevel = 0; 1242 1287 1243 1288 /** @todo Optimize IRQ handling. */ … … 1248 1293 || HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RIRBOIS) 1249 1294 || (HDA_REG(pThis, STATESTS) & HDA_REG(pThis, WAKEEN)))) 1250 fIrq = true;1295 uLevel = 1; 1251 1296 1252 1297 if ( IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 0) … … 1259 1304 || IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 7)) 1260 1305 { 1261 fIrq = true;1306 uLevel = 1; 1262 1307 } 1263 1308 1264 1309 if (HDA_REG_FLAG_VALUE(pThis, INTCTL, GIE)) 1265 1310 { 1266 Log3Func((" %s\n", fIrq ? "Asserted" : "Deasserted"));1267 PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0 , fIrq);1311 Log3Func(("Level=%d\n", uLevel)); 1312 PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0 , uLevel); 1268 1313 } 1269 1314 … … 1442 1487 static int hdaCORBCmdProcess(PHDASTATE pThis) 1443 1488 { 1444 PFNHDACODECVERBPROCESSOR pfn = (PFNHDACODECVERBPROCESSOR)NULL;1445 1446 1489 int rc = hdaCmdSync(pThis, true); 1447 1490 if (RT_FAILURE(rc)) … … 1453 1496 1454 1497 Assert((corbWp != corbRp)); 1455 Log FlowFunc(("CORB(RP:%x, WP:%x) RIRBWP:%x\n", HDA_REG(pThis, CORBRP), HDA_REG(pThis, CORBWP), HDA_REG(pThis, RIRBWP)));1498 Log3Func(("CORB(RP:%x, WP:%x) RIRBWP:%x\n", HDA_REG(pThis, CORBRP), HDA_REG(pThis, CORBWP), HDA_REG(pThis, RIRBWP))); 1456 1499 1457 1500 while (corbRp != corbWp) 1458 1501 { 1459 uint32_t cmd; 1460 uint64_t resp; 1461 pfn = NULL; 1462 corbRp++; 1463 cmd = pThis->pu32CorbBuf[corbRp]; 1464 1465 rc = pThis->pCodec->pfnLookup(pThis->pCodec, HDA_CODEC_CMD(cmd, 0 /* Codec index */), &pfn); 1466 if (RT_SUCCESS(rc)) 1467 { 1468 AssertPtr(pfn); 1469 rc = pfn(pThis->pCodec, HDA_CODEC_CMD(cmd, 0 /* LUN */), &resp); 1470 } 1471 1472 if (RT_FAILURE(rc)) 1473 AssertRCReturn(rc, rc); 1502 uint64_t uResp; 1503 uint32_t uCmd = pThis->pu32CorbBuf[++corbRp]; 1504 1505 int rc2 = pThis->pCodec->pfnLookup(pThis->pCodec, HDA_CODEC_CMD(uCmd, 0 /* Codec index */), &uResp); 1506 if (RT_FAILURE(rc2)) 1507 LogFunc(("Codec lookup failed with rc=%Rrc\n", rc2)); 1508 1474 1509 (rirbWp)++; 1475 1510 1476 LogFunc(("verb:%08x->%016lx\n", cmd, resp)); 1477 if ( (resp & CODEC_RESPONSE_UNSOLICITED) 1511 if ( (uResp & CODEC_RESPONSE_UNSOLICITED) 1478 1512 && !HDA_REG_FLAG_VALUE(pThis, GCTL, UR)) 1479 1513 { 1480 LogFunc((" unexpected unsolicited response.\n"));1514 LogFunc(("Unexpected unsolicited response\n")); 1481 1515 HDA_REG(pThis, CORBRP) = corbRp; 1482 1516 return rc; 1483 1517 } 1484 1518 1485 pThis->pu64RirbBuf[rirbWp] = resp;1519 pThis->pu64RirbBuf[rirbWp] = uResp; 1486 1520 1487 1521 pThis->u8RespIntCnt++; … … 1489 1523 break; 1490 1524 } 1525 1491 1526 HDA_REG(pThis, CORBRP) = corbRp; 1492 1527 HDA_REG(pThis, RIRBWP) = rirbWp; 1528 1493 1529 rc = hdaCmdSync(pThis, false); 1494 LogFunc(("CORB(RP:%x, WP:%x) RIRBWP:%x\n", HDA_REG(pThis, CORBRP), 1495 HDA_REG(pThis, CORBWP), HDA_REG(pThis, RIRBWP))); 1530 1531 Log3Func(("CORB(RP:%x, WP:%x) RIRBWP:%x\n", HDA_REG(pThis, CORBRP), HDA_REG(pThis, CORBWP), HDA_REG(pThis, RIRBWP))); 1532 1496 1533 if (HDA_REG_FLAG_VALUE(pThis, RIRBCTL, RIC)) 1497 1534 { … … 1501 1538 rc = hdaProcessInterrupt(pThis); 1502 1539 } 1540 1503 1541 if (RT_FAILURE(rc)) 1504 1542 AssertRCReturn(rc, rc); … … 1533 1571 AssertPtrReturnVoid(pStrmSt); 1534 1572 1535 LogFlowFunc(("[SD%RU8]: Destroy \n", pStrmSt->u8SD));1573 LogFlowFunc(("[SD%RU8]: Destroying ...\n", pStrmSt->u8SD)); 1536 1574 1537 1575 int rc2 = hdaStreamStop(pStrmSt); 1538 1576 AssertRC(rc2); 1577 1578 hdaStreamMapDestroy(&pStrmSt->State.Mapping); 1539 1579 1540 1580 if (pStrmSt->State.hMtx != NIL_RTSEMMUTEX) … … 1555 1595 } 1556 1596 1557 static int hdaStreamInit(PHDASTATE pThis, PHDASTREAM pStr mSt, uint8_t u8SD)1597 static int hdaStreamInit(PHDASTATE pThis, PHDASTREAM pStream, uint8_t u8SD) 1558 1598 { 1559 1599 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1560 AssertPtrReturn(pStrmSt, VERR_INVALID_POINTER); 1561 1562 pStrmSt->u8SD = u8SD; 1563 pStrmSt->u64BDLBase = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, pStrmSt->u8SD), 1564 HDA_STREAM_REG(pThis, BDPU, pStrmSt->u8SD)); 1565 pStrmSt->u16LVI = HDA_STREAM_REG(pThis, LVI, pStrmSt->u8SD); 1566 pStrmSt->u32CBL = HDA_STREAM_REG(pThis, CBL, pStrmSt->u8SD); 1567 pStrmSt->u16FIFOS = hdaSDFIFOSToBytes(HDA_STREAM_REG(pThis, FIFOS, pStrmSt->u8SD)); 1568 1569 RT_ZERO(pStrmSt->State.BDLE); 1570 pStrmSt->State.uCurBDLE = 0; 1600 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1601 1602 pStream->u8SD = u8SD; 1603 pStream->u64BDLBase = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, pStream->u8SD), 1604 HDA_STREAM_REG(pThis, BDPU, pStream->u8SD)); 1605 pStream->u16LVI = HDA_STREAM_REG(pThis, LVI, pStream->u8SD); 1606 pStream->u32CBL = HDA_STREAM_REG(pThis, CBL, pStream->u8SD); 1607 pStream->u16FIFOS = hdaSDFIFOSToBytes(HDA_STREAM_REG(pThis, FIFOS, pStream->u8SD)); 1608 1609 RT_ZERO(pStream->State.BDLE); 1610 pStream->State.uCurBDLE = 0; 1611 1612 hdaStreamMapReset(&pStream->State.Mapping); 1571 1613 1572 1614 LogFlowFunc(("[SD%RU8]: DMA @ 0x%x (%RU32 bytes), LVI=%RU16, FIFOS=%RU16\n", 1573 pStr mSt->u8SD, pStrmSt->u64BDLBase, pStrmSt->u32CBL, pStrmSt->u16LVI, pStrmSt->u16FIFOS));1615 pStream->u8SD, pStream->u64BDLBase, pStream->u32CBL, pStream->u16LVI, pStream->u16FIFOS)); 1574 1616 1575 1617 #ifdef DEBUG 1576 uint64_t u64BaseDMA = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, pStr mSt->u8SD),1577 HDA_STREAM_REG(pThis, BDPU, pStr mSt->u8SD));1578 uint16_t u16LVI = HDA_STREAM_REG(pThis, LVI, pStr mSt->u8SD);1579 uint32_t u32CBL = HDA_STREAM_REG(pThis, CBL, pStr mSt->u8SD);1618 uint64_t u64BaseDMA = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, pStream->u8SD), 1619 HDA_STREAM_REG(pThis, BDPU, pStream->u8SD)); 1620 uint16_t u16LVI = HDA_STREAM_REG(pThis, LVI, pStream->u8SD); 1621 uint32_t u32CBL = HDA_STREAM_REG(pThis, CBL, pStream->u8SD); 1580 1622 1581 1623 LogFlowFunc(("\t-> DMA @ 0x%x, LVI=%RU16, CBL=%RU32\n", u64BaseDMA, u16LVI, u32CBL)); … … 1587 1629 } 1588 1630 1589 static void hdaStreamReset(PHDASTATE pThis, PHDASTREAM pStrmSt , uint8_t u8Strm)1631 static void hdaStreamReset(PHDASTATE pThis, PHDASTREAM pStrmSt) 1590 1632 { 1591 1633 AssertPtrReturnVoid(pThis); 1592 1634 AssertPtrReturnVoid(pStrmSt); 1593 AssertReturnVoid(u8Strm <= HDA_MAX_STREAMS); 1635 1636 const uint8_t uSD = pStrmSt->u8SD; 1594 1637 1595 1638 #ifdef VBOX_STRICT 1596 AssertReleaseMsg(!RT_BOOL(HDA_STREAM_REG(pThis, CTL, u8Strm) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)), 1597 ("[SD%RU8] Cannot reset stream while in running state\n", u8Strm)); 1598 #endif 1639 AssertReleaseMsg(!RT_BOOL(HDA_STREAM_REG(pThis, CTL, uSD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)), 1640 ("[SD%RU8] Cannot reset stream while in running state\n", uSD)); 1641 #endif 1642 1643 LogFunc(("[SD%RU8]: Reset\n", uSD)); 1599 1644 1600 1645 /* … … 1613 1658 * Second, initialize the registers. 1614 1659 */ 1615 HDA_STREAM_REG(pThis, STS, u 8Strm) = 0;1660 HDA_STREAM_REG(pThis, STS, uSD) = HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY); 1616 1661 /* According to the ICH6 datasheet, 0x40000 is the default value for stream descriptor register 23:20 1617 1662 * bits are reserved for stream number 18.2.33, resets SDnCTL except SRST bit. */ 1618 HDA_STREAM_REG(pThis, CTL, u 8Strm) = 0x40000 | (HDA_STREAM_REG(pThis, CTL, u8Strm) & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST));1663 HDA_STREAM_REG(pThis, CTL, uSD) = 0x40000 | (HDA_STREAM_REG(pThis, CTL, uSD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST)); 1619 1664 /* ICH6 defines default values (0x77 for input and 0xBF for output descriptors) of FIFO size. 18.2.39. */ 1620 HDA_STREAM_REG(pThis, FIFOS, u 8Strm) = u8Strm < 4? HDA_SDINFIFO_120B : HDA_SDONFIFO_192B;1665 HDA_STREAM_REG(pThis, FIFOS, uSD) = hdaGetDirFromSD(uSD) == PDMAUDIODIR_IN ? HDA_SDINFIFO_120B : HDA_SDONFIFO_192B; 1621 1666 /* See 18.2.38: Always defaults to 0x4 (32 bytes). */ 1622 HDA_STREAM_REG(pThis, FIFOW, u8Strm) = HDA_SDFIFOW_32B; 1623 HDA_STREAM_REG(pThis, LPIB, u8Strm) = 0; 1624 HDA_STREAM_REG(pThis, CBL, u8Strm) = 0; 1625 HDA_STREAM_REG(pThis, LVI, u8Strm) = 0; 1626 HDA_STREAM_REG(pThis, FMT, u8Strm) = HDA_SDFMT_MAKE(HDA_SDFMT_TYPE_PCM, HDA_SDFMT_BASE_44KHZ, 1627 HDA_SDFMT_MULT_1X, HDA_SDFMT_DIV_1X, HDA_SDFMT_16_BIT, 1628 HDA_SDFMT_CHAN_STEREO); 1629 HDA_STREAM_REG(pThis, BDPU, u8Strm) = 0; 1630 HDA_STREAM_REG(pThis, BDPL, u8Strm) = 0; 1631 1632 /* 1633 * Third, match the internal state to the just set registers. 1634 */ 1635 pStrmSt->u8SD = u8Strm; 1636 pStrmSt->u64BDLBase = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, u8Strm), 1637 HDA_STREAM_REG(pThis, BDPU, u8Strm)); 1638 pStrmSt->u32CBL = HDA_STREAM_REG(pThis, CBL, u8Strm); 1639 pStrmSt->u16FIFOS = HDA_STREAM_REG(pThis, FIFOS, u8Strm); 1640 pStrmSt->u16FMT = HDA_STREAM_REG(pThis, FMT, u8Strm); 1641 pStrmSt->u16LVI = HDA_STREAM_REG(pThis, LVI, u8Strm); 1642 1643 LogFunc(("[SD%RU8]: Reset\n", u8Strm)); 1667 HDA_STREAM_REG(pThis, FIFOW, uSD) = HDA_SDFIFOW_32B; 1668 HDA_STREAM_REG(pThis, LPIB, uSD) = 0; 1669 HDA_STREAM_REG(pThis, CBL, uSD) = 0; 1670 HDA_STREAM_REG(pThis, LVI, uSD) = 0; 1671 HDA_STREAM_REG(pThis, FMT, uSD) = HDA_SDFMT_MAKE(HDA_SDFMT_TYPE_PCM, HDA_SDFMT_BASE_44KHZ, 1672 HDA_SDFMT_MULT_1X, HDA_SDFMT_DIV_1X, HDA_SDFMT_16_BIT, 1673 HDA_SDFMT_CHAN_STEREO); 1674 HDA_STREAM_REG(pThis, BDPU, uSD) = 0; 1675 HDA_STREAM_REG(pThis, BDPL, uSD) = 0; 1676 1677 int rc2 = hdaStreamInit(pThis, pStrmSt, uSD); 1678 AssertRC(rc2); 1679 1680 /* Report that we're done resetting this stream. */ 1681 HDA_STREAM_REG(pThis, CTL, uSD) = 0; 1644 1682 1645 1683 /* Exit reset state. */ … … 1692 1730 } 1693 1731 1732 static int hdaStreamChannelExtract(PPDMAUDIOSTREAMCHANNEL pChan, const void *pvBuf, size_t cbBuf) 1733 { 1734 AssertPtrReturn(pChan, VERR_INVALID_POINTER); 1735 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 1736 AssertReturn(cbBuf, VERR_INVALID_PARAMETER); 1737 1738 AssertRelease(pChan->cbOff <= cbBuf); 1739 1740 const uint8_t *pu8Buf = (const uint8_t *)pvBuf; 1741 1742 size_t cbSrc = cbBuf - pChan->cbOff; 1743 const uint8_t *pvSrc = &pu8Buf[pChan->cbOff]; 1744 1745 size_t cbDst; 1746 uint8_t *pvDst; 1747 RTCircBufAcquireWriteBlock(pChan->Data.pCircBuf, cbBuf, (void **)&pvDst, &cbDst); 1748 1749 cbSrc = RT_MIN(cbSrc, cbDst); 1750 1751 while (cbSrc) 1752 { 1753 AssertBreak(cbDst >= cbSrc); 1754 1755 /* Enough data for at least one next frame? */ 1756 if (cbSrc < pChan->cbFrame) 1757 break; 1758 1759 memcpy(pvDst, pvSrc, pChan->cbFrame); 1760 1761 /* Advance to next channel frame in stream. */ 1762 pvSrc += pChan->cbStep; 1763 Assert(cbSrc >= pChan->cbStep); 1764 cbSrc -= pChan->cbStep; 1765 1766 /* Advance destination by one frame. */ 1767 pvDst += pChan->cbFrame; 1768 Assert(cbDst >= pChan->cbFrame); 1769 cbDst -= pChan->cbFrame; 1770 1771 /* Adjust offset. */ 1772 pChan->cbOff += pChan->cbFrame; 1773 } 1774 1775 RTCircBufReleaseWriteBlock(pChan->Data.pCircBuf, cbDst); 1776 1777 return VINF_SUCCESS; 1778 } 1779 1780 static int hdaStreamChannelAdvance(PPDMAUDIOSTREAMCHANNEL pChan, size_t cbAdv) 1781 { 1782 AssertPtrReturn(pChan, VERR_INVALID_POINTER); 1783 1784 if (!cbAdv) 1785 return VINF_SUCCESS; 1786 1787 return VINF_SUCCESS; 1788 } 1789 1790 static int hdaStreamChannelDataInit(PPDMAUDIOSTREAMCHANNELDATA pChanData, uint32_t fFlags) 1791 { 1792 int rc = RTCircBufCreate(&pChanData->pCircBuf, 256); /** @todo Make this configurable? */ 1793 if (RT_SUCCESS(rc)) 1794 { 1795 pChanData->fFlags = fFlags; 1796 } 1797 1798 return rc; 1799 } 1800 1801 /** 1802 * Frees a stream channel data block again. 1803 * 1804 * @param pChanData Pointer to channel data to free. 1805 */ 1806 static void hdaStreamChannelDataDestroy(PPDMAUDIOSTREAMCHANNELDATA pChanData) 1807 { 1808 if (!pChanData) 1809 return; 1810 1811 if (pChanData->pCircBuf) 1812 { 1813 RTCircBufDestroy(pChanData->pCircBuf); 1814 pChanData->pCircBuf = NULL; 1815 } 1816 1817 pChanData->fFlags = PDMAUDIOSTREAMCHANNELDATA_FLAG_NONE; 1818 } 1819 1820 static int hdaStreamChannelAcquireData(PPDMAUDIOSTREAMCHANNELDATA pChanData, void *pvData, size_t *pcbData) 1821 { 1822 AssertPtrReturn(pChanData, VERR_INVALID_POINTER); 1823 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 1824 AssertPtrReturn(pcbData, VERR_INVALID_POINTER); 1825 1826 RTCircBufAcquireReadBlock(pChanData->pCircBuf, 256 /** @todo Make this configurarble? */, &pvData, &pChanData->cbAcq); 1827 1828 *pcbData = pChanData->cbAcq; 1829 return VINF_SUCCESS; 1830 } 1831 1832 static int hdaStreamChannelReleaseData(PPDMAUDIOSTREAMCHANNELDATA pChanData) 1833 { 1834 AssertPtrReturn(pChanData, VERR_INVALID_POINTER); 1835 RTCircBufReleaseReadBlock(pChanData->pCircBuf, pChanData->cbAcq); 1836 1837 return VINF_SUCCESS; 1838 } 1839 1694 1840 static int hdaStreamWaitForStateChange(PHDASTREAM pStrmSt, RTMSINTERVAL msTimeout) 1695 1841 { … … 1821 1967 } 1822 1968 1823 static int hdaRegReadOUTPAY(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)1824 {1825 uint16_t u16OUTSTRMPAY = HDA_REG(pThis, OUTPAY);1826 LogFlowFunc(("%RU16\n", u16OUTSTRMPAY));1827 1828 if (pu32Value)1829 *pu32Value = u16OUTSTRMPAY;1830 return VINF_SUCCESS;1831 }1832 1833 static int hdaRegWriteOUTPAY(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)1834 {1835 LogFlowFunc(("%RU16\n", (uint16_t)u32Value));1836 return hdaRegWriteU16(pThis, iReg, u32Value);1837 }1838 1839 static int hdaRegReadOUTSTRMPAY(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)1840 {1841 uint16_t u16OUTSTRMPAY = HDA_REG(pThis, OUTSTRMPAY);1842 LogFlowFunc(("%RU16\n", u16OUTSTRMPAY));1843 1844 if (pu32Value)1845 *pu32Value = u16OUTSTRMPAY;1846 return VINF_SUCCESS;1847 }1848 1849 static int hdaRegWriteOUTSTRMPAY(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)1850 {1851 LogFlowFunc(("%RU16\n", (uint16_t)u32Value));1852 return hdaRegWriteU16(pThis, iReg, u32Value);1853 }1854 1855 1969 static int hdaRegReadINTSTS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value) 1856 1970 { … … 1864 1978 } 1865 1979 1866 for (uint8_t i = 0; i < HDA_MAX_STREAMS; i++) 1867 { 1868 const uint32_t u32STS = HDA_STREAM_REG(pThis, STS, i); 1869 bool fReport = (u32STS & HDA_REG_FIELD_FLAG_MASK(SDSTS, DE)) 1870 || (u32STS & HDA_REG_FIELD_FLAG_MASK(SDSTS, FE)) 1871 || (u32STS & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)); 1872 v |= fReport ? RT_BIT(i) : 0; 1873 } 1874 1875 v |= v ? RT_BIT(31) : 0; 1876 1877 if (pu32Value) 1878 *pu32Value = v; 1879 1980 #define HDA_MARK_STREAM(x) \ 1981 if (/* Descriptor Error */ \ 1982 (SDSTS((pThis), x) & HDA_REG_FIELD_FLAG_MASK(SDSTS, DE)) \ 1983 /* FIFO Error */ \ 1984 || (SDSTS((pThis), x) & HDA_REG_FIELD_FLAG_MASK(SDSTS, FE)) \ 1985 /* Buffer Completion Interrupt Status */ \ 1986 || (SDSTS((pThis), x) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS))) \ 1987 { \ 1988 Log3Func(("[SD%RU8] BCIS: Marked\n", x)); \ 1989 v |= RT_BIT(x); \ 1990 } 1991 1992 HDA_MARK_STREAM(0); /* SD0: Input. */ 1993 HDA_MARK_STREAM(4); /* SD4: Output. */ 1994 1995 #undef HDA_MARK_STREAM 1996 1997 /* "OR" bit of all interrupt status bits. */ 1998 if (v) 1999 v |= RT_BIT(31); 2000 2001 *pu32Value = v; 1880 2002 return VINF_SUCCESS; 1881 2003 } … … 2011 2133 bool fInReset = RT_BOOL(HDA_REG_IND(pThis, iReg) & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST)); 2012 2134 2135 uint32_t uVal = HDA_REG_IND(pThis, iReg); 2136 LogFunc(("uVal=%RU32 vs u32Value=%RU32\n", uVal, u32Value)); 2137 2013 2138 if (HDA_REG_IND(pThis, iReg) == u32Value) /* Value already set? */ 2014 2139 return VINF_SUCCESS; … … 2075 2200 2076 2201 LogFunc(("[SD%RU8]: Guest initiated enter to stream reset\n", pStrmSt->u8SD)); 2077 hdaStreamReset(pThis, pStrmSt , pStrmSt->u8SD);2202 hdaStreamReset(pThis, pStrmSt); 2078 2203 #endif 2079 2204 } … … 2089 2214 LogFunc(("[SD%RU8]: fRun=%RTbool\n", pStrmSt->u8SD, fRun)); 2090 2215 2091 Assert(pStrmSt->u8SD < HDA_MAX_STREAMS); 2092 2093 /* 2094 * The register layout specifies that input streams (SDI) come first, 2095 * followed by the output streams (SDO). So every stream ID below HDA_MAX_SDI 2096 * is an input stream, whereas everything >= HDA_MAX_SDI is an output stream. 2097 */ 2098 PHDADRIVER pDrv; 2099 if (pStrmSt->u8SD < HDA_MAX_SDI) 2216 AUDMIXSINKCMD enmCmd = fRun 2217 ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE; 2218 2219 if (hdaGetDirFromSD(uSD) == PDMAUDIODIR_IN) 2100 2220 { 2101 2221 # ifdef VBOX_WITH_HDA_MIC_IN 2102 # error "Implement mic-in support!" 2103 # else 2104 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node) 2105 pDrv->pConnector->pfnEnableIn(pDrv->pConnector, 2106 pDrv->LineIn.pGstStrm, fRun); 2222 AudioMixerSinkCtl(pThis->pSinkMicIn, enmCmd); 2107 2223 # endif 2224 AudioMixerSinkCtl(pThis->pSinkLineIn, enmCmd); 2108 2225 } 2109 2226 else 2110 2227 { 2111 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node) 2112 { 2113 pDrv->pConnector->pfnEnableOut(pDrv->pConnector, pDrv->Front.pGstStrm, fRun); 2228 AudioMixerSinkCtl(pThis->pSinkFront, enmCmd); 2114 2229 # ifdef VBOX_WITH_HDA_51_SURROUND 2115 pDrv->pConnector->pfnEnableOut(pDrv->pConnector, pDrv->CenterLFE.pGstStrm, fRun);2116 pDrv->pConnector->pfnEnableOut(pDrv->pConnector, pDrv->Rear.pGstStrm, fRun);2230 AudioMixerSinkCtl(pThis->pSinkCenterLFE, enmCmd); 2231 AudioMixerSinkCtl(pThis->pSinkRear, enmCmd); 2117 2232 # endif 2118 } 2233 } 2234 2235 if (fRun) 2236 { 2237 /* (Re-)Fetch the current BDLE entry. */ 2238 rc2 = hdaBDLEFetch(pThis, &pStrmSt->State.BDLE, pStrmSt->u64BDLBase, pStrmSt->State.uCurBDLE); 2239 AssertRC(rc2); 2119 2240 } 2120 2241 } … … 2124 2245 #endif /* IN_RING3 */ 2125 2246 } 2247 2248 /* Make sure to handle interrupts here as well. */ 2249 hdaProcessInterrupt(pThis); 2126 2250 2127 2251 #ifdef IN_RING3 … … 2142 2266 2143 2267 uint32_t v = HDA_REG_IND(pThis, iReg); 2268 /* Clear (zero) FIFOE and DESE bits when writing 1 to it. */ 2144 2269 v &= ~(u32Value & v); 2270 2145 2271 HDA_REG_IND(pThis, iReg) = v; 2146 2272 … … 2211 2337 return VINF_SUCCESS; 2212 2338 2339 uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, FIFOS, iReg); 2213 2340 /** @todo Only allow updating FIFOS if RUN bit is 0? */ 2214 2341 uint32_t u32FIFOS = 0; 2215 2342 2216 /** @todo Check if this is a SDI and deny writes to this. */ 2343 if (hdaGetDirFromSD(uSD) == PDMAUDIODIR_IN) /* FIFOS for input streams is read-only. */ 2344 { 2345 LogRel(("HDA: Warning: Guest tried to write read-only FIFOS for input stream #%RU8, skipping\n", uSD)); 2346 AssertFailed(); 2347 return VINF_SUCCESS; 2348 } 2349 2217 2350 switch(u32Value) 2218 2351 { … … 2229 2362 /* Fall through is intentional. */ 2230 2363 default: 2364 LogRel(("HDA: Warning: Guest tried write unsupported FIFOS (0x%x) to input stream #%RU8, defaulting to 192 bytes\n", 2365 u32Value, uSD)); 2231 2366 u32FIFOS = HDA_SDONFIFO_192B; 2367 AssertFailed(); 2232 2368 break; 2233 2369 } … … 2246 2382 2247 2383 #ifdef IN_RING3 2248 static int hdaSDFMTToStrmCfg(uint32_t u32SDFMT, PPDMAUDIOSTREAMCFG p Cfg)2249 { 2250 AssertPtrReturn(p Cfg, VERR_INVALID_POINTER);2384 static int hdaSDFMTToStrmCfg(uint32_t u32SDFMT, PPDMAUDIOSTREAMCFG pStrmCfg) 2385 { 2386 AssertPtrReturn(pStrmCfg, VERR_INVALID_POINTER); 2251 2387 2252 2388 # define EXTRACT_VALUE(v, mask, shift) ((v & ((mask) << (shift))) >> (shift)) … … 2287 2423 } 2288 2424 2289 PDMAUDIOFMT enmFmt = AUD_FMT_S16; /* Default to 16-bit signed. */ 2290 uint8_t cSampleBits = 16; 2425 PDMAUDIOFMT enmFmt; 2291 2426 switch (EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_BITS_MASK, HDA_SDFMT_BITS_SHIFT)) 2292 2427 { 2293 2428 case 0: 2294 enmFmt = AUD_FMT_S8; 2295 cSampleBits = 8; 2429 enmFmt = PDMAUDIOFMT_S8; 2296 2430 break; 2297 2431 case 1: 2298 enmFmt = AUD_FMT_S16; 2299 break; 2300 case 2: 2301 cSampleBits = 20; 2302 break; 2303 case 3: 2304 cSampleBits = 24; 2432 enmFmt = PDMAUDIOFMT_S16; 2305 2433 break; 2306 2434 case 4: 2307 enmFmt = AUD_FMT_S32; 2308 cSampleBits = 32; 2435 enmFmt = PDMAUDIOFMT_S32; 2309 2436 break; 2310 2437 default: … … 2317 2444 if (RT_SUCCESS(rc)) 2318 2445 { 2319 p Cfg->uHz = u32Hz * u32HzMult / u32HzDiv;2320 p Cfg->cChannels = (u32SDFMT & 0xf) + 1;2321 p Cfg->enmFormat = enmFmt;2322 p Cfg->enmEndianness = PDMAUDIOHOSTENDIANNESS;2446 pStrmCfg->uHz = u32Hz * u32HzMult / u32HzDiv; 2447 pStrmCfg->cChannels = (u32SDFMT & 0xf) + 1; 2448 pStrmCfg->enmFormat = enmFmt; 2449 pStrmCfg->enmEndianness = PDMAUDIOHOSTENDIANNESS; 2323 2450 } 2324 2451 … … 2326 2453 return rc; 2327 2454 } 2328 #endif 2455 2456 static int hdaAddStreamOut(PHDASTATE pThis, PPDMAUDIOSTREAMCFG pCfg) 2457 { 2458 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 2459 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 2460 2461 AssertReturn(pCfg->enmDir == PDMAUDIODIR_OUT, VERR_INVALID_PARAMETER); 2462 2463 LogFlowFunc(("Stream=%s\n", pCfg->szName)); 2464 2465 int rc = VINF_SUCCESS; 2466 2467 bool fUseFront = true; /* Always use front out by default. */ 2468 #ifdef VBOX_WITH_HDA_51_SURROUND 2469 bool fUseRear; 2470 bool fUseCenter; 2471 bool fUseLFE; 2472 2473 fUseRear = fUseCenter = fUseLFE = false; 2474 2475 /* 2476 * Use commonly used setups for speaker configurations. 2477 */ 2478 2479 /** @todo Make the following configurable through mixer API and/or CFGM? */ 2480 switch (pCfg->cChannels) 2481 { 2482 case 3: /* 2.1: Front (Stereo) + LFE. */ 2483 { 2484 fUseLFE = true; 2485 break; 2486 } 2487 2488 case 4: /* Quadrophonic: Front (Stereo) + Rear (Stereo). */ 2489 { 2490 fUseRear = true; 2491 break; 2492 } 2493 2494 case 5: /* 4.1: Front (Stereo) + Rear (Stereo) + LFE. */ 2495 { 2496 fUseRear = true; 2497 fUseLFE = true; 2498 break; 2499 } 2500 2501 case 6: /* 5.1: Front (Stereo) + Rear (Stereo) + Center/LFE. */ 2502 { 2503 fUseRear = true; 2504 fUseCenter = true; 2505 fUseLFE = true; 2506 break; 2507 } 2508 2509 default: /* Unknown; fall back to 2 front channels (stereo). */ 2510 { 2511 rc = VERR_NOT_SUPPORTED; 2512 break; 2513 } 2514 } 2515 #else /* !VBOX_WITH_HDA_51_SURROUND */ 2516 if ( pCfg->cChannels != 1 /* Mono */ 2517 && pCfg->cChannels != 2 /* Stereo */) 2518 { 2519 rc = VERR_NOT_SUPPORTED; 2520 } 2521 #endif 2522 2523 if (RT_FAILURE(rc)) 2524 { 2525 LogRel(("HDA: Unsupported channel count (%RU8), falling back to stereo channels\n", pCfg->cChannels)); 2526 pCfg->cChannels = 2; 2527 } 2528 2529 do 2530 { 2531 if (fUseFront) 2532 { 2533 if (!RTStrPrintf(pCfg->szName, RT_ELEMENTS(pCfg->szName), "Front")) 2534 { 2535 rc = VERR_BUFFER_OVERFLOW; 2536 break; 2537 } 2538 2539 pCfg->DestSource.Dest = PDMAUDIOPLAYBACKDEST_FRONT; 2540 pCfg->cChannels = 2; 2541 rc = hdaCodecRemoveStream(pThis->pCodec, PDMAUDIOMIXERCTL_FRONT); 2542 if (RT_SUCCESS(rc)) 2543 rc = hdaCodecAddStream(pThis->pCodec, PDMAUDIOMIXERCTL_FRONT, pCfg); 2544 } 2545 2546 #ifdef VBOX_WITH_HDA_51_SURROUND 2547 if ( RT_SUCCESS(rc) 2548 && (fUseCenter || fUseLFE)) 2549 { 2550 if (!RTStrPrintf(pCfg->szName, RT_ELEMENTS(pCfg->szName), "Center/LFE")) 2551 { 2552 rc = VERR_BUFFER_OVERFLOW; 2553 break; 2554 } 2555 2556 pCfg->DestSource.Dest = PDMAUDIOPLAYBACKDEST_CENTER_LFE; 2557 pCfg->cChannels = (fUseCenter && fUseLFE) ? 2 : 1; 2558 rc = hdaCodecRemoveStream(pThis->pCodec, PDMAUDIOMIXERCTL_CENTER_LFE); 2559 if (RT_SUCCESS(rc)) 2560 rc = hdaCodecAddStream(pThis->pCodec, PDMAUDIOMIXERCTL_CENTER_LFE, pCfg); 2561 2562 RTStrFree(pszName); 2563 } 2564 2565 if ( RT_SUCCESS(rc) 2566 && fUseRear) 2567 { 2568 if (!RTStrPrintf(pCfg->szName, RT_ELEMENTS(pCfg->szName), "Rear")) 2569 { 2570 rc = VERR_BUFFER_OVERFLOW; 2571 break; 2572 } 2573 2574 pCfg->DestSource.Dest = PDMAUDIOPLAYBACKDEST_REAR; 2575 pCfg->cChannels = 2; 2576 rc = hdaCodecRemoveStream(pThis->pCodec, PDMAUDIOMIXERCTL_REAR); 2577 if (RT_SUCCESS(rc)) 2578 rc = hdaCodecAddStream(pThis->pCodec, PDMAUDIOMIXERCTL_REAR, pCfg); 2579 } 2580 #endif /* VBOX_WITH_HDA_51_SURROUND */ 2581 2582 } while (0); 2583 2584 return rc; 2585 } 2586 2587 static int hdaAddStreamIn(PHDASTATE pThis, PPDMAUDIOSTREAMCFG pCfg) 2588 { 2589 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 2590 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 2591 2592 AssertReturn(pCfg->enmDir == PDMAUDIODIR_IN, VERR_INVALID_PARAMETER); 2593 2594 LogFlowFunc(("Stream=%s\n", pCfg->szName)); 2595 2596 int rc; 2597 2598 switch (pCfg->DestSource.Source) 2599 { 2600 case PDMAUDIORECSOURCE_LINE: 2601 { 2602 pCfg->DestSource.Source = PDMAUDIORECSOURCE_LINE; 2603 pCfg->cChannels = 2; 2604 rc = hdaCodecRemoveStream(pThis->pCodec, PDMAUDIOMIXERCTL_LINE_IN); 2605 if (RT_SUCCESS(rc)) 2606 rc = hdaCodecAddStream(pThis->pCodec, PDMAUDIOMIXERCTL_LINE_IN, pCfg); 2607 break; 2608 } 2609 #ifdef VBOX_WITH_HDA_MIC_IN 2610 case PDMAUDIORECSOURCE_MIC: 2611 { 2612 pCfg->DestSource.Source = PDMAUDIORECSOURCE_MIC; 2613 pCfg->cChannels = 2; 2614 rc = hdaCodecRemoveStream(pThis->pCodec, PDMAUDIOMIXERCTL_MIC_IN); 2615 if (RT_SUCCESS(rc)) 2616 rc = hdaCodecAddStream(pThis->pCodec, PDMAUDIOMIXERCTL_MIC_IN, pCfg); 2617 break; 2618 } 2619 #endif 2620 default: 2621 rc = VERR_NOT_SUPPORTED; 2622 break; 2623 } 2624 2625 return rc; 2626 } 2627 #endif /* IN_RING3 */ 2329 2628 2330 2629 static int hdaRegWriteSDFMT(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value) 2331 2630 { 2332 2631 #ifdef IN_RING3 2632 if (HDA_REG_IND(pThis, iReg) == u32Value) /* Value already set? */ 2633 return VINF_SUCCESS; 2634 2333 2635 PDMAUDIOSTREAMCFG strmCfg; 2636 RT_ZERO(strmCfg); 2637 2334 2638 int rc = hdaSDFMTToStrmCfg(u32Value, &strmCfg); 2335 2639 if (RT_FAILURE(rc)) 2336 2640 return VINF_SUCCESS; /* Always return success to the MMIO handler. */ 2337 2641 2338 if (HDA_REG_IND(pThis, iReg) == u32Value) /* Value already set? */2339 return VINF_SUCCESS;2340 2341 2642 PHDASTREAM pStrmSt = hdaStreamFromSD(pThis, HDA_SD_NUM_FROM_REG(pThis, FMT, iReg)); 2342 2643 if (!pStrmSt) … … 2350 2651 AssertRC(rc); 2351 2652 2352 LogFlowFunc(("[SD%RU8]: Hz=%RU32, Channels=%RU8, enmFmt=%RU32\n", 2353 pStrmSt->u8SD, strmCfg.uHz, strmCfg.cChannels, strmCfg.enmFormat)); 2354 2355 PDMAUDIOMIXERCTL enmMixerCtl; 2356 #ifdef VBOX_WITH_HDA_51_SURROUND 2357 # error "Implement me!" 2358 #endif 2359 2360 enmMixerCtl = PDMAUDIOMIXERCTL_FRONT; 2361 strmCfg.DestSource.Dest = PDMAUDIOPLAYBACKDEST_FRONT; 2653 LogFunc(("[SD%RU8]: Hz=%RU32, Channels=%RU8, enmFmt=%RU32\n", 2654 pStrmSt->u8SD, strmCfg.uHz, strmCfg.cChannels, strmCfg.enmFormat)); 2655 2656 /* Set audio direction. */ 2657 strmCfg.enmDir = hdaGetDirFromSD(pStrmSt->u8SD); 2658 2659 /* 2660 * Initialize the stream mapping in any case, regardless if 2661 * we support surround audio or not. This is needed to handle 2662 * the supported channels within a single audio stream, e.g. mono/stereo. 2663 * 2664 * In other words, the stream mapping *always* knowns the real 2665 * number of channels in a single audio stream. 2666 */ 2667 rc = hdaStreamMapInit(&pStrmSt->State.Mapping, &strmCfg); 2668 AssertRC(rc); 2362 2669 2363 2670 if (RT_SUCCESS(rc)) 2364 2671 { 2672 int rc2; 2365 2673 PHDADRIVER pDrv; 2366 2674 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node) 2367 2675 { 2368 int rc2 = hdaCodecRemoveStream(pThis->pCodec, enmMixerCtl); 2369 if (RT_SUCCESS(rc2)) 2370 rc2 = hdaCodecAddStream(pThis->pCodec, enmMixerCtl, &strmCfg); 2676 switch (strmCfg.enmDir) 2677 { 2678 case PDMAUDIODIR_OUT: 2679 rc2 = hdaAddStreamOut(pThis, &strmCfg); 2680 break; 2681 2682 case PDMAUDIODIR_IN: 2683 rc2 = hdaAddStreamIn(pThis, &strmCfg); 2684 break; 2685 2686 default: 2687 rc2 = VERR_NOT_SUPPORTED; 2688 AssertFailed(); 2689 break; 2690 } 2371 2691 2372 2692 if ( RT_FAILURE(rc2) … … 2506 2826 { 2507 2827 #ifdef IN_RING3 2508 PFNHDACODECVERBPROCESSOR pfn = NULL; 2509 uint64_t resp; 2510 uint32_t cmd = HDA_REG(pThis, IC); 2828 uint32_t uCmd = HDA_REG(pThis, IC); 2829 2511 2830 if (HDA_REG(pThis, CORBWP) != HDA_REG(pThis, CORBRP)) 2512 2831 { 2513 2832 /* 2514 * 3.4.3 defines behavior of immediate Command status register.2833 * 3.4.3: Defines behavior of immediate Command status register. 2515 2834 */ 2516 LogRel((" guest attempted process immediate verb (%x) with active CORB\n", cmd));2835 LogRel(("HDA: Guest attempted process immediate verb (%x) with active CORB\n", uCmd)); 2517 2836 return rc; 2518 2837 } 2838 2519 2839 HDA_REG(pThis, IRS) = HDA_REG_FIELD_FLAG_MASK(IRS, ICB); /* busy */ 2520 LogFunc(("IC:%x\n", cmd)); 2521 2522 rc = pThis->pCodec->pfnLookup(pThis->pCodec, 2523 HDA_CODEC_CMD(cmd, 0 /* LUN */), 2524 &pfn); 2525 if (RT_FAILURE(rc)) 2526 AssertRCReturn(rc, rc); 2527 rc = pfn(pThis->pCodec, 2528 HDA_CODEC_CMD(cmd, 0 /* LUN */), &resp); 2529 if (RT_FAILURE(rc)) 2530 AssertRCReturn(rc, rc); 2531 2532 HDA_REG(pThis, IR) = (uint32_t)resp; 2533 LogFunc(("IR:%x\n", HDA_REG(pThis, IR))); 2534 HDA_REG(pThis, IRS) = HDA_REG_FIELD_FLAG_MASK(IRS, IRV); /* result is ready */ 2840 2841 uint64_t uResp; 2842 int rc2 = pThis->pCodec->pfnLookup(pThis->pCodec, 2843 HDA_CODEC_CMD(uCmd, 0 /* LUN */), &uResp); 2844 if (RT_FAILURE(rc2)) 2845 LogFunc(("Codec lookup failed with rc=%Rrc\n", rc2)); 2846 2847 HDA_REG(pThis, IR) = (uint32_t)uResp; /** @todo r=andy Do we need a 64-bit response? */ 2848 HDA_REG(pThis, IRS) = HDA_REG_FIELD_FLAG_MASK(IRS, IRV); /* result is ready */ 2535 2849 HDA_REG(pThis, IRS) &= ~HDA_REG_FIELD_FLAG_MASK(IRS, ICB); /* busy is clear */ 2536 2850 #else /* !IN_RING3 */ … … 2589 2903 2590 2904 /* Also make sure to handle the DMA position enable bit. */ 2591 pThis->fDMAPosition = pThis->au32Regs[iRegMem] & RT_BIT_32(0);2905 pThis->fDMAPosition = RT_BOOL(pThis->u64DPBase & RT_BIT_64(0)); 2592 2906 LogRel(("HDA: %s DMA position buffer\n", pThis->fDMAPosition ? "Enabled" : "Disabled")); 2593 2907 break; … … 2670 2984 AssertPtrReturn(pBDLE, VERR_INVALID_POINTER); 2671 2985 AssertReturn(u64BaseDMA, VERR_INVALID_PARAMETER); 2986 2987 if (!u64BaseDMA) 2988 { 2989 LogRel2(("HDA: Unable to fetch BDLE #%RU16 - no base DMA address set (yet)\n", u16Entry)); 2990 return VERR_NOT_FOUND; 2991 } 2672 2992 /** @todo Compare u16Entry with LVI. */ 2673 2993 … … 2686 3006 return VERR_INVALID_STATE; 2687 3007 2688 pBDLE->fIntOnCompletion = (*(uint32_t *)&uBundleEntry[12]) & 0x1;3008 pBDLE->fIntOnCompletion = (*(uint32_t *)&uBundleEntry[12]) & RT_BIT(0); 2689 3009 2690 3010 return VINF_SUCCESS; … … 2699 3019 DECLINLINE(uint32_t) hdaStreamGetTransferSize(PHDASTATE pThis, PHDASTREAM pStrmSt, uint32_t cbMax) 2700 3020 { 2701 AssertPtrReturn(pThis, 0);3021 AssertPtrReturn(pThis, 0); 2702 3022 AssertPtrReturn(pStrmSt, 0); 2703 3023 … … 2707 3027 PHDABDLE pBDLE = &pStrmSt->State.BDLE; 2708 3028 2709 uint32_t cbFree = pStrmSt->u32CBL - HDA_STREAM_REG(pThis, LPIB, pStrmSt->u8SD); 3029 uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStrmSt->u8SD); 3030 Assert(u32LPIB <= pStrmSt->u32CBL); 3031 3032 uint32_t cbFree = pStrmSt->u32CBL - u32LPIB; /** @todo Convert samples to bytes? */ 2710 3033 if (cbFree) 2711 3034 { … … 2771 3094 } 2772 3095 3096 #ifdef IN_RING3 3097 /** 3098 * Initializes a stream mapping structure according to the given stream configuration. 3099 * 3100 * @return IPRT status code. 3101 * @param pMapping Pointer to mapping to initialize. 3102 * @param pCfg Pointer to stream configuration to use. 3103 */ 3104 static int hdaStreamMapInit(PHDASTREAMMAPPING pMapping, PPDMAUDIOSTREAMCFG pCfg) 3105 { 3106 AssertPtrReturn(pMapping, VERR_INVALID_POINTER); 3107 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 3108 3109 AssertReturn(pCfg->cChannels, VERR_INVALID_PARAMETER); 3110 3111 hdaStreamMapReset(pMapping); 3112 3113 pMapping->paChannels = (PPDMAUDIOSTREAMCHANNEL)RTMemAlloc(sizeof(PDMAUDIOSTREAMCHANNEL) * pCfg->cChannels); 3114 if (!pMapping->paChannels) 3115 return VERR_NO_MEMORY; 3116 3117 PDMPCMPROPS Props; 3118 int rc = DrvAudioStreamCfgToProps(pCfg, &Props); 3119 if (RT_FAILURE(rc)) 3120 return rc; 3121 3122 Assert(RT_IS_POWER_OF_TWO(Props.cBits)); 3123 3124 /** @todo We assume all channels in a stream have the same format. */ 3125 PPDMAUDIOSTREAMCHANNEL pChan = pMapping->paChannels; 3126 for (uint8_t i = 0; i < pCfg->cChannels; i++) 3127 { 3128 pChan->uChannel = i; 3129 pChan->cbStep = (Props.cBits / 2); 3130 pChan->cbFrame = pChan->cbStep * pCfg->cChannels; 3131 pChan->cbFirst = i * pChan->cbStep; 3132 pChan->cbOff = pChan->cbFirst; 3133 3134 int rc2 = hdaStreamChannelDataInit(&pChan->Data, PDMAUDIOSTREAMCHANNELDATA_FLAG_NONE); 3135 if (RT_SUCCESS(rc)) 3136 rc = rc2; 3137 3138 if (RT_FAILURE(rc)) 3139 break; 3140 3141 pChan++; 3142 } 3143 3144 if (RT_SUCCESS(rc)) 3145 rc = RTCircBufCreate(&pMapping->pCircBuf, _4K); 3146 3147 if (RT_SUCCESS(rc)) 3148 { 3149 pMapping->cChannels = pCfg->cChannels; 3150 #ifdef VBOX_WITH_HDA_INTERLEAVING_STREAMS_SUPPORT 3151 pMapping->enmLayout = PDMAUDIOSTREAMLAYOUT_INTERLEAVED; 3152 #else 3153 pMapping->enmLayout = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED; 3154 #endif 3155 } 3156 3157 return rc; 3158 } 3159 3160 /** 3161 * Destroys a given stream mapping. 3162 * 3163 * @param pMapping Pointer to mapping to destroy. 3164 */ 3165 static void hdaStreamMapDestroy(PHDASTREAMMAPPING pMapping) 3166 { 3167 hdaStreamMapReset(pMapping); 3168 3169 if (pMapping->pCircBuf) 3170 { 3171 RTCircBufDestroy(pMapping->pCircBuf); 3172 pMapping->pCircBuf = NULL; 3173 } 3174 } 3175 3176 /** 3177 * Resets a given stream mapping. 3178 * 3179 * @param pMapping Pointer to mapping to reset. 3180 */ 3181 static void hdaStreamMapReset(PHDASTREAMMAPPING pMapping) 3182 { 3183 AssertPtrReturnVoid(pMapping); 3184 3185 pMapping->enmLayout = PDMAUDIOSTREAMLAYOUT_UNKNOWN; 3186 3187 if (pMapping->cChannels) 3188 { 3189 for (uint8_t i = 0; i < pMapping->cChannels; i++) 3190 hdaStreamChannelDataDestroy(&pMapping->paChannels[i].Data); 3191 3192 AssertPtr(pMapping->paChannels); 3193 RTMemFree(pMapping->paChannels); 3194 pMapping->paChannels = NULL; 3195 3196 pMapping->cChannels = 0; 3197 } 3198 } 3199 #endif /* IN_RING3 */ 3200 2773 3201 DECLINLINE(bool) hdaStreamNeedsNextBDLE(PHDASTATE pThis, PHDASTREAM pStrmSt) 2774 3202 { … … 2793 3221 pStrmSt->u8SD, u32LPIB, pStrmSt->u32CBL, fCBLLimitReached, fNeedsNextBDLE, pBDLE)); 2794 3222 2795 if (fCBLLimitReached)2796 {2797 /* Reset LPIB register. */2798 u32LPIB -= RT_MIN(u32LPIB, pStrmSt->u32CBL);2799 hdaStreamUpdateLPIB(pThis, pStrmSt, u32LPIB);2800 }2801 2802 3223 return fNeedsNextBDLE; 2803 3224 } … … 2811 3232 2812 3233 Assert(cbInc <= pStrmSt->u16FIFOS); 3234 3235 if (!cbInc) /* Nothing to do? Bail out early. */ 3236 return; 2813 3237 2814 3238 PHDABDLE pBDLE = &pStrmSt->State.BDLE; … … 2821 3245 if (pBDLE->State.cbBelowFIFOW == 0) /* Did we hit (or exceed) the watermark? */ 2822 3246 { 2823 const uint32_t u32LPIB = RT_MIN(HDA_STREAM_REG(pThis, LPIB, pStrmSt->u8SD) + cbInc, 2824 pStrmSt->u32CBL); 3247 uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStrmSt->u8SD); 3248 3249 AssertMsg(((u32LPIB + cbInc) <= pStrmSt->u32CBL), 3250 ("[SD%RU8] Increment (%RU32) exceeds CBL (%RU32): LPIB (%RU32)\n", 3251 pStrmSt->u8SD, cbInc, pStrmSt->u32CBL, u32LPIB)); 3252 3253 u32LPIB = RT_MIN(u32LPIB + cbInc, pStrmSt->u32CBL); 2825 3254 2826 3255 LogFlowFunc(("[SD%RU8]: LPIB: %RU32 -> %RU32, CBL=%RU32\n", … … 2833 3262 } 2834 3263 2835 static bool hdaStreamTransferIsComplete(PHDASTATE pThis, PHDASTREAM pStr mSt)3264 static bool hdaStreamTransferIsComplete(PHDASTATE pThis, PHDASTREAM pStream, bool *pfInterrupt) 2836 3265 { 2837 3266 AssertPtrReturn(pThis, true); 2838 AssertPtrReturn(pStrmSt, true); 2839 3267 AssertPtrReturn(pStream, true); 3268 3269 bool fInterrupt = false; 2840 3270 bool fIsComplete = false; 2841 3271 2842 PHDABDLE pBDLE = &pStr mSt->State.BDLE;2843 const uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStr mSt->u8SD);2844 2845 if ( pBDLE->State.u32BufOff >= pBDLE->u32BufSize2846 || u32LPIB >= pStrmSt->u32CBL)3272 PHDABDLE pBDLE = &pStream->State.BDLE; 3273 const uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStream->u8SD); 3274 3275 /* Check if the current BDLE entry is complete (full). */ 3276 if (pBDLE->State.u32BufOff >= pBDLE->u32BufSize) 2847 3277 { 2848 3278 Assert(pBDLE->State.u32BufOff <= pBDLE->u32BufSize); 2849 Assert(u32LPIB <= pStrmSt->u32CBL);2850 3279 2851 3280 if (/* IOC (Interrupt On Completion) bit set? */ … … 2855 3284 ) 2856 3285 { 2857 /** 2858 * Set the BCIS (Buffer Completion Interrupt Status) flag as the 2859 * last byte of data for the current descriptor has been fetched 2860 * from memory and put into the DMA FIFO. 2861 * 2862 ** @todo More carefully investigate BCIS flag. 2863 * 2864 * Speech synthesis works fine on Mac Guest if this bit isn't set 2865 * but in general sound quality gets worse. 2866 */ 2867 HDA_STREAM_REG(pThis, STS, pStrmSt->u8SD) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS); 3286 LogFlowFunc(("[SD%RU8]: %R[bdle] => COMPLETE\n", pStream->u8SD, pBDLE)); 2868 3287 2869 3288 /* … … 2871 3290 * we need to generate an interrupt. 2872 3291 */ 2873 if (HDA_STREAM_REG(pThis, CTL, pStr mSt->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE))2874 hdaProcessInterrupt(pThis);3292 if (HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE)) 3293 fInterrupt = true; 2875 3294 } 2876 3295 … … 2878 3297 } 2879 3298 2880 LogFlowFunc(("[SD%RU8]: u32LPIB=%RU32, CBL=%RU32, %R[bdle] => %s\n", 2881 pStrmSt->u8SD, u32LPIB, pStrmSt->u32CBL, pBDLE, fIsComplete ? "COMPLETE" : "INCOMPLETE")); 3299 if (pfInterrupt) 3300 *pfInterrupt = fInterrupt; 3301 3302 LogFlowFunc(("[SD%RU8]: u32LPIB=%RU32, CBL=%RU32, fIsComplete=%RTbool, fInterrupt=%RTbool, %R[bdle]\n", 3303 pStream->u8SD, u32LPIB, pStream->u32CBL, fIsComplete, fInterrupt, pBDLE)); 2882 3304 2883 3305 return fIsComplete; … … 2895 3317 /* pcbRead is optional. */ 2896 3318 2897 PHDABDLE pBDLE = &pStrmSt->State.BDLE;2898 2899 3319 int rc; 2900 3320 uint32_t cbRead = 0; 2901 uint32_t cbBuf = hdaStreamGetTransferSize(pThis, pStrmSt, cbMax); 2902 2903 LogFlowFunc(("cbBuf=%RU32, %R[bdle]\n", cbBuf, pBDLE)); 2904 2905 if (!cbBuf) 2906 { 2907 /* Nothing to write, bail out. */ 2908 rc = VINF_EOF; 2909 } 2910 else 2911 { 2912 rc = AudioMixerProcessSinkIn(pStrmSt->pSink, AUDMIXOP_BLEND, pBDLE->State.au8FIFO, cbBuf, &cbRead); 2913 if (RT_SUCCESS(rc)) 3321 3322 do 3323 { 3324 PHDABDLE pBDLE = &pStrmSt->State.BDLE; 3325 3326 uint32_t cbBuf = hdaStreamGetTransferSize(pThis, pStrmSt, cbMax); 3327 Log3Func(("cbBuf=%RU32, %R[bdle]\n", cbBuf, pBDLE)); 3328 3329 if (!cbBuf) 2914 3330 { 2915 Assert(cbRead); 2916 Assert(cbRead == cbBuf); 2917 Assert(cbRead <= pBDLE->u32BufSize - pBDLE->State.u32BufOff); 2918 2919 /* 2920 * Write to the BDLE's DMA buffer. 2921 */ 2922 rc = PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), 2923 pBDLE->u64BufAdr + pBDLE->State.u32BufOff, 2924 pBDLE->State.au8FIFO, cbRead); 2925 AssertRC(rc); 2926 2927 if (pBDLE->State.cbBelowFIFOW + cbRead > hdaStreamGetFIFOW(pThis, pStrmSt)) 2928 { 2929 pBDLE->State.u32BufOff += cbRead; 2930 pBDLE->State.cbBelowFIFOW = 0; 2931 //hdaBackendReadTransferReported(pBDLE, cbDMAData, cbRead, &cbRead, pcbAvail); 2932 } 2933 else 2934 { 2935 pBDLE->State.u32BufOff += cbRead; 2936 pBDLE->State.cbBelowFIFOW += cbRead; 2937 Assert(pBDLE->State.cbBelowFIFOW <= hdaStreamGetFIFOW(pThis, pStrmSt)); 2938 //hdaBackendTransferUnreported(pThis, pBDLE, pStreamDesc, cbRead, pcbAvail); 2939 2940 rc = VERR_NO_DATA; 2941 } 3331 rc = VINF_EOF; 3332 break; 2942 3333 } 2943 } 2944 2945 Assert(cbRead <= pStrmSt->u16FIFOS); 3334 3335 rc = AudioMixerSinkRead(pStrmSt->pSink, AUDMIXOP_BLEND, pBDLE->State.au8FIFO, cbBuf, &cbRead); 3336 if (RT_FAILURE(rc)) 3337 break; 3338 3339 if (!cbRead) 3340 { 3341 rc = VINF_EOF; 3342 break; 3343 } 3344 3345 /* Sanity checks. */ 3346 Assert(cbRead <= cbBuf); 3347 Assert(cbRead <= pBDLE->u32BufSize - pBDLE->State.u32BufOff); 3348 Assert(cbRead <= pStrmSt->u16FIFOS); 3349 3350 /* 3351 * Write to the BDLE's DMA buffer. 3352 */ 3353 rc = PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), 3354 pBDLE->u64BufAdr + pBDLE->State.u32BufOff, 3355 pBDLE->State.au8FIFO, cbRead); 3356 AssertRC(rc); 3357 3358 if (pBDLE->State.cbBelowFIFOW + cbRead > hdaStreamGetFIFOW(pThis, pStrmSt)) 3359 { 3360 pBDLE->State.u32BufOff += cbRead; 3361 pBDLE->State.cbBelowFIFOW = 0; 3362 //hdaBackendReadTransferReported(pBDLE, cbDMAData, cbRead, &cbRead, pcbAvail); 3363 } 3364 else 3365 { 3366 pBDLE->State.u32BufOff += cbRead; 3367 pBDLE->State.cbBelowFIFOW += cbRead; 3368 Assert(pBDLE->State.cbBelowFIFOW <= hdaStreamGetFIFOW(pThis, pStrmSt)); 3369 //hdaBackendTransferUnreported(pThis, pBDLE, pStreamDesc, cbRead, pcbAvail); 3370 3371 rc = VERR_NO_DATA; 3372 } 3373 3374 } while (0); 2946 3375 2947 3376 if (RT_SUCCESS(rc)) … … 2951 3380 } 2952 3381 2953 Log Func(("Returning cbRead=%RU32, rc=%Rrc\n", cbRead, rc));3382 Log3Func(("Returning cbRead=%RU32, rc=%Rrc\n", cbRead, rc)); 2954 3383 return rc; 2955 3384 } … … 2965 3394 2966 3395 uint32_t cbWritten = 0; 2967 uint32_t cb Data= hdaStreamGetTransferSize(pThis, pStrmSt, cbMax);2968 2969 Log FlowFunc(("cbData=%RU32, %R[bdle]\n", cbData, pBDLE));3396 uint32_t cbToWrite = hdaStreamGetTransferSize(pThis, pStrmSt, cbMax); 3397 3398 Log3Func(("cbToWrite=%RU32, %R[bdle]\n", cbToWrite, pBDLE)); 2970 3399 2971 3400 /* … … 2974 3403 */ 2975 3404 int rc; 2976 if (!cb Data)3405 if (!cbToWrite) 2977 3406 { 2978 3407 rc = VINF_EOF; … … 2980 3409 else 2981 3410 { 3411 void *pvBuf = pBDLE->State.au8FIFO + pBDLE->State.cbBelowFIFOW; 3412 Assert(cbToWrite >= pBDLE->State.cbBelowFIFOW); 3413 uint32_t cbBuf = cbToWrite - pBDLE->State.cbBelowFIFOW; 3414 2982 3415 /* 2983 3416 * Read from the current BDLE's DMA buffer. … … 2985 3418 rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), 2986 3419 pBDLE->u64BufAdr + pBDLE->State.u32BufOff, 2987 p BDLE->State.au8FIFO + pBDLE->State.cbBelowFIFOW, cbData);3420 pvBuf, cbBuf); 2988 3421 AssertRC(rc); 2989 2990 #if 0 3422 #if defined (RT_OS_LINUX) && defined(DEBUG) 2991 3423 RTFILE fh; 2992 RTFileOpen(&fh, " c:\\temp\\hdaWriteAudio.pcm",3424 RTFileOpen(&fh, "/tmp/hdaWriteAudio.pcm", 2993 3425 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE); 2994 RTFileWrite(fh, p BDLE->State.au8FIFO + pBDLE->State.cbBelowFIFOW, cbData, NULL);3426 RTFileWrite(fh, pvBuf, cbBuf, NULL); 2995 3427 RTFileClose(fh); 2996 3428 #endif 2997 3429 2998 3430 #ifdef VBOX_WITH_STATISTICS 2999 STAM_COUNTER_ADD(&pThis->StatBytesRead, cb Data);3431 STAM_COUNTER_ADD(&pThis->StatBytesRead, cbBuf); 3000 3432 #endif 3001 3433 /* 3002 3434 * Write to audio backend. We should ensure that we have enough bytes to copy to the backend. 3003 3435 */ 3004 uint32_t cbToWrite = cbData + pBDLE->State.cbBelowFIFOW; 3005 if (cbToWrite >= hdaStreamGetFIFOW(pThis, pStrmSt)) 3436 if (cbBuf >= hdaStreamGetFIFOW(pThis, pStrmSt)) 3006 3437 { 3007 uint32_t cbWrittenToStream; 3438 PHDASTREAMMAPPING pMapping = &pStrmSt->State.Mapping; 3439 3440 /** @todo Which channel is which? */ 3441 #ifdef VBOX_WITH_HDA_INTERLEAVING_STREAMS_SUPPORT 3442 PPDMAUDIOSTREAMCHANNEL pChanFront = &pMapping->paChannels[0]; 3443 #endif 3444 #ifdef VBOX_WITH_HDA_51_SURROUND 3445 PPDMAUDIOSTREAMCHANNEL pChanCenterLFE = &pMapping->paChannels[2]; /** @todo FIX! */ 3446 PPDMAUDIOSTREAMCHANNEL pChanRear = &pMapping->paChannels[4]; /** @todo FIX! */ 3447 #endif 3008 3448 int rc2; 3009 3449 3010 PHDADRIVER pDrv; 3011 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node) 3012 { 3013 if (pDrv->pConnector->pfnIsActiveOut(pDrv->pConnector, pDrv->Front.pGstStrm)) 3014 { 3450 void *pvDataFront = NULL; 3451 size_t cbDataFront; 3015 3452 #ifdef VBOX_WITH_HDA_INTERLEAVING_STREAMS_SUPPORT 3016 /** @todo Needs more hacking first. */ 3017 # if 0 3018 static int16_t restBuf = 0; 3019 static size_t cbRestOff = 0; 3020 3021 uint8_t temp[HDA_SDONFIFO_256B + 1]; 3022 3023 uint8_t *pu8Src = &pBDLE->State.au8FIFO[0]; 3024 uint8_t *pu8Dst = &temp[0]; 3025 3026 size_t cbSample = sizeof(int16_t) * 2; 3027 3028 size_t cbProc = 0; 3029 size_t cbToSkip = 5 * cbSample; 3030 size_t cbSkipSize = cbToSkip; 3031 size_t cbDstSize = 0; 3032 3033 while (cbProc < cbToWrite) 3034 { 3035 memcpy(pu8Dst, pu8Src, cbSample); 3036 3037 cbSkipSize = RT_MIN(cbToSkip, cbToWrite - cbProc); 3038 3039 pu8Src += 10; 3040 cbProc += cbSkipSize; 3041 3042 pu8Dst += 4; 3043 cbDstSize += cbSample; 3044 } 3045 3046 /* Sanity. */ 3047 AssertMsg(((cbDstSize * 8 /* Bit */) % 16) == 0, ("ASDF\n")); 3048 3049 LogFlowFunc(("cbRest=%zu, cbToWrite=%zu, cbProc=%zu, cbDstSize=%zu\n", 3050 0, cbToWrite, cbProc, cbDstSize)); 3051 3052 rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Out.pStrmOut, 3053 temp, cbDstSize, &cbWrittenToStream); 3054 # if 1 3055 RTFILE fh; 3056 RTFileOpen(&fh, "/tmp/hdaWriteAudio.pcm", 3057 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE); 3058 RTFileWrite(fh, temp, cbDstSize, NULL); 3059 RTFileClose(fh); 3060 # endif 3061 3062 # else 3063 int16_t *pvStart; 3064 size_t cbAcqWrite; 3065 RTCircBufAcquireWriteBlock(pThis->pCircBuf, cbToWrite, (void **)&pvStart, &cbAcqWrite); 3066 3067 uint8_t cChannels = 1; 3068 size_t cbSample = sizeof(int16_t); 3069 3070 int16_t *pi16Src = (int16_t *)&pBDLE->State.au8FIFO[0]; 3071 int16_t *pi16Dst = pvStart; 3072 3073 size_t cbProcSrc = 0; 3074 size_t cbProcDst = 0; 3075 3076 while (cbProcSrc < cbAcqWrite) 3077 { 3078 memcpy(pi16Dst, pi16Src, cbSample); 3079 3080 pi16Src += 6 * cChannels; 3081 pi16Dst += cChannels; 3082 3083 cbProcSrc += RT_MIN(cbAcqWrite - cbProcSrc, 6 * cbSample); 3084 cbProcDst += cbSample; 3085 3086 Assert(cbProcSrc <= cbAcqWrite); 3087 size_t cbLeft = cbAcqWrite - cbProcSrc; 3088 LogFlowFunc(("cbProcSrc=%zu, cbProcDst=%zu, cbLeft=%zu\n", cbProcSrc, cbProcDst, cbLeft)); 3089 if ( cbLeft 3090 && cbLeft < cChannels) 3091 { 3092 LogFlowFunc(("%zu bytes left ...\n", cbAcqWrite - cbProcSrc)); 3093 break; 3094 } 3095 } 3096 3097 RTCircBufReleaseWriteBlock(pThis->pCircBuf, cbProcDst); 3098 3099 LogFlowFunc(("cbAcqWrite=%zu, cbToWrite=%zu, cbProcSrc=%zu, cbProcDst=%zu\n", 3100 cbAcqWrite, cbToWrite, cbProcSrc, cbProcDst)); 3101 3102 size_t cbAcqRead = 0; 3103 RTCircBufAcquireReadBlock(pThis->pCircBuf, _4K, (void **)&pvStart, &cbAcqRead); 3104 # if 1 3105 RTFILE fh; 3106 RTFileOpen(&fh, "/tmp/hdaWriteAudio.pcm", 3107 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE); 3108 RTFileWrite(fh, pvStart, cbAcqRead, NULL); 3109 RTFileClose(fh); 3110 # endif 3111 rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Front.pGstStrm, 3112 pvStart, cbAcqRead, &cbWrittenToStream); 3113 3114 /** @todo Add support for writing to center/LFE + rear. */ 3115 3116 RTCircBufReleaseReadBlock(pThis->pCircBuf, cbAcqRead); 3117 # endif 3118 3119 #else /* !VBOX_WITH_HDA_INTERLEAVING_STREAMS_SUPPORT */ 3120 rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Front.pGstStrm, 3121 pBDLE->State.au8FIFO, cbToWrite, &cbWrittenToStream); 3122 #endif /* VBOX_WITH_HDA_INTERLEAVING_STREAMS_SUPPORT */ 3123 if (RT_SUCCESS(rc2)) 3124 { 3125 if (cbWrittenToStream < cbToWrite) /* Lagging behind? */ 3126 LogFlowFunc(("\tLUN#%RU8: Warning: Only written %RU32 / %RU32 bytes, expect lags\n", 3127 pDrv->uLUN, cbWrittenToStream, cbToWrite)); 3128 } 3129 } 3130 else /* Stream disabled, not fatal. */ 3131 { 3132 cbWrittenToStream = 0; 3133 rc2 = VERR_NOT_AVAILABLE; 3134 /* Keep going. */ 3135 } 3136 3137 LogFlowFunc(("\tLUN#%RU8: cbToWrite=%RU32, cbWrittenToStream=%RU32, rc=%Rrc\n", 3138 pDrv->uLUN, cbToWrite, cbWrittenToStream, rc2)); 3139 } 3453 rc2 = hdaStreamChannelExtract(pChanFront, pvBuf, cbBuf); 3454 AssertRC(rc2); 3455 3456 rc2 = hdaStreamChannelAcquireData(&pChanFront->Data, pvDataFront, &cbDataFront); 3457 AssertRC(rc2); 3458 #else 3459 /* Use stuff in the whole FIFO to use for the channel data. */ 3460 pvDataFront = pvBuf; 3461 cbDataFront = cbBuf; 3462 #endif 3463 #ifdef VBOX_WITH_HDA_51_SURROUND 3464 void *pvDataCenterLFE; 3465 size_t cbDataCenterLFE; 3466 rc2 = hdaStreamChannelExtract(pChanCenterLFE, pvBuf, cbBuf); 3467 AssertRC(rc2); 3468 3469 rc2 = hdaStreamChannelAcquireData(&pChanCenterLFE->Data, pvDataCenterLFE, &cbDataCenterLFE); 3470 AssertRC(rc2); 3471 3472 void *pvDataRear; 3473 size_t cbDataRear; 3474 rc2 = hdaStreamChannelExtract(pChanRear, pvBuf, cbBuf); 3475 AssertRC(rc2); 3476 3477 rc2 = hdaStreamChannelAcquireData(&pChanRear->Data, pvDataRear, &cbDataRear); 3478 AssertRC(rc2); 3479 #endif 3480 /* 3481 * Write data to according mixer sinks. 3482 */ 3483 rc2 = AudioMixerSinkWrite(pThis->pSinkFront, AUDMIXOP_COPY, pvDataFront, cbDataFront, 3484 NULL /* pcbWritten */); 3485 AssertRC(rc2); 3486 #ifdef VBOX_WITH_HDA_51_SURROUND 3487 rc2 = AudioMixerSinkWrite(pThis->pSinkCenterLFE, AUDMIXOP_COPY, pvDataCenterLFE, cbDataCenterLFE, 3488 NULL /* pcbWritten */); 3489 AssertRC(rc2); 3490 rc2 = AudioMixerSinkWrite(pThis->pSinkRear, AUDMIXOP_COPY, pvDataRear, cbDataRear, 3491 NULL /* pcbWritten */); 3492 AssertRC(rc2); 3493 #endif 3494 3495 #ifdef VBOX_WITH_HDA_INTERLEAVING_STREAMS_SUPPORT 3496 hdaStreamChannelReleaseData(&pChanFront->Data); 3497 #endif 3498 #ifdef VBOX_WITH_HDA_51_SURROUND 3499 hdaStreamChannelReleaseData(&pChanCenterLFE->Data); 3500 hdaStreamChannelReleaseData(&pChanRear->Data); 3501 #endif 3140 3502 3141 3503 /* Always report all data as being written; … … 3143 3505 cbWritten = cbToWrite; 3144 3506 3145 hdaBDLEUpdate(pBDLE, cb Data, cbWritten);3507 hdaBDLEUpdate(pBDLE, cbToWrite, cbWritten); 3146 3508 } 3147 3509 else … … 3165 3527 } 3166 3528 3167 Log Func(("Returning cbWritten=%RU32, rc=%Rrc\n", cbWritten, rc));3529 Log3Func(("Returning cbMax=%RU32, cbWritten=%RU32, rc=%Rrc\n", cbMax, cbWritten, rc)); 3168 3530 return rc; 3169 3531 } … … 3223 3585 } 3224 3586 3225 static DECLCALLBACK(int) hdaMixerAddStream In(PHDASTATE pThis, PAUDMIXSINK pSink, PPDMAUDIOSTREAMCFG pCfg)3587 static DECLCALLBACK(int) hdaMixerAddStream(PHDASTATE pThis, PAUDMIXSINK pSink, PPDMAUDIOSTREAMCFG pCfg) 3226 3588 { 3227 3589 AssertPtrReturn(pThis, VERR_INVALID_POINTER); … … 3229 3591 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 3230 3592 3231 AssertReturn(pCfg->enmDir == PDMAUDIODIR_IN, VERR_INVALID_PARAMETER); 3232 3233 LogFunc(("Sink=%s, Source=%ld\n", pSink->pszName, pCfg->DestSource.Source)); 3593 LogFunc(("Sink=%s, Stream=%s\n", pSink->pszName, pCfg->szName)); 3234 3594 3235 3595 int rc = VINF_SUCCESS; … … 3238 3598 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node) 3239 3599 { 3240 char *pszDesc; 3241 if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] %s", pDrv->uLUN, pCfg->pszName) <= 0) 3600 int rc2 = VINF_SUCCESS; 3601 PHDAMIXERSTREAM pStream; 3602 3603 if (pCfg->enmDir == PDMAUDIODIR_IN) 3242 3604 { 3243 rc = VERR_NO_MEMORY; 3244 break; 3605 switch (pCfg->DestSource.Source) 3606 { 3607 case PDMAUDIORECSOURCE_LINE: 3608 pStream = &pDrv->LineIn; 3609 break; 3610 #ifdef VBOX_WITH_HDA_MIC_IN 3611 case PDMAUDIORECSOURCE_MIC: 3612 pStream = &pDrv->MicIn; 3613 break; 3614 #endif 3615 default: 3616 rc2 = VERR_NOT_SUPPORTED; 3617 break; 3618 } 3245 3619 } 3246 3247 int rc2 = VINF_SUCCESS; 3248 PHDAINPUTSTREAM pStream; 3249 switch (pCfg->DestSource.Source) 3620 else if (pCfg->enmDir == PDMAUDIODIR_OUT) 3250 3621 { 3251 case PDMAUDIORECSOURCE_LINE: 3252 pStream = &pDrv->LineIn; 3253 break; 3254 #ifdef VBOX_WITH_HDA_MIC_IN 3255 case PDMAUDIORECSOURCE_MIC: 3256 pStream = &pDrv->MicIn; 3257 break; 3258 #endif 3259 default: 3260 rc2 = VERR_NOT_SUPPORTED; 3261 break; 3622 switch (pCfg->DestSource.Dest) 3623 { 3624 case PDMAUDIOPLAYBACKDEST_FRONT: 3625 pStream = &pDrv->Front; 3626 break; 3627 #ifdef VBOX_WITH_HDA_51_SURROUND 3628 case PDMAUDIOPLAYBACKDEST_CENTER_LFE: 3629 pStream = &pDrv->CenterLFE; 3630 break; 3631 case PDMAUDIOPLAYBACKDEST_REAR: 3632 pStream = &pDrv->Rear; 3633 break; 3634 #endif 3635 default: 3636 rc2 = VERR_NOT_SUPPORTED; 3637 break; 3638 } 3262 3639 } 3640 else 3641 rc2 = VERR_NOT_SUPPORTED; 3263 3642 3264 3643 if (RT_SUCCESS(rc2)) 3265 3644 { 3266 PPDMAUDIOGSTSTRMIN pGstStrm; 3267 PAUDMIXSTREAM pMixStrm; 3268 3269 rc2 = pDrv->pConnector->pfnCreateIn(pDrv->pConnector, pszDesc, pCfg, &pGstStrm); 3270 LogFlowFunc(("LUN#%RU8: Created input \"%s\", with rc=%Rrc\n", pDrv->uLUN, pszDesc, rc)); 3271 if (RT_SUCCESS(rc2)) 3272 rc2 = AudioMixerAddStreamIn(pSink, pDrv->pConnector, pGstStrm, 0 /* uFlags */, &pMixStrm); 3273 3645 PAUDMIXSTREAM pMixStrm; 3646 rc2 = AudioMixerStreamCreate(pDrv->pConnector, pCfg, 0 /* fFlags */, &pMixStrm); 3274 3647 if (RT_SUCCESS(rc2)) 3275 3648 { 3276 pStream->pGstStrm = pGstStrm; 3649 rc2 = AudioMixerSinkAddStream(pSink, pMixStrm); 3650 LogFlowFunc(("LUN#%RU8: Added \"%s\" to sink, rc=%Rrc\n", pDrv->uLUN, pCfg->szName , rc2)); 3651 } 3652 3653 if (RT_SUCCESS(rc2)) 3277 3654 pStream->pMixStrm = pMixStrm; 3278 }3279 3655 } 3280 3656 3281 3657 if (RT_SUCCESS(rc)) 3282 3658 rc = rc2; 3283 3284 RTStrFree(pszDesc);3285 }3286 3287 LogFlowFuncLeaveRC(rc);3288 return rc;3289 }3290 3291 static DECLCALLBACK(int) hdaMixerAddStreamOut(PHDASTATE pThis, PAUDMIXSINK pSink, PPDMAUDIOSTREAMCFG pCfg)3292 {3293 AssertPtrReturn(pThis, VERR_INVALID_POINTER);3294 AssertPtrReturn(pSink, VERR_INVALID_POINTER);3295 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);3296 3297 AssertReturn(pCfg->enmDir == PDMAUDIODIR_OUT, VERR_INVALID_PARAMETER);3298 3299 LogFunc(("Sink=%s, Dest=%ld\n", pSink->pszName, pCfg->DestSource.Dest));3300 3301 int rc = VINF_SUCCESS;3302 3303 PHDADRIVER pDrv;3304 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)3305 {3306 char *pszDesc;3307 if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] %s (%RU32Hz, %RU8 %s)",3308 pDrv->uLUN, pCfg->pszName, pCfg->uHz, pCfg->cChannels, pCfg->cChannels > 1 ? "Channels" : "Channel") <= 0)3309 {3310 rc = VERR_NO_MEMORY;3311 break;3312 }3313 3314 int rc2 = VINF_SUCCESS;3315 PHDAOUTPUTSTREAM pStream;3316 switch (pCfg->DestSource.Dest)3317 {3318 case PDMAUDIOPLAYBACKDEST_FRONT:3319 pStream = &pDrv->Front;3320 break;3321 #ifdef VBOX_WITH_HDA_51_SURROUND3322 case PDMAUDIOPLAYBACKDEST_CENTER_LFE:3323 pStream = &pDrv->CenterLFE;3324 break;3325 case PDMAUDIOPLAYBACKDEST_REAR:3326 pStream = &pDrv->Rear;3327 break;3328 #endif3329 default:3330 rc2 = VERR_NOT_SUPPORTED;3331 break;3332 }3333 3334 if (RT_SUCCESS(rc2))3335 {3336 PPDMAUDIOGSTSTRMOUT pGstStrm;3337 PAUDMIXSTREAM pMixStrm;3338 3339 rc2 = pDrv->pConnector->pfnCreateOut(pDrv->pConnector, pszDesc, pCfg, &pGstStrm);3340 LogFlowFunc(("LUN#%RU8: Created output \"%s\", with rc=%Rrc\n", pDrv->uLUN, pszDesc, rc2));3341 if (RT_SUCCESS(rc2))3342 rc2 = AudioMixerAddStreamOut(pSink, pDrv->pConnector, pGstStrm, 0 /* uFlags */, &pMixStrm);3343 3344 if (RT_SUCCESS(rc2))3345 {3346 pStream->pGstStrm = pGstStrm;3347 pStream->pMixStrm = pMixStrm;3348 }3349 }3350 3351 if (RT_SUCCESS(rc))3352 rc = rc2;3353 3354 RTStrFree(pszDesc);3355 3659 } 3356 3660 … … 3379 3683 if (pSink) 3380 3684 { 3381 if (pSink->enmDir == AUDMIXSINKDIR_INPUT) 3382 { 3383 rc = hdaMixerAddStreamIn(pThis, pSink, pCfg); 3384 } 3385 else if (pSink->enmDir == AUDMIXSINKDIR_OUTPUT) 3386 { 3387 rc = hdaMixerAddStreamOut(pThis, pSink, pCfg); 3388 } 3389 else 3390 { 3391 rc = VERR_INVALID_PARAMETER; 3392 AssertFailed(); 3393 } 3685 rc = hdaMixerAddStream(pThis, pSink, pCfg); 3394 3686 } 3395 3687 else 3396 3688 rc = VERR_NOT_FOUND; 3397 3689 3398 LogFlowFunc LeaveRC(rc);3690 LogFlowFunc(("Sink=%s, enmMixerCtl=%ld, rc=%Rrc\n", pSink->pszName, enmMixerCtl, rc)); 3399 3691 return rc; 3400 3692 } … … 3416 3708 if (pSink) 3417 3709 { 3418 if (pSink->enmDir == AUDMIXSINKDIR_INPUT) 3419 { 3420 /** @todo Remove streams. */ 3421 } 3422 else if (pSink->enmDir == AUDMIXSINKDIR_OUTPUT) 3423 { 3424 /** @todo Remove streams. */ 3425 } 3426 else 3427 { 3428 rc = VERR_INVALID_PARAMETER; 3429 AssertFailed(); 3430 } 3710 AudioMixerSinkRemoveAllStreams(pSink); 3711 rc = VINF_SUCCESS; 3431 3712 } 3432 3713 else 3433 3714 rc = VERR_NOT_FOUND; 3434 3715 3435 LogFlowFunc LeaveRC(rc);3716 LogFlowFunc(("enmMixerCtl=%ld, rc=%Rrc\n", enmMixerCtl, rc)); 3436 3717 return rc; 3437 3718 } … … 3455 3736 /* Set the volume. 3456 3737 * We assume that the codec already converted it to the correct range. */ 3457 rc = AudioMixerS etSinkVolume(pSink, pVol);3738 rc = AudioMixerSinkSetVolume(pSink, pVol); 3458 3739 } 3459 3740 else … … 3477 3758 uint32_t cbOutMin = UINT32_MAX; 3478 3759 3479 int rc;3480 PHDADRIVER pDrv;3481 3482 3760 uint64_t cTicksNow = TMTimerGet(pTimer); 3483 uint64_t cTicksElapsed = cTicksNow 3761 uint64_t cTicksElapsed = cTicksNow - pThis->uTimerTS; 3484 3762 uint64_t cTicksPerSec = TMTimerGetFreq(pTimer); 3485 3763 … … 3499 3777 uint32_t cbCodecSamplesMin = cCodecSamplesMin << 1; 3500 3778 3779 #if 0 3501 3780 /* 3502 3781 * Process all driver nodes. 3503 3782 */ 3783 PHDADRIVER pDrv; 3504 3784 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node) 3505 3785 { … … 3520 3800 * This is not the optimal solution, but as we have to deal with this on a timer-based approach 3521 3801 * (until we have the audio callbacks) we need to have device' DMA engines running. */ 3522 if (! pDrv->pConnector->pfnIsValidOut(pDrv->pConnector, pDrv->Front.pGstStrm))3802 if (!AudioMixerStreamIsValid(pDrv->Front.pMixStrm)) 3523 3803 { 3524 3804 /* Use the codec's (fixed) sampling rate. */ … … 3527 3807 } 3528 3808 3529 const bool fIsActiveOut = pDrv->pConnector->pfnIsActiveOut(pDrv->pConnector, pDrv->Front.p GstStrm);3809 const bool fIsActiveOut = pDrv->pConnector->pfnIsActiveOut(pDrv->pConnector, pDrv->Front.pMixStrm->InOut.pOut); 3530 3810 if ( RT_FAILURE(rc) 3531 3811 || !fIsActiveOut) 3532 3812 { 3533 uint32_t cSamplesMin = (int)((2 * cTicksElapsed * pDrv->Front.p GstStrm->Props.uHz + cTicksPerSec) / cTicksPerSec / 2);3534 uint32_t cbSamplesMin = AUDIOMIXBUF_S2B(&pDrv->Front.p GstStrm->MixBuf, cSamplesMin);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); 3535 3815 3536 3816 #ifdef DEBUG_TIMER … … 3543 3823 cbInMax = RT_MAX(cbInMax, cbIn); 3544 3824 } 3825 #else 3826 AudioMixerSinkUpdate(pThis->pSinkFront); 3827 cbOutMin = _4K; //cbCodecSamplesMin; 3828 cbInMax = _4K; 3829 #endif 3545 3830 3546 3831 #ifdef DEBUG_TIMER … … 3552 3837 3553 3838 /** @todo Determine the streams to be handled. */ 3554 PHDASTREAM pStrmStIn = &pThis->aStreams[0]; 3555 PHDASTREAM pStrmStOut = &pThis->aStreams[4]; 3839 PHDASTREAM pStreamLineIn = &pThis->aStreams[0]; 3840 #ifdef VBOX_WITH_HDA_MIC_IN 3841 /** @todo Anything to do for mic-in? */ 3842 #endif 3843 PHDASTREAM pStreamOut = &pThis->aStreams[4]; 3556 3844 3557 3845 /* Do the actual device transfers. */ 3558 hdaTransfer(pThis, pStr mStOut,cbOutMin /* cbToProcess */, NULL /* pcbProcessed */);3559 hdaTransfer(pThis, pStr mStIn, cbInMax /* cbToProcess */, NULL /* pcbProcessed */);3846 hdaTransfer(pThis, pStreamOut, cbOutMin /* cbToProcess */, NULL /* pcbProcessed */); 3847 hdaTransfer(pThis, pStreamLineIn, cbInMax /* cbToProcess */, NULL /* pcbProcessed */); 3560 3848 3561 3849 /* Kick the timer again. */ … … 3617 3905 #endif /* VBOX_WITH_AUDIO_CALLBACKS */ 3618 3906 3619 static int hdaTransfer(PHDASTATE pThis, PHDASTREAM pStr mSt, uint32_t cbToProcess, uint32_t *pcbProcessed)3907 static int hdaTransfer(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToProcess, uint32_t *pcbProcessed) 3620 3908 { 3621 3909 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 3622 AssertPtrReturn(pStr mSt, VERR_INVALID_POINTER);3910 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 3623 3911 /* pcbProcessed is optional. */ 3912 3913 // 44100 / 200 Hz Timer = cbToProcess = 220,8 3914 cbToProcess = 440; // FIFO SIZE 3624 3915 3625 3916 if (ASMAtomicReadBool(&pThis->fInReset)) /* HDA controller in reset mode? Bail out. */ … … 3633 3924 3634 3925 bool fProceed = true; 3635 int rc = RTSemMutexRequest(pStr mSt->State.hMtx, RT_INDEFINITE_WAIT);3926 int rc = RTSemMutexRequest(pStream->State.hMtx, RT_INDEFINITE_WAIT); 3636 3927 if (RT_FAILURE(rc)) 3637 3928 return rc; 3638 3929 3639 3930 /* Stop request received? */ 3640 if (pStr mSt->State.fDoStop)3641 { 3642 pStr mSt->State.fActive = false;3643 3644 rc = RTSemEventSignal(pStr mSt->State.hStateChangedEvent);3931 if (pStream->State.fDoStop) 3932 { 3933 pStream->State.fActive = false; 3934 3935 rc = RTSemEventSignal(pStream->State.hStateChangedEvent); 3645 3936 AssertRC(rc); 3646 3937 … … 3648 3939 } 3649 3940 /* Is the stream not in a running state currently? */ 3650 else if (!(HDA_STREAM_REG(pThis, CTL, pStr mSt->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)))3941 else if (!(HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN))) 3651 3942 fProceed = false; 3652 3943 /* Nothing to process? */ … … 3654 3945 fProceed = false; 3655 3946 3947 #if 0 3948 Log3Func(("[SD%RU8] fProceed=%RTbool, fRun=%RTbool, cbToProcess=%RU32\n", 3949 pStrmSt->u8SD, fProceed, HDA_STREAM_REG(pThis, CTL, pStrmSt->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN), 3950 cbToProcess)); 3951 #endif 3952 3953 if ((HDA_STREAM_REG(pThis, STS, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS))) 3954 { 3955 Log3Func(("[SD%RU8]: BCIS: Skipping\n", pStream->u8SD)); 3956 fProceed = false; 3957 } 3958 3656 3959 if (!fProceed) 3657 3960 { 3658 rc = RTSemMutexRelease(pStr mSt->State.hMtx);3961 rc = RTSemMutexRelease(pStream->State.hMtx); 3659 3962 AssertRC(rc); 3660 3963 … … 3665 3968 3666 3969 /* Sanity checks. */ 3667 Assert(pStr mSt->u8SD <= HDA_MAX_STREAMS);3668 Assert(pStr mSt->u64BDLBase);3669 Assert(pStr mSt->u32CBL);3970 Assert(pStream->u8SD <= HDA_MAX_STREAMS); 3971 Assert(pStream->u64BDLBase); 3972 Assert(pStream->u32CBL); 3670 3973 3671 3974 /* State sanity checks. */ 3672 Assert(pStrmSt->State.fInReset == false); 3673 3674 uint32_t cbProcessedTotal = 0; 3675 bool fIsComplete = false; 3676 3677 while (cbToProcess) 3678 { 3975 Assert(pStream->State.fInReset == false); 3976 3977 // uint32_t cbLeft = cbToProcess; 3978 uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStream->u8SD); 3979 Assert(u32LPIB <= pStream->u32CBL); 3980 3981 if (u32LPIB == pStream->u32CBL) 3982 u32LPIB = hdaStreamUpdateLPIB(pThis, pStream, 0); 3983 3984 uint32_t cbLeft = pStream->u32CBL - u32LPIB; 3985 uint32_t cbTotal = 0; 3986 3987 bool fInterrupt = false; 3988 3989 Log3Func(("cbLeft=%RU32\n", cbLeft)); 3990 3991 while (cbLeft) 3992 { 3993 #if 1 3679 3994 /* Do we need to fetch the next Buffer Descriptor Entry (BDLE)? */ 3680 if (hdaStreamNeedsNextBDLE(pThis, pStr mSt))3995 if (hdaStreamNeedsNextBDLE(pThis, pStream)) 3681 3996 { 3682 rc = hdaStreamGetNextBDLE(pThis, pStr mSt);3997 rc = hdaStreamGetNextBDLE(pThis, pStream); 3683 3998 if (RT_FAILURE(rc)) 3684 3999 break; 3685 4000 } 4001 #else 4002 PHDABDLE pBDLE = &pStream->State.BDLE; 4003 4004 /* Did we reach the CBL (Cyclic Buffer List) limit? */ 4005 bool fCBLLimitReached = u32LPIB >= pStream->u32CBL; 4006 4007 /* Do we need to use the next BDLE entry? Either because we reached 4008 * the CBL limit or our internal DMA buffer is full. */ 4009 bool fNeedsNextBDLE = ( fCBLLimitReached 4010 || (pBDLE->State.u32BufOff >= pBDLE->u32BufSize)); 4011 4012 Assert(u32LPIB <= pStream->u32CBL); 4013 Assert(pBDLE->State.u32BufOff <= pBDLE->u32BufSize); 4014 4015 if (fNeedsNextBDLE) 4016 { 4017 4018 4019 #if 1 4020 if (/* IOC (Interrupt On Completion) bit set? */ 4021 pBDLE->fIntOnCompletion 4022 /* All data put into the DMA FIFO? */ 4023 && pBDLE->State.cbBelowFIFOW == 0 4024 ) 4025 { 4026 // fSetIRQ = true; 4027 /* 4028 * If the ICE (IOCE, "Interrupt On Completion Enable") bit of the SDCTL register is set 4029 * we need to generate an interrupt. 4030 */ 4031 // if (HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE)) 4032 // PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0 , 1 /* Raised */); 4033 } 4034 #endif 4035 4036 4037 } 4038 #endif 3686 4039 3687 4040 /* Set the FIFORDY bit on the stream while doing the transfer. */ 3688 HDA_STREAM_REG(pThis, STS, pStrmSt->u8SD) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY); 3689 3690 /* 3691 * The register layout specifies that input streams (SDI) come first, 3692 * followed by the output streams (SDO). So every stream ID below HDA_MAX_SDI 3693 * is an input stream, whereas everything >= HDA_MAX_SDI is an output stream. 3694 */ 4041 // HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY); 4042 3695 4043 uint32_t cbProcessed; 3696 if ( pStrmSt->u8SD < HDA_MAX_SDI)3697 rc = hdaReadAudio (pThis, pStr mSt, cbToProcess, &cbProcessed);4044 if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_IN) 4045 rc = hdaReadAudio (pThis, pStream, cbLeft, &cbProcessed); 3698 4046 else 3699 rc = hdaWriteAudio(pThis, pStr mSt, cbToProcess, &cbProcessed);4047 rc = hdaWriteAudio(pThis, pStream, cbLeft, &cbProcessed); 3700 4048 3701 4049 /* Remove the FIFORDY bit again. */ 3702 HDA_STREAM_REG(pThis, STS, pStrmSt->u8SD) &= ~HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);4050 // HDA_STREAM_REG(pThis, STS, pStream->u8SD) &= ~HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY); 3703 4051 3704 4052 if (RT_FAILURE(rc)) 3705 4053 break; 3706 4054 3707 hdaStreamTransferUpdate(pThis, pStrmSt, cbProcessed); 3708 3709 cbToProcess -= RT_MIN(cbToProcess, cbProcessed); 4055 #if 1 4056 hdaStreamTransferUpdate(pThis, pStream, cbProcessed); 4057 4058 Assert(cbLeft >= cbProcessed); 4059 cbLeft -= cbProcessed; 4060 cbTotal += cbProcessed; 4061 4062 LogFlowFunc(("cbProcessed=%RU32, cbLeft=%RU32, cbTotal=%RU32, rc=%Rrc\n", 4063 cbProcessed, cbLeft, cbTotal, rc)); 4064 4065 if (rc == VINF_EOF) 4066 break; 4067 4068 if (hdaStreamTransferIsComplete(pThis, pStream, &fInterrupt)) 4069 { 4070 rc = hdaStreamGetNextBDLE(pThis, pStream); 4071 break; 4072 } 4073 #else 4074 Assert(cbProcessedLeft >= cbProcessed); 4075 cbProcessedLeft -= cbProcessed; 3710 4076 cbProcessedTotal += cbProcessed; 3711 4077 3712 LogFlowFunc(("cbProcessed=%RU32, cbToProcess=%RU32, cbProcessedTotal=%RU32, rc=%Rrc\n", 3713 cbProcessed, cbToProcess, cbProcessedTotal, rc)); 3714 3715 if (rc == VINF_EOF) 4078 4079 u32LPIB = hdaStreamUpdateLPIB(pThis, pStream, u32LPIB + cbProcessed); 4080 4081 Assert(u32LPIB <= pStream->u32CBL); 4082 if (u32LPIB == pStream->u32CBL) 4083 { 4084 // HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS); 4085 Log3Func(("[SD%RU8]: Transfer complete\n", pStream->u8SD)); 4086 #if 1 4087 if (/* IOC (Interrupt On Completion) bit set? */ 4088 pBDLE->fIntOnCompletion 4089 /* All data put into the DMA FIFO? */ 4090 && pBDLE->State.cbBelowFIFOW == 0 4091 ) 4092 { 4093 fSetIRQ = true; 4094 /* 4095 * If the ICE (IOCE, "Interrupt On Completion Enable") bit of the SDCTL register is set 4096 * we need to generate an interrupt. 4097 */ 4098 // if (HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE)) 4099 // PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0 , 1 /* Raised */); 4100 // fIRQ = true; 4101 } 4102 #endif 3716 4103 fIsComplete = true; 3717 3718 if (!fIsComplete) 3719 fIsComplete = hdaStreamTransferIsComplete(pThis, pStrmSt); 3720 3721 if (fIsComplete) 3722 break; 3723 } 4104 } 4105 4106 if ( fIsComplete 4107 || pBDLE->State.u32BufOff >= pBDLE->u32BufSize) 4108 { 4109 Assert(pBDLE->State.u32BufOff <= pBDLE->u32BufSize); 4110 4111 Log3Func(("[SD%RU8]: LPIB=%RU32, CBL=%RU32, %R[bdle] => Next BDLE\n", 4112 pStream->u8SD, u32LPIB, u32LPIB >= pStream->u32CBL, pBDLE)); 4113 4114 /* 4115 * Switch to the next BDLE entry and do a wrap around 4116 * if we reached the end of the Buffer Descriptor List (BDL). 4117 */ 4118 pStream->State.uCurBDLE++; 4119 if (pStream->State.uCurBDLE == pStream->u16LVI + 1) 4120 { 4121 pStream->State.uCurBDLE = 0; 4122 u32LPIB = hdaStreamUpdateLPIB(pThis, pStream, 0); 4123 } 4124 4125 hdaBDLEFetch(pThis, &pStream->State.BDLE, pStream->u64BDLBase, pStream->State.uCurBDLE); 4126 4127 if (/* IOC (Interrupt On Completion) bit set? */ 4128 pBDLE->fIntOnCompletion 4129 /* All data put into the DMA FIFO? */ 4130 && pBDLE->State.cbBelowFIFOW == 0 4131 ) 4132 { 4133 fSetIRQ = true; 4134 } 4135 } 4136 4137 #endif 4138 4139 /*if (fIsComplete) 4140 break;*/ 4141 } 4142 4143 if (fInterrupt) 4144 { 4145 /** 4146 * Set the BCIS (Buffer Completion Interrupt Status) flag as the 4147 * last byte of data for the current descriptor has been fetched 4148 * from memory and put into the DMA FIFO. 4149 * 4150 * Speech synthesis works fine on Mac Guest if this bit isn't set 4151 * but in general sound quality gets worse. 4152 * 4153 * This must be set in *any* case. 4154 */ 4155 HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS); 4156 Log3Func(("[SD%RU8]: BCIS: Set (fInterrupt=%RTbool)\n", pStream->u8SD, fInterrupt)); 4157 4158 hdaProcessInterrupt(pThis); 4159 } 4160 4161 #if 0 4162 if (fSetIRQ) 4163 { 4164 Log3Func(("[SD%RU8]: IRQ\n", pStream->u8SD)); 4165 4166 /** 4167 * Set the BCIS (Buffer Completion Interrupt Status) flag as the 4168 * last byte of data for the current descriptor has been fetched 4169 * from memory and put into the DMA FIFO. 4170 * 4171 * Speech synthesis works fine on Mac Guest if this bit isn't set 4172 * but in general sound quality gets worse. 4173 * 4174 * This must be set in *any* case. 4175 */ 4176 HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS); 4177 4178 /* 4179 * If the ICE (IOCE, "Interrupt On Completion Enable") bit of the SDCTL register is set 4180 * we need to generate an interrupt. 4181 */ 4182 if (HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE)) 4183 PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0 , 1 /* Raised */); 4184 } 4185 #endif 4186 4187 Log3Func(("Written %RU32 / %RU32 (left: %RU32), rc=%Rrc\n", cbTotal, cbToProcess, cbLeft, rc)); 3724 4188 3725 4189 if (RT_SUCCESS(rc)) 3726 4190 { 3727 4191 if (pcbProcessed) 3728 *pcbProcessed = cbProcessedTotal; 3729 } 3730 else 3731 LogFlowFunc(("Failed with %Rrc\n", rc)); 3732 3733 int rc2 = RTSemMutexRelease(pStrmSt->State.hMtx); 4192 *pcbProcessed = cbTotal; 4193 } 4194 4195 int rc2 = RTSemMutexRelease(pStream->State.hMtx); 3734 4196 if (RT_SUCCESS(rc)) 3735 4197 rc = rc2; … … 3838 4300 if (pThis->fInReset && idxRegDsc != HDA_REG_GCTL) 3839 4301 { 3840 LogRel2(("HDA: Access to register 0x%x is blocked while reset\n", idxRegDsc));4302 LogRel2(("HDA: Warning: Access to register 0x%x is blocked while reset\n", idxRegDsc)); 3841 4303 return VINF_SUCCESS; 3842 4304 } … … 3847 4309 #endif 3848 4310 int rc = g_aHdaRegMap[idxRegDsc].pfnWrite(pThis, idxRegDsc, u32Value); 3849 Log3Func((" write %#x -> %s[%db]; %x => %x%s\n", u32Value, g_aHdaRegMap[idxRegDsc].abbrev,4311 Log3Func(("Written value %#x to %s[%d byte]; %x => %x%s\n", u32Value, g_aHdaRegMap[idxRegDsc].abbrev, 3850 4312 g_aHdaRegMap[idxRegDsc].size, u32CurValue, pThis->au32Regs[idxRegMem], pszLog)); 3851 4313 return rc; … … 4380 4842 { 4381 4843 /* 4382 * Update s tuffafter the state changes.4844 * Update sinks after the state changes. 4383 4845 */ 4384 bool fEnableIn = RT_BOOL(HDA_SDCTL(pThis, 0 /** @todo Use a define. */) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)); 4846 AUDMIXSINKCMD enmCmdLineIn = RT_BOOL(HDA_SDCTL(pThis, 0 /** @todo Use a define. */) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)) 4847 ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE; 4385 4848 #ifdef VBOX_WITH_HDA_MIC_IN 4386 bool fEnableMicIn = RT_BOOL(HDA_SDCTL(pThis, 2 /** @todo Use a define. */) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)); 4387 #endif 4388 bool fEnableOut = RT_BOOL(HDA_SDCTL(pThis, 4 /** @todo Use a define. */) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)); 4389 4390 PHDADRIVER pDrv; 4391 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node) 4392 { 4393 PPDMIAUDIOCONNECTOR pCon = pDrv->pConnector; 4394 rc = pCon->pfnEnableIn(pCon, pDrv->LineIn.pGstStrm, fEnableIn); 4395 if (RT_FAILURE(rc)) 4396 break; 4397 #ifdef VBOX_WITH_HDA_MIC_IN 4398 rc = pCon->pfnEnableIn(pCon, pDrv->MicIn.pGstStrm, fEnableMicIn); 4399 if (RT_FAILURE(rc)) 4400 break; 4401 #endif 4402 rc = pCon->pfnEnableOut(pCon, pDrv->Front.pGstStrm, fEnableOut); 4403 if (RT_FAILURE(rc)) 4404 break; 4405 #ifdef VBOX_WITH_HDA_51_SURROUND 4406 rc = pCon->pfnEnableOut(pCon, pDrv->CenterLFE.pGstStrm, fEnableOut); 4407 if (RT_FAILURE(rc)) 4408 break; 4409 rc = pCon->pfnEnableOut(pCon, pDrv->Rear.pGstStrm, fEnableOut); 4410 if (RT_FAILURE(rc)) 4411 break; 4412 #endif 4413 if (RT_FAILURE(rc)) 4414 break; 4415 } 4849 AUDMIXSINKCMD enmCmdMicIn = RT_BOOL(HDA_SDCTL(pThis, 2 /** @todo Use a define. */) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)) 4850 ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE; 4851 #endif 4852 AUDMIXSINKCMD enmCmdOut = RT_BOOL(HDA_SDCTL(pThis, 4 /** @todo Use a define. */) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)) 4853 ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE; 4854 4855 # ifdef VBOX_WITH_HDA_MIC_IN 4856 AudioMixerSinkCtl(pThis->pSinkMicIn, enmCmdMicIn); 4857 # endif 4858 AudioMixerSinkCtl(pThis->pSinkLineIn, enmCmdLineIn); 4859 AudioMixerSinkCtl(pThis->pSinkFront, enmCmdOut); 4860 # ifdef VBOX_WITH_HDA_51_SURROUND 4861 AudioMixerSinkCtl(pThis->pSinkCenterLFE, enmCmdOut); 4862 AudioMixerSinkCtl(pThis->pSinkRear, enmCmdOut); 4863 # endif 4416 4864 } 4417 4865 … … 4423 4871 4424 4872 /* Also make sure to update the DMA position bit if this was enabled when saving the state. */ 4425 pThis->fDMAPosition = RT_BOOL( HDA_REG(pThis, DPLBASE) & RT_BIT_32(0));4873 pThis->fDMAPosition = RT_BOOL(pThis->u64DPBase & RT_BIT_64(0)); 4426 4874 } 4427 4875 else … … 4445 4893 PHDABDLE pBDLE = (PHDABDLE)pvValue; 4446 4894 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, 4447 "BDLE(idx:%RU32, off:%RU32, fifow:%RU32, DMA[%RU32 bytes @ 0x%x])", 4448 pBDLE->State.u32BDLIndex, pBDLE->State.u32BufOff, pBDLE->State.cbBelowFIFOW, pBDLE->u32BufSize, pBDLE->u64BufAdr); 4895 "BDLE(idx:%RU32, off:%RU32, fifow:%RU32, IOC:%RTbool, DMA[%RU32 bytes @ 0x%x])", 4896 pBDLE->State.u32BDLIndex, pBDLE->State.u32BufOff, pBDLE->State.cbBelowFIFOW, pBDLE->fIntOnCompletion, 4897 pBDLE->u32BufSize, pBDLE->u64BufAdr); 4449 4898 } 4450 4899 … … 4756 5205 * Stop any audio currently playing and/or recording. 4757 5206 */ 4758 PHDADRIVER pDrv; 4759 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node) 4760 { 4761 pDrv->pConnector->pfnEnableIn(pDrv->pConnector, pDrv->LineIn.pGstStrm, false /* Disable */); 5207 AudioMixerSinkCtl(pThis->pSinkFront, AUDMIXSINKCMD_DISABLE); 4762 5208 # ifdef VBOX_WITH_HDA_MIC_IN 4763 pDrv->pConnector->pfnEnableIn(pDrv->pConnector, pDrv->MicIn.pGstStrm, false /* Disable */);5209 AudioMixerSinkCtl(pThis->pSinkMicIn, AUDMIXSINKCMD_DISABLE); 4764 5210 # endif 4765 pDrv->pConnector->pfnEnableOut(pDrv->pConnector, pDrv->Front.pGstStrm, false /* Disable */);5211 AudioMixerSinkCtl(pThis->pSinkLineIn, AUDMIXSINKCMD_DISABLE); 4766 5212 # ifdef VBOX_WITH_HDA_51_SURROUND 4767 pDrv->pConnector->pfnEnableOut(pDrv->pConnector, pDrv->CenterLFE.pGstStrm, false /* Disable */);4768 pDrv->pConnector->pfnEnableOut(pDrv->pConnector, pDrv->Rear.pGstStrm, false /* Disable */);5213 AudioMixerSinkCtl(pThis->pSinkCenterLFE, AUDMIXSINKCMD_DISABLE); 5214 AudioMixerSinkCtl(pThis->pSinkRear, AUDMIXSINKCMD_DISABLE); 4769 5215 # endif 4770 }4771 5216 4772 5217 pThis->cbCorbBuf = 256 * sizeof(uint32_t); /** @todo Use a define here. */ … … 4789 5234 /* Remove the RUN bit from SDnCTL in case the stream was in a running state before. */ 4790 5235 HDA_STREAM_REG(pThis, CTL, i) &= ~HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN); 4791 hdaStreamReset(pThis, &pThis->aStreams[i] , i);5236 hdaStreamReset(pThis, &pThis->aStreams[i]); 4792 5237 } 4793 5238 … … 4830 5275 } 4831 5276 4832 if (pThis->pMixer)4833 {4834 AudioMixerDestroy(pThis->pMixer);4835 pThis->pMixer = NULL;4836 }4837 4838 5277 if (pThis->pCodec) 4839 5278 { 4840 int rc = hdaCodecDestruct(pThis->pCodec); 4841 AssertRC(rc); 5279 hdaCodecDestruct(pThis->pCodec); 4842 5280 4843 5281 RTMemFree(pThis->pCodec); … … 4957 5395 4958 5396 /** 4959 * Re-attach. 5397 * Powers off the device. 5398 * 5399 * @param pDevIns Device instance to power off. 5400 */ 5401 static DECLCALLBACK(void) hdaPowerOff(PPDMDEVINS pDevIns) 5402 { 5403 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE); 5404 5405 LogRel2(("HDA: Powering off ...\n")); 5406 5407 /** 5408 * Note: Destroy the mixer while powering off and *not* in hdaDestruct, 5409 * giving the mixer the chance to release any references held to 5410 * PDM audio streams it maintains. 5411 */ 5412 if (pThis->pMixer) 5413 { 5414 AudioMixerDestroy(pThis->pMixer); 5415 pThis->pMixer = NULL; 5416 } 5417 5418 /* Ditto goes for the codec, which in turn uses the mixer. */ 5419 hdaCodecPowerOff(pThis->pCodec); 5420 } 5421 5422 /** 5423 * Re-attaches a new driver to the device's driver chain. 4960 5424 * 4961 5425 * @returns VBox status code. 4962 * @param pThis Device instance .5426 * @param pThis Device instance to re-attach driver to. 4963 5427 * @param pDrv Driver instance used for attaching to. 4964 5428 * If NULL is specified, a new driver will be created and appended … … 5166 5630 5167 5631 RTListInit(&pThis->lstDrv); 5168 #ifdef VBOX_WITH_HDA_INTERLEAVING_STREAMS_SUPPORT5169 rc = RTCircBufCreate(&pThis->pCircBuf, _4K);5170 if (RT_FAILURE(rc))5171 return rc;5172 #endif5173 5632 5174 5633 uint8_t uLUN; … … 5205 5664 streamCfg.uHz = 44100; 5206 5665 streamCfg.cChannels = 2; 5207 streamCfg.enmFormat = AUD_FMT_S16;5666 streamCfg.enmFormat = PDMAUDIOFMT_S16; 5208 5667 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS; 5209 5668 … … 5215 5674 */ 5216 5675 #ifdef VBOX_WITH_HDA_51_SURROUND 5217 rc = AudioMixer AddSink(pThis->pMixer, "[Playback] Front",5218 AUDMIXSINKDIR_OUTPUT, &pThis->pSinkFront);5676 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Front", 5677 AUDMIXSINKDIR_OUTPUT, &pThis->pSinkFront); 5219 5678 AssertRC(rc); 5220 rc = AudioMixer AddSink(pThis->pMixer, "[Playback] Center / Subwoofer",5221 AUDMIXSINKDIR_OUTPUT, &pThis->pSinkCenterLFE);5679 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Center / Subwoofer", 5680 AUDMIXSINKDIR_OUTPUT, &pThis->pSinkCenterLFE); 5222 5681 AssertRC(rc); 5223 rc = AudioMixer AddSink(pThis->pMixer, "[Playback] Rear",5224 AUDMIXSINKDIR_OUTPUT, &pThis->pSinkRear);5682 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Rear", 5683 AUDMIXSINKDIR_OUTPUT, &pThis->pSinkRear); 5225 5684 AssertRC(rc); 5226 5685 #else 5227 rc = AudioMixer AddSink(pThis->pMixer, "[Playback] PCM Output",5228 AUDMIXSINKDIR_OUTPUT, &pThis->pSinkFront);5686 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] PCM Output", 5687 AUDMIXSINKDIR_OUTPUT, &pThis->pSinkFront); 5229 5688 AssertRC(rc); 5230 5689 #endif … … 5232 5691 * Add mixer input sinks. 5233 5692 */ 5234 rc = AudioMixer AddSink(pThis->pMixer, "[Recording] Line In",5235 AUDMIXSINKDIR_INPUT, &pThis->pSinkLineIn);5693 rc = AudioMixerCreateSink(pThis->pMixer, "[Recording] Line In", 5694 AUDMIXSINKDIR_INPUT, &pThis->pSinkLineIn); 5236 5695 AssertRC(rc); 5237 5696 #ifdef VBOX_WITH_HDA_MIC_IN 5238 rc = AudioMixer AddSink(pThis->pMixer, "[Recording] Microphone In",5239 AUDMIXSINKDIR_INPUT, &pThis->pSinkMicIn);5697 rc = AudioMixerCreateSink(pThis->pMixer, "[Recording] Microphone In", 5698 AUDMIXSINKDIR_INPUT, &pThis->pSinkMicIn); 5240 5699 AssertRC(rc); 5241 5700 #endif … … 5254 5713 return PDMDEV_SET_ERROR(pDevIns, VERR_NO_MEMORY, N_("Out of memory allocating HDA codec state")); 5255 5714 5256 /* Audio driver callbacks for multiplexing. */5715 /* Set codec callbacks. */ 5257 5716 pThis->pCodec->pfnMixerAddStream = hdaMixerAddStream; 5258 5717 pThis->pCodec->pfnMixerRemoveStream = hdaMixerRemoveStream; … … 5320 5779 AssertPtr(pCon); 5321 5780 5322 bool fValidLineIn = pCon->pfnIsValidIn(pCon, pDrv->LineIn.pGstStrm);5781 bool fValidLineIn = AudioMixerStreamIsValid(pDrv->LineIn.pMixStrm); 5323 5782 #ifdef VBOX_WITH_HDA_MIC_IN 5324 bool fValidMicIn = pCon->pfnIsValidIn (pCon, pDrv->MicIn.pGstStrm); 5325 #endif 5326 bool fValidOut = pCon->pfnIsValidOut(pCon, pDrv->Front.pGstStrm); 5783 bool fValidMicIn = AudioMixerStreamIsValid(pDrv->MicIn.pMixStrm); 5784 #endif 5785 bool fValidOut = AudioMixerStreamIsValid(pDrv->Front.pMixStrm); 5786 #ifdef VBOX_WITH_HDA_51_SURROUND 5787 /** @todo Anything to do here? */ 5788 #endif 5327 5789 5328 5790 if ( !fValidLineIn … … 5346 5808 5347 5809 PDMAUDIOBACKENDCFG backendCfg; 5348 int rc2 = pCon->pfnGetConfig uration(pCon, &backendCfg);5810 int rc2 = pCon->pfnGetConfig(pCon, &backendCfg); 5349 5811 if (RT_SUCCESS(rc2)) 5350 5812 { … … 5609 6071 NULL, 5610 6072 /* pfnPowerOff */ 5611 NULL,6073 hdaPowerOff, 5612 6074 /* pfnSoftReset */ 5613 6075 NULL, -
trunk/src/VBox/Devices/Audio/DevIchHdaCodec.cpp
r60643 r60925 1074 1074 CODEC_F1C_COLOR_GREEN, 1075 1075 CODEC_F1C_MISC_NONE, 1076 CODEC_F1C_ASSOCIATION_GROUP_ 0, 0xF/* Seq */);1076 CODEC_F1C_ASSOCIATION_GROUP_1, 0x0 /* Seq */); 1077 1077 goto port_init; 1078 1078 } … … 1098 1098 CODEC_F1C_COLOR_BLACK, 1099 1099 CODEC_F1C_MISC_NONE, 1100 CODEC_F1C_ASSOCIATION_GROUP_ 1, 0xE/* Seq */);1100 CODEC_F1C_ASSOCIATION_GROUP_0, 0x1 /* Seq */); 1101 1101 goto port_init; 1102 1102 } … … 1147 1147 CODEC_F1C_COLOR_PINK, 1148 1148 CODEC_F1C_MISC_NONE, 1149 CODEC_F1C_ASSOCIATION_GROUP_ 15, 0xD/* Seq */);1149 CODEC_F1C_ASSOCIATION_GROUP_4, 0x0 /* Seq */); 1150 1150 /* Fall through is intentional. */ 1151 1151 1152 port_init: 1152 1153 … … 1173 1174 | CODEC_F00_09_CAP_UNSOL 1174 1175 | CODEC_F00_09_CAP_STEREO; 1176 1175 1177 pNode->port.node.au32F00_param[0xC] = CODEC_F00_0C_CAP_INPUT 1176 1178 | CODEC_F00_0C_CAP_PRESENCE_DETECT; … … 1183 1185 CODEC_F1C_COLOR_BLUE, 1184 1186 CODEC_F1C_MISC_NONE, 1185 CODEC_F1C_ASSOCIATION_GROUP_ 15, 0xE/* Seq */);1187 CODEC_F1C_ASSOCIATION_GROUP_4, 0x1 /* Seq */); 1186 1188 break; 1187 1189 } … … 1198 1200 | CODEC_F00_09_CAP_OUT_AMP_PRESENT 1199 1201 | CODEC_F00_09_CAP_STEREO; 1202 1200 1203 pNode->port.node.au32F00_param[0xC] = CODEC_F00_0C_CAP_INPUT 1201 1204 | CODEC_F00_0C_CAP_OUTPUT; … … 1212 1215 CODEC_F1C_COLOR_ORANGE, 1213 1216 CODEC_F1C_MISC_NONE, 1214 CODEC_F1C_ASSOCIATION_GROUP_ 1, 0x0/* Seq */);1217 CODEC_F1C_ASSOCIATION_GROUP_0, 0x2 /* Seq */); 1215 1218 break; 1216 1219 } … … 1267 1270 CODEC_F1C_COLOR_BLACK, 1268 1271 CODEC_F1C_MISC_NONE, 1269 CODEC_F1C_ASSOCIATION_GROUP_ 3, 0x0 /* Seq */);1272 CODEC_F1C_ASSOCIATION_GROUP_5, 0x0 /* Seq */); 1270 1273 break; 1271 1274 } … … 1280 1283 { 1281 1284 pNode->adcmux.u32F01_param = 1; /* Connection select control index (STAC9220_NID_PIN_CD). */ 1282 1283 1285 /* Fall through is intentional. */ 1286 1284 1287 adcmux_init: 1285 1288 … … 1304 1307 1305 1308 /* STAC 9220 v10 6.21-22.{4,5} both(left and right) out amplifiers initialized with 0. */ 1306 RT_ BZERO(pNode->adcmux.B_params, AMPLIFIER_SIZE);1309 RT_ZERO(pNode->adcmux.B_params); 1307 1310 break; 1308 1311 } … … 1317 1320 pNode->pcbeep.node.au32F00_param[0xD] = CODEC_MAKE_F00_0D(0, 17, 3, 3); 1318 1321 1319 RT_ BZERO(pNode->pcbeep.B_params, AMPLIFIER_SIZE);1322 RT_ZERO(pNode->pcbeep.B_params); 1320 1323 break; 1321 1324 } … … 1334 1337 CODEC_F1C_COLOR_UNKNOWN, 1335 1338 CODEC_F1C_MISC_NONE, 1336 CODEC_F1C_ASSOCIATION_GROUP_ 15, 0xF/* Seq */);1339 CODEC_F1C_ASSOCIATION_GROUP_4, 0x2 /* Seq */); 1337 1340 break; 1338 1341 } … … 1355 1358 } 1356 1359 1357 case STAC9220_NID_AMP_ADC0: 1360 case STAC9220_NID_AMP_ADC0: /* ADC0Vol */ 1358 1361 { 1359 1362 pNode->adcvol.node.au32F02_param[0] = STAC9220_NID_ADC0_MUX; … … 1361 1364 } 1362 1365 1363 case STAC9220_NID_AMP_ADC1: 1366 case STAC9220_NID_AMP_ADC1: /* ADC1Vol */ 1364 1367 { 1365 1368 pNode->adcvol.node.au32F02_param[0] = STAC9220_NID_ADC1_MUX; 1366 1367 1369 /* Fall through is intentional. */ 1370 1368 1371 adcvol_init: 1369 1370 pNode->adcvol.u32F0c_param = 0;1371 1372 1372 1373 pNode->adcvol.node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_SELECTOR, 0, 0) … … 1379 1380 pNode->adcvol.node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(CODEC_F00_0E_LIST_NID_SHORT, 1 /* Entries */); 1380 1381 1381 RT_ BZERO(pNode->adcvol.B_params, AMPLIFIER_SIZE);1382 RT_ZERO(pNode->adcvol.B_params); 1382 1383 AMPLIFIER_REGISTER(pNode->adcvol.B_params, AMPLIFIER_IN, AMPLIFIER_LEFT, 0) = RT_BIT(7); 1383 1384 AMPLIFIER_REGISTER(pNode->adcvol.B_params, AMPLIFIER_IN, AMPLIFIER_RIGHT, 0) = RT_BIT(7); … … 1411 1412 | CODEC_F00_09_CAP_CONNECTION_LIST 1412 1413 | CODEC_F00_09_CAP_STEREO; 1414 1413 1415 pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_OUTPUT; 1414 1416 … … 1435 1437 return VINF_SUCCESS; 1436 1438 } 1437 1438 1439 1439 1440 static int stac9220Construct(PHDACODEC pThis) … … 1587 1588 * Verb processor functions. 1588 1589 */ 1589 DECLINLINE(bool) vrbIsValidNode(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)1590 {1591 AssertPtrReturn(pThis, false);1592 AssertPtrReturn(pResp, false);1593 1594 Assert(CODEC_CAD(cmd) == pThis->id);1595 Assert(CODEC_NID(cmd) < pThis->cTotalNodes);1596 if (CODEC_NID(cmd) >= pThis->cTotalNodes)1597 {1598 *pResp = 0;1599 1600 AssertMsgFailed(("Invalid node address: 0x%x (NID=0x%x [%RU8])\n", cmd, CODEC_NID(cmd)));1601 return false;1602 }1603 1604 return true;1605 }1606 1607 1590 static DECLCALLBACK(int) vrbProcUnimplemented(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 1608 1591 { … … 1624 1607 static DECLCALLBACK(int) vrbProcGetAmplifier(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 1625 1608 { 1626 if (!vrbIsValidNode(pThis, cmd, pResp))1627 return VINF_SUCCESS;1628 1629 1609 *pResp = 0; 1630 1610 … … 1673 1653 static DECLCALLBACK(int) vrbProcSetAmplifier(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 1674 1654 { 1675 if (!vrbIsValidNode(pThis, cmd, pResp))1676 return VINF_SUCCESS;1677 1678 1655 *pResp = 0; 1679 1656 … … 1735 1712 static DECLCALLBACK(int) vrbProcGetParameter(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 1736 1713 { 1737 if (!vrbIsValidNode(pThis, cmd, pResp))1738 return VINF_SUCCESS;1739 1740 1714 Assert((cmd & CODEC_VERB_8BIT_DATA) < CODECNODE_F00_PARAM_LENGTH); 1741 1715 if ((cmd & CODEC_VERB_8BIT_DATA) >= CODECNODE_F00_PARAM_LENGTH) … … 1754 1728 static DECLCALLBACK(int) vrbProcGetConSelectCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 1755 1729 { 1756 if (!vrbIsValidNode(pThis, cmd, pResp))1757 return VINF_SUCCESS;1758 1759 1730 *pResp = 0; 1760 1731 … … 1770 1741 *pResp = pThis->paNodes[CODEC_NID(cmd)].adcvol.u32F01_param; 1771 1742 else 1772 LogRel2(("HDA: Warning: Unhandled get connection select control command for NID0x% x: 0x%x\n", CODEC_NID(cmd), cmd));1743 LogRel2(("HDA: Warning: Unhandled get connection select control command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd)); 1773 1744 1774 1745 return VINF_SUCCESS; … … 1778 1749 static DECLCALLBACK(int) vrbProcSetConSelectCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 1779 1750 { 1780 if (!vrbIsValidNode(pThis, cmd, pResp))1781 return VINF_SUCCESS;1782 1783 1751 *pResp = 0; 1784 1752 … … 1795 1763 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].adcvol.u32F01_param; 1796 1764 else 1797 LogRel2(("HDA: Warning: Unhandled set connection select control command for NID0x% x: 0x%x\n", CODEC_NID(cmd), cmd));1765 LogRel2(("HDA: Warning: Unhandled set connection select control command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd)); 1798 1766 1799 1767 if (pu32Reg) … … 1806 1774 static DECLCALLBACK(int) vrbProcGetPinCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 1807 1775 { 1808 if (!vrbIsValidNode(pThis, cmd, pResp))1809 return VINF_SUCCESS;1810 1811 1776 *pResp = 0; 1812 1777 … … 1824 1789 *pResp = pThis->paNodes[CODEC_NID(cmd)].reserved.u32F07_param; 1825 1790 else 1826 LogRel2(("HDA: Warning: Unhandled get pin control command for NID0x% x: 0x%x\n", CODEC_NID(cmd), cmd));1791 LogRel2(("HDA: Warning: Unhandled get pin control command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd)); 1827 1792 1828 1793 return VINF_SUCCESS; … … 1832 1797 static DECLCALLBACK(int) vrbProcSetPinCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 1833 1798 { 1834 if (!vrbIsValidNode(pThis, cmd, pResp))1835 return VINF_SUCCESS;1836 1837 1799 *pResp = 0; 1838 1800 … … 1852 1814 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].reserved.u32F07_param; 1853 1815 else 1854 LogRel2(("HDA: Warning: Unhandled set pin control command for NID0x% x: 0x%x\n", CODEC_NID(cmd), cmd));1816 LogRel2(("HDA: Warning: Unhandled set pin control command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd)); 1855 1817 1856 1818 if (pu32Reg) … … 1863 1825 static DECLCALLBACK(int) vrbProcGetUnsolicitedEnabled(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 1864 1826 { 1865 if (!vrbIsValidNode(pThis, cmd, pResp))1866 return VINF_SUCCESS;1867 1868 1827 *pResp = 0; 1869 1828 … … 1881 1840 *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F08_param; 1882 1841 else 1883 LogRel2(("HDA: Warning: Unhandled get unsolicited enabled command for NID0x% x: 0x%x\n", CODEC_NID(cmd), cmd));1842 LogRel2(("HDA: Warning: Unhandled get unsolicited enabled command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd)); 1884 1843 1885 1844 return VINF_SUCCESS; … … 1889 1848 static DECLCALLBACK(int) vrbProcSetUnsolicitedEnabled(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 1890 1849 { 1891 if (!vrbIsValidNode(pThis, cmd, pResp))1892 return VINF_SUCCESS;1893 1894 1850 *pResp = 0; 1895 1851 … … 1908 1864 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digout.u32F08_param; 1909 1865 else 1910 LogRel2(("HDA: Warning: Unhandled set unsolicited enabled command for NID0x% x: 0x%x\n", CODEC_NID(cmd), cmd));1866 LogRel2(("HDA: Warning: Unhandled set unsolicited enabled command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd)); 1911 1867 1912 1868 if (pu32Reg) … … 1919 1875 static DECLCALLBACK(int) vrbProcGetPinSense(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 1920 1876 { 1921 if (!vrbIsValidNode(pThis, cmd, pResp))1922 return VINF_SUCCESS;1923 1924 1877 *pResp = 0; 1925 1878 … … 1929 1882 *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F09_param; 1930 1883 else 1931 LogRel2(("HDA: Warning: Unhandled get pin sense command for NID0x%x: 0x%x\n", CODEC_NID(cmd), cmd)); 1884 { 1885 AssertFailed(); 1886 LogRel2(("HDA: Warning: Unhandled get pin sense command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd)); 1887 } 1932 1888 1933 1889 return VINF_SUCCESS; … … 1937 1893 static DECLCALLBACK(int) vrbProcSetPinSense(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 1938 1894 { 1939 if (!vrbIsValidNode(pThis, cmd, pResp))1940 return VINF_SUCCESS;1941 1942 1895 *pResp = 0; 1943 1896 … … 1948 1901 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F09_param; 1949 1902 else 1950 LogRel2(("HDA: Warning: Unhandled set pin sense command for NID0x% x: 0x%x\n", CODEC_NID(cmd), cmd));1903 LogRel2(("HDA: Warning: Unhandled set pin sense command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd)); 1951 1904 1952 1905 if (pu32Reg) … … 1958 1911 static DECLCALLBACK(int) vrbProcGetConnectionListEntry(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 1959 1912 { 1960 if (!vrbIsValidNode(pThis, cmd, pResp))1961 return VINF_SUCCESS;1962 1963 1913 *pResp = 0; 1964 1914 … … 1976 1926 static DECLCALLBACK(int) vrbProcGetProcessingState(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 1977 1927 { 1978 if (!vrbIsValidNode(pThis, cmd, pResp))1979 return VINF_SUCCESS;1980 1981 1928 *pResp = 0; 1982 1929 … … 1990 1937 static DECLCALLBACK(int) vrbProcSetProcessingState(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 1991 1938 { 1992 if (!vrbIsValidNode(pThis, cmd, pResp))1993 return VINF_SUCCESS;1994 1995 1939 *pResp = 0; 1996 1940 … … 2003 1947 static DECLCALLBACK(int) vrbProcGetDigitalConverter(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 2004 1948 { 2005 if (!vrbIsValidNode(pThis, cmd, pResp))2006 return VINF_SUCCESS;2007 2008 1949 *pResp = 0; 2009 1950 … … 2018 1959 static int codecSetDigitalConverter(PHDACODEC pThis, uint32_t cmd, uint8_t u8Offset, uint64_t *pResp) 2019 1960 { 2020 if (!vrbIsValidNode(pThis, cmd, pResp))2021 return VINF_SUCCESS;2022 2023 1961 *pResp = 0; 2024 1962 … … 2109 2047 Assert(CODEC_CAD(cmd) == pThis->id); 2110 2048 Assert(CODEC_NID(cmd) == STAC9220_NID_AFG); 2049 2111 2050 if ( CODEC_NID(cmd) == STAC9220_NID_AFG 2112 2051 && pThis->pfnCodecNodeReset) 2113 2052 { 2114 2053 uint8_t i; 2115 LogFlowFunc(("enters reset\n")); 2116 Assert(pThis->pfnCodecNodeReset); 2054 LogFunc(("Entering reset ...\n")); 2055 2056 //pThis->fInReset = true; 2057 2117 2058 for (i = 0; i < pThis->cTotalNodes; ++i) 2118 {2119 2059 pThis->pfnCodecNodeReset(pThis, i, &pThis->paNodes[i]); 2120 } 2121 pThis->fInReset = false; 2122 LogFlowFunc(("exits reset\n")); 2123 } 2060 2061 //pThis->fInReset = false; 2062 2063 LogFunc(("Exited reset\n")); 2064 } 2065 2124 2066 *pResp = 0; 2125 2067 return VINF_SUCCESS; … … 2129 2071 static DECLCALLBACK(int) vrbProcGetPowerState(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 2130 2072 { 2131 if (!vrbIsValidNode(pThis, cmd, pResp))2132 return VINF_SUCCESS;2133 2134 2073 *pResp = 0; 2135 2074 … … 2138 2077 else if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd))) 2139 2078 *pResp = pThis->paNodes[CODEC_NID(cmd)].dac.u32F05_param; 2079 else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd))) 2080 *pResp = pThis->paNodes[CODEC_NID(cmd)].adc.u32F05_param; 2140 2081 else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd))) 2141 2082 *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F05_param; 2142 2083 else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd))) 2143 2084 *pResp = pThis->paNodes[CODEC_NID(cmd)].digout.u32F05_param; 2144 else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))2145 *pResp = pThis->paNodes[CODEC_NID(cmd)].adc.u32F05_param;2146 2085 else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd))) 2147 2086 *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F05_param; … … 2151 2090 *pResp = pThis->paNodes[CODEC_NID(cmd)].reserved.u32F05_param; 2152 2091 else 2153 LogRel2(("HDA: Warning: Unhandled get power state command for NID0x% x: 0x%x\n", CODEC_NID(cmd), cmd));2154 2155 LogFunc((" NID=0x%x, fReset=%RTbool, fStopOk=%RTbool, Set=%RU8, Act=%RU8\n",2156 CODEC_NID(cmd), CODEC_F05_IS_RESET(*pResp), CODEC_F05_IS_STOPOK(*pResp), CODEC_F05_ SET(*pResp), CODEC_F05_ACT(*pResp)));2092 LogRel2(("HDA: Warning: Unhandled get power state command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd)); 2093 2094 LogFunc(("[NID0x%02x]: fReset=%RTbool, fStopOk=%RTbool, Act=D%RU8, Set=D%RU8\n", 2095 CODEC_NID(cmd), CODEC_F05_IS_RESET(*pResp), CODEC_F05_IS_STOPOK(*pResp), CODEC_F05_ACT(*pResp), CODEC_F05_SET(*pResp))); 2157 2096 return VINF_SUCCESS; 2158 2097 } 2159 2098 2160 2099 /* 705 */ 2100 #if 1 2161 2101 static DECLCALLBACK(int) vrbProcSetPowerState(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 2162 2102 { 2163 if (!vrbIsValidNode(pThis, cmd, pResp))2164 return VINF_SUCCESS;2165 2166 2103 *pResp = 0; 2167 2104 … … 2184 2121 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].reserved.u32F05_param; 2185 2122 else 2186 LogRel2(("HDA: Warning: Unhandled set power state command for NID0x%x: 0x%x\n", CODEC_NID(cmd), cmd)); 2123 { 2124 AssertFailed(); 2125 LogRel2(("HDA: Warning: Unhandled set power state command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd)); 2126 } 2187 2127 2188 2128 if (!pu32Reg) … … 2191 2131 bool fReset = CODEC_F05_IS_RESET (*pu32Reg); 2192 2132 bool fStopOk = CODEC_F05_IS_STOPOK(*pu32Reg); 2133 bool fError = CODEC_F05_IS_ERROR (*pu32Reg); 2193 2134 uint8_t uPwrAct = CODEC_F05_ACT (*pu32Reg); 2194 2135 uint8_t uPwrSet = CODEC_F05_SET (*pu32Reg); 2136 2195 2137 uint8_t uPwrCmd = CODEC_F05_SET (cmd); 2196 2138 2197 LogFunc(("[NID=0x%x] Cmd=D%RU8, Act=D%RU8, Set=D%RU8 (AFG Act=D%RU8, Set=D%RU8)\n", 2198 CODEC_NID(cmd), uPwrCmd, uPwrAct, uPwrSet, 2139 LogFunc(("[NID0x%02x] Cmd=D%RU8, fReset=%RTbool, fStopOk=%RTbool, fError=%RTbool, uPwrAct=D%RU8, uPwrSet=D%RU8\n", 2140 CODEC_NID(cmd), uPwrCmd, fReset, fStopOk, fError, uPwrAct, uPwrSet)); 2141 2142 LogFunc(("AFG: Act=D%RU8, Set=D%RU8\n", 2199 2143 CODEC_F05_ACT(pThis->paNodes[STAC9220_NID_AFG].afg.u32F05_param), 2200 2144 CODEC_F05_SET(pThis->paNodes[STAC9220_NID_AFG].afg.u32F05_param))); 2201 2145 2202 const uint8_t uAFGPwrSet = CODEC_F05_SET(pThis->paNodes[STAC9220_NID_AFG].afg.u32F05_param);2203 2204 /* If this is the AFG node, PS-Act always matches the PS-Set power state.*/2205 2146 if (CODEC_NID(cmd) == STAC9220_NID_AFG) 2206 {2207 2147 *pu32Reg = CODEC_MAKE_F05(fReset, fStopOk, 0, uPwrCmd /* PS-Act */, uPwrCmd /* PS-Set */); 2208 2148 2149 const uint8_t uAFGPwrAct = CODEC_F05_ACT(pThis->paNodes[STAC9220_NID_AFG].afg.u32F05_param); 2150 if (uAFGPwrAct == CODEC_F05_D0) /* Only propagate power state if AFG is on (D0). */ 2151 { 2209 2152 /* Propagate to all other nodes under this AFG. */ 2210 LogFunc(("Propagating Set=D%RU8 to all nodes ...\n", uPwrCmd));2153 LogFunc(("Propagating Act=D%RU8 (AFG), Set=D%RU8 to all AFG child nodes ...\n", uAFGPwrAct, uPwrCmd)); 2211 2154 2212 2155 #define PROPAGATE_PWR_STATE(_aList, _aMember) \ 2213 2156 { \ 2214 2157 const uint8_t *pu8NodeIndex = &_aList[0]; \ 2215 while (*( pu8NodeIndex++)) \2158 while (*(++pu8NodeIndex)) \ 2216 2159 { \ 2217 2160 pThis->paNodes[*pu8NodeIndex]._aMember.u32F05_param = \ 2218 CODEC_MAKE_F05(fReset, fStopOk, 0, RT_MIN((uAFGPwrSet + 1), CODEC_F05_D3), \ 2219 uPwrCmd /* Always update PS-Set with command power state just received. */); \ 2220 LogFunc(("\t[NID=0x%x]: Act=D%RU8, Set=D%RU8\n", *pu8NodeIndex, \ 2161 CODEC_MAKE_F05(fReset, fStopOk, 0, uAFGPwrAct, uPwrCmd); \ 2162 LogFunc(("\t[NID0x%02x]: Act=D%RU8, Set=D%RU8\n", *pu8NodeIndex, \ 2221 2163 CODEC_F05_ACT(pThis->paNodes[*pu8NodeIndex]._aMember.u32F05_param), \ 2222 2164 CODEC_F05_SET(pThis->paNodes[*pu8NodeIndex]._aMember.u32F05_param))); \ … … 2235 2177 } 2236 2178 /* 2237 * If this node is a reqular node (not the AFG one), ad popt PS-Set of the AFG node2179 * If this node is a reqular node (not the AFG one), adopt PS-Set of the AFG node 2238 2180 * as PS-Set of this node. PS-Act always is one level under PS-Set here. 2239 2181 */ 2240 2182 else 2241 2183 { 2184 *pu32Reg = CODEC_MAKE_F05(fReset, fStopOk, 0, uAFGPwrAct, uPwrCmd); 2185 } 2186 2187 LogFunc(("[NID0x%02x] fReset=%RTbool, fStopOk=%RTbool, Act=D%RU8, Set=D%RU8\n", 2188 CODEC_NID(cmd), 2189 CODEC_F05_IS_RESET(*pu32Reg), CODEC_F05_IS_STOPOK(*pu32Reg), CODEC_F05_ACT(*pu32Reg), CODEC_F05_SET(*pu32Reg))); 2190 2191 return VINF_SUCCESS; 2192 } 2193 #else 2194 DECLINLINE(void) codecPropogatePowerState(uint32_t *pu32F05_param) 2195 { 2196 Assert(pu32F05_param); 2197 if (!pu32F05_param) 2198 return; 2199 bool fReset = CODEC_F05_IS_RESET(*pu32F05_param); 2200 bool fStopOk = CODEC_F05_IS_STOPOK(*pu32F05_param); 2201 uint8_t u8SetPowerState = CODEC_F05_SET(*pu32F05_param); 2202 *pu32F05_param = CODEC_MAKE_F05(fReset, fStopOk, 0, u8SetPowerState, u8SetPowerState); 2203 } 2204 2205 static DECLCALLBACK(int) vrbProcSetPowerState(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 2206 { 2207 Assert(CODEC_CAD(cmd) == pThis->id); 2208 Assert(CODEC_NID(cmd) < pThis->cTotalNodes); 2209 if (CODEC_NID(cmd) >= pThis->cTotalNodes) 2210 { 2211 LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd))); 2212 return VINF_SUCCESS; 2213 } 2214 *pResp = 0; 2215 uint32_t *pu32Reg; 2216 if (CODEC_NID(cmd) == 1 /* AFG */) 2217 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].afg.u32F05_param; 2218 else if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd))) 2219 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].dac.u32F05_param; 2220 else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd))) 2221 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F05_param; 2222 else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd))) 2223 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].adc.u32F05_param; 2224 else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd))) 2225 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F05_param; 2226 else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd))) 2227 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F05_param; 2228 else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd))) 2229 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].reserved.u32F05_param; 2230 else 2231 AssertFailedReturn(VINF_SUCCESS); 2232 2233 bool fReset = CODEC_F05_IS_RESET(*pu32Reg); 2234 bool fStopOk = CODEC_F05_IS_STOPOK(*pu32Reg); 2235 2236 if (CODEC_NID(cmd) != 1 /* AFG */) 2237 { 2238 /* 2239 * We shouldn't propogate actual power state, which actual for AFG 2240 */ 2242 2241 *pu32Reg = CODEC_MAKE_F05(fReset, fStopOk, 0, 2243 RT_MIN((uAFGPwrSet + 1), CODEC_F05_D3), 2244 uPwrCmd /* Always update PS-Set with command power state just received. */); 2245 } 2246 2247 if (pu32Reg) 2248 hdaCodecSetRegisterU8(pu32Reg, cmd, 0); 2249 2250 LogFunc(("[NID=0x%x] fReset=%RTbool, fStopOk=%RTbool, Act=D%RU8, Set=D%RU8\n", 2251 CODEC_NID(cmd), fReset, fStopOk, CODEC_F05_ACT(*pu32Reg), CODEC_F05_SET(*pu32Reg))); 2252 2253 return VINF_SUCCESS; 2254 } 2242 CODEC_F05_ACT(pThis->paNodes[1].afg.u32F05_param), 2243 CODEC_F05_SET(cmd)); 2244 } 2245 2246 /* Propagate next power state only if AFG is on or verb modifies AFG power state */ 2247 if ( CODEC_NID(cmd) == 1 /* AFG */ 2248 || !CODEC_F05_ACT(pThis->paNodes[1].afg.u32F05_param)) 2249 { 2250 *pu32Reg = CODEC_MAKE_F05(fReset, fStopOk, 0, CODEC_F05_SET(cmd), CODEC_F05_SET(cmd)); 2251 if ( CODEC_NID(cmd) == 1 /* AFG */ 2252 && (CODEC_F05_SET(cmd)) == CODEC_F05_D0) 2253 { 2254 /* now we're powered on AFG and may propogate power states on nodes */ 2255 const uint8_t *pu8NodeIndex = &pThis->au8Dacs[0]; 2256 while (*(++pu8NodeIndex)) 2257 codecPropogatePowerState(&pThis->paNodes[*pu8NodeIndex].dac.u32F05_param); 2258 2259 pu8NodeIndex = &pThis->au8Adcs[0]; 2260 while (*(++pu8NodeIndex)) 2261 codecPropogatePowerState(&pThis->paNodes[*pu8NodeIndex].adc.u32F05_param); 2262 2263 pu8NodeIndex = &pThis->au8DigInPins[0]; 2264 while (*(++pu8NodeIndex)) 2265 codecPropogatePowerState(&pThis->paNodes[*pu8NodeIndex].digin.u32F05_param); 2266 } 2267 } 2268 return VINF_SUCCESS; 2269 } 2270 #endif 2255 2271 2256 2272 static DECLCALLBACK(int) vrbProcGetStreamId(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 2257 2273 { 2258 if (!vrbIsValidNode(pThis, cmd, pResp))2259 return VINF_SUCCESS;2260 2261 2274 *pResp = 0; 2262 2275 … … 2272 2285 *pResp = pThis->paNodes[CODEC_NID(cmd)].reserved.u32F06_param; 2273 2286 else 2274 LogRel2(("HDA: Warning: Unhandled get stream ID command for NID0x% x: 0x%x\n", CODEC_NID(cmd), cmd));2275 2276 LogFlowFunc(("[NID0x%x] Stream ID is 0x%x\n",2277 CODEC_NID(cmd), CODEC_F00_06_GET_STREAM_ID(*pResp))); 2287 LogRel2(("HDA: Warning: Unhandled get stream ID command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd)); 2288 2289 /*LogFlowFunc(("[NID0x%02x] Stream ID is 0x%x\n", 2290 CODEC_NID(cmd), CODEC_F00_06_GET_STREAM_ID(*pResp)));*/ 2278 2291 2279 2292 return VINF_SUCCESS; … … 2283 2296 static DECLCALLBACK(int) vrbProcSetStreamId(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 2284 2297 { 2285 if (!vrbIsValidNode(pThis, cmd, pResp))2286 return VINF_SUCCESS;2287 2288 2298 *pResp = 0; 2289 2299 … … 2300 2310 pu32Addr = &pThis->paNodes[CODEC_NID(cmd)].reserved.u32F06_param; 2301 2311 else 2302 LogRel2(("HDA: Warning: Unhandled set stream ID command for NID0x% x: 0x%x\n", CODEC_NID(cmd), cmd));2303 2304 LogFlowFunc(("[NID0x%x] Setting new stream ID to 0x%x\n",2305 CODEC_NID(cmd), CODEC_F00_06_GET_STREAM_ID(cmd))); 2312 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)));*/ 2306 2316 2307 2317 if (pu32Addr) … … 2314 2324 static DECLCALLBACK(int) vrbProcGetConverterFormat(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 2315 2325 { 2316 if (!vrbIsValidNode(pThis, cmd, pResp))2317 return VINF_SUCCESS;2318 2319 2326 *pResp = 0; 2320 2327 … … 2330 2337 *pResp = pThis->paNodes[CODEC_NID(cmd)].reserved.u32A_param; 2331 2338 else 2332 LogRel2(("HDA: Warning: Unhandled get converter format command for NID0x% x: 0x%x\n", CODEC_NID(cmd), cmd));2339 LogRel2(("HDA: Warning: Unhandled get converter format command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd)); 2333 2340 2334 2341 return VINF_SUCCESS; … … 2338 2345 static DECLCALLBACK(int) vrbProcSetConverterFormat(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 2339 2346 { 2340 if (!vrbIsValidNode(pThis, cmd, pResp))2341 return VINF_SUCCESS;2342 2343 2347 *pResp = 0; 2344 2348 … … 2352 2356 hdaCodecSetRegisterU16(&pThis->paNodes[CODEC_NID(cmd)].spdifin.u32A_param, cmd, 0); 2353 2357 else 2354 LogRel2(("HDA: Warning: Unhandled set converter format command for NID0x% x: 0x%x\n", CODEC_NID(cmd), cmd));2358 LogRel2(("HDA: Warning: Unhandled set converter format command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd)); 2355 2359 2356 2360 return VINF_SUCCESS; … … 2360 2364 static DECLCALLBACK(int) vrbProcGetEAPD_BTLEnabled(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 2361 2365 { 2362 if (!vrbIsValidNode(pThis, cmd, pResp))2363 return VINF_SUCCESS;2364 2365 2366 *pResp = 0; 2366 2367 … … 2372 2373 *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F0c_param; 2373 2374 else 2374 LogRel2(("HDA: Warning: Unhandled get EAPD/BTL enabled command for NID0x% x: 0x%x\n", CODEC_NID(cmd), cmd));2375 LogRel2(("HDA: Warning: Unhandled get EAPD/BTL enabled command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd)); 2375 2376 2376 2377 return VINF_SUCCESS; … … 2380 2381 static DECLCALLBACK(int) vrbProcSetEAPD_BTLEnabled(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 2381 2382 { 2382 if (!vrbIsValidNode(pThis, cmd, pResp))2383 return VINF_SUCCESS;2384 2385 2383 *pResp = 0; 2386 2384 … … 2393 2391 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F0c_param; 2394 2392 else 2395 LogRel2(("HDA: Warning: Unhandled set EAPD/BTL enabled command for NID0x% x: 0x%x\n", CODEC_NID(cmd), cmd));2393 LogRel2(("HDA: Warning: Unhandled set EAPD/BTL enabled command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd)); 2396 2394 2397 2395 if (pu32Reg) … … 2404 2402 static DECLCALLBACK(int) vrbProcGetVolumeKnobCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 2405 2403 { 2406 if (!vrbIsValidNode(pThis, cmd, pResp))2407 return VINF_SUCCESS;2408 2409 2404 *pResp = 0; 2410 2405 … … 2412 2407 *pResp = pThis->paNodes[CODEC_NID(cmd)].volumeKnob.u32F0f_param; 2413 2408 else 2414 LogRel2(("HDA: Warning: Unhandled get volume knob control command for NID0x% x: 0x%x\n", CODEC_NID(cmd), cmd));2409 LogRel2(("HDA: Warning: Unhandled get volume knob control command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd)); 2415 2410 2416 2411 return VINF_SUCCESS; … … 2420 2415 static DECLCALLBACK(int) vrbProcSetVolumeKnobCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 2421 2416 { 2422 if (!vrbIsValidNode(pThis, cmd, pResp))2423 return VINF_SUCCESS;2424 2425 2417 *pResp = 0; 2426 2418 … … 2429 2421 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].volumeKnob.u32F0f_param; 2430 2422 else 2431 LogRel2(("HDA: Warning: Unhandled set volume knob control command for NID0x% x: 0x%x\n", CODEC_NID(cmd), cmd));2423 LogRel2(("HDA: Warning: Unhandled set volume knob control command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd)); 2432 2424 2433 2425 if (pu32Reg) … … 2440 2432 static DECLCALLBACK(int) vrbProcGetGPIOData(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 2441 2433 { 2442 if (!vrbIsValidNode(pThis, cmd, pResp))2443 return VINF_SUCCESS;2444 2445 2434 *pResp = 0; 2446 2435 … … 2451 2440 static DECLCALLBACK(int) vrbProcSetGPIOData(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 2452 2441 { 2453 if (!vrbIsValidNode(pThis, cmd, pResp))2454 return VINF_SUCCESS;2455 2456 2442 *pResp = 0; 2457 2443 … … 2462 2448 static DECLCALLBACK(int) vrbProcGetGPIOEnableMask(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 2463 2449 { 2464 if (!vrbIsValidNode(pThis, cmd, pResp))2465 return VINF_SUCCESS;2466 2467 2450 *pResp = 0; 2468 2451 … … 2473 2456 static DECLCALLBACK(int) vrbProcSetGPIOEnableMask(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 2474 2457 { 2475 if (!vrbIsValidNode(pThis, cmd, pResp))2476 return VINF_SUCCESS;2477 2478 2458 *pResp = 0; 2479 2459 … … 2484 2464 static DECLCALLBACK(int) vrbProcGetGPIOUnsolisted(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 2485 2465 { 2486 if (!vrbIsValidNode(pThis, cmd, pResp))2487 return VINF_SUCCESS;2488 2489 2466 *pResp = 0; 2490 2467 … … 2493 2470 *pResp = pThis->paNodes[1].afg.u32F17_param; 2494 2471 else 2495 LogRel2(("HDA: Warning: Unhandled get GPIO unsolisted command for NID0x% x: 0x%x\n", CODEC_NID(cmd), cmd));2472 LogRel2(("HDA: Warning: Unhandled get GPIO unsolisted command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd)); 2496 2473 2497 2474 return VINF_SUCCESS; … … 2501 2478 static DECLCALLBACK(int) vrbProcSetGPIOUnsolisted(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 2502 2479 { 2503 if (!vrbIsValidNode(pThis, cmd, pResp))2504 return VINF_SUCCESS;2505 2506 2480 *pResp = 0; 2507 2481 … … 2510 2484 pu32Reg = &pThis->paNodes[1].afg.u32F17_param; 2511 2485 else 2512 LogRel2(("HDA: Warning: Unhandled set GPIO unsolisted command for NID0x% x: 0x%x\n", CODEC_NID(cmd), cmd));2486 LogRel2(("HDA: Warning: Unhandled set GPIO unsolisted command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd)); 2513 2487 2514 2488 if (pu32Reg) … … 2521 2495 static DECLCALLBACK(int) vrbProcGetConfig(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 2522 2496 { 2523 if (!vrbIsValidNode(pThis, cmd, pResp))2524 return VINF_SUCCESS;2525 2526 2497 *pResp = 0; 2527 2498 … … 2539 2510 *pResp = pThis->paNodes[CODEC_NID(cmd)].reserved.u32F1c_param; 2540 2511 else 2541 LogRel2(("HDA: Warning: Unhandled get config command for NID0x% x: 0x%x\n", CODEC_NID(cmd), cmd));2512 LogRel2(("HDA: Warning: Unhandled get config command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd)); 2542 2513 2543 2514 return VINF_SUCCESS; … … 2560 2531 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].reserved.u32F1c_param; 2561 2532 else 2562 LogRel2(("HDA: Warning: Unhandled set config command (%RU8) for NID0x% x: 0x%x\n", u8Offset, CODEC_NID(cmd), cmd));2533 LogRel2(("HDA: Warning: Unhandled set config command (%RU8) for NID0x%02x: 0x%x\n", u8Offset, CODEC_NID(cmd), cmd)); 2563 2534 2564 2535 if (pu32Reg) … … 2571 2542 static DECLCALLBACK(int) vrbProcSetConfig0(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 2572 2543 { 2573 if (!vrbIsValidNode(pThis, cmd, pResp))2574 return VINF_SUCCESS;2575 2576 2544 *pResp = 0; 2577 2545 return codecSetConfigX(pThis, cmd, 0); … … 2581 2549 static DECLCALLBACK(int) vrbProcSetConfig1(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 2582 2550 { 2583 if (!vrbIsValidNode(pThis, cmd, pResp))2584 return VINF_SUCCESS;2585 2586 2551 *pResp = 0; 2587 2552 return codecSetConfigX(pThis, cmd, 8); … … 2591 2556 static DECLCALLBACK(int) vrbProcSetConfig2(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 2592 2557 { 2593 if (!vrbIsValidNode(pThis, cmd, pResp))2594 return VINF_SUCCESS;2595 2596 2558 *pResp = 0; 2597 2559 return codecSetConfigX(pThis, cmd, 16); … … 2601 2563 static DECLCALLBACK(int) vrbProcSetConfig3(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 2602 2564 { 2603 if (!vrbIsValidNode(pThis, cmd, pResp))2604 return VINF_SUCCESS;2605 2606 2565 *pResp = 0; 2607 2566 return codecSetConfigX(pThis, cmd, 24); 2608 2567 } 2609 2568 2569 /* F04 */ 2570 static DECLCALLBACK(int) vrbProcGetSDISelect(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 2571 { 2572 *pResp = 0; 2573 2574 if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd))) 2575 *pResp = pThis->paNodes[CODEC_NID(cmd)].dac.u32F04_param; 2576 else 2577 LogRel2(("HDA: Warning: Unhandled get SDI select command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd)); 2578 2579 return VINF_SUCCESS; 2580 } 2581 2582 /* 704 */ 2583 static DECLCALLBACK(int) vrbProcSetSDISelect(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp) 2584 { 2585 *pResp = 0; 2586 2587 uint32_t *pu32Reg = NULL; 2588 if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd))) 2589 pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].dac.u32F04_param; 2590 else 2591 LogRel2(("HDA: Warning: Unhandled set SDI select command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd)); 2592 2593 if (pu32Reg) 2594 hdaCodecSetRegisterU8(pu32Reg, cmd, 0); 2595 2596 return VINF_SUCCESS; 2597 } 2610 2598 2611 2599 /** … … 2615 2603 static const CODECVERB g_aCodecVerbs[] = 2616 2604 { 2617 /* verb | verb mask | callback */ 2618 /* ----------- -------------------- ----------------------- */ 2619 { 0x000F0000, CODEC_VERB_8BIT_CMD , vrbProcGetParameter }, 2620 { 0x000F0100, CODEC_VERB_8BIT_CMD , vrbProcGetConSelectCtrl }, 2621 { 0x00070100, CODEC_VERB_8BIT_CMD , vrbProcSetConSelectCtrl }, 2622 { 0x000F0600, CODEC_VERB_8BIT_CMD , vrbProcGetStreamId }, 2623 { 0x00070600, CODEC_VERB_8BIT_CMD , vrbProcSetStreamId }, 2624 { 0x000F0700, CODEC_VERB_8BIT_CMD , vrbProcGetPinCtrl }, 2625 { 0x00070700, CODEC_VERB_8BIT_CMD , vrbProcSetPinCtrl }, 2626 { 0x000F0800, CODEC_VERB_8BIT_CMD , vrbProcGetUnsolicitedEnabled }, 2627 { 0x00070800, CODEC_VERB_8BIT_CMD , vrbProcSetUnsolicitedEnabled }, 2628 { 0x000F0900, CODEC_VERB_8BIT_CMD , vrbProcGetPinSense }, 2629 { 0x00070900, CODEC_VERB_8BIT_CMD , vrbProcSetPinSense }, 2630 { 0x000F0200, CODEC_VERB_8BIT_CMD , vrbProcGetConnectionListEntry }, 2631 { 0x000F0300, CODEC_VERB_8BIT_CMD , vrbProcGetProcessingState }, 2632 { 0x00070300, CODEC_VERB_8BIT_CMD , vrbProcSetProcessingState }, 2633 { 0x000F0D00, CODEC_VERB_8BIT_CMD , vrbProcGetDigitalConverter }, 2634 { 0x00070D00, CODEC_VERB_8BIT_CMD , vrbProcSetDigitalConverter1 }, 2635 { 0x00070E00, CODEC_VERB_8BIT_CMD , vrbProcSetDigitalConverter2 }, 2636 { 0x000F2000, CODEC_VERB_8BIT_CMD , vrbProcGetSubId }, 2637 { 0x00072000, CODEC_VERB_8BIT_CMD , vrbProcSetSubId0 }, 2638 { 0x00072100, CODEC_VERB_8BIT_CMD , vrbProcSetSubId1 }, 2639 { 0x00072200, CODEC_VERB_8BIT_CMD , vrbProcSetSubId2 }, 2640 { 0x00072300, CODEC_VERB_8BIT_CMD , vrbProcSetSubId3 }, 2641 { 0x0007FF00, CODEC_VERB_8BIT_CMD , vrbProcReset }, 2642 { 0x000F0500, CODEC_VERB_8BIT_CMD , vrbProcGetPowerState }, 2643 { 0x00070500, CODEC_VERB_8BIT_CMD , vrbProcSetPowerState }, 2644 { 0x000F0C00, CODEC_VERB_8BIT_CMD , vrbProcGetEAPD_BTLEnabled }, 2645 { 0x00070C00, CODEC_VERB_8BIT_CMD , vrbProcSetEAPD_BTLEnabled }, 2646 { 0x000F0F00, CODEC_VERB_8BIT_CMD , vrbProcGetVolumeKnobCtrl }, 2647 { 0x00070F00, CODEC_VERB_8BIT_CMD , vrbProcSetVolumeKnobCtrl }, 2648 { 0x000F1500, CODEC_VERB_8BIT_CMD , vrbProcGetGPIOData }, 2649 { 0x00071500, CODEC_VERB_8BIT_CMD , vrbProcSetGPIOData }, 2650 { 0x000F1600, CODEC_VERB_8BIT_CMD , vrbProcGetGPIOEnableMask }, 2651 { 0x00071600, CODEC_VERB_8BIT_CMD , vrbProcSetGPIOEnableMask }, 2652 { 0x000F1700, CODEC_VERB_8BIT_CMD , vrbProcGetGPIOUnsolisted }, 2653 { 0x00071700, CODEC_VERB_8BIT_CMD , vrbProcSetGPIOUnsolisted }, 2654 { 0x000F1C00, CODEC_VERB_8BIT_CMD , vrbProcGetConfig }, 2655 { 0x00071C00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig0 }, 2656 { 0x00071D00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig1 }, 2657 { 0x00071E00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig2 }, 2658 { 0x00071F00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig3 }, 2659 { 0x000A0000, CODEC_VERB_16BIT_CMD, vrbProcGetConverterFormat }, 2660 { 0x00020000, CODEC_VERB_16BIT_CMD, vrbProcSetConverterFormat }, 2661 { 0x000B0000, CODEC_VERB_16BIT_CMD, vrbProcGetAmplifier }, 2662 { 0x00030000, CODEC_VERB_16BIT_CMD, vrbProcSetAmplifier }, 2605 /* Verb Verb mask Callback Name 2606 * ---------- --------------------- ---------------------------------------------------------- 2607 */ 2608 { 0x000F0000, CODEC_VERB_8BIT_CMD , vrbProcGetParameter , "GetParameter " }, 2609 { 0x000F0100, CODEC_VERB_8BIT_CMD , vrbProcGetConSelectCtrl , "GetConSelectCtrl " }, 2610 { 0x00070100, CODEC_VERB_8BIT_CMD , vrbProcSetConSelectCtrl , "SetConSelectCtrl " }, 2611 { 0x000F0600, CODEC_VERB_8BIT_CMD , vrbProcGetStreamId , "GetStreamId " }, 2612 { 0x00070600, CODEC_VERB_8BIT_CMD , vrbProcSetStreamId , "SetStreamId " }, 2613 { 0x000F0700, CODEC_VERB_8BIT_CMD , vrbProcGetPinCtrl , "GetPinCtrl " }, 2614 { 0x00070700, CODEC_VERB_8BIT_CMD , vrbProcSetPinCtrl , "SetPinCtrl " }, 2615 { 0x000F0800, CODEC_VERB_8BIT_CMD , vrbProcGetUnsolicitedEnabled , "GetUnsolicitedEnabled " }, 2616 { 0x00070800, CODEC_VERB_8BIT_CMD , vrbProcSetUnsolicitedEnabled , "SetUnsolicitedEnabled " }, 2617 { 0x000F0900, CODEC_VERB_8BIT_CMD , vrbProcGetPinSense , "GetPinSense " }, 2618 { 0x00070900, CODEC_VERB_8BIT_CMD , vrbProcSetPinSense , "SetPinSense " }, 2619 { 0x000F0200, CODEC_VERB_8BIT_CMD , vrbProcGetConnectionListEntry , "GetConnectionListEntry" }, 2620 { 0x000F0300, CODEC_VERB_8BIT_CMD , vrbProcGetProcessingState , "GetProcessingState " }, 2621 { 0x00070300, CODEC_VERB_8BIT_CMD , vrbProcSetProcessingState , "SetProcessingState " }, 2622 { 0x000F0D00, CODEC_VERB_8BIT_CMD , vrbProcGetDigitalConverter , "GetDigitalConverter " }, 2623 { 0x00070D00, CODEC_VERB_8BIT_CMD , vrbProcSetDigitalConverter1 , "SetDigitalConverter1 " }, 2624 { 0x00070E00, CODEC_VERB_8BIT_CMD , vrbProcSetDigitalConverter2 , "SetDigitalConverter2 " }, 2625 { 0x000F2000, CODEC_VERB_8BIT_CMD , vrbProcGetSubId , "GetSubId " }, 2626 { 0x00072000, CODEC_VERB_8BIT_CMD , vrbProcSetSubId0 , "SetSubId0 " }, 2627 { 0x00072100, CODEC_VERB_8BIT_CMD , vrbProcSetSubId1 , "SetSubId1 " }, 2628 { 0x00072200, CODEC_VERB_8BIT_CMD , vrbProcSetSubId2 , "SetSubId2 " }, 2629 { 0x00072300, CODEC_VERB_8BIT_CMD , vrbProcSetSubId3 , "SetSubId3 " }, 2630 { 0x0007FF00, CODEC_VERB_8BIT_CMD , vrbProcReset , "Reset " }, 2631 { 0x000F0500, CODEC_VERB_8BIT_CMD , vrbProcGetPowerState , "GetPowerState " }, 2632 { 0x00070500, CODEC_VERB_8BIT_CMD , vrbProcSetPowerState , "SetPowerState " }, 2633 { 0x000F0C00, CODEC_VERB_8BIT_CMD , vrbProcGetEAPD_BTLEnabled , "GetEAPD_BTLEnabled " }, 2634 { 0x00070C00, CODEC_VERB_8BIT_CMD , vrbProcSetEAPD_BTLEnabled , "SetEAPD_BTLEnabled " }, 2635 { 0x000F0F00, CODEC_VERB_8BIT_CMD , vrbProcGetVolumeKnobCtrl , "GetVolumeKnobCtrl " }, 2636 { 0x00070F00, CODEC_VERB_8BIT_CMD , vrbProcSetVolumeKnobCtrl , "SetVolumeKnobCtrl " }, 2637 { 0x000F1500, CODEC_VERB_8BIT_CMD , vrbProcGetGPIOData , "GetGPIOData " }, 2638 { 0x00071500, CODEC_VERB_8BIT_CMD , vrbProcSetGPIOData , "SetGPIOData " }, 2639 { 0x000F1600, CODEC_VERB_8BIT_CMD , vrbProcGetGPIOEnableMask , "GetGPIOEnableMask " }, 2640 { 0x00071600, CODEC_VERB_8BIT_CMD , vrbProcSetGPIOEnableMask , "SetGPIOEnableMask " }, 2641 { 0x000F1700, CODEC_VERB_8BIT_CMD , vrbProcGetGPIOUnsolisted , "GetGPIOUnsolisted " }, 2642 { 0x00071700, CODEC_VERB_8BIT_CMD , vrbProcSetGPIOUnsolisted , "SetGPIOUnsolisted " }, 2643 { 0x000F1C00, CODEC_VERB_8BIT_CMD , vrbProcGetConfig , "GetConfig " }, 2644 { 0x00071C00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig0 , "SetConfig0 " }, 2645 { 0x00071D00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig1 , "SetConfig1 " }, 2646 { 0x00071E00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig2 , "SetConfig2 " }, 2647 { 0x00071F00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig3 , "SetConfig3 " }, 2648 { 0x000A0000, CODEC_VERB_16BIT_CMD, vrbProcGetConverterFormat , "GetConverterFormat " }, 2649 { 0x00020000, CODEC_VERB_16BIT_CMD, vrbProcSetConverterFormat , "SetConverterFormat " }, 2650 { 0x000B0000, CODEC_VERB_16BIT_CMD, vrbProcGetAmplifier , "GetAmplifier " }, 2651 { 0x00030000, CODEC_VERB_16BIT_CMD, vrbProcSetAmplifier , "SetAmplifier " }, 2652 { 0x000F0400, CODEC_VERB_8BIT_CMD , vrbProcGetSDISelect , "GetSDISelect " }, 2653 { 0x00070400, CODEC_VERB_8BIT_CMD , vrbProcSetSDISelect , "SetSDISelect " } 2663 2654 /** @todo Implement 0x7e7: IDT Set GPIO (STAC922x only). */ 2664 2655 }; … … 2717 2708 2718 2709 CODECDBG_INDENT 2710 codecDbgPrintf(pInfo, "Connections: %RU8\n", CODEC_F00_0E_COUNT(paReg00[0xE])); 2719 2711 codecDbgPrintf(pInfo, "Amplifier Caps:\n"); 2720 2712 uint32_t uReg = paReg00[0xD]; … … 2731 2723 CODEC_F00_12_STEP_SIZE(uReg), 2732 2724 CODEC_F00_12_OFFSET(uReg), 2733 RT_BOOL(CODEC_F00_ 0D_IS_CAP_MUTE(uReg)));2725 RT_BOOL(CODEC_F00_12_IS_CAP_MUTE(uReg))); 2734 2726 CODECDBG_UNINDENT 2735 2727 CODECDBG_UNINDENT … … 2762 2754 } 2763 2755 2764 static void codecDbgPrintNode(PCODECDBGINFO pInfo, PCODECNODE pNode )2756 static void codecDbgPrintNode(PCODECDBGINFO pInfo, PCODECNODE pNode, bool fRecursive) 2765 2757 { 2766 2758 codecDbgPrintf(pInfo, "Node 0x%02x (%02RU8): ", pNode->node.id, pNode->node.id); … … 2854 2846 else 2855 2847 CODECDBG_PRINT("UNKNOWN TYPE 0x%x\n", pNode->node.id); 2848 2849 if (fRecursive) 2850 { 2851 #define CODECDBG_PRINT_CONLIST_ENTRY(_aNode, _aEntry) \ 2852 if (cCnt >= _aEntry) \ 2853 { \ 2854 const uint8_t uID = RT_BYTE##_aEntry(_aNode->node.au32F02_param[0x0]); \ 2855 if (pNode->node.id == uID) \ 2856 codecDbgPrintNode(pInfo, _aNode, false /* fRecursive */); \ 2857 } 2858 2859 /* Slow recursion, but this is debug stuff anyway. */ 2860 for (uint8_t i = 0; i < pInfo->pThis->cTotalNodes; i++) 2861 { 2862 const PCODECNODE pSubNode = &pInfo->pThis->paNodes[i]; 2863 if (pSubNode->node.id == pNode->node.id) 2864 continue; 2865 2866 const uint8_t cCnt = CODEC_F00_0E_COUNT(pSubNode->node.au32F00_param[0xE]); 2867 if (cCnt == 0) /* No connections present? Skip. */ 2868 continue; 2869 2870 CODECDBG_INDENT 2871 CODECDBG_PRINT_CONLIST_ENTRY(pSubNode, 1) 2872 CODECDBG_PRINT_CONLIST_ENTRY(pSubNode, 2) 2873 CODECDBG_PRINT_CONLIST_ENTRY(pSubNode, 3) 2874 CODECDBG_PRINT_CONLIST_ENTRY(pSubNode, 4) 2875 CODECDBG_UNINDENT 2876 } 2877 2878 #undef CODECDBG_PRINT_CONLIST_ENTRY 2879 } 2856 2880 } 2857 2881 2858 2882 static DECLCALLBACK(void) codecDbgListNodes(PHDACODEC pThis, PCDBGFINFOHLP pHlp, const char *pszArgs) 2859 2883 { 2860 pHlp->pfnPrintf(pHlp, "HDA LINK \n");2884 pHlp->pfnPrintf(pHlp, "HDA LINK / INPUTS\n"); 2861 2885 2862 2886 CODECDBGINFO dbgInfo; … … 2871 2895 { 2872 2896 PCODECNODE pNode = &pThis->paNodes[i]; 2873 if (pNode->node.au32F00_param[0xE] == 0) /* Start with all nodes connected directly to the HDA (Azalia) link. */ 2874 codecDbgPrintNode(&dbgInfo, pNode); 2897 2898 /* Start with all nodes which have connection entries set. */ 2899 if (CODEC_F00_0E_COUNT(pNode->node.au32F00_param[0xE])) 2900 codecDbgPrintNode(&dbgInfo, pNode, true /* fRecursive */); 2875 2901 } 2876 2902 CODECDBG_UNINDENT … … 2883 2909 #endif 2884 2910 2885 static DECLCALLBACK(int) codecLookup(PHDACODEC pThis, uint32_t cmd, PPFNHDACODECVERBPROCESSOR pfn) 2886 { 2887 Assert(CODEC_CAD(cmd) == pThis->id); 2911 static DECLCALLBACK(int) codecLookup(PHDACODEC pThis, uint32_t cmd, uint64_t *puResp) 2912 { 2913 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 2914 AssertPtrReturn(puResp, VERR_INVALID_POINTER); 2915 2916 if (CODEC_CAD(cmd) != pThis->id) 2917 { 2918 *puResp = 0; 2919 AssertMsgFailed(("Unknown codec address 0x%x\n", CODEC_CAD(cmd))); 2920 return VERR_INVALID_PARAMETER; 2921 } 2888 2922 2889 2923 if ( CODEC_VERBDATA(cmd) == 0 2890 2924 || CODEC_NID(cmd) >= pThis->cTotalNodes) 2891 2925 { 2892 *pfn = vrbProcUnimplemented; 2893 AssertMsgFailed(("Unknown / invalid node 0x%x\n", CODEC_NID(cmd))); 2894 return VINF_SUCCESS; 2895 } 2896 2897 for (int i = 0; i < pThis->cVerbs; i++) 2926 *puResp = 0; 2927 AssertMsgFailed(("[NID0x%02x] Unknown / invalid node or data (0x%x)\n", CODEC_NID(cmd), CODEC_VERBDATA(cmd))); 2928 return VERR_INVALID_PARAMETER; 2929 } 2930 2931 /** @todo r=andy Implement a binary search here. */ 2932 for (size_t i = 0; i < pThis->cVerbs; i++) 2898 2933 { 2899 2934 if ((CODEC_VERBDATA(cmd) & pThis->paVerbs[i].mask) == pThis->paVerbs[i].verb) 2900 2935 { 2901 *pfn = pThis->paVerbs[i].pfn; 2902 return VINF_SUCCESS; 2903 } 2904 } 2905 2906 *pfn = vrbProcUnimplemented; 2907 2908 LogFlowFunc(("[NID0x%x] Callback for %x not found\n", CODEC_NID(cmd), CODEC_VERBDATA(cmd))); 2909 return VINF_SUCCESS; 2936 int rc2 = pThis->paVerbs[i].pfn(pThis, cmd, puResp); 2937 AssertRC(rc2); 2938 Log3Func(("[NID0x%02x] (0x%x) %s: 0x%x -> 0x%x\n", 2939 CODEC_NID(cmd), pThis->paVerbs[i].verb, pThis->paVerbs[i].pszName, CODEC_VERB_PAYLOAD8(cmd), *puResp)); 2940 return rc2; 2941 } 2942 } 2943 2944 *puResp = 0; 2945 LogFunc(("[NID0x%02x] Callback for %x not found\n", CODEC_NID(cmd), CODEC_VERBDATA(cmd))); 2946 return VERR_NOT_FOUND; 2910 2947 } 2911 2948 … … 2923 2960 switch (enmMixerCtl) 2924 2961 { 2962 case PDMAUDIOMIXERCTL_VOLUME: 2963 case PDMAUDIOMIXERCTL_FRONT: 2964 #ifdef VBOX_WITH_HDA_51_SURROUND 2965 case PDMAUDIOMIXERCTL_CENTER_LFE: 2966 case PDMAUDIOMIXERCTL_REAR: 2967 #endif 2968 { 2969 break; 2970 } 2925 2971 case PDMAUDIOMIXERCTL_LINE_IN: 2926 2972 #ifdef VBOX_WITH_HDA_MIC_IN … … 2928 2974 #endif 2929 2975 { 2930 pCfg->enmDir = PDMAUDIODIR_IN;2931 2976 break; 2932 2977 } 2933 2934 case PDMAUDIOMIXERCTL_VOLUME:2935 case PDMAUDIOMIXERCTL_FRONT:2936 {2937 pCfg->enmDir = PDMAUDIODIR_OUT;2938 break;2939 }2940 2941 2978 default: 2942 2979 AssertMsgFailed(("Mixer control %ld not implemented\n", enmMixerCtl)); … … 2954 2991 int hdaCodecRemoveStream(PHDACODEC pThis, PDMAUDIOMIXERCTL enmMixerCtl) 2955 2992 { 2956 return VINF_SUCCESS; 2993 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 2994 2995 int rc = pThis->pfnMixerRemoveStream(pThis->pHDAState, enmMixerCtl); 2996 2997 LogFlowFuncLeaveRC(rc); 2998 return rc; 2957 2999 } 2958 3000 … … 3033 3075 } 3034 3076 3035 int hdaCodecDestruct(PHDACODEC pThis) 3036 { 3037 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 3077 /** 3078 * Powers off the codec. 3079 * 3080 * @param pThis Codec to power off. 3081 */ 3082 void hdaCodecPowerOff(PHDACODEC pThis) 3083 { 3084 if (!pThis) 3085 return; 3086 3087 LogFlowFuncEnter(); 3088 3089 LogRel2(("HDA: Powering off codec ...\n")); 3090 3091 int rc2 = hdaCodecRemoveStream(pThis, PDMAUDIOMIXERCTL_FRONT); 3092 AssertRC(rc2); 3093 #ifdef VBOX_WITH_HDA_51_SURROUND 3094 rc2 = hdaCodecRemoveStream(pThis, PDMAUDIOMIXERCTL_CENTER_LFE); 3095 AssertRC(rc2); 3096 rc2 = hdaCodecRemoveStream(pThis, PDMAUDIOMIXERCTL_REAR); 3097 AssertRC(rc2); 3098 #endif 3099 3100 #ifdef VBOX_WITH_HDA_MIC_IN 3101 rc2 = hdaCodecRemoveStream(pThis, PDMAUDIOMIXERCTL_MIC_IN); 3102 AssertRC(rc2); 3103 #endif 3104 rc2 = hdaCodecRemoveStream(pThis, PDMAUDIOMIXERCTL_LINE_IN); 3105 AssertRC(rc2); 3106 } 3107 3108 void hdaCodecDestruct(PHDACODEC pThis) 3109 { 3110 if (!pThis) 3111 return; 3112 3113 LogFlowFuncEnter(); 3038 3114 3039 3115 if (pThis->paNodes) … … 3042 3118 pThis->paNodes = NULL; 3043 3119 } 3044 3045 return VINF_SUCCESS;3046 3120 } 3047 3121 … … 3064 3138 3065 3139 int rc = stac9220Construct(pThis); 3066 AssertRC (rc);3140 AssertRCReturn(rc, rc); 3067 3141 3068 3142 /* Common root node initializers. */ … … 3076 3150 pThis->paNodes[STAC9220_NID_AFG].afg.u32F20_param = CODEC_MAKE_F20(pThis->u16VendorId, pThis->u8BSKU, pThis->u8AssemblyId); 3077 3151 3078 /* Initialize the streams to some default values (44.1 kHz, 16-bit signed, 2 channels). 3079 * The codec's (fixed) delivery rate is 48kHz, so a frame will be delivered every 20.83us. */ 3080 PDMAUDIOSTREAMCFG strmCfg; 3081 strmCfg.pszName = NULL; 3082 strmCfg.uHz = 44100; 3083 strmCfg.cChannels = 2; 3084 strmCfg.enmFormat = AUD_FMT_S16; 3085 strmCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS; 3086 3087 /* 3088 * Output streams. 3089 */ 3090 strmCfg.enmDir = PDMAUDIODIR_OUT; 3091 3092 /* Front. */ 3093 strmCfg.DestSource.Dest = PDMAUDIOPLAYBACKDEST_FRONT; 3094 rc = hdaCodecAddStream(pThis, PDMAUDIOMIXERCTL_FRONT, &strmCfg); 3095 AssertRC(rc); 3152 do 3153 { 3154 /* Initialize the streams to some default values (44.1 kHz, 16-bit signed, 2 channels). 3155 * The codec's (fixed) delivery rate is 48kHz, so a frame will be delivered every 20.83us. */ 3156 PDMAUDIOSTREAMCFG strmCfg; 3157 RT_ZERO(strmCfg); 3158 strmCfg.uHz = 44100; 3159 strmCfg.cChannels = 2; 3160 strmCfg.enmFormat = PDMAUDIOFMT_S16; 3161 strmCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS; 3162 3163 /* 3164 * Output streams. 3165 */ 3166 strmCfg.enmDir = PDMAUDIODIR_OUT; 3167 3168 /* Front. */ 3169 RTStrPrintf(strmCfg.szName, RT_ELEMENTS(strmCfg.szName), "Front"); 3170 strmCfg.DestSource.Dest = PDMAUDIOPLAYBACKDEST_FRONT; 3171 rc = hdaCodecAddStream(pThis, PDMAUDIOMIXERCTL_FRONT, &strmCfg); 3172 AssertRCBreak(rc); 3096 3173 3097 3174 #ifdef VBOX_WITH_HDA_51_SURROUND 3098 /* Center / LFE. */ 3099 strmCfg.DestSource.Dest = PDMAUDIOPLAYBACKDEST_CENTER_LFE; 3100 rc = hdaCodecAddStream(pThis, PDMAUDIOMIXERCTL_CENTER_LFE, &strmCfg); 3101 AssertRC(rc); 3102 3103 /* Rear. */ 3104 strmCfg.DestSource.Dest = PDMAUDIOPLAYBACKDEST_REAR; 3105 rc = hdaCodecAddStream(pThis, PDMAUDIOMIXERCTL_REAR, &strmCfg); 3106 AssertRC(rc); 3175 /* Center / LFE. */ 3176 RTStrPrintf(strmCfg.szName, RT_ELEMENTS(strmCfg.szName), "Center / LFE"); 3177 strmCfg.DestSource.Dest = PDMAUDIOPLAYBACKDEST_CENTER_LFE; 3178 /** @todo Handle mono channel if only center *or* LFE is available? */ 3179 rc = hdaCodecAddStream(pThis, PDMAUDIOMIXERCTL_CENTER_LFE, &strmCfg); 3180 AssertRCBreak(rc); 3181 3182 /* Rear. */ 3183 RTStrPrintf(strmCfg.szName, RT_ELEMENTS(strmCfg.szName), "Rear"); 3184 strmCfg.DestSource.Dest = PDMAUDIOPLAYBACKDEST_REAR; 3185 rc = hdaCodecAddStream(pThis, PDMAUDIOMIXERCTL_REAR, &strmCfg); 3186 AssertRCBreak(rc); 3107 3187 #endif 3108 3188 3109 /*3110 * Input streams.3111 */3112 strmCfg.enmDir = PDMAUDIODIR_IN;3189 /* 3190 * Input streams. 3191 */ 3192 strmCfg.enmDir = PDMAUDIODIR_IN; 3113 3193 3114 3194 #ifdef VBOX_WITH_HDA_MIC_IN 3115 strmCfg.DestSource.Source = PDMAUDIORECSOURCE_MIC; 3116 rc = hdaCodecAddStream(pThis, PDMAUDIOMIXERCTL_MIC_IN, &strmCfg); 3117 AssertRC(rc); 3195 RTStrPrintf(strmCfg.szName, RT_ELEMENTS(strmCfg.szName), "Microphone In"); 3196 strmCfg.DestSource.Source = PDMAUDIORECSOURCE_MIC; 3197 rc = hdaCodecAddStream(pThis, PDMAUDIOMIXERCTL_MIC_IN, &strmCfg); 3198 AssertRCBreak(rc); 3118 3199 #endif 3119 strmCfg.DestSource.Source = PDMAUDIORECSOURCE_LINE; 3120 rc = hdaCodecAddStream(pThis, PDMAUDIOMIXERCTL_LINE_IN, &strmCfg); 3121 AssertRC(rc); 3200 RTStrPrintf(strmCfg.szName, RT_ELEMENTS(strmCfg.szName), "Line In"); 3201 strmCfg.DestSource.Source = PDMAUDIORECSOURCE_LINE; 3202 rc = hdaCodecAddStream(pThis, PDMAUDIOMIXERCTL_LINE_IN, &strmCfg); 3203 AssertRCBreak(rc); 3204 3205 } while (0); 3206 3207 /** @todo Handle rc here? */ 3122 3208 3123 3209 /* -
trunk/src/VBox/Devices/Audio/DevIchHdaCodec.h
r60353 r60925 41 41 typedef struct CODECVERB 42 42 { 43 uint32_t verb; 44 /** operation bitness mask */ 45 uint32_t mask; 43 /** Verb. */ 44 uint32_t verb; 45 /** Verb mask. */ 46 uint32_t mask; 47 /** Function pointer for implementation callback. */ 46 48 PFNHDACODECVERBPROCESSOR pfn; 49 /** Friendly name, for debugging. */ 50 const char *pszName; 47 51 } CODECVERB; 48 52 … … 65 69 66 70 CODECVERB const *paVerbs; 67 intcVerbs;71 size_t cVerbs; 68 72 69 73 PCODECNODE paNodes; … … 95 99 DECLR3CALLBACKMEMBER(int, pfnMixerSetVolume, (PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl, PPDMAUDIOVOLUME pVol)); 96 100 /** Callbacks by codec implementation. */ 97 DECLR3CALLBACKMEMBER(int, pfnLookup, (PHDACODEC pThis, uint32_t verb, PPFNHDACODECVERBPROCESSOR));101 DECLR3CALLBACKMEMBER(int, pfnLookup, (PHDACODEC pThis, uint32_t uVerb, uint64_t *puResp)); 98 102 DECLR3CALLBACKMEMBER(int, pfnReset, (PHDACODEC pThis)); 99 103 DECLR3CALLBACKMEMBER(int, pfnCodecNodeReset, (PHDACODEC pThis, uint8_t, PCODECNODE)); … … 104 108 105 109 int hdaCodecConstruct(PPDMDEVINS pDevIns, PHDACODEC pThis, uint16_t uLUN, PCFGMNODE pCfg); 106 int hdaCodecDestruct(PHDACODEC pThis); 110 void hdaCodecDestruct(PHDACODEC pThis); 111 void hdaCodecPowerOff(PHDACODEC pThis); 107 112 int hdaCodecSaveState(PHDACODEC pThis, PSSMHANDLE pSSM); 108 113 int hdaCodecLoadState(PHDACODEC pThis, PSSMHANDLE pSSM, uint32_t uVersion); -
trunk/src/VBox/Devices/Audio/DevSB16.cpp
r60653 r60925 79 79 R3PTRTYPE(PPDMAUDIOGSTSTRMOUT) pStrmOut; 80 80 /** Mixer handle for output stream. */ 81 R3PTRTYPE(PAUDMIXSTREAM) p hStrmOut;81 R3PTRTYPE(PAUDMIXSTREAM) pMixStrm; 82 82 } SB16OUTPUTSTREAM, *PSB16OUTPUTSTREAM; 83 83 … … 473 473 static void dma_cmd8(PSB16STATE pThis, int mask, int dma_len) 474 474 { 475 pThis->fmt = AUD_FMT_U8;475 pThis->fmt = PDMAUDIOFMT_U8; 476 476 pThis->use_hdma = 0; 477 477 pThis->fmt_bits = 8; … … 576 576 577 577 if (16 == pThis->fmt_bits) 578 pThis->fmt = pThis->fmt_signed ? AUD_FMT_S16 : AUD_FMT_U16;578 pThis->fmt = pThis->fmt_signed ? PDMAUDIOFMT_S16 : PDMAUDIOFMT_U16; 579 579 else 580 pThis->fmt = pThis->fmt_signed ? AUD_FMT_S8 : AUD_FMT_U8;580 pThis->fmt = pThis->fmt_signed ? PDMAUDIOFMT_S8 : PDMAUDIOFMT_U8; 581 581 582 582 pThis->left_till_irq = pThis->block_size; … … 1095 1095 uint8_t rvol = sb16MixRegToVol(pThis, 0x33); 1096 1096 PDMAUDIOVOLUME vol = { false, lvol, rvol }; 1097 AudioMixerS etSinkVolume(pThis->pSinkOutput, &vol);1097 AudioMixerSinkSetVolume(pThis->pSinkOutput, &vol); 1098 1098 } 1099 1099 … … 1108 1108 streamCfg.uHz = pThis->freq; 1109 1109 streamCfg.cChannels = 1; /* Mono */ 1110 streamCfg.enmFormat = AUD_FMT_U8;1110 streamCfg.enmFormat = PDMAUDIOFMT_U8; 1111 1111 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS; 1112 1112 … … 1318 1318 1319 1319 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 1320 pDrv->Out.p hStrmOut= NULL;1320 pDrv->Out.pMixStrm = NULL; 1321 1321 1322 1322 pThis->pSinkOutput = NULL; … … 1364 1364 streamCfg.uHz = 44100; 1365 1365 streamCfg.cChannels = 2; 1366 streamCfg.enmFormat = AUD_FMT_S16;1366 streamCfg.enmFormat = PDMAUDIOFMT_S16; 1367 1367 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS; 1368 1368 … … 1371 1371 1372 1372 /* Add all required audio sinks. */ 1373 rc2 = AudioMixerAddSink(pThis->pMixer, "[Playback] PCM Output", 1374 AUDMIXSINKDIR_OUTPUT, &pThis->pSinkOutput); 1373 rc2 = AudioMixerCreateSink(pThis->pMixer, "[Playback] PCM Output", AUDMIXSINKDIR_OUTPUT, &pThis->pSinkOutput); 1375 1374 AssertRC(rc2); 1376 1375 } … … 2066 2065 } 2067 2066 2068 int rc2 = pDrv->pConnector->pfnCreateOut(pDrv->pConnector, pszDesc, pCfg, &pDrv->Out.pStrmOut); 2069 LogFlowFunc(("LUN#%RU8: Created output with rc=%Rrc\n", uLUN, rc)); 2070 if (rc2 == VINF_SUCCESS) /* Note: Could return VWRN_ALREADY_EXISTS. */ 2067 AudioMixerSinkRemoveStream(pThis->pSinkOutput, pDrv->Out.pMixStrm); 2068 2069 AudioMixerStreamDestroy(pDrv->Out.pMixStrm); 2070 pDrv->Out.pMixStrm = NULL; 2071 2072 int rc2 = AudioMixerStreamCreate(pDrv->pConnector, pCfg, 0 /* fFlags */, &pDrv->Out.pMixStrm); 2073 if (RT_SUCCESS(rc2)) 2071 2074 { 2072 AudioMixerRemoveStream(pThis->pSinkOutput, pDrv->Out.phStrmOut); 2073 rc = AudioMixerAddStreamOut(pThis->pSinkOutput, 2074 pDrv->pConnector, pDrv->Out.pStrmOut, 2075 0 /* uFlags */, 2076 &pDrv->Out.phStrmOut); 2075 rc2 = AudioMixerSinkAddStream(pThis->pSinkOutput, pDrv->Out.pMixStrm); 2076 LogFlowFunc(("LUN#%RU8: Created output \"%s\", rc=%Rrc\n", pDrv->uLUN, pszDesc, rc2)); 2077 2077 } 2078 2078 … … 2150 2150 2151 2151 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 2152 pDrv->Out.p hStrmOut= NULL;2152 pDrv->Out.pMixStrm = NULL; 2153 2153 2154 2154 pThis->pSinkOutput = NULL; -
trunk/src/VBox/Devices/Audio/DrvAudio.cpp
r60651 r60925 65 65 #include "AudioMixBuffer.h" 66 66 67 static int drvAudioAllocHstIn(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMIN *ppHstStrmIn); 68 static int drvAudioAllocHstOut(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMOUT *ppHstStrmOut); 69 static int drvAudioCreateStreamPairIn(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOGSTSTRMIN *ppGstStrmIn); 70 static int drvAudioDestroyHstIn(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMIN pHstStrmIn); 67 71 static int drvAudioDestroyGstIn(PDRVAUDIO pThis, PPDMAUDIOGSTSTRMIN pGstStrmIn); 68 69 static int drvAudioAllocHstIn(PDRVAUDIO pThis, const char *pszName, PPDMAUDIOSTREAMCFG pCfg, PDMAUDIORECSOURCE enmRecSource, PPDMAUDIOHSTSTRMIN *ppHstStrmIn); 70 static int drvAudioDestroyHstIn(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMIN pHstStrmIn); 71 72 int drvAudioAddHstOut(PDRVAUDIO pThis, const char *pszName, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMOUT *ppHstStrmOut) 72 static int drvAudioDestroyGstOut(PDRVAUDIO pThis, PPDMAUDIOGSTSTRMOUT pGstStrmOut); 73 static PPDMAUDIOHSTSTRMIN drvAudioFindAnyHstIn(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMIN pHstStrmIn); 74 static PPDMAUDIOHSTSTRMOUT drvAudioFindAnyHstOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut); 75 static PPDMAUDIOHSTSTRMOUT drvAudioFindSpecificOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut, PPDMAUDIOSTREAMCFG pCfg); 76 77 static int drvAudioGstInInit(PPDMAUDIOGSTSTRMIN pGstStrmIn, PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg); 78 79 static void drvAudioHstInFreeRes(PPDMAUDIOHSTSTRMIN pHstStrmIn); 80 static void drvAudioHstOutFreeRes(PPDMAUDIOHSTSTRMOUT pHstStrmOut); 81 82 83 int drvAudioAddHstOut(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMOUT *ppHstStrmOut) 73 84 { 74 85 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 75 AssertPtrReturn(pszName, VERR_INVALID_POINTER);76 86 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 77 87 … … 81 91 if (!pHstStrmOut) 82 92 { 83 rc = drvAudioAllocHstOut(pThis, p szName, pCfg, &pHstStrmOut);93 rc = drvAudioAllocHstOut(pThis, pCfg, &pHstStrmOut); 84 94 if (RT_FAILURE(rc)) 85 95 pHstStrmOut = drvAudioFindAnyHstOut(pThis, NULL /* pHstStrmOut */); … … 113 123 } 114 124 115 PDMAUDIOFMT fmt = drvAudioHlpStringToFormat(pszValue);116 if (fmt == AUD_FMT_INVALID)125 PDMAUDIOFMT fmt = DrvAudioStrToAudFmt(pszValue); 126 if (fmt == PDMAUDIOFMT_INVALID) 117 127 { 118 128 *pfDefault = true; … … 275 285 switch (pCfg->enmFormat) 276 286 { 277 case AUD_FMT_S8:278 case AUD_FMT_U8:279 case AUD_FMT_S16:280 case AUD_FMT_U16:281 case AUD_FMT_S32:282 case AUD_FMT_U32:287 case PDMAUDIOFMT_S8: 288 case PDMAUDIOFMT_U8: 289 case PDMAUDIOFMT_S16: 290 case PDMAUDIOFMT_U16: 291 case PDMAUDIOFMT_S32: 292 case PDMAUDIOFMT_U32: 283 293 break; 284 294 default: … … 294 304 } 295 305 296 /**297 * Clears a sample buffer by the given amount of audio samples.298 *299 * @return IPRT status code.300 * @param pPCMProps PCM properties to use for the buffer to clear.301 * @param pvBuf Buffer to clear.302 * @param cbBuf Size (in bytes) of the buffer.303 * @param cSamples Number of audio samples to clear in the buffer.304 */305 void DrvAudioClearBuf(PPDMPCMPROPS pPCMProps, void *pvBuf, size_t cbBuf, uint32_t cSamples)306 {307 AssertPtrReturnVoid(pPCMProps);308 AssertPtrReturnVoid(pvBuf);309 310 if (!cbBuf || !cSamples)311 return;312 313 Log2Func(("pPCMInfo=%p, pvBuf=%p, cSamples=%RU32, fSigned=%RTbool, cBits=%RU8, cShift=%RU8\n",314 pPCMProps, pvBuf, cSamples, pPCMProps->fSigned, pPCMProps->cBits, pPCMProps->cShift));315 316 if (pPCMProps->fSigned)317 {318 memset(pvBuf, 0, cSamples << pPCMProps->cShift);319 }320 else321 {322 switch (pPCMProps->cBits)323 {324 case 8:325 {326 memset(pvBuf, 0x80, cSamples << pPCMProps->cShift);327 break;328 }329 330 case 16:331 {332 uint16_t *p = (uint16_t *)pvBuf;333 int shift = pPCMProps->cChannels - 1;334 short s = INT16_MAX;335 336 if (pPCMProps->fSwapEndian)337 s = RT_BSWAP_U16(s);338 339 for (unsigned i = 0; i < cSamples << shift; i++)340 p[i] = s;341 342 break;343 }344 345 case 32:346 {347 uint32_t *p = (uint32_t *)pvBuf;348 int shift = pPCMProps->cChannels - 1;349 int32_t s = INT32_MAX;350 351 if (pPCMProps->fSwapEndian)352 s = RT_BSWAP_U32(s);353 354 for (unsigned i = 0; i < cSamples << shift; i++)355 p[i] = s;356 357 break;358 }359 360 default:361 {362 AssertMsgFailed(("Invalid bits: %RU8\n", pPCMProps->cBits));363 break;364 }365 }366 }367 }368 369 306 static int drvAudioControlHstIn(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMIN pHstStrmIn, PDMAUDIOSTREAMCMD enmStreamCmd) 370 307 { … … 375 312 if (RT_FAILURE(rc)) 376 313 return rc; 314 315 LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd)); 377 316 378 317 switch (enmStreamCmd) … … 384 323 rc = pThis->pHostDrvAudio->pfnControlIn(pThis->pHostDrvAudio, pHstStrmIn, PDMAUDIOSTREAMCMD_ENABLE); 385 324 if (RT_SUCCESS(rc)) 386 {387 325 pHstStrmIn->fStatus |= PDMAUDIOSTRMSTS_FLAG_ENABLED; 388 }389 else390 LogFlowFunc(("Backend reported an error when opening input stream, rc=%Rrc\n", rc));391 326 } 392 327 else … … 403 338 if (RT_SUCCESS(rc)) 404 339 { 405 pHstStrmIn->fStatus = PDMAUDIOSTRMSTS_FLAG_NONE; /* Clear all. */340 pHstStrmIn->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_ENABLED; 406 341 AudioMixBufClear(&pHstStrmIn->MixBuf); 407 342 } 408 else409 LogFlowFunc(("Backend vetoed closing output stream, rc=%Rrc\n", rc));410 343 } 411 344 else … … 419 352 if (!(pHstStrmIn->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED)) 420 353 { 421 Assert(pHstStrmIn->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED);422 354 rc = pThis->pHostDrvAudio->pfnControlIn(pThis->pHostDrvAudio, pHstStrmIn, PDMAUDIOSTREAMCMD_PAUSE); 423 355 if (RT_SUCCESS(rc)) 424 {425 LogFunc(("[%s] Pausing stream\n", pHstStrmIn->MixBuf.pszName));426 356 pHstStrmIn->fStatus |= PDMAUDIOSTRMSTS_FLAG_PAUSED; 427 }428 else429 LogFlowFunc(("Backend vetoed pausing input stream, rc=%Rrc\n", rc));430 357 } 431 358 else … … 439 366 if (pHstStrmIn->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED) 440 367 { 441 Assert(pHstStrmIn->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED);442 368 rc = pThis->pHostDrvAudio->pfnControlIn(pThis->pHostDrvAudio, pHstStrmIn, PDMAUDIOSTREAMCMD_RESUME); 443 369 if (RT_SUCCESS(rc)) 444 {445 370 pHstStrmIn->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PAUSED; 446 LogFunc(("[%s] Resumed stream\n", pHstStrmIn->MixBuf.pszName));447 }448 else449 LogFlowFunc(("Backend vetoed resuming input stream, rc=%Rrc\n", rc));450 371 } 451 372 else … … 461 382 } 462 383 384 LogFunc(("[%s] Returned %Rrc\n", pHstStrmIn->MixBuf.pszName, rc)); 385 463 386 int rc2 = RTCritSectLeave(&pHstStrmIn->CritSect); 464 387 if (RT_SUCCESS(rc)) … … 470 393 static int drvAudioControlHstOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut, PDMAUDIOSTREAMCMD enmStreamCmd) 471 394 { 472 AssertPtrReturn(pThis, VERR_INVALID_POINTER);395 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 473 396 AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER); 474 397 … … 476 399 if (RT_FAILURE(rc)) 477 400 return rc; 401 402 LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd)); 478 403 479 404 switch (enmStreamCmd) … … 488 413 Assert(!(pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE)); 489 414 pHstStrmOut->fStatus |= PDMAUDIOSTRMSTS_FLAG_ENABLED; 490 LogFunc(("[%s] Enabled stream\n", pHstStrmOut->MixBuf.pszName));491 415 } 492 else493 LogFlowFunc(("[%s] Backend reported an error when enabling output stream, rc=%Rrc\n",494 pHstStrmOut->MixBuf.pszName, rc));495 416 } 496 417 else … … 507 428 if (RT_SUCCESS(rc)) 508 429 { 509 pHstStrmOut->fStatus = PDMAUDIOSTRMSTS_FLAG_NONE; /* Clear all. */430 pHstStrmOut->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_ENABLED; 510 431 AudioMixBufClear(&pHstStrmOut->MixBuf); 511 512 LogFunc(("[%s] Disabled stream\n", pHstStrmOut->MixBuf.pszName));513 432 } 514 else515 LogFlowFunc(("[%s] Backend vetoed disabling output stream, rc=%Rrc\n", pHstStrmOut->MixBuf.pszName, rc));516 433 } 517 434 else … … 525 442 if (!(pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED)) 526 443 { 527 Assert(pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED);528 444 rc = pThis->pHostDrvAudio->pfnControlOut(pThis->pHostDrvAudio, pHstStrmOut, PDMAUDIOSTREAMCMD_PAUSE); 529 445 if (RT_SUCCESS(rc)) 530 {531 446 pHstStrmOut->fStatus |= PDMAUDIOSTRMSTS_FLAG_PAUSED; 532 LogFunc(("[%s] Pausing stream\n", pHstStrmOut->MixBuf.pszName));533 }534 else535 LogFlowFunc(("[%s] Backend vetoed pausing output stream, rc=%Rrc\n", pHstStrmOut->MixBuf.pszName, rc));536 447 } 537 448 else … … 545 456 if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED) 546 457 { 547 Assert(pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED);548 458 rc = pThis->pHostDrvAudio->pfnControlOut(pThis->pHostDrvAudio, pHstStrmOut, PDMAUDIOSTREAMCMD_RESUME); 549 459 if (RT_SUCCESS(rc)) 550 {551 460 pHstStrmOut->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PAUSED; 552 LogFunc(("[%s] Resumed stream\n", pHstStrmOut->MixBuf.pszName));553 }554 else555 LogFlowFunc(("[%s] Backend vetoed resuming output stream, rc=%Rrc\n", pHstStrmOut->MixBuf.pszName, rc));556 461 } 557 462 else … … 567 472 } 568 473 474 LogFunc(("[%s] Returned %Rrc\n", pHstStrmOut->MixBuf.pszName, rc)); 475 569 476 int rc2 = RTCritSectLeave(&pHstStrmOut->CritSect); 570 477 if (RT_SUCCESS(rc)) … … 574 481 } 575 482 576 int drvAudioDestroyHstOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut)577 { 578 AssertPtrReturn(pThis, VERR_INVALID_POINTER);483 static int drvAudioDestroyHstOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut) 484 { 485 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 579 486 AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER); 580 487 581 488 LogFlowFunc(("%s\n", pHstStrmOut->MixBuf.pszName)); 582 489 583 int rc; 490 int rc = VINF_SUCCESS; 491 584 492 if (RTListIsEmpty(&pHstStrmOut->lstGstStrmOut)) 585 493 { 586 rc = pThis->pHostDrvAudio->pfnFiniOut(pThis->pHostDrvAudio, pHstStrmOut); 587 if (RT_SUCCESS(rc)) 588 { 589 drvAudioHstOutFreeRes(pHstStrmOut); 590 591 /* Remove from driver instance list. */ 592 RTListNodeRemove(&pHstStrmOut->Node); 593 594 if (RTCritSectIsInitialized(&pHstStrmOut->CritSect)) 595 { 596 int rc2 = RTCritSectDelete(&pHstStrmOut->CritSect); 597 AssertRC(rc2); 598 } 599 600 RTMemFree(pHstStrmOut); 601 pThis->cStreamsFreeOut++; 602 return VINF_SUCCESS; 603 } 494 drvAudioHstOutFreeRes(pHstStrmOut); 495 496 /* Remove from driver instance list. */ 497 RTListNodeRemove(&pHstStrmOut->Node); 498 499 if (RTCritSectIsInitialized(&pHstStrmOut->CritSect)) 500 { 501 int rc2 = RTCritSectDelete(&pHstStrmOut->CritSect); 502 AssertRC(rc2); 503 } 504 505 RTMemFree(pHstStrmOut); 506 pHstStrmOut = NULL; 507 508 pThis->cStreamsFreeOut++; 604 509 } 605 510 else 606 511 { 607 rc = VERR_ACCESS_DENIED; 608 LogFlowFunc(("[%s] Still is being used, rc=%Rrc\n", pHstStrmOut->MixBuf.pszName, rc)); 609 } 610 611 return rc; 612 } 613 614 int drvAudioDestroyGstOut(PDRVAUDIO pThis, PPDMAUDIOGSTSTRMOUT pGstStrmOut) 512 rc = VERR_WRONG_ORDER; 513 LogFlowFunc(("[%s] Still is being used, skipping\n", pHstStrmOut->MixBuf.pszName)); 514 } 515 516 LogFlowFuncLeaveRC(rc); 517 return rc; 518 } 519 520 static int drvAudioDestroyGstOut(PDRVAUDIO pThis, PPDMAUDIOGSTSTRMOUT pGstStrmOut) 615 521 { 616 522 AssertPtrReturn(pThis, VERR_INVALID_POINTER); … … 619 525 return VINF_SUCCESS; 620 526 527 LogFlowFunc(("%s\n", pGstStrmOut->MixBuf.pszName)); 528 621 529 if (pGstStrmOut->State.cRefs > 1) /* Do other objects still have a reference to it? Bail out. */ 622 530 return VERR_WRONG_ORDER; 623 531 624 drvAudioGstOutFreeRes(pGstStrmOut); 625 532 AudioMixBufDestroy(&pGstStrmOut->MixBuf); 533 534 /* Is this guest stream associate to a host stream? */ 626 535 if (pGstStrmOut->pHstStrmOut) 627 536 { 628 537 /* Unregister from parent first. */ 629 538 RTListNodeRemove(&pGstStrmOut->Node); 630 631 /* Try destroying the associated host output stream. This could632 * be skipped if there are other guest output streams with this633 * host stream. */634 drvAudioDestroyHstOut(pThis, pGstStrmOut->pHstStrmOut);635 539 } 636 540 637 541 RTMemFree(pGstStrmOut); 542 pGstStrmOut = NULL; 638 543 639 544 return VINF_SUCCESS; 640 545 } 641 546 642 PPDMAUDIOHSTSTRMIN drvAudioFindNextHstIn(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMIN pHstStrmIn)547 static PPDMAUDIOHSTSTRMIN drvAudioFindAnyHstIn(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMIN pHstStrmIn) 643 548 { 644 549 if (pHstStrmIn) … … 653 558 } 654 559 655 PPDMAUDIOHSTSTRMIN drvAudioFindNextEnabledHstIn(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMIN pHstStrmIn) 656 { 657 while ((pHstStrmIn = drvAudioFindNextHstIn(pThis, pHstStrmIn))) 658 if (pHstStrmIn->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED) 659 return pHstStrmIn; 660 661 return NULL; 662 } 663 664 PPDMAUDIOHSTSTRMIN drvAudioFindNextEqHstIn(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMIN pHstStrmIn, 665 PPDMAUDIOSTREAMCFG pCfg) 666 { 667 while ((pHstStrmIn = drvAudioFindNextHstIn(pThis, pHstStrmIn))) 668 if (drvAudioPCMPropsAreEqual(&pHstStrmIn->Props, pCfg)) 669 return pHstStrmIn; 670 671 return NULL; 672 } 673 674 static int drvAudioHstInAdd(PDRVAUDIO pThis, const char *pszName, PPDMAUDIOSTREAMCFG pCfg, PDMAUDIORECSOURCE enmRecSource, 675 PPDMAUDIOHSTSTRMIN *ppHstStrmIn) 676 { 677 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 678 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 560 static int drvAudioHstInAdd(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMIN *ppHstStrmIn) 561 { 562 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 563 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 679 564 AssertPtrReturn(ppHstStrmIn, VERR_INVALID_POINTER); 680 565 681 566 PPDMAUDIOHSTSTRMIN pHstStrmIn; 682 int rc = drvAudioAllocHstIn(pThis, p szName, pCfg, enmRecSource, &pHstStrmIn);567 int rc = drvAudioAllocHstIn(pThis, pCfg, &pHstStrmIn); 683 568 if (RT_SUCCESS(rc)) 684 569 *ppHstStrmIn = pHstStrmIn; … … 688 573 } 689 574 690 int drvAudioGstOutInit(PPDMAUDIOGSTSTRMOUT pGstStrmOut, PPDMAUDIOHSTSTRMOUT pHostStrmOut, 691 const char *pszName, PPDMAUDIOSTREAMCFG pCfg) 575 static void drvAudioHstInFreeRes(PPDMAUDIOHSTSTRMIN pHstStrmIn) 576 { 577 if (!pHstStrmIn) 578 return; 579 580 AudioMixBufDestroy(&pHstStrmIn->MixBuf); 581 } 582 583 static int drvAudioGstOutInit(PPDMAUDIOGSTSTRMOUT pGstStrmOut, PPDMAUDIOHSTSTRMOUT pHostStrmOut, PPDMAUDIOSTREAMCFG pCfg) 692 584 { 693 585 AssertPtrReturn(pGstStrmOut, VERR_INVALID_POINTER); 694 586 AssertPtrReturn(pHostStrmOut, VERR_INVALID_POINTER); 695 AssertPtrReturn(pszName, VERR_INVALID_POINTER);696 587 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 697 588 … … 699 590 if (RT_SUCCESS(rc)) 700 591 { 701 char *psz Temp;702 if (RTStrAPrintf(&psz Temp, "%s (Guest)", pszName) <= 0)592 char *pszName; 593 if (RTStrAPrintf(&pszName, "%s (Guest)", pCfg->szName) <= 0) 703 594 return VERR_NO_MEMORY; 704 595 705 rc = AudioMixBufInit(&pGstStrmOut->MixBuf, psz Temp, &pGstStrmOut->Props, AudioMixBufSize(&pHostStrmOut->MixBuf));596 rc = AudioMixBufInit(&pGstStrmOut->MixBuf, pszName, &pGstStrmOut->Props, AudioMixBufSize(&pHostStrmOut->MixBuf)); 706 597 if (RT_SUCCESS(rc)) 707 598 rc = AudioMixBufLinkTo(&pGstStrmOut->MixBuf, &pHostStrmOut->MixBuf); 708 709 RTStrFree(pszTemp);710 599 711 600 if (RT_SUCCESS(rc)) … … 715 604 pGstStrmOut->State.fEmpty = true; 716 605 717 pGstStrmOut->State.pszName = RTStrDup(pszName); 718 if (!pGstStrmOut->State.pszName) 719 return VERR_NO_MEMORY; 606 RTStrPrintf(pGstStrmOut->State.szName, RT_ELEMENTS(pGstStrmOut->State.szName), 607 "%s", pszName); 720 608 721 609 pGstStrmOut->pHstStrmOut = pHostStrmOut; 722 610 } 723 } 724 725 LogFlowFunc(("pszName=%s, rc=%Rrc\n", pszName, rc)); 726 return rc; 727 } 728 729 int drvAudioAllocHstOut(PDRVAUDIO pThis, const char *pszName, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMOUT *ppHstStrmOut) 611 612 RTStrFree(pszName); 613 } 614 615 LogFlowFunc(("pszName=%s, rc=%Rrc\n", pCfg->szName, rc)); 616 return rc; 617 } 618 619 static int drvAudioAllocHstOut(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMOUT *ppHstStrmOut) 730 620 { 731 621 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 732 AssertPtrReturn(pszName, VERR_INVALID_POINTER); 733 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 622 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 734 623 735 624 if (!pThis->cStreamsFreeOut) … … 755 644 756 645 int rc; 757 bool fInitialized = false;758 646 759 647 do … … 761 649 RTListInit(&pHstStrmOut->lstGstStrmOut); 762 650 763 uint32_t cSamples; 764 rc = pThis->pHostDrvAudio->pfnInitOut(pThis->pHostDrvAudio, pHstStrmOut, pCfg, &cSamples); 651 uint32_t cSamples = 0; 652 rc = pThis->pHostDrvAudio->pfnInitOut 653 ? pThis->pHostDrvAudio->pfnInitOut(pThis->pHostDrvAudio, pHstStrmOut, pCfg, &cSamples) : VINF_SUCCESS; 654 765 655 if (RT_FAILURE(rc)) 766 656 { … … 769 659 } 770 660 771 fInitialized = true;772 773 char *psz Temp;774 if (RTStrAPrintf(&psz Temp, "%s (Host)", pszName) <= 0)661 pHstStrmOut->fStatus |= PDMAUDIOSTRMSTS_FLAG_INITIALIZED; 662 663 char *pszName; 664 if (RTStrAPrintf(&pszName, "%s (Host)", pCfg->szName) <= 0) 775 665 { 776 666 rc = VERR_NO_MEMORY; … … 778 668 } 779 669 780 rc = AudioMixBufInit(&pHstStrmOut->MixBuf, psz Temp, &pHstStrmOut->Props, cSamples);670 rc = AudioMixBufInit(&pHstStrmOut->MixBuf, pszName, &pHstStrmOut->Props, cSamples); 781 671 if (RT_SUCCESS(rc)) 782 672 rc = RTCritSectInit(&pHstStrmOut->CritSect); … … 788 678 } 789 679 790 RTStrFree(psz Temp);680 RTStrFree(pszName); 791 681 792 682 } while (0); … … 794 684 if (RT_FAILURE(rc)) 795 685 { 796 if (fInitialized) 797 { 798 int rc2 = pThis->pHostDrvAudio->pfnFiniOut(pThis->pHostDrvAudio, pHstStrmOut); 799 AssertRC(rc2); 686 if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED) 687 { 688 int rc2 = pThis->pHostDrvAudio->pfnFiniOut 689 ? pThis->pHostDrvAudio->pfnFiniOut(pThis->pHostDrvAudio, pHstStrmOut) : VINF_SUCCESS; 690 if (RT_SUCCESS(rc2)) 691 pHstStrmOut->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_INITIALIZED; 800 692 } 801 693 … … 810 702 } 811 703 812 int drvAudioCreateStreamPairOut(PDRVAUDIO pThis, const char *pszName, 813 PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOGSTSTRMOUT *ppGstStrmOut) 704 static int drvAudioCreateStreamPairOut(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOGSTSTRMOUT *ppGstStrmOut) 814 705 { 815 706 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 816 AssertPtrReturn(pszName, VERR_INVALID_POINTER);817 707 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 818 708 … … 821 711 if (!pGstStrmOut) 822 712 { 823 LogFlowFunc(("Failed to allocate memory for guest output stream \"%s\"\n", p szName));713 LogFlowFunc(("Failed to allocate memory for guest output stream \"%s\"\n", pCfg->szName)); 824 714 return VERR_NO_MEMORY; 825 715 } … … 829 719 */ 830 720 PPDMAUDIOHSTSTRMOUT pHstStrmOut; 831 int rc = drvAudioAddHstOut(pThis, p szName, pCfg, &pHstStrmOut);721 int rc = drvAudioAddHstOut(pThis, pCfg, &pHstStrmOut); 832 722 if (RT_FAILURE(rc)) 833 723 { 834 LogFlowFunc(("Error adding host output stream \"%s\", rc=%Rrc\n", p szName, rc));724 LogFlowFunc(("Error adding host output stream \"%s\", rc=%Rrc\n", pCfg->szName, rc)); 835 725 836 726 RTMemFree(pGstStrmOut); … … 842 732 * by the device emulation (which in turn was/could be set by the guest OS). 843 733 */ 844 rc = drvAudioGstOutInit(pGstStrmOut, pHstStrmOut, p szName, pCfg);734 rc = drvAudioGstOutInit(pGstStrmOut, pHstStrmOut, pCfg); 845 735 if (RT_SUCCESS(rc)) 846 736 { … … 858 748 } 859 749 860 static int drvAudioCreateStreamPairIn(PDRVAUDIO pThis, const char *pszName, PDMAUDIORECSOURCE enmRecSource, 861 PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOGSTSTRMIN *ppGstStrmIn) 750 static int drvAudioCreateStreamPairIn(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOGSTSTRMIN *ppGstStrmIn) 862 751 { 863 752 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 864 AssertPtrReturn(pszName, VERR_INVALID_POINTER);865 753 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 866 754 … … 873 761 */ 874 762 PPDMAUDIOHSTSTRMIN pHstStrmIn; 875 int rc = drvAudioHstInAdd(pThis, p szName, pCfg, enmRecSource, &pHstStrmIn);763 int rc = drvAudioHstInAdd(pThis, pCfg, &pHstStrmIn); 876 764 if (RT_FAILURE(rc)) 877 765 { 878 LogFunc(("Failed to add host audio input stream \"%s\", rc=%Rrc\n", p szName, rc));766 LogFunc(("Failed to add host audio input stream \"%s\", rc=%Rrc\n", pCfg->szName, rc)); 879 767 880 768 RTMemFree(pGstStrmIn); … … 886 774 * by the device emulation (which in turn was/could be set by the guest OS). 887 775 */ 888 rc = drvAudioGstInInit(pGstStrmIn, pHstStrmIn, p szName, pCfg);776 rc = drvAudioGstInInit(pGstStrmIn, pHstStrmIn, pCfg); 889 777 if (RT_SUCCESS(rc)) 890 778 { … … 908 796 * @param pHstStrmIn Pointer to host input stream to associate this guest 909 797 * stream with. 910 * @param pszName Pointer to stream name to use for this stream.911 798 * @param pCfg Pointer to stream configuration to use. 912 799 */ 913 int drvAudioGstInInit(PPDMAUDIOGSTSTRMIN pGstStrmIn, PPDMAUDIOHSTSTRMIN pHstStrmIn, 914 const char *pszName, PPDMAUDIOSTREAMCFG pCfg) 800 static int drvAudioGstInInit(PPDMAUDIOGSTSTRMIN pGstStrmIn, PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg) 915 801 { 916 802 AssertPtrReturn(pGstStrmIn, VERR_INVALID_POINTER); 917 803 AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER); 918 AssertPtrReturn(pszName, VERR_INVALID_POINTER);919 804 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 920 805 … … 922 807 if (RT_SUCCESS(rc)) 923 808 { 924 char *pszTemp; 925 if (RTStrAPrintf(&pszTemp, "%s (Guest)", pszName) <= 0) 809 char *pszName; 810 if (RTStrAPrintf(&pszName, "%s (Guest)", 811 strlen(pCfg->szName) ? pCfg->szName : "<Untitled>") <= 0) 812 { 926 813 return VERR_NO_MEMORY; 927 928 rc = AudioMixBufInit(&pGstStrmIn->MixBuf, pszTemp, &pGstStrmIn->Props, AudioMixBufSize(&pHstStrmIn->MixBuf)); 814 } 815 816 rc = AudioMixBufInit(&pGstStrmIn->MixBuf, pszName, &pGstStrmIn->Props, AudioMixBufSize(&pHstStrmIn->MixBuf)); 929 817 if (RT_SUCCESS(rc)) 930 818 rc = AudioMixBufLinkTo(&pHstStrmIn->MixBuf, &pGstStrmIn->MixBuf); 931 819 932 RTStrFree(pszTemp);933 934 820 if (RT_SUCCESS(rc)) 935 821 { 936 822 #ifdef DEBUG 937 drvAudioStreamCfgPrint(pCfg);823 DrvAudioStreamCfgPrint(pCfg); 938 824 #endif 939 825 pGstStrmIn->State.cRefs = 1; … … 941 827 pGstStrmIn->State.fEmpty = true; 942 828 943 pGstStrmIn->State.pszName = RTStrDup(pszName); 944 if (!pGstStrmIn->State.pszName) 945 return VERR_NO_MEMORY; 829 RTStrPrintf(pGstStrmIn->State.szName, RT_ELEMENTS(pGstStrmIn->State.szName), 830 "%s", pszName); 946 831 947 832 pGstStrmIn->pHstStrmIn = pHstStrmIn; 948 833 } 949 } 950 951 LogFlowFunc(("pszName=%s, rc=%Rrc\n", pszName, rc)); 952 return rc; 953 } 954 955 static int drvAudioAllocHstIn(PDRVAUDIO pThis, const char *pszName, PPDMAUDIOSTREAMCFG pCfg, 956 PDMAUDIORECSOURCE enmRecSource, PPDMAUDIOHSTSTRMIN *ppHstStrmIn) 834 835 RTStrFree(pszName); 836 } 837 838 LogFlowFunc(("pszName=%s, rc=%Rrc\n", pCfg->szName, rc)); 839 return rc; 840 } 841 842 static int drvAudioAllocHstIn(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMIN *ppHstStrmIn) 957 843 { 958 844 if (!pThis->cStreamsFreeIn) … … 979 865 980 866 int rc; 981 bool fInitialized = false;982 867 983 868 do 984 869 { 985 uint32_t cSamples; 986 rc = pThis->pHostDrvAudio->pfnInitIn(pThis->pHostDrvAudio, pHstStrmIn, 987 pCfg, enmRecSource, &cSamples); 870 uint32_t cSamples = 0; 871 rc = pThis->pHostDrvAudio->pfnInitIn 872 ? pThis->pHostDrvAudio->pfnInitIn(pThis->pHostDrvAudio, pHstStrmIn, 873 pCfg, pCfg->DestSource.Source, &cSamples) : VINF_SUCCESS; 988 874 if (RT_FAILURE(rc)) 989 875 { … … 992 878 } 993 879 994 fInitialized = true;995 996 char *psz Temp;997 if (RTStrAPrintf(&psz Temp, "%s (Host)", pszName) <= 0)880 pHstStrmIn->fStatus |= PDMAUDIOSTRMSTS_FLAG_INITIALIZED; 881 882 char *pszName; 883 if (RTStrAPrintf(&pszName, "%s (Host)", pCfg->szName) <= 0) 998 884 { 999 885 rc = VERR_NO_MEMORY; … … 1001 887 } 1002 888 1003 rc = AudioMixBufInit(&pHstStrmIn->MixBuf, psz Temp, &pHstStrmIn->Props, cSamples);889 rc = AudioMixBufInit(&pHstStrmIn->MixBuf, pszName, &pHstStrmIn->Props, cSamples); 1004 890 if (RT_SUCCESS(rc)) 1005 891 rc = RTCritSectInit(&pHstStrmIn->CritSect); … … 1011 897 } 1012 898 1013 RTStrFree(psz Temp);899 RTStrFree(pszName); 1014 900 1015 901 } while (0); … … 1017 903 if (RT_FAILURE(rc)) 1018 904 { 1019 if (fInitialized) 1020 { 1021 int rc2 = pThis->pHostDrvAudio->pfnFiniIn(pThis->pHostDrvAudio, 1022 pHstStrmIn); 1023 AssertRC(rc2); 905 if (pHstStrmIn->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED) 906 { 907 int rc2 = pThis->pHostDrvAudio->pfnFiniIn 908 ? pThis->pHostDrvAudio->pfnFiniIn(pThis->pHostDrvAudio, pHstStrmIn) : VINF_SUCCESS; 909 if (RT_SUCCESS(rc2)) 910 pHstStrmIn->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_INITIALIZED; 1024 911 } 1025 912 … … 1116 1003 } 1117 1004 1118 LogFlowFunc(("%s -> %s: Written pvBuf=%p,cbBuf=%RU32, cWritten=%RU32 (%RU32 bytes), cMixed=%RU32, rc=%Rrc\n",1119 pGstStrmOut->MixBuf.pszName, pHstStrmOut->MixBuf.pszName, pvBuf,cbBuf, cWritten,1005 LogFlowFunc(("%s -> %s: cbBuf=%RU32, cWritten=%RU32 (%RU32 bytes), cMixed=%RU32, rc=%Rrc\n", 1006 pGstStrmOut->MixBuf.pszName, pHstStrmOut->MixBuf.pszName, cbBuf, cWritten, 1120 1007 AUDIOMIXBUF_S2B(&pGstStrmOut->MixBuf, cWritten), cMixed, rc)); 1121 1008 … … 1127 1014 } 1128 1015 1129 PPDMAUDIOHSTSTRMOUT drvAudioFindAnyHstOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut)1016 static PPDMAUDIOHSTSTRMOUT drvAudioFindAnyHstOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut) 1130 1017 { 1131 1018 if (pHstStrmOut) … … 1140 1027 } 1141 1028 1142 PPDMAUDIOHSTSTRMOUT drvAudioHstFindAnyEnabledOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHostStrmOut)1029 static PPDMAUDIOHSTSTRMOUT drvAudioHstFindAnyEnabledOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHostStrmOut) 1143 1030 { 1144 1031 while ((pHostStrmOut = drvAudioFindAnyHstOut(pThis, pHostStrmOut))) … … 1151 1038 } 1152 1039 1153 PPDMAUDIOHSTSTRMOUT drvAudioFindSpecificOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut,1154 PPDMAUDIOSTREAMCFG pCfg)1040 static PPDMAUDIOHSTSTRMOUT drvAudioFindSpecificOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut, 1041 PPDMAUDIOSTREAMCFG pCfg) 1155 1042 { 1156 1043 while ((pHstStrmOut = drvAudioFindAnyHstOut(pThis, pHstStrmOut))) 1157 1044 { 1158 if ( drvAudioPCMPropsAreEqual(&pHstStrmOut->Props, pCfg))1045 if (DrvAudioPCMPropsAreEqual(&pHstStrmOut->Props, pCfg)) 1159 1046 return pHstStrmOut; 1160 1047 } … … 1165 1052 int drvAudioDestroyHstIn(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMIN pHstStrmIn) 1166 1053 { 1054 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1055 AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER); 1056 1057 LogFlowFunc(("%s\n", pHstStrmIn->MixBuf.pszName)); 1058 1059 int rc = VINF_SUCCESS; 1060 1061 if (!pHstStrmIn->pGstStrmIn) 1062 { 1063 drvAudioHstInFreeRes(pHstStrmIn); 1064 1065 if (RTCritSectIsInitialized(&pHstStrmIn->CritSect)) 1066 { 1067 int rc2 = RTCritSectDelete(&pHstStrmIn->CritSect); 1068 AssertRC(rc2); 1069 } 1070 1071 /* Remove from driver instance list. */ 1072 RTListNodeRemove(&pHstStrmIn->Node); 1073 1074 RTMemFree(pHstStrmIn); 1075 pThis->cStreamsFreeIn++; 1076 } 1077 else 1078 { 1079 rc = VERR_WRONG_ORDER; 1080 LogFlowFunc(("[%s] Still is being used, skipping\n", pHstStrmIn->MixBuf.pszName)); 1081 } 1082 1083 LogFlowFuncLeaveRC(rc); 1084 return rc; 1085 } 1086 1087 static int drvAudioDestroyGstIn(PDRVAUDIO pThis, PPDMAUDIOGSTSTRMIN pGstStrmIn) 1088 { 1167 1089 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1168 AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);1169 1170 LogFlowFunc(("%s\n", pHstStrmIn->MixBuf.pszName));1171 1172 int rc;1173 if (!pHstStrmIn->pGstStrmIn) /* No parent anymore? */1174 {1175 rc = pThis->pHostDrvAudio->pfnFiniIn(pThis->pHostDrvAudio, pHstStrmIn);1176 if (RT_SUCCESS(rc))1177 {1178 drvAudioHstInFreeRes(pHstStrmIn);1179 1180 if (RTCritSectIsInitialized(&pHstStrmIn->CritSect))1181 {1182 int rc2 = RTCritSectDelete(&pHstStrmIn->CritSect);1183 AssertRC(rc2);1184 }1185 1186 /* Remove from driver instance list. */1187 RTListNodeRemove(&pHstStrmIn->Node);1188 1189 RTMemFree(pHstStrmIn);1190 pThis->cStreamsFreeIn++;1191 }1192 }1193 else1194 {1195 rc = VERR_ACCESS_DENIED;1196 LogFlowFunc(("[%s] Still is being used, rc=%Rrc\n", pHstStrmIn->MixBuf.pszName, rc));1197 }1198 1199 return rc;1200 }1201 1202 static int drvAudioDestroyGstIn(PDRVAUDIO pThis, PPDMAUDIOGSTSTRMIN pGstStrmIn)1203 {1204 AssertPtrReturn(pThis, VERR_INVALID_POINTER);1205 1206 LogFlowFunc(("%s\n", pGstStrmIn->MixBuf.pszName));1207 1090 1208 1091 if (!pGstStrmIn) 1209 1092 return VINF_SUCCESS; 1210 1093 1094 LogFlowFunc(("%s\n", pGstStrmIn->MixBuf.pszName)); 1095 1211 1096 if (pGstStrmIn->State.cRefs > 1) /* Do other objects still have a reference to it? Bail out. */ 1212 1097 return VERR_WRONG_ORDER; 1213 1098 1214 drvAudioGstInFreeRes(pGstStrmIn); 1215 1099 AudioMixBufDestroy(&pGstStrmIn->MixBuf); 1100 1101 /* Is this guest stream associate to a host stream? */ 1216 1102 if (pGstStrmIn->pHstStrmIn) 1217 1103 { 1218 1104 /* Unlink child. */ 1219 1105 pGstStrmIn->pHstStrmIn->pGstStrmIn = NULL; 1220 1221 /* Try destroying the associated host input stream. This could1222 * be skipped if there are other guest input streams with this1223 * host stream. */1224 drvAudioDestroyHstIn(pThis, pGstStrmIn->pHstStrmIn);1225 1106 } 1226 1107 1227 1108 RTMemFree(pGstStrmIn); 1109 pGstStrmIn = NULL; 1228 1110 1229 1111 return VINF_SUCCESS; 1112 } 1113 1114 static DECLCALLBACK(uint32_t) drvAudioAddRefIn(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMIN pGstStrm) 1115 { 1116 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1117 AssertPtrReturn(pGstStrm, VERR_INVALID_POINTER); 1118 1119 NOREF(pInterface); 1120 1121 return ++pGstStrm->State.cRefs; 1122 } 1123 1124 static DECLCALLBACK(uint32_t) drvAudioAddRefOut(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMOUT pGstStrm) 1125 { 1126 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1127 AssertPtrReturn(pGstStrm, VERR_INVALID_POINTER); 1128 1129 NOREF(pInterface); 1130 1131 return ++pGstStrm->State.cRefs; 1132 } 1133 1134 static DECLCALLBACK(uint32_t) drvAudioReleaseIn(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMIN pGstStrm) 1135 { 1136 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1137 AssertPtrReturn(pGstStrm, VERR_INVALID_POINTER); 1138 1139 NOREF(pInterface); 1140 1141 Assert(pGstStrm->State.cRefs); 1142 if (pGstStrm->State.cRefs) 1143 pGstStrm->State.cRefs--; 1144 1145 return pGstStrm->State.cRefs; 1146 } 1147 1148 static DECLCALLBACK(uint32_t) drvAudioReleaseOut(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMOUT pGstStrm) 1149 { 1150 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1151 AssertPtrReturn(pGstStrm, VERR_INVALID_POINTER); 1152 1153 NOREF(pInterface); 1154 1155 Assert(pGstStrm->State.cRefs); 1156 if (pGstStrm->State.cRefs) 1157 pGstStrm->State.cRefs--; 1158 1159 return pGstStrm->State.cRefs; 1230 1160 } 1231 1161 … … 1309 1239 1310 1240 PPDMAUDIOHSTSTRMIN pHstStrmIn = NULL; 1311 while ((pHstStrmIn = drvAudioFindNextEnabledHstIn(pThis, pHstStrmIn))) 1312 { 1241 while ((pHstStrmIn = drvAudioFindAnyHstIn(pThis, pHstStrmIn))) 1242 { 1243 /* Disabled? Skip it! */ 1244 if (!(pHstStrmIn->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED)) 1245 continue; 1246 1313 1247 /* Call the host backend to capture the audio input data. */ 1314 1248 uint32_t cSamplesCaptured; … … 1373 1307 AssertRC(rc); 1374 1308 1375 if (!pThis->BackendCfg.cMaxStreamsOut) 1309 if ( !pThis->BackendCfg.cSinks 1310 || !pThis->BackendCfg.cMaxStreamsOut) 1376 1311 { 1377 1312 int rc2 = RTCritSectLeave(&pThis->CritSect); … … 1422 1357 if (RT_FAILURE(rc2)) 1423 1358 { 1424 rc2= pThis->pHostDrvAudio->pfnControlOut(pThis->pHostDrvAudio, pHstStrmOut, PDMAUDIOSTREAMCMD_DISABLE);1425 AssertRC(rc 2);1359 int rc3 = pThis->pHostDrvAudio->pfnControlOut(pThis->pHostDrvAudio, pHstStrmOut, PDMAUDIOSTREAMCMD_DISABLE); 1360 AssertRC(rc3); 1426 1361 } 1427 1362 else … … 1620 1555 } 1621 1556 1622 if (pThis->BackendCfg.cbStreamOut) 1623 { 1557 pThis->cStreamsFreeIn = 0; 1558 pThis->cStreamsFreeOut = 0; 1559 1560 if (pThis->BackendCfg.cSinks) 1561 { 1562 Assert(pThis->BackendCfg.cbStreamOut); 1563 1624 1564 pThis->cStreamsFreeOut = pThis->BackendCfg.cMaxStreamsOut; 1625 1565 } 1626 else 1627 pThis->cStreamsFreeOut = 0; 1628 1629 if (pThis->BackendCfg.cbStreamIn) 1630 { 1631 /* 1632 * Note: 1633 * - Our AC'97 emulation has two inputs, line (ac97.pi) and microphone (ac97.mc). 1634 * - Our HDA emulation currently has only line input (hda.pi). 1635 */ 1566 1567 if (pThis->BackendCfg.cSources) 1568 { 1569 Assert(pThis->BackendCfg.cbStreamIn); 1570 1636 1571 pThis->cStreamsFreeIn = pThis->BackendCfg.cMaxStreamsIn; 1637 1572 } 1638 else1639 pThis->cStreamsFreeIn = 0;1640 1573 1641 1574 LogFlowFunc(("cStreamsFreeIn=%RU8, cStreamsFreeOut=%RU8\n", pThis->cStreamsFreeIn, pThis->cStreamsFreeOut)); … … 1660 1593 1661 1594 PPDMAUDIOHSTSTRMOUT pHstStrmOut = NULL; 1662 while ((pHstStrmOut = drvAudio HstFindAnyEnabledOut(pThis, pHstStrmOut)))1595 while ((pHstStrmOut = drvAudioFindAnyHstOut(pThis, pHstStrmOut))) 1663 1596 drvAudioControlHstOut(pThis, pHstStrmOut, enmCmd); 1664 1597 1665 1598 PPDMAUDIOHSTSTRMIN pHstStrmIn = NULL; 1666 while ((pHstStrmIn = drvAudioFind NextEnabledHstIn(pThis, pHstStrmIn)))1599 while ((pHstStrmIn = drvAudioFindAnyHstIn(pThis, pHstStrmIn))) 1667 1600 drvAudioControlHstIn(pThis, pHstStrmIn, enmCmd); 1668 1601 } … … 1674 1607 1675 1608 PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO); 1676 LogFlowFunc(("p DrvAudio=%p, pDrvIns=%p\n", pThis, pDrvIns));1609 LogFlowFunc(("pThis=%p, pDrvIns=%p\n", pThis, pDrvIns)); 1677 1610 1678 1611 RTListInit(&pThis->lstHstStrmIn); … … 1703 1636 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1704 1637 1705 AssertPtrReturn(pGstStrmIn, VERR_INVALID_POINTER); 1638 if (!pGstStrmIn) 1639 return VERR_NOT_AVAILABLE; 1640 1706 1641 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 1707 1642 AssertReturn(cbBuf, VERR_INVALID_PARAMETER); … … 1754 1689 { 1755 1690 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1756 /* pGstStrmOut is optional. */ 1691 1692 if (!pGstStrmOut) 1693 return VERR_NOT_AVAILABLE; 1757 1694 1758 1695 PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface); … … 1760 1697 int rc = VINF_SUCCESS; 1761 1698 1762 if (pGstStrmOut) 1763 { 1764 PPDMAUDIOHSTSTRMOUT pHstStrmOut = pGstStrmOut->pHstStrmOut; 1765 AssertPtr(pHstStrmOut); 1766 1767 if (fEnable) 1768 { 1769 /* Is a pending disable outstanding? Then disable first. */ 1770 if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE) 1699 PPDMAUDIOHSTSTRMOUT pHstStrmOut = pGstStrmOut->pHstStrmOut; 1700 AssertPtr(pHstStrmOut); 1701 1702 if (fEnable) 1703 { 1704 /* Is a pending disable outstanding? Then disable first. */ 1705 if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE) 1706 { 1707 rc = drvAudioControlHstOut(pThis, pHstStrmOut, PDMAUDIOSTREAMCMD_DISABLE); 1708 if (RT_SUCCESS(rc)) 1709 pHstStrmOut->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE; 1710 } 1711 1712 if (RT_SUCCESS(rc)) 1713 rc = drvAudioControlHstOut(pThis, pHstStrmOut, PDMAUDIOSTREAMCMD_ENABLE); 1714 } 1715 else /* Disable */ 1716 { 1717 if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED) 1718 { 1719 uint32_t cGstStrmsActive = 0; 1720 1721 /* 1722 * Check if there are any active guest streams assigned 1723 * to this host stream which still are being marked as active. 1724 * 1725 * In that case we have to defer closing the host stream and 1726 * wait until all guest streams have been finished. 1727 */ 1728 PPDMAUDIOGSTSTRMOUT pIter; 1729 RTListForEach(&pHstStrmOut->lstGstStrmOut, pIter, PDMAUDIOGSTSTRMOUT, Node) 1771 1730 { 1731 if (pIter->State.fActive) 1732 { 1733 cGstStrmsActive++; 1734 break; /* At least one assigned & active guest stream is enough. */ 1735 } 1736 } 1737 1738 /* Do we need to defer closing the host stream? */ 1739 if (cGstStrmsActive >= 1) 1740 pHstStrmOut->fStatus |= PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE; 1741 1742 /* Can we close the host stream now instead of deferring it? */ 1743 if (!(pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE)) 1772 1744 rc = drvAudioControlHstOut(pThis, pHstStrmOut, PDMAUDIOSTREAMCMD_DISABLE); 1773 if (RT_SUCCESS(rc)) 1774 pHstStrmOut->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE; 1775 } 1776 1777 if (RT_SUCCESS(rc)) 1778 rc = drvAudioControlHstOut(pThis, pHstStrmOut, PDMAUDIOSTREAMCMD_ENABLE); 1779 } 1780 else /* Disable */ 1781 { 1782 if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED) 1783 { 1784 uint32_t cGstStrmsActive = 0; 1785 1786 /* 1787 * Check if there are any active guest streams assigned 1788 * to this host stream which still are being marked as active. 1789 * 1790 * In that case we have to defer closing the host stream and 1791 * wait until all guest streams have been finished. 1792 */ 1793 PPDMAUDIOGSTSTRMOUT pIter; 1794 RTListForEach(&pHstStrmOut->lstGstStrmOut, pIter, PDMAUDIOGSTSTRMOUT, Node) 1795 { 1796 if (pIter->State.fActive) 1797 { 1798 cGstStrmsActive++; 1799 break; /* At least one assigned & active guest stream is enough. */ 1800 } 1801 } 1802 1803 /* Do we need to defer closing the host stream? */ 1804 if (cGstStrmsActive >= 1) 1805 pHstStrmOut->fStatus |= PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE; 1806 1807 /* Can we close the host stream now instead of deferring it? */ 1808 if (!(pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE)) 1809 rc = drvAudioControlHstOut(pThis, pHstStrmOut, PDMAUDIOSTREAMCMD_DISABLE); 1810 } 1811 } 1812 1813 if (RT_SUCCESS(rc)) 1814 pGstStrmOut->State.fActive = fEnable; 1815 1816 LogFlowFunc(("%s: fEnable=%RTbool, fStatus=0x%x, rc=%Rrc\n", 1817 pGstStrmOut->MixBuf.pszName, fEnable, pHstStrmOut->fStatus, rc)); 1818 } 1745 } 1746 } 1747 1748 if (RT_SUCCESS(rc)) 1749 pGstStrmOut->State.fActive = fEnable; 1750 1751 LogFlowFunc(("%s: fEnable=%RTbool, fStatus=0x%x, rc=%Rrc\n", 1752 pGstStrmOut->MixBuf.pszName, fEnable, pHstStrmOut->fStatus, rc)); 1819 1753 1820 1754 return rc; … … 1825 1759 { 1826 1760 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1827 /* pGstStrmIn is optional. */ 1761 1762 if (!pGstStrmIn) 1763 return VERR_NOT_AVAILABLE; 1828 1764 1829 1765 PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface); … … 1831 1767 int rc = VINF_SUCCESS; 1832 1768 1833 if (pGstStrmIn) 1834 { 1835 PPDMAUDIOHSTSTRMIN pHstStrmIn = pGstStrmIn->pHstStrmIn; 1836 AssertPtr(pHstStrmIn); 1837 1838 LogFlowFunc(("%s: fEnable=%RTbool\n", pGstStrmIn->MixBuf.pszName, fEnable)); 1839 1840 rc = drvAudioControlHstIn(pThis, pHstStrmIn, 1841 fEnable ? PDMAUDIOSTREAMCMD_ENABLE : PDMAUDIOSTREAMCMD_DISABLE); 1842 if (RT_SUCCESS(rc)) 1843 pGstStrmIn->State.fActive = fEnable; 1844 1845 LogFlowFunc(("%s: fEnable=%RTbool, rc=%Rrc\n", pGstStrmIn->MixBuf.pszName, fEnable, rc)); 1846 } 1769 PPDMAUDIOHSTSTRMIN pHstStrmIn = pGstStrmIn->pHstStrmIn; 1770 AssertPtr(pHstStrmIn); 1771 1772 rc = drvAudioControlHstIn(pThis, pHstStrmIn, 1773 fEnable ? PDMAUDIOSTREAMCMD_ENABLE : PDMAUDIOSTREAMCMD_DISABLE); 1774 if (RT_SUCCESS(rc)) 1775 pGstStrmIn->State.fActive = fEnable; 1776 1777 LogFlowFunc(("%s: fEnable=%RTbool, rc=%Rrc\n", pGstStrmIn->MixBuf.pszName, fEnable, rc)); 1847 1778 1848 1779 return rc; … … 1861 1792 } 1862 1793 1863 static DECLCALLBACK(int) drvAudioCreateIn(PPDMIAUDIOCONNECTOR pInterface, const char *pszName,1864 PPDMAUDIO STREAMCFG pCfg, PPDMAUDIOGSTSTRMIN *ppGstStrmIn)1794 static DECLCALLBACK(int) drvAudioCreateIn(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAMCFG pCfg, 1795 PPDMAUDIOGSTSTRMIN *ppGstStrmIn) 1865 1796 { 1866 1797 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1867 AssertPtrReturn(ppGstStrmIn, VERR_INVALID_POINTER);1868 AssertPtrReturn(pszName, VERR_INVALID_POINTER);1869 1798 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 1870 1799 AssertPtrReturn(ppGstStrmIn, VERR_INVALID_POINTER); … … 1878 1807 return rc; 1879 1808 1880 LogFlowFunc((" pszName=%s, pCfg=%p\n", pszName, pCfg));1809 LogFlowFunc(("szName=%s\n", pCfg->szName)); 1881 1810 1882 1811 if (!drvAudioStreamCfgIsValid(pCfg)) … … 1889 1818 { 1890 1819 PPDMAUDIOGSTSTRMIN pGstStrmIn; 1891 rc = drvAudioCreateStreamPairIn(pThis, p szName, pCfg->DestSource.Source, pCfg, &pGstStrmIn);1820 rc = drvAudioCreateStreamPairIn(pThis, pCfg, &pGstStrmIn); 1892 1821 if (RT_SUCCESS(rc)) 1893 1822 *ppGstStrmIn = pGstStrmIn; … … 1902 1831 } 1903 1832 1904 static DECLCALLBACK(int) drvAudioCreateOut(PPDMIAUDIOCONNECTOR pInterface, const char *pszName,1905 PPDMAUDIO STREAMCFG pCfg, PPDMAUDIOGSTSTRMOUT *ppGstStrmOut)1833 static DECLCALLBACK(int) drvAudioCreateOut(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAMCFG pCfg, 1834 PPDMAUDIOGSTSTRMOUT *ppGstStrmOut) 1906 1835 { 1907 1836 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1908 AssertPtrReturn(pszName, VERR_INVALID_POINTER);1909 1837 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 1910 1838 AssertPtrReturn(ppGstStrmOut, VERR_INVALID_POINTER); … … 1918 1846 return rc; 1919 1847 1920 LogFlowFunc(("pszName=%s , pCfg=%p\n", pszName, pCfg));1848 LogFlowFunc(("pszName=%s\n", pCfg->szName)); 1921 1849 1922 1850 if (!drvAudioStreamCfgIsValid(pCfg)) … … 1929 1857 { 1930 1858 PPDMAUDIOGSTSTRMOUT pGstStrmOut; 1931 rc = drvAudioCreateStreamPairOut(pThis, p szName, pCfg, &pGstStrmOut);1859 rc = drvAudioCreateStreamPairOut(pThis, pCfg, &pGstStrmOut); 1932 1860 if (RT_SUCCESS(rc)) 1933 1861 *ppGstStrmOut = pGstStrmOut; … … 1942 1870 } 1943 1871 1944 static DECLCALLBACK(int) drvAudioGetConfig uration(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOBACKENDCFG pCfg)1872 static DECLCALLBACK(int) drvAudioGetConfig(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOBACKENDCFG pCfg) 1945 1873 { 1946 1874 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); … … 2006 1934 PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface); 2007 1935 1936 if (!pGstStrmIn) 1937 return; 1938 2008 1939 int rc2 = RTCritSectEnter(&pThis->CritSect); 2009 1940 AssertRC(rc2); 2010 1941 2011 if (pGstStrmIn)2012 drvAudioDestroyGstIn(pThis, pGstStrmIn);1942 rc2 = drvAudioDestroyGstIn(pThis, pGstStrmIn); 1943 AssertRC(rc2); 2013 1944 2014 1945 rc2 = RTCritSectLeave(&pThis->CritSect); … … 2023 1954 PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface); 2024 1955 1956 if (!pGstStrmOut) 1957 return; 1958 2025 1959 int rc2 = RTCritSectEnter(&pThis->CritSect); 2026 1960 AssertRC(rc2); 2027 1961 2028 if (pGstStrmOut)2029 drvAudioDestroyGstOut(pThis, pGstStrmOut);1962 rc2 = drvAudioDestroyGstOut(pThis, pGstStrmOut); 1963 AssertRC(rc2); 2030 1964 2031 1965 rc2 = RTCritSectLeave(&pThis->CritSect); 2032 1966 AssertRC(rc2); 1967 } 1968 1969 void drvAudioHstOutFreeRes(PPDMAUDIOHSTSTRMOUT pHstStrmOut) 1970 { 1971 AssertPtrReturnVoid(pHstStrmOut); 1972 AudioMixBufDestroy(&pHstStrmOut->MixBuf); 2033 1973 } 2034 1974 … … 2058 1998 static DECLCALLBACK(void) drvAudioPowerOff(PPDMDRVINS pDrvIns) 2059 1999 { 2000 PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO); 2001 2060 2002 LogFlowFuncEnter(); 2061 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns); 2062 2063 PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO); 2064 2065 if (!pThis->pHostDrvAudio) 2066 return; 2067 2068 /* Tear down all host output streams. */ 2003 2004 /* First, disable all streams. */ 2005 drvAudioStateHandler(pDrvIns, PDMAUDIOSTREAMCMD_DISABLE); 2006 2007 int rc2; 2008 2069 2009 PPDMAUDIOHSTSTRMOUT pHstStrmOut = NULL; 2070 2010 while ((pHstStrmOut = drvAudioFindAnyHstOut(pThis, pHstStrmOut))) 2071 2011 { 2072 drvAudioControlHstOut(pThis, pHstStrmOut, PDMAUDIOSTREAMCMD_DISABLE); 2073 pThis->pHostDrvAudio->pfnFiniOut(pThis->pHostDrvAudio, pHstStrmOut); 2074 } 2075 2076 /* Tear down all host input streams. */ 2012 if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED) 2013 { 2014 rc2 = pThis->pHostDrvAudio->pfnFiniOut 2015 ? pThis->pHostDrvAudio->pfnFiniOut(pThis->pHostDrvAudio, pHstStrmOut) : VINF_SUCCESS; 2016 if (RT_SUCCESS(rc2)) 2017 pHstStrmOut->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_INITIALIZED; 2018 } 2019 else 2020 rc2 = VINF_SUCCESS; 2021 2022 AssertMsgRC(rc2, ("Host output stream %p failed to uninit: %Rrc\n", pHstStrmOut, rc2)); 2023 } 2024 2077 2025 PPDMAUDIOHSTSTRMIN pHstStrmIn = NULL; 2078 while ((pHstStrmIn = drvAudioFindNextHstIn(pThis, pHstStrmIn))) 2079 { 2080 drvAudioControlHstIn(pThis, pHstStrmIn, PDMAUDIOSTREAMCMD_DISABLE); 2081 pThis->pHostDrvAudio->pfnFiniIn(pThis->pHostDrvAudio, pHstStrmIn); 2082 } 2083 2026 while ((pHstStrmIn = drvAudioFindAnyHstIn(pThis, pHstStrmIn))) 2027 { 2028 if (pHstStrmIn->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED) 2029 { 2030 rc2 = pThis->pHostDrvAudio->pfnFiniIn 2031 ? pThis->pHostDrvAudio->pfnFiniIn(pThis->pHostDrvAudio, pHstStrmIn) : VINF_SUCCESS; 2032 if (RT_SUCCESS(rc2)) 2033 pHstStrmIn->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_INITIALIZED; 2034 } 2035 else 2036 rc2 = VINF_SUCCESS; 2037 2038 AssertMsgRC(rc2, ("Host input stream %p failed to uninit: %Rrc\n", pHstStrmIn, rc2)); 2039 } 2040 2041 /* 2042 * Last call for the driver below us. 2043 * Let it know that we reached end of life. 2044 */ 2084 2045 if (pThis->pHostDrvAudio->pfnShutdown) 2085 2046 pThis->pHostDrvAudio->pfnShutdown(pThis->pHostDrvAudio); 2086 2047 2087 #ifdef VBOX_WITH_AUDIO_CALLBACKS 2088 PPDMAUDIOCALLBACK pCB, pCBNext; 2089 RTListForEachSafe(&pThis->lstCBIn, pCB, pCBNext, PDMAUDIOCALLBACK, Node) 2090 drvAudioCallbackDestroy(pCB); 2091 2092 RTListForEachSafe(&pThis->lstCBOut, pCB, pCBNext, PDMAUDIOCALLBACK, Node) 2093 drvAudioCallbackDestroy(pCB); 2094 #endif 2048 pThis->pHostDrvAudio = NULL; 2095 2049 2096 2050 LogFlowFuncLeave(); … … 2117 2071 /* IAudioConnector. */ 2118 2072 pThis->IAudioConnector.pfnQueryStatus = drvAudioQueryStatus; 2073 pThis->IAudioConnector.pfnAddRefIn = drvAudioAddRefIn; 2074 pThis->IAudioConnector.pfnAddRefOut = drvAudioAddRefOut; 2075 pThis->IAudioConnector.pfnReleaseIn = drvAudioReleaseIn; 2076 pThis->IAudioConnector.pfnReleaseOut = drvAudioReleaseOut; 2119 2077 pThis->IAudioConnector.pfnRead = drvAudioRead; 2120 2078 pThis->IAudioConnector.pfnWrite = drvAudioWrite; 2121 pThis->IAudioConnector.pfnGetConfig uration = drvAudioGetConfiguration;2079 pThis->IAudioConnector.pfnGetConfig = drvAudioGetConfig; 2122 2080 pThis->IAudioConnector.pfnIsActiveIn = drvAudioIsActiveIn; 2123 2081 pThis->IAudioConnector.pfnIsActiveOut = drvAudioIsActiveOut; … … 2179 2137 PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO); 2180 2138 2181 if (RTCritSectIsInitialized(&pThis->CritSect)) 2182 { 2183 int rc2 = RTCritSectDelete(&pThis->CritSect); 2139 int rc2 = RTCritSectEnter(&pThis->CritSect); 2140 AssertRC(rc2); 2141 2142 /* 2143 * Note: No calls here to the driver below us anymore, 2144 * as PDM already has destroyed it. 2145 * If you need to call something from the host driver, 2146 * do this in drvAudioPowerOff() instead. 2147 */ 2148 2149 /* 2150 * Destroy all host input streams. 2151 */ 2152 PPDMAUDIOHSTSTRMOUT pHstStrmOut = NULL; 2153 while ((pHstStrmOut = drvAudioFindAnyHstOut(pThis, pHstStrmOut))) 2154 { 2155 rc2 = drvAudioDestroyHstOut(pThis, pHstStrmOut); 2184 2156 AssertRC(rc2); 2185 } 2157 2158 /* Sanity. */ 2159 Assert(RTListIsEmpty(&pHstStrmOut->lstGstStrmOut)); 2160 2161 pHstStrmOut = NULL; 2162 } 2163 2164 /* 2165 * Destroy all host input streams. 2166 */ 2167 PPDMAUDIOHSTSTRMIN pHstStrmIn = NULL; 2168 while ((pHstStrmIn = drvAudioFindAnyHstIn(pThis, pHstStrmIn))) 2169 { 2170 rc2 = drvAudioDestroyHstIn(pThis, pHstStrmIn); 2171 AssertRC(rc2); 2172 2173 /* Sanity. */ 2174 Assert(pHstStrmIn->pGstStrmIn == NULL); 2175 2176 pHstStrmIn = NULL; 2177 } 2178 2179 /* Sanity. */ 2180 Assert(RTListIsEmpty(&pThis->lstHstStrmIn)); 2181 Assert(RTListIsEmpty(&pThis->lstHstStrmOut)); 2182 2183 #ifdef VBOX_WITH_AUDIO_CALLBACKS 2184 /* 2185 * Destroy callbacks, if any. 2186 */ 2187 PPDMAUDIOCALLBACK pCB, pCBNext; 2188 RTListForEachSafe(&pThis->lstCBIn, pCB, pCBNext, PDMAUDIOCALLBACK, Node) 2189 drvAudioCallbackDestroy(pCB); 2190 2191 RTListForEachSafe(&pThis->lstCBOut, pCB, pCBNext, PDMAUDIOCALLBACK, Node) 2192 drvAudioCallbackDestroy(pCB); 2193 #endif 2194 2195 rc2 = RTCritSectLeave(&pThis->CritSect); 2196 AssertRC(rc2); 2197 2198 rc2 = RTCritSectDelete(&pThis->CritSect); 2199 AssertRC(rc2); 2200 2201 LogFlowFuncLeave(); 2186 2202 } 2187 2203 … … 2256 2272 PDM_DRVREG_VERSION 2257 2273 }; 2274 -
trunk/src/VBox/Devices/Audio/DrvAudio.h
r60353 r60925 113 113 ( (PDRVAUDIO)((uintptr_t)pInterface - RT_OFFSETOF(DRVAUDIO, IAudioConnector)) ) 114 114 115 //const char *drvAudioHlpFormatToString(PDMAUDIOFMT fmt); 116 const char *drvAudioRecSourceToString(PDMAUDIORECSOURCE enmRecSource); 117 PDMAUDIOFMT drvAudioHlpStringToFormat(const char *pszFormat); 118 119 bool drvAudioPCMPropsAreEqual(PPDMPCMPROPS info, PPDMAUDIOSTREAMCFG pCfg); 120 void drvAudioStreamCfgPrint(PPDMAUDIOSTREAMCFG pCfg); 121 122 /* AUDIO IN function declarations. */ 123 void drvAudioHlpPcmSwFreeResourcesIn(PPDMAUDIOGSTSTRMIN pGstStrmIn); 124 void drvAudioGstInFreeRes(PPDMAUDIOGSTSTRMIN pGstStrmIn); 125 void drvAudioGstInRemove(PPDMAUDIOGSTSTRMIN pGstStrmIn); 126 uint32_t drvAudioHstInFindMinCaptured(PPDMAUDIOHSTSTRMIN pHstStrmIn); 127 void drvAudioHstInFreeRes(PPDMAUDIOHSTSTRMIN pHstStrmIn); 128 uint32_t drvAudioHstInGetFree(PPDMAUDIOHSTSTRMIN pHstStrmIn); 129 uint32_t drvAudioHstInGetLive(PPDMAUDIOHSTSTRMIN pHstStrmIn); 130 void drvAudioGstInRemove(PPDMAUDIOGSTSTRMIN pGstStrmIn); 131 int drvAudioGstInInit(PPDMAUDIOGSTSTRMIN pGstStrmIn, PPDMAUDIOHSTSTRMIN pHstStrmIn, const char *pszName, PPDMAUDIOSTREAMCFG pCfg); 132 133 PPDMAUDIOHSTSTRMIN drvAudioFindNextHstIn(PDRVAUDIO pDrvAudio, PPDMAUDIOHSTSTRMIN pHstStrmIn); 134 PPDMAUDIOHSTSTRMIN drvAudioFindNextEnabledHstIn(PDRVAUDIO pDrvAudio, PPDMAUDIOHSTSTRMIN pHstStrmIn); 135 PPDMAUDIOHSTSTRMIN drvAudioFindNextEqHstIn(PDRVAUDIO pDrvAudio, PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg); 136 137 /* AUDIO OUT function declarations. */ 138 int drvAudioGstOutAlloc(PPDMAUDIOGSTSTRMOUT pGstStrmOut); 139 void drvAudioGstOutFreeRes(PPDMAUDIOGSTSTRMOUT pGstStrmOut); 140 void drvAudioHstOutFreeRes(PPDMAUDIOHSTSTRMOUT pHstStrmOut); 141 int drvAudioDestroyGstOut(PDRVAUDIO pDrvAudio, PPDMAUDIOGSTSTRMOUT pGstStrmOut); 142 void drvAudioDestroyHstOut(PDRVAUDIO pDrvAudio, PDMAUDIOHSTSTRMOUT pHstStrmOut); 143 int drvAudioGstOutInit(PPDMAUDIOGSTSTRMOUT pGstStrmOut, PPDMAUDIOHSTSTRMOUT pHstStrmOut, const char *pszName, PPDMAUDIOSTREAMCFG pCfg); 144 145 PPDMAUDIOHSTSTRMOUT drvAudioFindAnyHstOut(PDRVAUDIO pDrvAudio, PPDMAUDIOHSTSTRMOUT pHstStrmOut); 146 PPDMAUDIOHSTSTRMOUT drvAudioHstFindAnyEnabledOut(PDRVAUDIO pDrvAudio, PPDMAUDIOHSTSTRMOUT pHstStrmOut); 147 PPDMAUDIOHSTSTRMOUT drvAudioFindSpecificOut(PDRVAUDIO pDrvAudio, PPDMAUDIOHSTSTRMOUT pHstStrmOut, PPDMAUDIOSTREAMCFG pCfg); 148 int drvAudioAllocHstOut(PDRVAUDIO pDrvAudio, const char *pszName, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMOUT *ppHstStrmOut); 149 int drvAudioHlpPcmHwAddOut(PDRVAUDIO pDrvAudio, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMOUT *ppHstStrmOut); 150 int drvAudioHlpPcmCreateVoicePairOut(PDRVAUDIO pDrvAudio, const char *pszName, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOGSTSTRMOUT *ppGstStrmOut); 151 152 /* Common functions between DrvAudio and backends (host audio drivers). */ 115 const char *DrvAudioAudFmtToStr(PDMAUDIOFMT enmFmt); 153 116 void DrvAudioClearBuf(PPDMPCMPROPS pPCMInfo, void *pvBuf, size_t cbBuf, uint32_t cSamples); 117 bool DrvAudioPCMPropsAreEqual(PPDMPCMPROPS pPCMInfo, PPDMAUDIOSTREAMCFG pCfg); 118 const char *DrvAudRecSrcToStr(PDMAUDIORECSOURCE enmRecSource); 119 void DrvAudioStreamCfgPrint(PPDMAUDIOSTREAMCFG pCfg); 154 120 int DrvAudioStreamCfgToProps(PPDMAUDIOSTREAMCFG pCfg, PPDMPCMPROPS pProps); 121 PDMAUDIOFMT DrvAudioStrToAudFmt(const char *pszFmt); 155 122 156 123 #endif /* DRV_AUDIO_H */ -
trunk/src/VBox/Devices/Audio/DrvAudioCommon.cpp
r60353 r60925 7 7 8 8 /* 9 * Copyright (C) 2006-201 5Oracle Corporation9 * Copyright (C) 2006-2016 Oracle Corporation 10 10 * 11 11 * This file is part of VirtualBox Open Source Edition (OSE), as … … 61 61 #include "AudioMixBuffer.h" 62 62 63 bool drvAudioPCMPropsAreEqual(PPDMPCMPROPS pProps, PPDMAUDIOSTREAMCFG pCfg); 64 65 const char *drvAudioRecSourceToString(PDMAUDIORECSOURCE enmRecSource) 66 { 67 switch (enmRecSource) 68 { 69 case PDMAUDIORECSOURCE_MIC: return "Microphone In"; 70 case PDMAUDIORECSOURCE_CD: return "CD"; 71 case PDMAUDIORECSOURCE_VIDEO: return "Video"; 72 case PDMAUDIORECSOURCE_AUX: return "AUX"; 73 case PDMAUDIORECSOURCE_LINE: return "Line In"; 74 case PDMAUDIORECSOURCE_PHONE: return "Phone"; 75 default: 76 break; 77 } 78 79 AssertMsgFailed(("Bogus recording source %ld\n", enmRecSource)); 63 /** 64 * Clears a sample buffer by the given amount of audio samples. 65 * 66 * @return IPRT status code. 67 * @param pPCMProps PCM properties to use for the buffer to clear. 68 * @param pvBuf Buffer to clear. 69 * @param cbBuf Size (in bytes) of the buffer. 70 * @param cSamples Number of audio samples to clear in the buffer. 71 */ 72 void DrvAudioClearBuf(PPDMPCMPROPS pPCMProps, void *pvBuf, size_t cbBuf, uint32_t cSamples) 73 { 74 AssertPtrReturnVoid(pPCMProps); 75 AssertPtrReturnVoid(pvBuf); 76 77 if (!cbBuf || !cSamples) 78 return; 79 80 Log2Func(("pPCMInfo=%p, pvBuf=%p, cSamples=%RU32, fSigned=%RTbool, cBits=%RU8, cShift=%RU8\n", 81 pPCMProps, pvBuf, cSamples, pPCMProps->fSigned, pPCMProps->cBits, pPCMProps->cShift)); 82 83 if (pPCMProps->fSigned) 84 { 85 memset(pvBuf, 0, cSamples << pPCMProps->cShift); 86 } 87 else 88 { 89 switch (pPCMProps->cBits) 90 { 91 case 8: 92 { 93 memset(pvBuf, 0x80, cSamples << pPCMProps->cShift); 94 break; 95 } 96 97 case 16: 98 { 99 uint16_t *p = (uint16_t *)pvBuf; 100 int shift = pPCMProps->cChannels - 1; 101 short s = INT16_MAX; 102 103 if (pPCMProps->fSwapEndian) 104 s = RT_BSWAP_U16(s); 105 106 for (unsigned i = 0; i < cSamples << shift; i++) 107 p[i] = s; 108 109 break; 110 } 111 112 case 32: 113 { 114 uint32_t *p = (uint32_t *)pvBuf; 115 int shift = pPCMProps->cChannels - 1; 116 int32_t s = INT32_MAX; 117 118 if (pPCMProps->fSwapEndian) 119 s = RT_BSWAP_U32(s); 120 121 for (unsigned i = 0; i < cSamples << shift; i++) 122 p[i] = s; 123 124 break; 125 } 126 127 default: 128 { 129 AssertMsgFailed(("Invalid bits: %RU8\n", pPCMProps->cBits)); 130 break; 131 } 132 } 133 } 134 } 135 136 const char *DrvAudRecSrcToStr(PDMAUDIORECSOURCE enmRecSrc) 137 { 138 switch (enmRecSrc) 139 { 140 case PDMAUDIORECSOURCE_MIC: return "Microphone In"; 141 case PDMAUDIORECSOURCE_CD: return "CD"; 142 case PDMAUDIORECSOURCE_VIDEO: return "Video"; 143 case PDMAUDIORECSOURCE_AUX: return "AUX"; 144 case PDMAUDIORECSOURCE_LINE: return "Line In"; 145 case PDMAUDIORECSOURCE_PHONE: return "Phone"; 146 default: 147 break; 148 } 149 150 AssertMsgFailed(("Invalid recording source %ld\n", enmRecSrc)); 80 151 return "Unknown"; 81 152 } 82 153 83 const char * drvAudioHlpFormatToString(PDMAUDIOFMT enmFormat)84 { 85 switch (enmF ormat)86 { 87 case AUD_FMT_U8:154 const char *DrvAudioAudFmtToStr(PDMAUDIOFMT enmFmt) 155 { 156 switch (enmFmt) 157 { 158 case PDMAUDIOFMT_U8: 88 159 return "U8"; 89 160 90 case AUD_FMT_U16:161 case PDMAUDIOFMT_U16: 91 162 return "U16"; 92 163 93 case AUD_FMT_U32:164 case PDMAUDIOFMT_U32: 94 165 return "U32"; 95 166 96 case AUD_FMT_S8:167 case PDMAUDIOFMT_S8: 97 168 return "S8"; 98 169 99 case AUD_FMT_S16:170 case PDMAUDIOFMT_S16: 100 171 return "S16"; 101 172 102 case AUD_FMT_S32:173 case PDMAUDIOFMT_S32: 103 174 return "S32"; 104 175 … … 107 178 } 108 179 109 AssertMsgFailed(("Bogus audio format %ld\n", enmF ormat));180 AssertMsgFailed(("Bogus audio format %ld\n", enmFmt)); 110 181 return "Invalid"; 111 182 } 112 183 113 PDMAUDIOFMT drvAudioHlpStringToFormat(const char *pszFormat) 114 { 115 if (!RTStrICmp(pszFormat, "u8")) 116 return AUD_FMT_U8; 117 else if (!RTStrICmp(pszFormat, "u16")) 118 return AUD_FMT_U16; 119 else if (!RTStrICmp(pszFormat, "u32")) 120 return AUD_FMT_U32; 121 else if (!RTStrICmp(pszFormat, "s8")) 122 return AUD_FMT_S8; 123 else if (!RTStrICmp(pszFormat, "s16")) 124 return AUD_FMT_S16; 125 else if (!RTStrICmp(pszFormat, "s32")) 126 return AUD_FMT_S32; 127 128 AssertMsgFailed(("Bogus audio format \"%s\"\n", pszFormat)); 129 return AUD_FMT_INVALID; 130 } 131 132 /*********************************** In Stream Functions **********************************************/ 133 134 void drvAudioGstInFreeRes(PPDMAUDIOGSTSTRMIN pGstStrmIn) 135 { 136 AssertPtrReturnVoid(pGstStrmIn); 137 138 if (pGstStrmIn->State.pszName) 139 { 140 RTStrFree(pGstStrmIn->State.pszName); 141 pGstStrmIn->State.pszName = NULL; 142 } 143 144 AudioMixBufDestroy(&pGstStrmIn->MixBuf); 145 } 146 147 void drvAudioHstInFreeRes(PPDMAUDIOHSTSTRMIN pHstStrmIn) 148 { 149 AssertPtrReturnVoid(pHstStrmIn); 150 AudioMixBufDestroy(&pHstStrmIn->MixBuf); 151 } 152 153 void drvAudioGstOutFreeRes(PPDMAUDIOGSTSTRMOUT pGstStrmOut) 154 { 155 if (!pGstStrmOut) 156 return; 157 158 if (pGstStrmOut->State.pszName) 159 { 160 RTStrFree(pGstStrmOut->State.pszName); 161 pGstStrmOut->State.pszName = NULL; 162 } 163 164 AudioMixBufDestroy(&pGstStrmOut->MixBuf); 165 } 166 167 #if 0 168 169 /** 170 * Finds the minimum number of not yet captured samples of all 171 * attached guest input streams for a certain host input stream. 172 * 173 * @return uint32_t Minimum number of not yet captured samples. 174 * UINT32_MAX if none found. 175 * @param pHstStrmIn Host input stream to check for. 176 */ 177 inline uint32_t drvAudioHstInFindMinCaptured(PPDMAUDIOHSTSTRMIN pHstStrmIn) 178 { 179 AssertPtrReturn(pHstStrmIn, 0); 180 uint32_t cMinSamples = UINT32_MAX; 181 182 PPDMAUDIOGSTSTRMIN pGstStrmIn; 183 RTListForEach(&pHstStrmIn->lstGstStrmIn, pGstStrmIn, PDMAUDIOGSTSTRMIN, Node) 184 { 185 if (pGstStrmIn->State.fActive) 186 cMinSamples = RT_MIN(cMinSamples, audioMixBufMixed(&pGstStrmIn->MixBuf)); 187 } 188 189 #ifdef DEBUG_andy 190 LogFlowFunc(("cMinSamples=%RU32\n", cMinSamples)); 191 #endif 192 return cMinSamples; 193 } 194 195 uint32_t drvAudioHstInGetFree(PPDMAUDIOHSTSTRMIN pHstStrmIn) 196 { 197 AssertPtrReturn(pHstStrmIn, 0); 198 199 return audioMixBufSize(&pHstStrmIn->MixBuf) - drvAudioHstInGetLive(pHstStrmIn); 200 } 201 202 uint32_t drvAudioHstInGetLive(PPDMAUDIOHSTSTRMIN pHstStrmIn) 203 { 204 AssertPtrReturn(pHstStrmIn, 0); 205 206 uint32_t cMinSamplesCaptured = drvAudioHstInFindMinCaptured(pHstStrmIn); 207 uint32_t cSamplesCaptured = audioMixBufMixed(&pHstStrmIn->MixBuf); 208 209 Assert(cSamplesCaptured >= cMinSamplesCaptured); 210 uint32_t cSamplesLive = cSamplesCaptured - cMinSamplesCaptured; 211 Assert(cSamplesLive <= audioMixBufSize(&pHstStrmIn->MixBuf)); 212 213 #ifdef DEBUG_andy 214 LogFlowFunc(("cSamplesLive=%RU32\n", cSamplesLive)); 215 #endif 216 return cSamplesLive; 217 } 218 #endif 219 220 void drvAudioHstOutFreeRes(PPDMAUDIOHSTSTRMOUT pHstStrmOut) 221 { 222 AssertPtrReturnVoid(pHstStrmOut); 223 AudioMixBufDestroy(&pHstStrmOut->MixBuf); 224 } 225 226 #if 0 227 /** 228 * Returns the number of live sample data (in bytes) of a certain 229 * guest input stream. 230 * 231 * @return uint32_t Live sample data (in bytes), 0 if none. 232 * @param pGstStrmIn Guest input stream to check for. 233 */ 234 uint32_t drvAudioGstInGetLiveBytes(PPDMAUDIOGSTSTRMIN pGstStrmIn) 235 { 236 AssertPtrReturn(pGstStrmIn, 0); 237 AssertPtrReturn(pGstStrmIn->pHstStrmIn, 0); 238 239 Assert(pGstStrmIn->pHstStrmIn->cTotalSamplesCaptured >= pGstStrmIn->cTotalHostSamplesRead); 240 uint32_t cSamplesLive = pGstStrmIn->pHstStrmIn->cTotalSamplesCaptured - pGstStrmIn->cTotalHostSamplesRead; 241 if (!cSamplesLive) 242 return 0; 243 Assert(cSamplesLive <= pGstStrmIn->pHstStrmIn->cSamples); 244 245 /** @todo Document / refactor this! */ 246 return (((int64_t) cSamplesLive << 32) / pGstStrmIn->State.uFreqRatio) << pGstStrmIn->Props.cShift; 247 } 248 249 250 /** 251 * Returns the total number of unused sample data (in bytes) of a certain 252 * guest output stream. 253 * 254 * @return uint32_t Number of unused sample data (in bytes), 0 if all used up. 255 * @param pGstStrmOut Guest output stream to check for. 256 */ 257 uint32_t drvAudioGstOutGetFreeBytes(PPDMAUDIOGSTSTRMOUT pGstStrmOut) 258 { 259 AssertPtrReturn(pGstStrmOut, 0); 260 261 Assert(pGstStrmOut->cTotalSamplesWritten <= pGstStrmOut->pHstStrmOut->cSamples); 262 uint32_t cSamplesFree = pGstStrmOut->pHstStrmOut->cSamples 263 - pGstStrmOut->cTotalSamplesWritten; 264 if (!cSamplesFree) 265 return 0; 266 267 /** @todo Document / refactor this! */ 268 return (((int64_t) cSamplesFree << 32) / pGstStrmOut->State.uFreqRatio) << pGstStrmOut->Props.cShift; 269 } 270 #endif 271 272 bool drvAudioPCMPropsAreEqual(PPDMPCMPROPS pProps, PPDMAUDIOSTREAMCFG pCfg) 184 PDMAUDIOFMT DrvAudioStrToAudFmt(const char *pszFmt) 185 { 186 AssertPtrReturn(pszFmt, PDMAUDIOFMT_INVALID); 187 188 if (!RTStrICmp(pszFmt, "u8")) 189 return PDMAUDIOFMT_U8; 190 else if (!RTStrICmp(pszFmt, "u16")) 191 return PDMAUDIOFMT_U16; 192 else if (!RTStrICmp(pszFmt, "u32")) 193 return PDMAUDIOFMT_U32; 194 else if (!RTStrICmp(pszFmt, "s8")) 195 return PDMAUDIOFMT_S8; 196 else if (!RTStrICmp(pszFmt, "s16")) 197 return PDMAUDIOFMT_S16; 198 else if (!RTStrICmp(pszFmt, "s32")) 199 return PDMAUDIOFMT_S32; 200 201 AssertMsgFailed(("Invalid audio format \"%s\"\n", pszFmt)); 202 return PDMAUDIOFMT_INVALID; 203 } 204 205 bool DrvAudioPCMPropsAreEqual(PPDMPCMPROPS pProps, PPDMAUDIOSTREAMCFG pCfg) 273 206 { 274 207 int cBits = 8; … … 277 210 switch (pCfg->enmFormat) 278 211 { 279 case AUD_FMT_S8:280 fSigned = true; 281 case AUD_FMT_U8:282 break; 283 284 case AUD_FMT_S16:285 fSigned = true; 286 case AUD_FMT_U16:212 case PDMAUDIOFMT_S8: 213 fSigned = true; 214 case PDMAUDIOFMT_U8: 215 break; 216 217 case PDMAUDIOFMT_S16: 218 fSigned = true; 219 case PDMAUDIOFMT_U16: 287 220 cBits = 16; 288 221 break; 289 222 290 case AUD_FMT_S32:291 fSigned = true; 292 case AUD_FMT_U32:223 case PDMAUDIOFMT_S32: 224 fSigned = true; 225 case PDMAUDIOFMT_U32: 293 226 cBits = 32; 294 227 break; … … 304 237 && pProps->cBits == cBits 305 238 && pProps->fSwapEndian == !(pCfg->enmEndianness == PDMAUDIOHOSTENDIANNESS); 306 307 LogFlowFunc(("fEqual=%RTbool\n", fEqual));308 239 return fEqual; 309 240 } … … 328 259 switch (pCfg->enmFormat) 329 260 { 330 case AUD_FMT_S8:331 fSigned = true; 332 case AUD_FMT_U8:333 break; 334 335 case AUD_FMT_S16:336 fSigned = true; 337 case AUD_FMT_U16:261 case PDMAUDIOFMT_S8: 262 fSigned = true; 263 case PDMAUDIOFMT_U8: 264 break; 265 266 case PDMAUDIOFMT_S16: 267 fSigned = true; 268 case PDMAUDIOFMT_U16: 338 269 cBits = 16; 339 270 cShift = 1; 340 271 break; 341 272 342 case AUD_FMT_S32:343 fSigned = true; 344 case AUD_FMT_U32:273 case PDMAUDIOFMT_S32: 274 fSigned = true; 275 case PDMAUDIOFMT_U32: 345 276 cBits = 32; 346 277 cShift = 2; … … 368 299 } 369 300 370 void drvAudioStreamCfgPrint(PPDMAUDIOSTREAMCFG pCfg) 371 { 372 LogFlowFunc(("uHz=%RU32, cChannels=%RU8, enmFormat=", 373 pCfg->uHz, pCfg->cChannels)); 301 void DrvAudioStreamCfgPrint(PPDMAUDIOSTREAMCFG pCfg) 302 { 303 AssertPtrReturnVoid(pCfg); 304 305 LogFlowFunc(("uHz=%RU32, cChannels=%RU8, enmFormat=", pCfg->uHz, pCfg->cChannels)); 374 306 375 307 switch (pCfg->enmFormat) 376 308 { 377 case AUD_FMT_S8:309 case PDMAUDIOFMT_S8: 378 310 LogFlow(("S8")); 379 311 break; 380 case AUD_FMT_U8:312 case PDMAUDIOFMT_U8: 381 313 LogFlow(("U8")); 382 314 break; 383 case AUD_FMT_S16:315 case PDMAUDIOFMT_S16: 384 316 LogFlow(("S16")); 385 317 break; 386 case AUD_FMT_U16:318 case PDMAUDIOFMT_U16: 387 319 LogFlow(("U16")); 388 320 break; 389 case AUD_FMT_S32:321 case PDMAUDIOFMT_S32: 390 322 LogFlow(("S32")); 391 323 break; 392 case AUD_FMT_U32:324 case PDMAUDIOFMT_U32: 393 325 LogFlow(("U32")); 394 326 break; … … 412 344 } 413 345 } 346 -
trunk/src/VBox/Devices/Audio/DrvHostALSAAudio.cpp
r59989 r60925 181 181 switch (fmt) 182 182 { 183 case AUD_FMT_S8:183 case PDMAUDIOFMT_S8: 184 184 return SND_PCM_FORMAT_S8; 185 185 186 case AUD_FMT_U8:186 case PDMAUDIOFMT_U8: 187 187 return SND_PCM_FORMAT_U8; 188 188 189 case AUD_FMT_S16:189 case PDMAUDIOFMT_S16: 190 190 return SND_PCM_FORMAT_S16_LE; 191 191 192 case AUD_FMT_U16:192 case PDMAUDIOFMT_U16: 193 193 return SND_PCM_FORMAT_U16_LE; 194 194 195 case AUD_FMT_S32:195 case PDMAUDIOFMT_S32: 196 196 return SND_PCM_FORMAT_S32_LE; 197 197 198 case AUD_FMT_U32:198 case PDMAUDIOFMT_U32: 199 199 return SND_PCM_FORMAT_U32_LE; 200 200 … … 216 216 { 217 217 case SND_PCM_FORMAT_S8: 218 *pFmt = AUD_FMT_S8;218 *pFmt = PDMAUDIOFMT_S8; 219 219 if (pEndianness) 220 220 *pEndianness = PDMAUDIOENDIANNESS_LITTLE; … … 222 222 223 223 case SND_PCM_FORMAT_U8: 224 *pFmt = AUD_FMT_U8;224 *pFmt = PDMAUDIOFMT_U8; 225 225 if (pEndianness) 226 226 *pEndianness = PDMAUDIOENDIANNESS_LITTLE; … … 228 228 229 229 case SND_PCM_FORMAT_S16_LE: 230 *pFmt = AUD_FMT_S16;230 *pFmt = PDMAUDIOFMT_S16; 231 231 if (pEndianness) 232 232 *pEndianness = PDMAUDIOENDIANNESS_LITTLE; … … 234 234 235 235 case SND_PCM_FORMAT_U16_LE: 236 *pFmt = AUD_FMT_U16;236 *pFmt = PDMAUDIOFMT_U16; 237 237 if (pEndianness) 238 238 *pEndianness = PDMAUDIOENDIANNESS_LITTLE; … … 240 240 241 241 case SND_PCM_FORMAT_S16_BE: 242 *pFmt = AUD_FMT_S16;242 *pFmt = PDMAUDIOFMT_S16; 243 243 if (pEndianness) 244 244 *pEndianness = PDMAUDIOENDIANNESS_BIG; … … 246 246 247 247 case SND_PCM_FORMAT_U16_BE: 248 *pFmt = AUD_FMT_U16;248 *pFmt = PDMAUDIOFMT_U16; 249 249 if (pEndianness) 250 250 *pEndianness = PDMAUDIOENDIANNESS_BIG; … … 252 252 253 253 case SND_PCM_FORMAT_S32_LE: 254 *pFmt = AUD_FMT_S32;254 *pFmt = PDMAUDIOFMT_S32; 255 255 if (pEndianness) 256 256 *pEndianness = PDMAUDIOENDIANNESS_LITTLE; … … 258 258 259 259 case SND_PCM_FORMAT_U32_LE: 260 *pFmt = AUD_FMT_U32;260 *pFmt = PDMAUDIOFMT_U32; 261 261 if (pEndianness) 262 262 *pEndianness = PDMAUDIOENDIANNESS_LITTLE; … … 264 264 265 265 case SND_PCM_FORMAT_S32_BE: 266 *pFmt = AUD_FMT_S32;266 *pFmt = PDMAUDIOFMT_S32; 267 267 if (pEndianness) 268 268 *pEndianness = PDMAUDIOENDIANNESS_BIG; … … 270 270 271 271 case SND_PCM_FORMAT_U32_BE: 272 *pFmt = AUD_FMT_U32;272 *pFmt = PDMAUDIOFMT_U32; 273 273 if (pEndianness) 274 274 *pEndianness = PDMAUDIOENDIANNESS_BIG; … … 1109 1109 1110 1110 ALSAAUDIOSTREAMCFG obt; 1111 rc = alsaStreamOpen(false /* f alse*/, &req, &obt, &phPCM);1111 rc = alsaStreamOpen(false /* fIn */, &req, &obt, &phPCM); 1112 1112 if (RT_FAILURE(rc)) 1113 1113 break; … … 1365 1365 LogRel2(("ALSA: Error enumerating PCM devices: %Rrc (%d)\n", RTErrConvertFromErrno(err), err)); 1366 1366 1367 /* ALSA only allows one input and one output used at a time for 1368 * the selected device(s). */ 1369 pCfg->cMaxStreamsIn = 1; 1370 pCfg->cMaxStreamsOut = 1; 1367 /* ALSA allows exactly one input and one output used at a time for the selected device(s). */ 1368 pCfg->cMaxStreamsIn = 1; 1369 pCfg->cMaxStreamsOut = 1; 1371 1370 1372 1371 return VINF_SUCCESS; -
trunk/src/VBox/Devices/Audio/DrvHostDSound.cpp
r60353 r60925 221 221 switch (pCfg->enmFormat) 222 222 { 223 case AUD_FMT_S8:224 case AUD_FMT_U8:223 case PDMAUDIOFMT_S8: 224 case PDMAUDIOFMT_U8: 225 225 pFmt->wBitsPerSample = 8; 226 226 break; 227 227 228 case AUD_FMT_S16:229 case AUD_FMT_U16:228 case PDMAUDIOFMT_S16: 229 case PDMAUDIOFMT_U16: 230 230 pFmt->wBitsPerSample = 16; 231 231 pFmt->nAvgBytesPerSec <<= 1; … … 233 233 break; 234 234 235 case AUD_FMT_S32:236 case AUD_FMT_U32:235 case PDMAUDIOFMT_S32: 236 case PDMAUDIOFMT_U32: 237 237 pFmt->wBitsPerSample = 32; 238 238 pFmt->nAvgBytesPerSec <<= 2; … … 916 916 { 917 917 DSLOG(("DSound: Guest \"%s\" is using host \"%s\"\n", 918 drvAudioRecSourceToString(pDSoundStrmIn->enmRecSource), pDev->pszName));918 DrvAudRecSrcToStr(pDSoundStrmIn->enmRecSource), pDev->pszName)); 919 919 920 920 pGUID = &pDev->Guid; … … 925 925 /* This always has to be in the release log. */ 926 926 LogRel(("DSound: Guest \"%s\" is using host device with GUID: %s\n", 927 drvAudioRecSourceToString(pDSoundStrmIn->enmRecSource), pszGUID? pszGUID: "{?}"));927 DrvAudRecSrcToStr(pDSoundStrmIn->enmRecSource), pszGUID? pszGUID: "{?}")); 928 928 RTStrFree(pszGUID); 929 929 -
trunk/src/VBox/Devices/Audio/DrvHostNullAudio.cpp
r59987 r60925 104 104 NOREF(pInterface); 105 105 106 LogFlowFuncLeaveRC(VINF_SUCCESS); 106 107 return VINF_SUCCESS; 107 108 } … … 123 124 } 124 125 125 return VINF_SUCCESS; 126 LogFlowFuncLeaveRC(rc); 127 return rc; 126 128 } 127 129 … … 146 148 } 147 149 else 148 {149 150 rc = VERR_NO_MEMORY; 150 }151 151 } 152 152 153 LogFlowFuncLeaveRC(rc); 153 154 return rc; 154 155 } … … 231 232 static DECLCALLBACK(int) drvHostNullAudioFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn) 232 233 { 234 LogFlowFuncLeaveRC(VINF_SUCCESS); 233 235 return VINF_SUCCESS; 234 236 } … … 236 238 static DECLCALLBACK(int) drvHostNullAudioFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut) 237 239 { 240 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface); 241 238 242 PNULLAUDIOSTREAMOUT pNullStrmOut = (PNULLAUDIOSTREAMOUT)pHstStrmOut; 239 243 if ( pNullStrmOut … … 241 245 { 242 246 RTMemFree(pNullStrmOut->pu8PlayBuffer); 247 pNullStrmOut->pu8PlayBuffer = NULL; 243 248 } 249 250 LogFlowFuncLeaveRC(VINF_SUCCESS); 244 251 return VINF_SUCCESS; 245 252 } -
trunk/src/VBox/Devices/Audio/DrvHostOSSAudio.cpp
r59992 r60925 155 155 switch (fmt) 156 156 { 157 case AUD_FMT_S8:157 case PDMAUDIOFMT_S8: 158 158 return AFMT_S8; 159 159 160 case AUD_FMT_U8:160 case PDMAUDIOFMT_U8: 161 161 return AFMT_U8; 162 162 163 case AUD_FMT_S16:163 case PDMAUDIOFMT_S16: 164 164 return AFMT_S16_LE; 165 165 166 case AUD_FMT_U16:166 case PDMAUDIOFMT_U16: 167 167 return AFMT_U16_LE; 168 168 … … 180 180 { 181 181 case AFMT_S8: 182 *pFmt = AUD_FMT_S8;182 *pFmt = PDMAUDIOFMT_S8; 183 183 if (pENDIANNESS) 184 184 *pENDIANNESS = PDMAUDIOENDIANNESS_LITTLE; … … 186 186 187 187 case AFMT_U8: 188 *pFmt = AUD_FMT_U8;188 *pFmt = PDMAUDIOFMT_U8; 189 189 if (pENDIANNESS) 190 190 *pENDIANNESS = PDMAUDIOENDIANNESS_LITTLE; … … 192 192 193 193 case AFMT_S16_LE: 194 *pFmt = AUD_FMT_S16;194 *pFmt = PDMAUDIOFMT_S16; 195 195 if (pENDIANNESS) 196 196 *pENDIANNESS = PDMAUDIOENDIANNESS_LITTLE; … … 198 198 199 199 case AFMT_U16_LE: 200 *pFmt = AUD_FMT_U16;200 *pFmt = PDMAUDIOFMT_U16; 201 201 if (pENDIANNESS) 202 202 *pENDIANNESS = PDMAUDIOENDIANNESS_LITTLE; … … 204 204 205 205 case AFMT_S16_BE: 206 *pFmt = AUD_FMT_S16;206 *pFmt = PDMAUDIOFMT_S16; 207 207 if (pENDIANNESS) 208 208 *pENDIANNESS = PDMAUDIOENDIANNESS_BIG; … … 210 210 211 211 case AFMT_U16_BE: 212 *pFmt = AUD_FMT_U16;212 *pFmt = PDMAUDIOFMT_U16; 213 213 if (pENDIANNESS) 214 214 *pENDIANNESS = PDMAUDIOENDIANNESS_BIG; -
trunk/src/VBox/Devices/Audio/DrvHostPulseAudio.cpp
r59989 r60925 182 182 switch (fmt) 183 183 { 184 case AUD_FMT_U8:184 case PDMAUDIOFMT_U8: 185 185 return PA_SAMPLE_U8; 186 186 187 case AUD_FMT_S16:187 case PDMAUDIOFMT_S16: 188 188 return PA_SAMPLE_S16LE; 189 189 190 190 #ifdef PA_SAMPLE_S32LE 191 case AUD_FMT_S32:191 case PDMAUDIOFMT_S32: 192 192 return PA_SAMPLE_S32LE; 193 193 #endif … … 206 206 { 207 207 case PA_SAMPLE_U8: 208 *pFmt = AUD_FMT_U8;208 *pFmt = PDMAUDIOFMT_U8; 209 209 *pEndianness = PDMAUDIOENDIANNESS_LITTLE; 210 210 break; 211 211 212 212 case PA_SAMPLE_S16LE: 213 *pFmt = AUD_FMT_S16;213 *pFmt = PDMAUDIOFMT_S16; 214 214 *pEndianness = PDMAUDIOENDIANNESS_LITTLE; 215 215 break; 216 216 217 217 case PA_SAMPLE_S16BE: 218 *pFmt = AUD_FMT_S16;218 *pFmt = PDMAUDIOFMT_S16; 219 219 *pEndianness = PDMAUDIOENDIANNESS_BIG; 220 220 break; … … 222 222 #ifdef PA_SAMPLE_S32LE 223 223 case PA_SAMPLE_S32LE: 224 *pFmt = AUD_FMT_S32;224 *pFmt = PDMAUDIOFMT_S32; 225 225 *pEndianness = PDMAUDIOENDIANNESS_LITTLE; 226 226 break; … … 229 229 #ifdef PA_SAMPLE_S32BE 230 230 case PA_SAMPLE_S32BE: 231 *pFmt = AUD_FMT_S32;231 *pFmt = PDMAUDIOFMT_S32; 232 232 *pEndianness = PDMAUDIOENDIANNESS_BIG; 233 233 break; … … 899 899 if (!cLive) 900 900 { 901 LogFlowFunc(("%p: No live samples, skipping\n", pHstStrmOut)); 902 901 #if 0 902 LogFlowFunc(("No live samples, skipping\n")); 903 #endif 903 904 if (pcSamplesPlayed) 904 905 *pcSamplesPlayed = 0; -
trunk/src/VBox/Devices/Audio/testcase/tstAudioMixBuffer.cpp
r60354 r60925 48 48 44100, /* Hz */ 49 49 2 /* Channels */, 50 AUD_FMT_S16 /* Format */,50 PDMAUDIOFMT_S16 /* Format */, 51 51 PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */ 52 52 }; … … 150 150 44100, /* Hz */ 151 151 2 /* Channels */, 152 AUD_FMT_S16 /* Format */,152 PDMAUDIOFMT_S16 /* Format */, 153 153 PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */ 154 154 }; … … 168 168 22050, /* Hz */ 169 169 2 /* Channels */, 170 AUD_FMT_S16 /* Format */,170 PDMAUDIOFMT_S16 /* Format */, 171 171 PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */ 172 172 }; … … 186 186 48000, /* Hz */ 187 187 2 /* Channels */, 188 AUD_FMT_S16 /* Format */,188 PDMAUDIOFMT_S16 /* Format */, 189 189 PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */ 190 190 }; … … 271 271 44100, /* Hz */ 272 272 1 /* Channels */, 273 AUD_FMT_U8 /* Format */,273 PDMAUDIOFMT_U8 /* Format */, 274 274 PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */ 275 275 }; … … 295 295 22050, /* Hz */ 296 296 1 /* Channels */, 297 AUD_FMT_U8 /* Format */,297 PDMAUDIOFMT_U8 /* Format */, 298 298 PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */ 299 299 }; … … 381 381 44100, /* Hz */ 382 382 1 /* Channels */, 383 AUD_FMT_S16 /* Format */,383 PDMAUDIOFMT_S16 /* Format */, 384 384 PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */ 385 385 }; … … 398 398 22050, /* Hz */ 399 399 1 /* Channels */, 400 AUD_FMT_S16 /* Format */,400 PDMAUDIOFMT_S16 /* Format */, 401 401 PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */ 402 402 }; … … 485 485 44100, /* Hz */ 486 486 2 /* Channels */, 487 AUD_FMT_S16 /* Format */,487 PDMAUDIOFMT_S16 /* Format */, 488 488 PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */ 489 489 }; -
trunk/src/VBox/Devices/Makefile.kmk
r60693 r60925 540 540 # --- Audio bits. --- 541 541 542 if 0 543 VBoxDD_DEFS += VBOX_WITH_HDA_INTERLEAVING_STREAMS_SUPPORT 544 VBoxDD_DEFS += VBOX_WITH_HDA_51_SURROUND 545 endif 546 542 547 VBoxDD_SOURCES += \ 543 548 Audio/AudioMixBuffer.cpp \ -
trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp
r60804 r60925 1923 1923 GEN_CHECK_OFF(AC97DRIVER, Out); 1924 1924 1925 GEN_CHECK_SIZE(HDAINPUTSTREAM); 1926 GEN_CHECK_OFF(HDAINPUTSTREAM, pGstStrm); 1927 GEN_CHECK_OFF(HDAINPUTSTREAM, pMixStrm); 1928 1929 GEN_CHECK_SIZE(HDAOUTPUTSTREAM); 1930 GEN_CHECK_OFF(HDAOUTPUTSTREAM, pGstStrm); 1931 GEN_CHECK_OFF(HDAOUTPUTSTREAM, pMixStrm); 1925 GEN_CHECK_SIZE(HDAMIXERSTREAM); 1926 GEN_CHECK_OFF(HDAMIXERSTREAM, DestSource); 1927 GEN_CHECK_OFF(HDAMIXERSTREAM, pMixStrm); 1932 1928 1933 1929 GEN_CHECK_SIZE(HDADRIVER); … … 1943 1939 #endif 1944 1940 GEN_CHECK_OFF(HDADRIVER, Front); 1941 #ifdef VBOX_WITH_HDA_51_SURROUND 1942 GEN_CHECK_OFF(HDADRIVER, CenterLFE); 1943 GEN_CHECK_OFF(HDADRIVER, Rear); 1944 #endif 1945 1945 1946 1946 GEN_CHECK_SIZE(HDABDLESTATE); … … 2015 2015 GEN_CHECK_OFF(HDASTATE, u64BaseTS); 2016 2016 GEN_CHECK_OFF(HDASTATE, u8RespIntCnt); 2017 #ifdef VBOX_WITH_HDA_INTERLEAVING_STREAMS_SUPPORT2018 GEN_CHECK_OFF(HDASTATE, pCircBuf);2019 #endif2020 2017 2021 2018 #ifdef VBOX_WITH_NVME_IMPL -
trunk/src/VBox/Main/src-client/DrvAudioVideoRec.cpp
r59987 r60925 139 139 switch (as->enmFormat) 140 140 { 141 case AUD_FMT_S8:141 case PDMAUDIOFMT_S8: 142 142 fSigned = 1; 143 case AUD_FMT_U8:143 case PDMAUDIOFMT_U8: 144 144 break; 145 145 146 case AUD_FMT_S16:146 case PDMAUDIOFMT_S16: 147 147 fSigned = 1; 148 case AUD_FMT_U16:148 case PDMAUDIOFMT_U16: 149 149 cBits = 16; 150 150 cShift = 1; 151 151 break; 152 152 153 case AUD_FMT_S32:153 case PDMAUDIOFMT_S32: 154 154 fSigned = 1; 155 case AUD_FMT_U32:155 case PDMAUDIOFMT_U32: 156 156 cBits = 32; 157 157 cShift = 2;
Note:
See TracChangeset
for help on using the changeset viewer.