- Timestamp:
- Dec 5, 2018 9:34:58 AM (6 years ago)
- Location:
- trunk/src/VBox/Devices
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DevHDA.cpp
r75866 r75962 57 57 #include "HDACodec.h" 58 58 #include "HDAStream.h" 59 # if defined(VBOX_WITH_HDA_AUDIO_INTERLEAVING_STREAMS_SUPPORT) || defined(VBOX_WITH_AUDIO_HDA_51_SURROUND)60 # include "HDAStreamChannel.h"61 # endif62 59 #include "HDAStreamMap.h" 63 60 #include "HDAStreamPeriod.h" … … 108 105 #else 109 106 # error "Please specify your HDA device vendor/device IDs" 110 #endif111 112 /* Make sure that interleaving streams support is enabled if the 5.1 surround code is being used. */113 #if defined (VBOX_WITH_AUDIO_HDA_51_SURROUND) && !defined(VBOX_WITH_HDA_AUDIO_INTERLEAVING_STREAMS_SUPPORT)114 # define VBOX_WITH_HDA_AUDIO_INTERLEAVING_STREAMS_SUPPORT115 107 #endif 116 108 … … 1312 1304 uSD, fRun, fInRun, fReset, fInReset, u32Value)); 1313 1305 1306 # ifdef DEBUG 1307 if (hdaGetDirFromSD(uSD) == PDMAUDIODIR_OUT) 1308 { 1309 const uint8_t uStripeCtl = ((u32Value >> HDA_SDCTL_STRIPE_SHIFT) & HDA_SDCTL_STRIPE_MASK) + 1; 1310 LogFunc(("[SD%RU8] Using %RU8 SDOs (stripe control)\n", uSD, uStripeCtl)); 1311 } 1312 # endif 1313 1314 1314 /* 1315 1315 * Extract the stream tag the guest wants to use for this specific … … 1810 1810 } 1811 1811 } 1812 # else /* !VBOX_WITH_AUDIO_HDA_51_SURROUND */1813 /* Only support mono or stereo channels. */1814 if ( pCfg->Props.cChannels != 1 /* Mono */1815 && pCfg->Props.cChannels != 2 /* Stereo */)1816 {1817 rc = VERR_NOT_SUPPORTED;1818 }1819 1812 # endif /* !VBOX_WITH_AUDIO_HDA_51_SURROUND */ 1820 1813 … … 1839 1832 pCfg->enmLayout = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED; 1840 1833 1841 pCfg->Props.cChannels = 2;1842 1834 pCfg->Props.cShift = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pCfg->Props.cBytes, pCfg->Props.cChannels); 1843 1835 … … 1855 1847 1856 1848 pCfg->Props.cChannels = (fUseCenter && fUseLFE) ? 2 : 1; 1857 pCfg->Props.cShift = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pCfg->Props.cB its, pCfg->Props.cChannels);1849 pCfg->Props.cShift = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pCfg->Props.cBytes, pCfg->Props.cChannels); 1858 1850 1859 1851 rc = hdaCodecAddStream(pThis->pCodec, PDMAUDIOMIXERCTL_CENTER_LFE, pCfg); … … 1869 1861 1870 1862 pCfg->Props.cChannels = 2; 1871 pCfg->Props.cShift = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pCfg->Props.cB its, pCfg->Props.cChannels);1863 pCfg->Props.cShift = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pCfg->Props.cBytes, pCfg->Props.cChannels); 1872 1864 1873 1865 rc = hdaCodecAddStream(pThis->pCodec, PDMAUDIOMIXERCTL_REAR, pCfg); … … 2485 2477 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 2486 2478 2487 LogFunc((" Sink=%s, Stream=%s\n", pMixSink->pszName, pCfg->szName));2479 LogFunc(("szSink=%s, szStream=%s, cChannels=%RU8\n", pMixSink->pszName, pCfg->szName, pCfg->Props.cChannels)); 2488 2480 2489 2481 PPDMAUDIOSTREAMCFG pStreamCfg = DrvAudioHlpStreamCfgDup(pCfg); -
trunk/src/VBox/Devices/Audio/DevHDACommon.cpp
r75866 r75962 340 340 # endif 341 341 if (pStream->Dbg.Runtime.fEnabled) 342 DrvAudioHlpFileWrite(pStream->Dbg.Runtime.pFileDMA , (uint8_t *)pvBuf + cbReadTotal, cbChunk, 0 /* fFlags */);342 DrvAudioHlpFileWrite(pStream->Dbg.Runtime.pFileDMARaw, (uint8_t *)pvBuf + cbReadTotal, cbChunk, 0 /* fFlags */); 343 343 344 344 STAM_COUNTER_ADD(&pThis->StatBytesRead, cbChunk); … … 406 406 407 407 if (pStream->Dbg.Runtime.fEnabled) 408 DrvAudioHlpFileWrite(pStream->Dbg.Runtime.pFileDMA , (uint8_t *)pvBuf + cbWrittenTotal, cbChunk, 0 /* fFlags */);408 DrvAudioHlpFileWrite(pStream->Dbg.Runtime.pFileDMARaw, (uint8_t *)pvBuf + cbWrittenTotal, cbChunk, 0 /* fFlags */); 409 409 410 410 rc = PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), -
trunk/src/VBox/Devices/Audio/DevHDACommon.h
r75866 r75962 91 91 * 92 92 * Lowering this value can ask for trouble, as backends then can run 93 * into data underruns. */ 94 #define HDA_TIMER_HZ_DEFAULT 100 93 * into data underruns. 94 * 95 * Note: For handling surround setups (e.g. 5.1 speaker setups) we need 96 * a higher Hz rate, as the device emulation otherwise will come into 97 * timing trouble, making the output (DMA reads) crackling. */ 98 #define HDA_TIMER_HZ_DEFAULT 200 95 99 96 100 /** Default position adjustment (in audio samples). … … 113 117 /** HDA's (fixed) audio frame size in bytes. 114 118 * We only support 16-bit stereo frames at the moment. */ 115 #define HDA_FRAME_SIZE 119 #define HDA_FRAME_SIZE_DEFAULT 4 116 120 117 121 /** Offset of the SD0 register map. */ -
trunk/src/VBox/Devices/Audio/HDAStream.cpp
r75866 r75962 94 94 95 95 if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_IN) 96 RTStrPrintf(szFile, sizeof(szFile), "hdaDMA WriteSD%RU8", pStream->u8SD);96 RTStrPrintf(szFile, sizeof(szFile), "hdaDMARawWriteSD%RU8", pStream->u8SD); 97 97 else 98 RTStrPrintf(szFile, sizeof(szFile), "hdaDMAR eadSD%RU8", pStream->u8SD);98 RTStrPrintf(szFile, sizeof(szFile), "hdaDMARawReadSD%RU8", pStream->u8SD); 99 99 100 100 rc2 = DrvAudioHlpFileNameGet(szPath, sizeof(szPath), pThis->Dbg.szOutPath, szFile, … … 102 102 AssertRC(rc2); 103 103 104 rc2 = DrvAudioHlpFileCreate(PDMAUDIOFILETYPE_WAV, szPath, PDMAUDIOFILE_FLAG_NONE, &pStream->Dbg.Runtime.pFileDMA); 104 rc2 = DrvAudioHlpFileCreate(PDMAUDIOFILETYPE_WAV, szPath, PDMAUDIOFILE_FLAG_NONE, &pStream->Dbg.Runtime.pFileDMARaw); 105 AssertRC(rc2); 106 107 if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_IN) 108 RTStrPrintf(szFile, sizeof(szFile), "hdaDMAWriteMappedSD%RU8", pStream->u8SD); 109 else 110 RTStrPrintf(szFile, sizeof(szFile), "hdaDMAReadMappedSD%RU8", pStream->u8SD); 111 112 rc2 = DrvAudioHlpFileNameGet(szPath, sizeof(szPath), pThis->Dbg.szOutPath, szFile, 113 0 /* uInst */, PDMAUDIOFILETYPE_WAV, PDMAUDIOFILENAME_FLAG_NONE); 114 AssertRC(rc2); 115 116 rc2 = DrvAudioHlpFileCreate(PDMAUDIOFILETYPE_WAV, szPath, PDMAUDIOFILE_FLAG_NONE, &pStream->Dbg.Runtime.pFileDMAMapped); 105 117 AssertRC(rc2); 106 118 107 119 /* Delete stale debugging files from a former run. */ 108 120 DrvAudioHlpFileDelete(pStream->Dbg.Runtime.pFileStream); 109 DrvAudioHlpFileDelete(pStream->Dbg.Runtime.pFileDMA); 121 DrvAudioHlpFileDelete(pStream->Dbg.Runtime.pFileDMARaw); 122 DrvAudioHlpFileDelete(pStream->Dbg.Runtime.pFileDMAMapped); 110 123 } 111 124 … … 160 173 pStream->Dbg.Runtime.pFileStream = NULL; 161 174 162 DrvAudioHlpFileDestroy(pStream->Dbg.Runtime.pFileDMA); 163 pStream->Dbg.Runtime.pFileDMA = NULL; 175 DrvAudioHlpFileDestroy(pStream->Dbg.Runtime.pFileDMARaw); 176 pStream->Dbg.Runtime.pFileDMARaw = NULL; 177 178 DrvAudioHlpFileDestroy(pStream->Dbg.Runtime.pFileDMAMapped); 179 pStream->Dbg.Runtime.pFileDMAMapped = NULL; 164 180 } 165 181 … … 245 261 return VINF_SUCCESS; 246 262 } 247 248 /* Set the stream's frame size. */249 pStream->State.cbFrameSize = pCfg->Props.cChannels * pCfg->Props.cBytes;250 LogFunc(("[SD%RU8] cChannels=%RU8, cBytes=%RU8 -> cbFrameSize=%RU32\n",251 pStream->u8SD, pCfg->Props.cChannels, pCfg->Props.cBytes, pStream->State.cbFrameSize));252 Assert(pStream->State.cbFrameSize); /* Frame size must not be 0. */253 263 254 264 /* … … 263 273 AssertRCReturn(rc, rc); 264 274 275 #ifndef VBOX_WITH_AUDIO_HDA_51_SURROUND 276 /* 277 * When not running with surround support enabled, override the channel count 278 * with stereo (2) channels so that we at least can properly work with those. 279 * 280 * Note: This also involves dealing with surround setups the guest might has set up for us. 281 */ 282 pCfg->Props.cChannels = 2; 283 #endif 284 265 285 LogFunc(("[SD%RU8] DMA @ 0x%x (%RU32 bytes), LVI=%RU16, FIFOS=%RU16, Hz=%RU32, rc=%Rrc\n", 266 286 pStream->u8SD, pStream->u64BDLBase, pStream->u32CBL, pStream->u16LVI, pStream->u16FIFOS, … … 268 288 269 289 /* Make sure that mandatory parameters are set up correctly. */ 270 AssertStmt(pStream->u32CBL % pStream->State. cbFrameSize == 0, rc = VERR_INVALID_PARAMETER);271 AssertStmt(pStream->u16LVI >= 1, rc = VERR_INVALID_PARAMETER);290 AssertStmt(pStream->u32CBL % pStream->State.Mapping.cbFrameSize == 0, rc = VERR_INVALID_PARAMETER); 291 AssertStmt(pStream->u16LVI >= 1, rc = VERR_INVALID_PARAMETER); 272 292 273 293 if (RT_SUCCESS(rc)) … … 275 295 /* Make sure that the chosen Hz rate dividable by the stream's rate. */ 276 296 if (pStream->State.Cfg.Props.uHz % pThis->uTimerHz != 0) 277 LogRel(("HDA: Device timer (%RU32) does not fit to stream # RU8 timing (%RU32)\n",278 pThis->uTimerHz, pStream-> State.Cfg.Props.uHz));297 LogRel(("HDA: Device timer (%RU32) does not fit to stream #%RU8 timing (%RU32)\n", 298 pThis->uTimerHz, pStream->u8SD, pStream->State.Cfg.Props.uHz)); 279 299 280 300 /* Figure out how many transfer fragments we're going to use for this stream. */ … … 318 338 #ifdef VBOX_WITH_INTEL_HDA 319 339 /* Intel ICH / PCH: 1 frame. */ 320 if (BDLE.Desc.u32BufSize == 1 * pStream->State.cbFrameSize)340 if (BDLE.Desc.u32BufSize == (uint32_t)(1 * pStream->State.Mapping.cbFrameSize)) 321 341 { 322 342 cfPosAdjust = 1; 323 343 } 324 344 /* Intel Baytrail / Braswell: 32 frames. */ 325 else if (BDLE.Desc.u32BufSize == 32 * pStream->State.cbFrameSize)345 else if (BDLE.Desc.u32BufSize == (uint32_t)(32 * pStream->State.Mapping.cbFrameSize)) 326 346 { 327 347 cfPosAdjust = 32; … … 344 364 * position adjustment. 345 365 */ 346 if ( (cfPosAdjust * pStream->State. cbFrameSize) == BDLE.Desc.u32BufSize366 if ( (cfPosAdjust * pStream->State.Mapping.cbFrameSize) == BDLE.Desc.u32BufSize 347 367 && cFragments) 348 368 { … … 365 385 pStream->State.cbTransferSize = pStream->u32CBL / cFragments; 366 386 Assert(pStream->State.cbTransferSize); 367 Assert(pStream->State.cbTransferSize % pStream->State. cbFrameSize == 0);387 Assert(pStream->State.cbTransferSize % pStream->State.Mapping.cbFrameSize == 0); 368 388 369 389 /* Calculate the bytes we need to transfer to / from the stream's DMA per iteration. 370 390 * This is bound to the device's Hz rate and thus to the (virtual) timing the device expects. */ 371 pStream->State.cbTransferChunk = (pStream->State.Cfg.Props.uHz / pThis->uTimerHz) * pStream->State. cbFrameSize;391 pStream->State.cbTransferChunk = (pStream->State.Cfg.Props.uHz / pThis->uTimerHz) * pStream->State.Mapping.cbFrameSize; 372 392 Assert(pStream->State.cbTransferChunk); 373 Assert(pStream->State.cbTransferChunk % pStream->State. cbFrameSize == 0);393 Assert(pStream->State.cbTransferChunk % pStream->State.Mapping.cbFrameSize == 0); 374 394 375 395 /* Make sure that the transfer chunk does not exceed the overall transfer size. */ … … 379 399 pStream->State.cbTransferProcessed = 0; 380 400 pStream->State.cTransferPendingInterrupts = 0; 381 pStream->State.cbDMALeft = 0;382 401 pStream->State.tsLastUpdateNs = 0; 383 402 … … 542 561 } 543 562 544 if (!DrvAudioHlpFileIsOpen(pStream->Dbg.Runtime.pFileDMA)) 545 { 546 int rc2 = DrvAudioHlpFileOpen(pStream->Dbg.Runtime.pFileDMA, PDMAUDIOFILE_DEFAULT_OPEN_FLAGS, 563 if (!DrvAudioHlpFileIsOpen(pStream->Dbg.Runtime.pFileDMARaw)) 564 { 565 int rc2 = DrvAudioHlpFileOpen(pStream->Dbg.Runtime.pFileDMARaw, PDMAUDIOFILE_DEFAULT_OPEN_FLAGS, 566 &pStream->State.Cfg.Props); 567 AssertRC(rc2); 568 } 569 570 if (!DrvAudioHlpFileIsOpen(pStream->Dbg.Runtime.pFileDMAMapped)) 571 { 572 int rc2 = DrvAudioHlpFileOpen(pStream->Dbg.Runtime.pFileDMAMapped, PDMAUDIOFILE_DEFAULT_OPEN_FLAGS, 547 573 &pStream->State.Cfg.Props); 548 574 AssertRC(rc2); … … 916 942 * make sure that we process them first as a whole. */ 917 943 if (pStream->State.cPosAdjustFramesLeft) 918 cbChunk = RT_MIN(cbChunk, uint32_t(pStream->State.cPosAdjustFramesLeft * pStream->State. cbFrameSize));944 cbChunk = RT_MIN(cbChunk, uint32_t(pStream->State.cPosAdjustFramesLeft * pStream->State.Mapping.cbFrameSize)); 919 945 920 946 Log3Func(("[SD%RU8] cbChunk=%RU32, cPosAdjustFramesLeft=%RU16\n", … … 977 1003 if (RT_SUCCESS(rc)) 978 1004 { 979 const uint32_t cbDMAFree = (uint32_t)RTCircBufFree(pCircBuf); 980 Assert(cbDMAFree >= cbDMA); /* This must always hold. */ 981 982 #ifndef VBOX_WITH_HDA_AUDIO_INTERLEAVING_STREAMS_SUPPORT 1005 const uint32_t cbFree = (uint32_t)RTCircBufFree(pCircBuf); 1006 983 1007 /* 984 1008 * Most guests don't use different stream frame sizes than … … 988 1012 * Only macOS guests need the frame extraction branch below at the moment AFAIK. 989 1013 */ 990 if (pStream->State. cbFrameSize == HDA_FRAME_SIZE)1014 if (pStream->State.Mapping.cbFrameSize == HDA_FRAME_SIZE_DEFAULT) 991 1015 { 992 1016 uint32_t cbDMARead = 0; 993 uint32_t cbDMALeft = RT_MIN(cbDMA, cb DMAFree);1017 uint32_t cbDMALeft = RT_MIN(cbDMA, cbFree); 994 1018 995 1019 while (cbDMALeft) … … 1021 1045 * and just discard the other channel's data. 1022 1046 * 1047 * I know, the following code is horribly slow, but seems to work for now. 1048 ** @todo Optimize channel data extraction! Use some SSE(3) / intrinsics? 1023 1049 */ 1024 /** @todo Optimize this stuff -- copying only one frame a time is expensive. */ 1025 uint32_t cbDMARead = pStream->State.cbDMALeft ? pStream->State.cbFrameSize - pStream->State.cbDMALeft : 0; 1026 uint32_t cbDMALeft = RT_MIN(cbDMA, cbDMAFree); 1027 1028 while (cbDMALeft >= pStream->State.cbFrameSize) 1050 for (unsigned m = 0; m < pStream->State.Mapping.cMappings; m++) 1029 1051 { 1030 void *pvBuf; size_t cbBuf; 1031 RTCircBufAcquireWriteBlock(pCircBuf, HDA_FRAME_SIZE, &pvBuf, &cbBuf); 1032 1033 AssertBreak(cbDMARead <= sizeof(abChunk)); 1034 1035 if (cbBuf) 1036 memcpy(pvBuf, abChunk + cbDMARead, cbBuf); 1037 1038 RTCircBufReleaseWriteBlock(pCircBuf, cbBuf); 1039 1040 Assert(cbDMALeft >= pStream->State.cbFrameSize); 1041 cbDMALeft -= pStream->State.cbFrameSize; 1042 cbDMARead += pStream->State.cbFrameSize; 1052 const uint32_t cbFrame = pStream->State.Mapping.cbFrameSize; 1053 1054 Assert(cbFree >= cbDMA); 1055 1056 PPDMAUDIOSTREAMMAP pMap = &pStream->State.Mapping.paMappings[m]; 1057 AssertPtr(pMap); 1058 1059 Log3Func(("Mapping #%u: Start (cbDMA=%RU32, cbFrame=%RU32, cbOff=%RU32)\n", 1060 m, cbDMA, cbFrame, pMap->cbOff)); 1061 1062 uint8_t *pbSrcBuf = abChunk; 1063 size_t cbSrcOff = pMap->cbOff; 1064 Assert(cbChunk >= cbSrcOff); 1065 1066 for (unsigned i = 0; i < cbDMA / cbFrame; i++) 1067 { 1068 void *pvDstBuf; size_t cbDstBuf; 1069 RTCircBufAcquireWriteBlock(pCircBuf, pMap->cbSize, &pvDstBuf, &cbDstBuf); 1070 1071 Assert(cbDstBuf >= pMap->cbSize); 1072 1073 if (cbDstBuf) 1074 { 1075 Log3Func(("Mapping #%u: Frame #%02u: cbSize=%zu, cbFirst=%zu, cbOff=%zu, cbDstBuf=%zu, cbSrcOff=%zu\n", 1076 m, i, pMap->cbSize, pMap->cbFirst, pMap->cbOff, cbDstBuf, cbSrcOff)); 1077 1078 memcpy(pvDstBuf, pbSrcBuf + cbSrcOff, cbDstBuf); 1079 1080 #if 0 /* Too slow, even for release builds, so disabled it. */ 1081 if (pStream->Dbg.Runtime.fEnabled) 1082 DrvAudioHlpFileWrite(pStream->Dbg.Runtime.pFileDMAMapped, pvDstBuf, cbDstBuf, 1083 0 /* fFlags */); 1084 #endif 1085 Assert(cbSrcOff <= cbDMA); 1086 if (cbSrcOff + cbFrame + pMap->cbFirst <= cbDMA) 1087 cbSrcOff += cbFrame + pMap->cbFirst; 1088 1089 Log3Func(("Mapping #%u: Frame #%02u: -> cbSrcOff=%zu\n", m, i, cbSrcOff)); 1090 } 1091 1092 RTCircBufReleaseWriteBlock(pCircBuf, cbDstBuf); 1093 } 1094 1095 Log3Func(("Mapping #%u: End cbSize=%zu, cbDMA=%RU32, cbSrcOff=%zu\n", 1096 m, pMap->cbSize, cbDMA, cbSrcOff)); 1097 1098 Assert(cbSrcOff <= cbDMA); 1099 1100 const uint32_t cbSrcLeft = cbDMA - (uint32_t)cbSrcOff; 1101 if (cbSrcLeft) 1102 { 1103 Log3Func(("Mapping #%u: cbSrcLeft=%RU32\n", m, cbSrcLeft)); 1104 1105 if (cbSrcLeft >= pMap->cbSize) 1106 { 1107 void *pvDstBuf; size_t cbDstBuf; 1108 RTCircBufAcquireWriteBlock(pCircBuf, pMap->cbSize, &pvDstBuf, &cbDstBuf); 1109 1110 Assert(cbDstBuf >= pMap->cbSize); 1111 1112 if (cbDstBuf) 1113 { 1114 memcpy(pvDstBuf, pbSrcBuf + cbSrcOff, cbDstBuf); 1115 } 1116 1117 RTCircBufReleaseWriteBlock(pCircBuf, cbDstBuf); 1118 } 1119 1120 Assert(pMap->cbFrame >= cbSrcLeft); 1121 pMap->cbOff = pMap->cbFrame - cbSrcLeft; 1122 } 1123 else 1124 pMap->cbOff = 0; 1125 1126 Log3Func(("Mapping #%u finish (cbSrcOff=%zu, cbOff=%zu)\n", m, cbSrcOff, pMap->cbOff)); 1043 1127 } 1044 1045 pStream->State.cbDMALeft = cbDMALeft;1046 Assert(pStream->State.cbDMALeft < pStream->State.cbFrameSize);1047 1128 } 1048 #else1049 /** @todo This needs making use of HDAStreamMap + HDAStreamChannel. */1050 # error "Implement reading interleaving streams support here."1051 #endif1052 1129 } 1053 1130 else … … 1127 1204 1128 1205 /* Do the position adjustment accounting. */ 1129 pStream->State.cPosAdjustFramesLeft -= RT_MIN(pStream->State.cPosAdjustFramesLeft, cbDMA / pStream->State.cbFrameSize); 1206 pStream->State.cPosAdjustFramesLeft -= 1207 RT_MIN(pStream->State.cPosAdjustFramesLeft, cbDMA / pStream->State.Mapping.cbFrameSize); 1130 1208 1131 1209 if (RT_FAILURE(rc)) … … 1144 1222 if (pStream->State.cPosAdjustFramesLeft == 0) 1145 1223 { 1146 hdaR3StreamPeriodInc(pPeriod, RT_MIN(cbProcessed / pStream->State. cbFrameSize,1224 hdaR3StreamPeriodInc(pPeriod, RT_MIN(cbProcessed / pStream->State.Mapping.cbFrameSize, 1147 1225 hdaR3StreamPeriodGetRemainingFrames(pPeriod))); 1148 1226 … … 1176 1254 + hdaR3StreamPeriodFramesToWalClk(pPeriod, 1177 1255 pStream->State.cbTransferProcessed 1178 / pStream->State. cbFrameSize),1256 / pStream->State.Mapping.cbFrameSize), 1179 1257 false /* fForce */); 1180 1258 RT_NOREF(fWalClkSet); -
trunk/src/VBox/Devices/Audio/HDAStream.h
r73833 r75962 61 61 * whereas for output streams this dumps data being read from the device FIFO. */ 62 62 R3PTRTYPE(PPDMAUDIOFILE) pFileStream; 63 /** File for dumping DMA reads / writes.63 /** File for dumping raw DMA reads / writes. 64 64 * For input streams, this dumps data being written to the device DMA, 65 65 * whereas for output streams this dumps data being read from the device DMA. */ 66 R3PTRTYPE(PPDMAUDIOFILE) pFileDMA; 66 R3PTRTYPE(PPDMAUDIOFILE) pFileDMARaw; 67 /** File for dumping mapped (that is, extracted) DMA reads / writes. */ 68 R3PTRTYPE(PPDMAUDIOFILE) pFileDMAMapped; 67 69 } HDASTREAMDBGINFORT, *PHDASTREAMDBGINFORT; 68 70 … … 124 126 #endif 125 127 /** This stream's data mapping. */ 126 HDASTREAMMAP PINGMapping;128 HDASTREAMMAP Mapping; 127 129 /** Current BDLE (Buffer Descriptor List Entry). */ 128 130 HDABDLE BDLE; … … 148 150 * BDLE interrupt-on-completion (IOC) bits set. */ 149 151 uint8_t cTransferPendingInterrupts; 150 /** The stream's current audio frame size (in bytes). */ 151 uint32_t cbFrameSize; 152 uint8_t Padding2[4]; 152 153 /** How many audio data frames are left to be processed 153 154 * for the position adjustment handling. … … 155 156 * 0 if position adjustment handling is done or inactive. */ 156 157 uint16_t cPosAdjustFramesLeft; 157 uint8_t Padding 2[2];158 uint8_t Padding3[2]; 158 159 /** (Virtual) clock ticks per byte. */ 159 160 uint64_t cTicksPerByte; … … 165 166 * Should match SDFMT. */ 166 167 PDMAUDIOSTREAMCFG Cfg; 167 uint32_t Padding 3;168 uint32_t Padding4; 168 169 #ifdef HDA_USE_DMA_ACCESS_HANDLER 169 170 /** List of DMA handlers. */ 170 171 RTLISTANCHORR3 lstDMAHandlers; 171 172 #endif 172 /** How much DMA data from a previous transfer is left to be processed (in bytes).173 * This can happen if the stream's frame size is bigger (e.g. 16 bytes) than174 * the current DMA FIFO can hold (e.g. 10 bytes). Mostly needed for more complex175 * stuff like interleaved surround streams. */176 uint16_t cbDMALeft;177 /** Unused, padding. */178 uint8_t abPadding4[2+4];179 173 /** Timestamp (in ns) of last stream update. */ 180 174 uint64_t tsLastUpdateNs; -
trunk/src/VBox/Devices/Audio/HDAStreamChannel.cpp
r71736 r75962 66 66 67 67 /** 68 * Extracts HDA audio stream data and stores it into the given stream channel data block.69 *70 * @returns IPRT status code.71 * @param pChan Channel data to extract audio stream data into.72 * @param pvBuf Buffer of audio data to extract.73 * @param cbBuf Size (in bytes) of audio data to extract.74 */75 int hdaR3StreamChannelExtract(PPDMAUDIOSTREAMCHANNEL pChan, const void *pvBuf, size_t cbBuf)76 {77 AssertPtrReturn(pChan, VERR_INVALID_POINTER);78 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);79 AssertReturn(cbBuf, VERR_INVALID_PARAMETER);80 81 AssertRelease(pChan->cbOff <= cbBuf);82 83 const uint8_t *pu8Buf = (const uint8_t *)pvBuf;84 85 size_t cbSrc = cbBuf - pChan->cbOff;86 const uint8_t *pvSrc = &pu8Buf[pChan->cbOff];87 88 size_t cbDst;89 uint8_t *pvDst;90 RTCircBufAcquireWriteBlock(pChan->Data.pCircBuf, cbBuf, (void **)&pvDst, &cbDst);91 92 cbSrc = RT_MIN(cbSrc, cbDst);93 94 while (cbSrc)95 {96 AssertBreak(cbDst >= cbSrc);97 98 /* Enough data for at least one next frame? */99 if (cbSrc < pChan->cbFrame)100 break;101 102 memcpy(pvDst, pvSrc, pChan->cbFrame);103 104 /* Advance to next channel frame in stream. */105 pvSrc += pChan->cbStep;106 Assert(cbSrc >= pChan->cbStep);107 cbSrc -= pChan->cbStep;108 109 /* Advance destination by one frame. */110 pvDst += pChan->cbFrame;111 Assert(cbDst >= pChan->cbFrame);112 cbDst -= pChan->cbFrame;113 114 /* Adjust offset. */115 pChan->cbOff += pChan->cbFrame;116 }117 118 RTCircBufReleaseWriteBlock(pChan->Data.pCircBuf, cbDst);119 120 return VINF_SUCCESS;121 }122 123 /**124 * Advances the current read / write pointer by a certain amount.125 *126 * @returns IPRT status code.127 * @param pChan Channel data to advance read / write pointer for.128 * @param cbAdv Amount (in bytes) to advance read / write pointer.129 *130 * @remark Currently not used / implemented.131 */132 int hdaR3StreamChannelAdvance(PPDMAUDIOSTREAMCHANNEL pChan, size_t cbAdv)133 {134 AssertPtrReturn(pChan, VERR_INVALID_POINTER);135 136 if (!cbAdv)137 return VINF_SUCCESS;138 139 return VINF_SUCCESS;140 }141 142 /**143 68 * Acquires (reads) audio channel data. 144 69 * Must be released when done with hdaR3StreamChannelReleaseData(). -
trunk/src/VBox/Devices/Audio/HDAStreamChannel.h
r71736 r75962 21 21 int hdaR3StreamChannelDataInit(PPDMAUDIOSTREAMCHANNELDATA pChanData, uint32_t fFlags); 22 22 void hdaR3StreamChannelDataDestroy(PPDMAUDIOSTREAMCHANNELDATA pChanData); 23 int hdaR3StreamChannelExtract(PPDMAUDIOSTREAMCHANNEL pChan, const void *pvBuf, size_t cbBuf);24 int hdaR3StreamChannelAdvance(PPDMAUDIOSTREAMCHANNEL pChan, size_t cbAdv);25 23 int hdaR3StreamChannelAcquireData(PPDMAUDIOSTREAMCHANNELDATA pChanData, void *ppvData, size_t *pcbData); 26 24 int hdaR3StreamChannelReleaseData(PPDMAUDIOSTREAMCHANNELDATA pChanData); -
trunk/src/VBox/Devices/Audio/HDAStreamMap.cpp
r73529 r75962 5 5 6 6 /* 7 * Copyright (C) 2017 Oracle Corporation7 * Copyright (C) 2017-2018 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 35 35 #ifdef IN_RING3 36 36 37 static int hdaR3StreamMapSetup(PHDASTREAMMAP pMap, PPDMAUDIOPCMPROPS pProps); 38 37 39 /** 38 40 * Initializes a stream mapping structure according to the given PCM properties. 39 41 * 40 42 * @return IPRT status code. 41 * @param pMap pingPointer to mapping to initialize.43 * @param pMap Pointer to mapping to initialize. 42 44 * @param pProps Pointer to PCM properties to use for initialization. 43 45 */ 44 int hdaR3StreamMapInit(PHDASTREAMMAP PING pMapping, PPDMAUDIOPCMPROPS pProps)46 int hdaR3StreamMapInit(PHDASTREAMMAP pMap, PPDMAUDIOPCMPROPS pProps) 45 47 { 46 AssertPtrReturn(pMap ping, VERR_INVALID_POINTER);48 AssertPtrReturn(pMap, VERR_INVALID_POINTER); 47 49 AssertPtrReturn(pProps, VERR_INVALID_POINTER); 48 50 … … 50 52 return VERR_INVALID_PARAMETER; 51 53 52 hdaR3StreamMapReset(pMap ping);54 hdaR3StreamMapReset(pMap); 53 55 54 pMapping->paChannels = (PPDMAUDIOSTREAMCHANNEL)RTMemAlloc(sizeof(PDMAUDIOSTREAMCHANNEL) * pProps->cChannels);55 if ( !pMapping->paChannels)56 return VERR_NO_MEMORY;56 int rc = hdaR3StreamMapSetup(pMap, pProps); 57 if (RT_FAILURE(rc)) 58 return rc; 57 59 58 int rc = VINF_SUCCESS; 59 60 Assert(RT_IS_POWER_OF_TWO(pProps->cBytes * 8)); 61 62 /** @todo We assume all channels in a stream have the same format. */ 63 PPDMAUDIOSTREAMCHANNEL pChan = pMapping->paChannels; 64 for (uint8_t i = 0; i < pProps->cChannels; i++) 65 { 66 pChan->uChannel = i; 67 pChan->cbStep = pProps->cBytes; 68 pChan->cbFrame = pChan->cbStep * pProps->cChannels; 69 pChan->cbFirst = i * pChan->cbStep; 70 pChan->cbOff = pChan->cbFirst; 71 72 int rc2 = hdaR3StreamChannelDataInit(&pChan->Data, PDMAUDIOSTREAMCHANNELDATA_FLAG_NONE); 73 if (RT_SUCCESS(rc)) 74 rc = rc2; 75 76 if (RT_FAILURE(rc)) 77 break; 78 79 pChan++; 80 } 81 60 #ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND 82 61 if ( RT_SUCCESS(rc) 83 62 /* Create circular buffer if not created yet. */ 84 && !pMap ping->pCircBuf)63 && !pMap->pCircBuf) 85 64 { 86 rc = RTCircBufCreate(&pMap ping->pCircBuf, _4K); /** @todo Make size configurable? */65 rc = RTCircBufCreate(&pMap->pCircBuf, _4K); /** @todo Make size configurable? */ 87 66 } 67 #endif 88 68 89 69 if (RT_SUCCESS(rc)) 90 70 { 91 pMapping->cChannels = pProps->cChannels; 92 #ifdef VBOX_WITH_HDA_AUDIO_INTERLEAVING_STREAMS_SUPPORT 93 pMapping->enmLayout = PDMAUDIOSTREAMLAYOUT_INTERLEAVED; 94 #else 95 pMapping->enmLayout = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED; 96 #endif 71 pMap->cbFrameSize = pProps->cChannels * pProps->cBytes; 72 73 LogFunc(("cChannels=%RU8, cBytes=%RU8 -> cbFrameSize=%RU32\n", 74 pProps->cChannels, pProps->cBytes, pMap->cbFrameSize)); 75 76 Assert(pMap->cbFrameSize); /* Frame size must not be 0. */ 77 78 pMap->enmLayout = PDMAUDIOSTREAMLAYOUT_INTERLEAVED; 97 79 } 98 80 … … 104 86 * Destroys a given stream mapping. 105 87 * 106 * @param pMap pingPointer to mapping to destroy.88 * @param pMap Pointer to mapping to destroy. 107 89 */ 108 void hdaR3StreamMapDestroy(PHDASTREAMMAP PING pMapping)90 void hdaR3StreamMapDestroy(PHDASTREAMMAP pMap) 109 91 { 110 hdaR3StreamMapReset(pMap ping);92 hdaR3StreamMapReset(pMap); 111 93 112 if (pMapping->pCircBuf) 94 #ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND 95 if (pMap->pCircBuf) 113 96 { 114 RTCircBufDestroy(pMap ping->pCircBuf);115 pMap ping->pCircBuf = NULL;97 RTCircBufDestroy(pMap->pCircBuf); 98 pMap->pCircBuf = NULL; 116 99 } 100 #endif 117 101 } 118 102 … … 121 105 * Resets a given stream mapping. 122 106 * 123 * @param pMap pingPointer to mapping to reset.107 * @param pMap Pointer to mapping to reset. 124 108 */ 125 void hdaR3StreamMapReset(PHDASTREAMMAP PING pMapping)109 void hdaR3StreamMapReset(PHDASTREAMMAP pMap) 126 110 { 127 AssertPtrReturnVoid(pMap ping);111 AssertPtrReturnVoid(pMap); 128 112 129 pMap ping->enmLayout = PDMAUDIOSTREAMLAYOUT_UNKNOWN;113 pMap->enmLayout = PDMAUDIOSTREAMLAYOUT_UNKNOWN; 130 114 131 if (pMap ping->cChannels)115 if (pMap->paMappings) 132 116 { 133 for (uint8_t i = 0; i < pMap ping->cChannels; i++)134 hdaR3StreamChannelDataDestroy(&pMap ping->paChannels[i].Data);117 for (uint8_t i = 0; i < pMap->cMappings; i++) 118 hdaR3StreamChannelDataDestroy(&pMap->paMappings[i].Data); 135 119 136 AssertPtr(pMapping->paChannels); 137 RTMemFree(pMapping->paChannels); 138 pMapping->paChannels = NULL; 120 RTMemFree(pMap->paMappings); 121 pMap->paMappings = NULL; 139 122 140 pMap ping->cChannels = 0;123 pMap->cMappings = 0; 141 124 } 142 125 } 143 126 127 128 /** 129 * Sets up a stream mapping according to the given properties / configuration. 130 * 131 * @return VBox status code, or VERR_NOT_SUPPORTED if the channel setup is not supported (yet). 132 * @param pMap Pointer to mapping to set up. 133 * @param pProps PCM audio properties to use for lookup. 134 */ 135 static int hdaR3StreamMapSetup(PHDASTREAMMAP pMap, PPDMAUDIOPCMPROPS pProps) 136 { 137 int rc; 138 139 /** @todo We ASSUME that all channels in a stream ... 140 * - have the same format 141 * - are in a consecutive order with no gaps in between 142 * - have a simple (raw) data layout 143 * - work in a non-striped fashion, e.g. interleaved (only on one SDn, not spread over multiple SDns) */ 144 if ( pProps->cChannels == 1 /* Mono */ 145 || pProps->cChannels == 2 /* Stereo */ 146 || pProps->cChannels == 4 /* Quadrophonic */ 147 || pProps->cChannels == 6) /* Surround (5.1) */ 148 { 149 /* For now we don't have anything other as mono / stereo channels being covered by the backends. 150 * So just set up one channel covering those and skipping the rest (like configured rear or center/LFE outputs). */ 151 pMap->cMappings = 1; 152 pMap->paMappings = (PPDMAUDIOSTREAMMAP)RTMemAlloc(sizeof(PDMAUDIOSTREAMMAP) * pMap->cMappings); 153 if (!pMap->paMappings) 154 return VERR_NO_MEMORY; 155 156 PPDMAUDIOSTREAMMAP pMapLR = &pMap->paMappings[0]; 157 158 pMapLR->aID[0] = PDMAUDIOSTREAMCHANNELID_FRONT_LEFT; 159 pMapLR->aID[1] = PDMAUDIOSTREAMCHANNELID_FRONT_RIGHT; 160 pMapLR->cbFrame = pProps->cBytes * pProps->cChannels; 161 pMapLR->cbSize = pProps->cBytes * 2 /* Front left + Front right channels */; 162 pMapLR->cbFirst = 0; 163 pMapLR->cbOff = pMapLR->cbFirst; 164 165 rc = hdaR3StreamChannelDataInit(&pMapLR->Data, PDMAUDIOSTREAMCHANNELDATA_FLAG_NONE); 166 AssertRC(rc); 167 } 168 else 169 rc = VERR_NOT_SUPPORTED; /** @todo r=andy Support more setups. */ 170 171 return rc; 172 } 144 173 #endif /* IN_RING3 */ 145 174 -
trunk/src/VBox/Devices/Audio/HDAStreamMap.h
r71754 r75962 1 1 /* $Id$ */ 2 2 /** @file 3 * HDAStreamMap.h - Stream map pingfunctions for HD Audio.3 * HDAStreamMap.h - Stream map functions for HD Audio. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 2017 Oracle Corporation7 * Copyright (C) 2017-2018 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 22 22 * Structure for keeping an audio stream data mapping. 23 23 */ 24 typedef struct HDASTREAMMAP PING24 typedef struct HDASTREAMMAP 25 25 { 26 26 /** The stream's layout. */ 27 PDMAUDIOSTREAMLAYOUT enmLayout; 28 /** Number of audio channels in this stream. */ 29 uint8_t cChannels; 30 /** Array of audio channels. */ 31 R3PTRTYPE(PPDMAUDIOSTREAMCHANNEL) paChannels; 27 PDMAUDIOSTREAMLAYOUT enmLayout; 28 uint8_t cbFrameSize; 29 /** Number of mappings in paMappings. */ 30 uint8_t cMappings; 31 uint8_t aPadding[2]; 32 /** Array of stream mappings. 33 * Note: The mappings *must* be layed out in an increasing order, e.g. 34 * how the data appears in the given data block. */ 35 R3PTRTYPE(PPDMAUDIOSTREAMMAP) paMappings; 36 #if HC_ARCH_BITS == 32 37 RTR3PTR Padding1; 38 #endif 39 #ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND 32 40 /** Circular buffer holding for holding audio data for this mapping. */ 33 R3PTRTYPE(PRTCIRCBUF) pCircBuf; 34 } HDASTREAMMAPPING; 35 AssertCompileSizeAlignment(HDASTREAMMAPPING, 8); 36 typedef HDASTREAMMAPPING *PHDASTREAMMAPPING; 41 R3PTRTYPE(PRTCIRCBUF) pCircBuf; 42 #endif 43 } HDASTREAMMAP; 44 AssertCompileSizeAlignment(HDASTREAMMAP, 8); 45 typedef HDASTREAMMAP *PHDASTREAMMAP; 37 46 38 47 /** @name Stream mapping functions. … … 40 49 */ 41 50 #ifdef IN_RING3 42 int hdaR3StreamMapInit(PHDASTREAMMAP PINGpMapping, PPDMAUDIOPCMPROPS pProps);43 void hdaR3StreamMapDestroy(PHDASTREAMMAP PINGpMapping);44 void hdaR3StreamMapReset(PHDASTREAMMAP PINGpMapping);51 int hdaR3StreamMapInit(PHDASTREAMMAP pMapping, PPDMAUDIOPCMPROPS pProps); 52 void hdaR3StreamMapDestroy(PHDASTREAMMAP pMapping); 53 void hdaR3StreamMapReset(PHDASTREAMMAP pMapping); 45 54 #endif /* IN_RING3 */ 46 55 /** @} */ -
trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp
r75867 r75962 1976 1976 GEN_CHECK_OFF(HDABDLE, State); 1977 1977 1978 GEN_CHECK_SIZE(HDASTREAMMAP); 1979 1978 1980 GEN_CHECK_SIZE(HDASTREAMSTATE); 1979 1981 GEN_CHECK_OFF(HDASTREAMSTATE, uCurBDLE);
Note:
See TracChangeset
for help on using the changeset viewer.