Changeset 67899 in vbox
- Timestamp:
- Jul 11, 2017 11:03:53 AM (7 years ago)
- Location:
- trunk/src/VBox/Devices
- Files:
-
- 3 added
- 4 edited
-
Audio/DevHDA.cpp (modified) (21 diffs)
-
Audio/DevHDA.h (added)
-
Audio/DevHDACommon.h (modified) (3 diffs)
-
Audio/HDACodec.h (modified) (1 diff)
-
Audio/HDAStream.cpp (added)
-
Audio/HDAStream.h (added)
-
Makefile.kmk (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DevHDA.cpp
r67855 r67899 1 1 /* $Id$ */ 2 2 /** @file 3 * DevHDA - VBox Intel HD Audio Controller.3 * DevHDA.cpp - VBox Intel HD Audio Controller. 4 4 * 5 5 * Implemented against the specifications found in "High Definition Audio … … 47 47 #include "AudioMixBuffer.h" 48 48 #include "AudioMixer.h" 49 50 #include "DevHDA.h" 51 #include "DevHDACommon.h" 52 49 53 #include "HDACodec.h" 54 #include "HDAStream.h" 50 55 # if defined(VBOX_WITH_HDA_AUDIO_INTERLEAVING_STREAMS_SUPPORT) || defined(VBOX_WITH_AUDIO_HDA_51_SURROUND) 51 56 # include "HDAStreamChannel.h" … … 53 58 #include "HDAStreamMap.h" 54 59 #include "HDAStreamPeriod.h" 55 #include "DevHDACommon.h" 60 56 61 #include "DrvAudio.h" 57 62 … … 107 112 #endif 108 113 109 /** Default timer frequency (in Hz).110 *111 * Note: Keep in mind that the Hz rate has nothing to do with samples rates112 * or DMA / interrupt timing -- it's purely needed in order to drive113 * the data flow at a constant (and sufficient) rate.114 *115 * Lowering this value can ask for trouble, as backends then can run116 * into data underruns. */117 #define HDA_TIMER_HZ 200118 119 /** HDA's (fixed) audio frame size in bytes.120 * We only support 16-bit stereo frames at the moment. */121 #define HDA_FRAME_SIZE 4122 123 /**124 * At the moment we support 4 input + 4 output streams max, which is 8 in total.125 * Bidirectional streams are currently *not* supported.126 *127 * Note: When changing any of those values, be prepared for some saved state128 * fixups / trouble!129 */130 #define HDA_MAX_SDI 4131 #define HDA_MAX_SDO 4132 #define HDA_MAX_STREAMS (HDA_MAX_SDI + HDA_MAX_SDO)133 AssertCompile(HDA_MAX_SDI <= HDA_MAX_SDO);134 135 /** Number of general registers. */136 #define HDA_NUM_GENERAL_REGS 34137 /** Number of total registers in the HDA's register map. */138 #define HDA_NUM_REGS (HDA_NUM_GENERAL_REGS + (HDA_MAX_STREAMS * 10 /* Each stream descriptor has 10 registers */))139 /** Total number of stream tags (channels). Index 0 is reserved / invalid. */140 #define HDA_MAX_TAGS 16141 142 /**143 * NB: Register values stored in memory (au32Regs[]) are indexed through144 * the HDA_RMX_xxx macros (also HDA_MEM_IND_NAME()). On the other hand, the145 * register descriptors in g_aHdaRegMap[] are indexed through the146 * HDA_REG_xxx macros (also HDA_REG_IND_NAME()).147 *148 * The au32Regs[] layout is kept unchanged for saved state149 * compatibility.150 */151 152 /* Registers */153 #define HDA_REG_IND_NAME(x) HDA_REG_##x154 #define HDA_MEM_IND_NAME(x) HDA_RMX_##x155 #define HDA_REG_IND(pThis, x) ((pThis)->au32Regs[g_aHdaRegMap[x].mem_idx])156 #define HDA_REG(pThis, x) (HDA_REG_IND((pThis), HDA_REG_IND_NAME(x)))157 158 159 #define HDA_REG_GCAP 0 /* range 0x00-0x01*/160 #define HDA_RMX_GCAP 0161 /* GCAP HDASpec 3.3.2 This macro encodes the following information about HDA in a compact manner:162 * oss (15:12) - number of output streams supported163 * iss (11:8) - number of input streams supported164 * bss (7:3) - number of bidirectional streams supported165 * bds (2:1) - number of serial data out (SDO) signals supported166 * b64sup (0) - 64 bit addressing supported.167 */168 #define HDA_MAKE_GCAP(oss, iss, bss, bds, b64sup) \169 ( (((oss) & 0xF) << 12) \170 | (((iss) & 0xF) << 8) \171 | (((bss) & 0x1F) << 3) \172 | (((bds) & 0x3) << 2) \173 | ((b64sup) & 1))174 175 #define HDA_REG_VMIN 1 /* 0x02 */176 #define HDA_RMX_VMIN 1177 178 #define HDA_REG_VMAJ 2 /* 0x03 */179 #define HDA_RMX_VMAJ 2180 181 #define HDA_REG_OUTPAY 3 /* 0x04-0x05 */182 #define HDA_RMX_OUTPAY 3183 184 #define HDA_REG_INPAY 4 /* 0x06-0x07 */185 #define HDA_RMX_INPAY 4186 187 #define HDA_REG_GCTL 5 /* 0x08-0x0B */188 #define HDA_RMX_GCTL 5189 #define HDA_GCTL_UNSOL RT_BIT(8) /* Accept Unsolicited Response Enable */190 #define HDA_GCTL_FCNTRL RT_BIT(1) /* Flush Control */191 #define HDA_GCTL_CRST RT_BIT(0) /* Controller Reset */192 193 #define HDA_REG_WAKEEN 6 /* 0x0C */194 #define HDA_RMX_WAKEEN 6195 196 #define HDA_REG_STATESTS 7 /* 0x0E */197 #define HDA_RMX_STATESTS 7198 #define HDA_STATESTS_SCSF_MASK 0x7 /* State Change Status Flags (6.2.8). */199 200 #define HDA_REG_GSTS 8 /* 0x10-0x11*/201 #define HDA_RMX_GSTS 8202 #define HDA_GSTS_FSTS RT_BIT(1) /* Flush Status */203 204 #define HDA_REG_OUTSTRMPAY 9 /* 0x18 */205 #define HDA_RMX_OUTSTRMPAY 112206 207 #define HDA_REG_INSTRMPAY 10 /* 0x1a */208 #define HDA_RMX_INSTRMPAY 113209 210 #define HDA_REG_INTCTL 11 /* 0x20 */211 #define HDA_RMX_INTCTL 9212 #define HDA_INTCTL_GIE RT_BIT(31) /* Global Interrupt Enable */213 #define HDA_INTCTL_CIE RT_BIT(30) /* Controller Interrupt Enable */214 /* Bits 0-29 correspond to streams 0-29. */215 #define HDA_STRMINT_MASK 0xFF /* Streams 0-7 implemented. Applies to INTCTL and INTSTS. */216 217 #define HDA_REG_INTSTS 12 /* 0x24 */218 #define HDA_RMX_INTSTS 10219 #define HDA_INTSTS_GIS RT_BIT(31) /* Global Interrupt Status */220 #define HDA_INTSTS_CIS RT_BIT(30) /* Controller Interrupt Status */221 /* Bits 0-29 correspond to streams 0-29. */222 223 #define HDA_REG_WALCLK 13 /* 0x30 */224 /* NB: HDA_RMX_WALCLK is not defined because the register is not stored in memory. */225 226 /* Note: The HDA specification defines a SSYNC register at offset 0x38. The227 * ICH6/ICH9 datahseet defines SSYNC at offset 0x34. The Linux HDA driver matches228 * the datasheet.229 */230 #define HDA_REG_SSYNC 14 /* 0x34 */231 #define HDA_RMX_SSYNC 12232 233 #define HDA_REG_CORBLBASE 15 /* 0x40 */234 #define HDA_RMX_CORBLBASE 13235 236 #define HDA_REG_CORBUBASE 16 /* 0x44 */237 #define HDA_RMX_CORBUBASE 14238 239 #define HDA_REG_CORBWP 17 /* 0x48 */240 #define HDA_RMX_CORBWP 15241 242 #define HDA_REG_CORBRP 18 /* 0x4A */243 #define HDA_RMX_CORBRP 16244 #define HDA_CORBRP_RST RT_BIT(15) /* CORB Read Pointer Reset */245 246 #define HDA_REG_CORBCTL 19 /* 0x4C */247 #define HDA_RMX_CORBCTL 17248 #define HDA_CORBCTL_DMA RT_BIT(1) /* Enable CORB DMA Engine */249 #define HDA_CORBCTL_CMEIE RT_BIT(0) /* CORB Memory Error Interrupt Enable */250 251 #define HDA_REG_CORBSTS 20 /* 0x4D */252 #define HDA_RMX_CORBSTS 18253 254 #define HDA_REG_CORBSIZE 21 /* 0x4E */255 #define HDA_RMX_CORBSIZE 19256 /* NB: Up to and including ICH 10, sizes of CORB and RIRB are fixed at 256 entries. */257 258 #define HDA_REG_RIRBLBASE 22 /* 0x50 */259 #define HDA_RMX_RIRBLBASE 20260 261 #define HDA_REG_RIRBUBASE 23 /* 0x54 */262 #define HDA_RMX_RIRBUBASE 21263 264 #define HDA_REG_RIRBWP 24 /* 0x58 */265 #define HDA_RMX_RIRBWP 22266 #define HDA_RIRBWP_RST RT_BIT(15) /* RIRB Write Pointer Reset */267 268 #define HDA_REG_RINTCNT 25 /* 0x5A */269 #define HDA_RMX_RINTCNT 23270 #define RINTCNT_N(pThis) (HDA_REG(pThis, RINTCNT) & 0xff)271 272 #define HDA_REG_RIRBCTL 26 /* 0x5C */273 #define HDA_RMX_RIRBCTL 24274 #define HDA_RIRBCTL_ROIC RT_BIT(2) /* Response Overrun Interrupt Control */275 #define HDA_RIRBCTL_RDMAEN RT_BIT(1) /* RIRB DMA Enable */276 #define HDA_RIRBCTL_RINTCTL RT_BIT(0) /* Response Interrupt Control */277 278 #define HDA_REG_RIRBSTS 27 /* 0x5D */279 #define HDA_RMX_RIRBSTS 25280 #define HDA_RIRBSTS_RIRBOIS RT_BIT(2) /* Response Overrun Interrupt Status */281 #define HDA_RIRBSTS_RINTFL RT_BIT(0) /* Response Interrupt Flag */282 283 #define HDA_REG_RIRBSIZE 28 /* 0x5E */284 #define HDA_RMX_RIRBSIZE 26285 286 #define HDA_REG_IC 29 /* 0x60 */287 #define HDA_RMX_IC 27288 289 #define HDA_REG_IR 30 /* 0x64 */290 #define HDA_RMX_IR 28291 292 #define HDA_REG_IRS 31 /* 0x68 */293 #define HDA_RMX_IRS 29294 #define HDA_IRS_IRV RT_BIT(1) /* Immediate Result Valid */295 #define HDA_IRS_ICB RT_BIT(0) /* Immediate Command Busy */296 297 #define HDA_REG_DPLBASE 32 /* 0x70 */298 #define HDA_RMX_DPLBASE 30299 300 #define HDA_REG_DPUBASE 33 /* 0x74 */301 #define HDA_RMX_DPUBASE 31302 303 #define DPBASE_ADDR_MASK (~(uint64_t)0x7f)304 305 #define HDA_STREAM_REG_DEF(name, num) (HDA_REG_SD##num##name)306 #define HDA_STREAM_RMX_DEF(name, num) (HDA_RMX_SD##num##name)307 /* Note: sdnum here _MUST_ be stream reg number [0,7]. */308 #define HDA_STREAM_REG(pThis, name, sdnum) (HDA_REG_IND((pThis), HDA_REG_SD0##name + (sdnum) * 10))309 310 #define HDA_SD_NUM_FROM_REG(pThis, func, reg) ((reg - HDA_STREAM_REG_DEF(func, 0)) / 10)311 312 /** @todo Condense marcos! */313 314 #define HDA_REG_SD0CTL HDA_NUM_GENERAL_REGS /* 0x80; other streams offset by 0x20 */315 #define HDA_RMX_SD0CTL 32316 #define HDA_RMX_SD1CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 10)317 #define HDA_RMX_SD2CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 20)318 #define HDA_RMX_SD3CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 30)319 #define HDA_RMX_SD4CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 40)320 #define HDA_RMX_SD5CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 50)321 #define HDA_RMX_SD6CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 60)322 #define HDA_RMX_SD7CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 70)323 324 #define HDA_SDCTL_NUM_MASK 0xF325 #define HDA_SDCTL_NUM_SHIFT 20326 #define HDA_SDCTL_DIR RT_BIT(19) /* Direction (Bidirectional streams only!) */327 #define HDA_SDCTL_TP RT_BIT(18) /* Traffic Priority (PCI Express) */328 #define HDA_SDCTL_STRIPE_MASK 0x3329 #define HDA_SDCTL_STRIPE_SHIFT 16330 #define HDA_SDCTL_DEIE RT_BIT(4) /* Descriptor Error Interrupt Enable */331 #define HDA_SDCTL_FEIE RT_BIT(3) /* FIFO Error Interrupt Enable */332 #define HDA_SDCTL_IOCE RT_BIT(2) /* Interrupt On Completion Enable */333 #define HDA_SDCTL_RUN RT_BIT(1) /* Stream Run */334 #define HDA_SDCTL_SRST RT_BIT(0) /* Stream Reset */335 336 #define HDA_REG_SD0STS 35 /* 0x83; other streams offset by 0x20 */337 #define HDA_RMX_SD0STS 33338 #define HDA_RMX_SD1STS (HDA_STREAM_RMX_DEF(STS, 0) + 10)339 #define HDA_RMX_SD2STS (HDA_STREAM_RMX_DEF(STS, 0) + 20)340 #define HDA_RMX_SD3STS (HDA_STREAM_RMX_DEF(STS, 0) + 30)341 #define HDA_RMX_SD4STS (HDA_STREAM_RMX_DEF(STS, 0) + 40)342 #define HDA_RMX_SD5STS (HDA_STREAM_RMX_DEF(STS, 0) + 50)343 #define HDA_RMX_SD6STS (HDA_STREAM_RMX_DEF(STS, 0) + 60)344 #define HDA_RMX_SD7STS (HDA_STREAM_RMX_DEF(STS, 0) + 70)345 346 #define HDA_SDSTS_FIFORDY RT_BIT(5) /* FIFO Ready */347 #define HDA_SDSTS_DESE RT_BIT(4) /* Descriptor Error */348 #define HDA_SDSTS_FIFOE RT_BIT(3) /* FIFO Error */349 #define HDA_SDSTS_BCIS RT_BIT(2) /* Buffer Completion Interrupt Status */350 351 #define HDA_REG_SD0LPIB 36 /* 0x84; other streams offset by 0x20 */352 #define HDA_REG_SD1LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 10) /* 0xA4 */353 #define HDA_REG_SD2LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 20) /* 0xC4 */354 #define HDA_REG_SD3LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 30) /* 0xE4 */355 #define HDA_REG_SD4LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 40) /* 0x104 */356 #define HDA_REG_SD5LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 50) /* 0x124 */357 #define HDA_REG_SD6LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 60) /* 0x144 */358 #define HDA_REG_SD7LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 70) /* 0x164 */359 #define HDA_RMX_SD0LPIB 34360 #define HDA_RMX_SD1LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 10)361 #define HDA_RMX_SD2LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 20)362 #define HDA_RMX_SD3LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 30)363 #define HDA_RMX_SD4LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 40)364 #define HDA_RMX_SD5LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 50)365 #define HDA_RMX_SD6LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 60)366 #define HDA_RMX_SD7LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 70)367 368 #define HDA_REG_SD0CBL 37 /* 0x88; other streams offset by 0x20 */369 #define HDA_RMX_SD0CBL 35370 #define HDA_RMX_SD1CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 10)371 #define HDA_RMX_SD2CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 20)372 #define HDA_RMX_SD3CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 30)373 #define HDA_RMX_SD4CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 40)374 #define HDA_RMX_SD5CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 50)375 #define HDA_RMX_SD6CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 60)376 #define HDA_RMX_SD7CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 70)377 378 #define HDA_REG_SD0LVI 38 /* 0x8C; other streams offset by 0x20 */379 #define HDA_RMX_SD0LVI 36380 #define HDA_RMX_SD1LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 10)381 #define HDA_RMX_SD2LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 20)382 #define HDA_RMX_SD3LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 30)383 #define HDA_RMX_SD4LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 40)384 #define HDA_RMX_SD5LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 50)385 #define HDA_RMX_SD6LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 60)386 #define HDA_RMX_SD7LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 70)387 388 #define HDA_REG_SD0FIFOW 39 /* 0x8E; other streams offset by 0x20 */389 #define HDA_RMX_SD0FIFOW 37390 #define HDA_RMX_SD1FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 10)391 #define HDA_RMX_SD2FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 20)392 #define HDA_RMX_SD3FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 30)393 #define HDA_RMX_SD4FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 40)394 #define HDA_RMX_SD5FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 50)395 #define HDA_RMX_SD6FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 60)396 #define HDA_RMX_SD7FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 70)397 398 /*399 * ICH6 datasheet defined limits for FIFOW values (18.2.38).400 */401 #define HDA_SDFIFOW_8B 0x2402 #define HDA_SDFIFOW_16B 0x3403 #define HDA_SDFIFOW_32B 0x4404 405 #define HDA_REG_SD0FIFOS 40 /* 0x90; other streams offset by 0x20 */406 #define HDA_RMX_SD0FIFOS 38407 #define HDA_RMX_SD1FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 10)408 #define HDA_RMX_SD2FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 20)409 #define HDA_RMX_SD3FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 30)410 #define HDA_RMX_SD4FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 40)411 #define HDA_RMX_SD5FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 50)412 #define HDA_RMX_SD6FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 60)413 #define HDA_RMX_SD7FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 70)414 415 /*416 * ICH6 datasheet defines limits for FIFOS registers (18.2.39)417 * formula: size - 1418 * Other values not listed are not supported.419 */420 /** Maximum FIFO size (in bytes). */421 #define HDA_FIFO_MAX 256422 423 #define HDA_SDIFIFO_120B 0x77 /* 8-, 16-, 20-, 24-, 32-bit Input Streams */424 #define HDA_SDIFIFO_160B 0x9F /* 20-, 24-bit Input Streams Streams */425 426 #define HDA_SDOFIFO_16B 0x0F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */427 #define HDA_SDOFIFO_32B 0x1F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */428 #define HDA_SDOFIFO_64B 0x3F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */429 #define HDA_SDOFIFO_128B 0x7F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */430 #define HDA_SDOFIFO_192B 0xBF /* 8-, 16-, 20-, 24-, 32-bit Output Streams */431 #define HDA_SDOFIFO_256B 0xFF /* 20-, 24-bit Output Streams */432 433 #define HDA_REG_SD0FMT 41 /* 0x92; other streams offset by 0x20 */434 #define HDA_RMX_SD0FMT 39435 #define HDA_RMX_SD1FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 10)436 #define HDA_RMX_SD2FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 20)437 #define HDA_RMX_SD3FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 30)438 #define HDA_RMX_SD4FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 40)439 #define HDA_RMX_SD5FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 50)440 #define HDA_RMX_SD6FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 60)441 #define HDA_RMX_SD7FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 70)442 443 #define HDA_REG_SD0BDPL 42 /* 0x98; other streams offset by 0x20 */444 #define HDA_RMX_SD0BDPL 40445 #define HDA_RMX_SD1BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 10)446 #define HDA_RMX_SD2BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 20)447 #define HDA_RMX_SD3BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 30)448 #define HDA_RMX_SD4BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 40)449 #define HDA_RMX_SD5BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 50)450 #define HDA_RMX_SD6BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 60)451 #define HDA_RMX_SD7BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 70)452 453 #define HDA_REG_SD0BDPU 43 /* 0x9C; other streams offset by 0x20 */454 #define HDA_RMX_SD0BDPU 41455 #define HDA_RMX_SD1BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 10)456 #define HDA_RMX_SD2BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 20)457 #define HDA_RMX_SD3BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 30)458 #define HDA_RMX_SD4BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 40)459 #define HDA_RMX_SD5BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 50)460 #define HDA_RMX_SD6BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 60)461 #define HDA_RMX_SD7BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 70)462 463 #define HDA_BDLE_FLAG_IOC RT_BIT(0) /* Interrupt on completion (IOC). */464 465 #define HDA_CODEC_CAD_SHIFT 28466 /* Encodes the (required) LUN into a codec command. */467 #define HDA_CODEC_CMD(cmd, lun) ((cmd) | (lun << HDA_CODEC_CAD_SHIFT))468 469 470 114 471 115 /********************************************************************************************************************************* 472 116 * Structures and Typedefs * 473 117 *********************************************************************************************************************************/ 474 475 /**476 * Internal state of a Buffer Descriptor List Entry (BDLE),477 * needed to keep track of the data needed for the actual device478 * emulation.479 */480 typedef struct HDABDLESTATE481 {482 /** Own index within the BDL (Buffer Descriptor List). */483 uint32_t u32BDLIndex;484 /** Number of bytes below the stream's FIFO watermark (SDFIFOW).485 * Used to check if we need fill up the FIFO again. */486 uint32_t cbBelowFIFOW;487 /** Current offset in DMA buffer (in bytes).*/488 uint32_t u32BufOff;489 uint32_t Padding;490 } HDABDLESTATE, *PHDABDLESTATE;491 492 /**493 * BDL description structure.494 * Do not touch this, as this must match to the HDA specs.495 */496 typedef struct HDABDLEDESC497 {498 /** Starting address of the actual buffer. Must be 128-bit aligned. */499 uint64_t u64BufAdr;500 /** Size of the actual buffer (in bytes). */501 uint32_t u32BufSize;502 /** Bit 0: Interrupt on completion; the controller will generate503 * an interrupt when the last byte of the buffer has been504 * fetched by the DMA engine.505 *506 * Rest is reserved for further use and must be 0. */507 uint32_t fFlags;508 } HDABDLEDESC, *PHDABDLEDESC;509 AssertCompileSize(HDABDLEDESC, 16); /* Always 16 byte. Also must be aligned on 128-byte boundary. */510 511 /**512 * Buffer Descriptor List Entry (BDLE) (3.6.3).513 */514 typedef struct HDABDLE515 {516 /** The actual BDL description. */517 HDABDLEDESC Desc;518 /** Internal state of this BDLE.519 * Not part of the actual BDLE registers. */520 HDABDLESTATE State;521 } HDABDLE, *PHDABDLE;522 523 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO524 /**525 * Structure keeping the HDA stream's state for asynchronous I/O.526 */527 typedef struct HDASTREAMSTATEAIO528 {529 /** Thread handle for the actual I/O thread. */530 RTTHREAD Thread;531 /** Event for letting the thread know there is some data to process. */532 RTSEMEVENT Event;533 /** Critical section for synchronizing access. */534 RTCRITSECT CritSect;535 /** Started indicator. */536 volatile bool fStarted;537 /** Shutdown indicator. */538 volatile bool fShutdown;539 /** Whether the thread should do any data processing or not. */540 volatile bool fEnabled;541 uint32_t Padding1;542 } HDASTREAMSTATEAIO, *PHDASTREAMSTATEAIO;543 #endif544 545 /**546 * Internal state of a HDA stream.547 */548 typedef struct HDASTREAMSTATE549 {550 /** Current BDLE to use. Wraps around to 0 if551 * maximum (cBDLE) is reached. */552 uint16_t uCurBDLE;553 /** Flag indicating whether this stream currently is554 * in reset mode and therefore not acccessible by the guest. */555 volatile bool fInReset;556 /** Unused, padding. */557 uint32_t Padding0;558 /** Critical section to serialize access. */559 RTCRITSECT CritSect;560 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO561 /** Asynchronous I/O state members. */562 HDASTREAMSTATEAIO AIO;563 #endif564 /** This stream's data mapping. */565 HDASTREAMMAPPING Mapping;566 /** Current BDLE (Buffer Descriptor List Entry). */567 HDABDLE BDLE;568 /** Circular buffer (FIFO) for holding DMA'ed data. */569 R3PTRTYPE(PRTCIRCBUF) pCircBuf;570 /** Timestamp of the last success DMA data transfer.571 * Used to calculate the time actually elapsed between two transfers. */572 uint64_t uTimerTS;573 /** The stream's period. Need for timing. */574 HDASTREAMPERIOD Period;575 /** The stream's current configuration.576 * Should match SDFMT. */577 PDMAUDIOSTREAMCFG strmCfg;578 #ifdef HDA_USE_DMA_ACCESS_HANDLER579 /** List of DMA handlers. */580 RTLISTANCHORR3 lstDMAHandlers;581 #endif582 /** Unused, padding. */583 uint8_t Padding1[3];584 } HDASTREAMSTATE, *PHDASTREAMSTATE;585 586 /**587 * Structure defining an HDA mixer sink.588 * Its purpose is to know which audio mixer sink is bound to589 * which SDn (SDI/SDO) device stream.590 *591 * This is needed in order to handle interleaved streams592 * (that is, multiple channels in one stream) or non-interleaved593 * streams (each channel has a dedicated stream).594 *595 * This is only known to the actual device emulation level.596 */597 typedef struct HDAMIXERSINK598 {599 /** SDn ID this sink is assigned to. 0 if not assigned. */600 uint8_t uSD;601 /** Channel ID of SDn ID. Only valid if SDn ID is valid. */602 uint8_t uChannel;603 uint8_t Padding[3];604 /** Pointer to the actual audio mixer sink. */605 R3PTRTYPE(PAUDMIXSINK) pMixSink;606 } HDAMIXERSINK, *PHDAMIXERSINK;607 608 #if defined (DEBUG) || defined(HDA_USE_DMA_ACCESS_HANDLER)609 typedef struct HDASTREAMDBGINFO610 {611 /** Critical section to serialize access if needed. */612 RTCRITSECT CritSect;613 uint32_t Padding1[2];614 /** Number of total read accesses. */615 uint64_t cReadsTotal;616 /** Number of total DMA bytes read. */617 uint64_t cbReadTotal;618 /** Timestamp (in ns) of last read access. */619 uint64_t tsLastReadNs;620 /** Number of total write accesses. */621 uint64_t cWritesTotal;622 /** Number of total DMA bytes written. */623 uint64_t cbWrittenTotal;624 /** Number of total write accesses since last iteration (Hz). */625 uint64_t cWritesHz;626 /** Number of total DMA bytes written since last iteration (Hz). */627 uint64_t cbWrittenHz;628 /** Timestamp (in ns) of beginning a new write slot. */629 uint64_t tsWriteSlotBegin;630 /** Number of current silence samples in a (consecutive) row. */631 uint64_t csSilence;632 /** Number of silent samples in a row to consider an audio block as audio gap (silence). */633 uint64_t cSilenceThreshold;634 /** How many bytes to skip in an audio stream before detecting silence.635 * (useful for intros and silence at the beginning of a song). */636 uint64_t cbSilenceReadMin;637 } HDASTREAMDBGINFO ,*PHDASTREAMDBGINFO;638 #endif /* defined (DEBUG) || defined(HDA_USE_DMA_ACCESS_HANDLER) */639 640 /**641 * Structure for keeping a HDA stream (SDI / SDO).642 *643 * Note: This HDA stream has nothing to do with a regular audio stream handled644 * by the audio connector or the audio mixer. This HDA stream is a serial data in/out645 * stream (SDI/SDO) defined in hardware and can contain multiple audio streams646 * in one single SDI/SDO (interleaving streams).647 *648 * How a specific SDI/SDO is mapped to our internal audio streams relies on the649 * stream channel mappings.650 *651 * Contains only register values which do *not* change until a652 * stream reset occurs.653 */654 typedef struct HDASTREAM655 {656 /** Stream descriptor number (SDn). */657 uint8_t u8SD;658 uint8_t Padding0[7];659 /** DMA base address (SDnBDPU - SDnBDPL). */660 uint64_t u64BDLBase;661 /** Cyclic Buffer Length (SDnCBL).662 * Represents the size of the ring buffer. */663 uint32_t u32CBL;664 /** Format (SDnFMT). */665 uint16_t u16FMT;666 /** FIFO Size (FIFOS).667 * Maximum number of bytes that may have been DMA'd into668 * memory but not yet transmitted on the link. */669 uint16_t u16FIFOS;670 /** FIFO Watermark. */671 uint16_t u16FIFOW;672 /** Last Valid Index (SDnLVI). */673 uint16_t u16LVI;674 uint16_t Padding1[2];675 /** Pointer to the HDA state this stream is attached to. */676 R3PTRTYPE(PHDASTATE) pHDAState;677 /** Pointer to HDA sink this stream is attached to. */678 R3PTRTYPE(PHDAMIXERSINK) pMixSink;679 /** Internal state of this stream. */680 HDASTREAMSTATE State;681 #ifdef DEBUG682 /** Debug information. */683 HDASTREAMDBGINFO Dbg;684 #endif685 } HDASTREAM, *PHDASTREAM;686 687 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO688 /**689 * Structure for keeping a HDA stream thread context.690 */691 typedef struct HDASTREAMTHREADCTX692 {693 PHDASTATE pThis;694 PHDASTREAM pStream;695 } HDASTREAMTHREADCTX, *PHDASTREAMTHREADCTX;696 #endif697 698 /**699 * Structure for mapping a stream tag to an HDA stream.700 */701 typedef struct HDATAG702 {703 /** Own stream tag. */704 uint8_t uTag;705 uint8_t Padding[7];706 /** Pointer to associated stream. */707 R3PTRTYPE(PHDASTREAM) pStream;708 } HDATAG, *PHDATAG;709 118 710 119 /** … … 792 201 } HDADRIVER; 793 202 794 #ifdef DEBUG795 /** @todo Make STAM values out of this? */796 typedef struct HDASTATEDBGINFO797 {798 /** Timestamp (in ns) of the last timer callback (hdaTimer).799 * Used to calculate the time actually elapsed between two timer callbacks. */800 uint64_t tsTimerLastCalledNs;801 /** IRQ debugging information. */802 struct803 {804 /** Timestamp (in ns) of last processed (asserted / deasserted) IRQ. */805 uint64_t tsProcessedLastNs;806 /** Timestamp (in ns) of last asserted IRQ. */807 uint64_t tsAssertedNs;808 /** How many IRQs have been asserted already. */809 uint64_t cAsserted;810 /** Accumulated elapsed time (in ns) of all IRQ being asserted. */811 uint64_t tsAssertedTotalNs;812 /** Timestamp (in ns) of last deasserted IRQ. */813 uint64_t tsDeassertedNs;814 /** How many IRQs have been deasserted already. */815 uint64_t cDeasserted;816 /** Accumulated elapsed time (in ns) of all IRQ being deasserted. */817 uint64_t tsDeassertedTotalNs;818 } IRQ;819 } HDASTATEDBGINFO, *PHDASTATEDBGINFO;820 #endif821 822 /**823 * ICH Intel HD Audio Controller state.824 */825 typedef struct HDASTATE826 {827 /** The PCI device structure. */828 PDMPCIDEV PciDev;829 /** R3 Pointer to the device instance. */830 PPDMDEVINSR3 pDevInsR3;831 /** R0 Pointer to the device instance. */832 PPDMDEVINSR0 pDevInsR0;833 /** R0 Pointer to the device instance. */834 PPDMDEVINSRC pDevInsRC;835 /** Padding for alignment. */836 uint32_t u32Padding;837 /** The base interface for LUN\#0. */838 PDMIBASE IBase;839 RTGCPHYS MMIOBaseAddr;840 /** The HDA's register set. */841 uint32_t au32Regs[HDA_NUM_REGS];842 /** Internal stream states. */843 HDASTREAM aStreams[HDA_MAX_STREAMS];844 /** Mapping table between stream tags and stream states. */845 HDATAG aTags[HDA_MAX_TAGS];846 /** CORB buffer base address. */847 uint64_t u64CORBBase;848 /** RIRB buffer base address. */849 uint64_t u64RIRBBase;850 /** DMA base address.851 * Made out of DPLBASE + DPUBASE (3.3.32 + 3.3.33). */852 uint64_t u64DPBase;853 /** Pointer to CORB buffer. */854 R3PTRTYPE(uint32_t *) pu32CorbBuf;855 /** Size in bytes of CORB buffer. */856 uint32_t cbCorbBuf;857 /** Padding for alignment. */858 uint32_t u32Padding1;859 /** Pointer to RIRB buffer. */860 R3PTRTYPE(uint64_t *) pu64RirbBuf;861 /** Size in bytes of RIRB buffer. */862 uint32_t cbRirbBuf;863 /** DMA position buffer enable bit. */864 bool fDMAPosition;865 /** Flag whether the R0 part is enabled. */866 bool fR0Enabled;867 /** Flag whether the RC part is enabled. */868 bool fRCEnabled;869 /** Number of active (running) SDn streams. */870 uint8_t cStreamsActive;871 #ifndef VBOX_WITH_AUDIO_HDA_CALLBACKS872 /** The timer for pumping data thru the attached LUN drivers. */873 PTMTIMERR3 pTimer;874 /** Flag indicating whether the timer is active or not. */875 bool fTimerActive;876 uint8_t u8Padding1[7];877 /** Timer ticks per Hz. */878 uint64_t cTimerTicks;879 /** The current timer expire time (in timer ticks). */880 uint64_t tsTimerExpire;881 #endif882 #ifdef VBOX_WITH_STATISTICS883 # ifndef VBOX_WITH_AUDIO_HDA_CALLBACKS884 STAMPROFILE StatTimer;885 # endif886 STAMPROFILE StatIn;887 STAMPROFILE StatOut;888 STAMCOUNTER StatBytesRead;889 STAMCOUNTER StatBytesWritten;890 #endif891 /** Pointer to HDA codec to use. */892 R3PTRTYPE(PHDACODEC) pCodec;893 /** List of associated LUN drivers (HDADRIVER). */894 RTLISTANCHORR3 lstDrv;895 /** The device' software mixer. */896 R3PTRTYPE(PAUDIOMIXER) pMixer;897 /** HDA sink for (front) output. */898 HDAMIXERSINK SinkFront;899 #ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND900 /** HDA sink for center / LFE output. */901 HDAMIXERSINK SinkCenterLFE;902 /** HDA sink for rear output. */903 HDAMIXERSINK SinkRear;904 #endif905 /** HDA mixer sink for line input. */906 HDAMIXERSINK SinkLineIn;907 #ifdef VBOX_WITH_AUDIO_HDA_MIC_IN908 /** Audio mixer sink for microphone input. */909 HDAMIXERSINK SinkMicIn;910 #endif911 /** Last updated WALCLK counter. */912 uint64_t u64WalClk;913 /** Response Interrupt Count (RINTCNT). */914 uint8_t u8RespIntCnt;915 /** Current IRQ level. */916 uint8_t u8IRQL;917 /** Padding for alignment. */918 uint8_t au8Padding2[6];919 #ifdef DEBUG920 HDASTATEDBGINFO Dbg;921 #endif922 } HDASTATE;923 /** Pointer to the ICH Intel HD Audio Controller state. */924 typedef HDASTATE *PHDASTATE;925 926 #ifdef VBOX_WITH_AUDIO_HDA_CALLBACKS927 typedef struct HDACALLBACKCTX928 {929 PHDASTATE pThis;930 PHDADRIVER pDriver;931 } HDACALLBACKCTX, *PHDACALLBACKCTX;932 #endif933 934 203 935 204 /********************************************************************************************************************************* … … 980 249 /** @} */ 981 250 982 /** @name {IOB}SDn utility functions.983 * @{984 */985 #ifdef IN_RING3986 static int hdaSDFMTToPCMProps(uint32_t u32SDFMT, PPDMAUDIOPCMPROPS pProps);987 #endif988 /** @} */989 990 251 /** @name Generic register read/write functions. 991 252 * @{ … … 1001 262 static int hdaRegReadU8(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value); 1002 263 static int hdaRegWriteU8(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value); 1003 /** @} */1004 1005 /** @name Stream functions.1006 * @{1007 */1008 #ifdef IN_RING31009 static void hdaStreamDestroy(PHDASTREAM pStream);1010 static int hdaStreamEnable(PHDASTREAM pStream, bool fEnable);1011 static uint32_t hdaStreamGetUsed(PHDASTREAM pStream);1012 static uint32_t hdaStreamGetFree(PHDASTREAM pStream);1013 static int hdaStreamTransfer(PHDASTREAM pStream, uint32_t cbToProcessMax);1014 DECLINLINE(uint32_t) hdaStreamUpdateLPIB(PHDASTREAM pStream, uint32_t u32LPIB);1015 static void hdaStreamLock(PHDASTREAM pStream);1016 static void hdaStreamUnlock(PHDASTREAM pStream);1017 static int hdaStreamRead(PHDASTREAM pStream, uint32_t cbToRead, uint32_t *pcbRead);1018 static int hdaStreamWrite(PHDASTREAM pStream, uint32_t cbToWrite, uint32_t *pcbWritten);1019 static void hdaStreamUpdate(PHDASTREAM pStream, bool fAsync);1020 # ifdef HDA_USE_DMA_ACCESS_HANDLER1021 static bool hdaStreamRegisterDMAHandlers(PHDASTREAM pStream);1022 static void hdaStreamUnregisterDMAHandlers(PHDASTREAM pStream);1023 # endif1024 #endif /* IN_RING3 */1025 /** @} */1026 1027 /** @name Async I/O stream functions.1028 * @{1029 */1030 #ifdef IN_RING31031 # ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO1032 static DECLCALLBACK(int) hdaStreamAsyncIOThread(RTTHREAD hThreadSelf, void *pvUser);1033 static int hdaStreamAsyncIOCreate(PHDASTREAM pStream);1034 static int hdaStreamAsyncIODestroy(PHDASTREAM pStream);1035 static int hdaStreamAsyncIONotify(PHDASTREAM pStream);1036 static void hdaStreamAsyncIOLock(PHDASTREAM pStream);1037 static void hdaStreamAsyncIOUnlock(PHDASTREAM pStream);1038 static void hdaStreamAsyncIOEnable(PHDASTREAM pStream, bool fEnable);1039 # endif1040 #endif1041 264 /** @} */ 1042 265 … … 1052 275 /** @} */ 1053 276 1054 /** @name BDLE (Buffer Descriptor List Entry) functions.1055 * @{1056 */1057 #ifdef IN_RING31058 static int hdaBDLEFetch(PHDASTATE pThis, PHDABDLE pBDLE, uint64_t u64BaseDMA, uint16_t u16Entry);1059 # ifdef LOG_ENABLED1060 static void hdaBDLEDumpAll(PHDASTATE pThis, uint64_t u64BaseDMA, uint16_t cBDLE);1061 # endif1062 #endif /* IN_RING3 */1063 /** @} */1064 1065 277 /** @name Timer functions. 1066 278 * @{ … … 1073 285 /** @} */ 1074 286 1075 /** @name Wall clock (WALCLK) functions.1076 * @{1077 */1078 uint64_t hdaWalClkGetCurrent(PHDASTATE pThis);1079 #ifdef IN_RING31080 bool hdaWalClkSet(PHDASTATE pThis, uint64_t u64WalClk, bool fForce);1081 #endif1082 /** @} */1083 287 1084 288 /********************************************************************************************************************************* 1085 289 * Global Variables * 1086 290 *********************************************************************************************************************************/ 1087 1088 /** Offset of the SD0 register map. */1089 #define HDA_REG_DESC_SD0_BASE 0x801090 1091 /** Turn a short global register name into an memory index and a stringized name. */1092 #define HDA_REG_IDX(abbrev) HDA_MEM_IND_NAME(abbrev), #abbrev1093 1094 /** Turns a short stream register name into an memory index and a stringized name. */1095 #define HDA_REG_IDX_STRM(reg, suff) HDA_MEM_IND_NAME(reg ## suff), #reg #suff1096 1097 /** Same as above for a register *not* stored in memory. */1098 #define HDA_REG_IDX_NOMEM(abbrev) 0, #abbrev1099 291 1100 292 /** No register description (RD) flags defined. */ … … 1134 326 1135 327 /* See 302349 p 6.2. */ 1136 static const struct HDAREGDESC 1137 { 1138 /** Register offset in the register space. */ 1139 uint32_t offset; 1140 /** Size in bytes. Registers of size > 4 are in fact tables. */ 1141 uint32_t size; 1142 /** Readable bits. */ 1143 uint32_t readable; 1144 /** Writable bits. */ 1145 uint32_t writable; 1146 /** Register descriptor (RD) flags of type HDA_RD_FLAG_. 1147 * These are used to specify the handling (read/write) 1148 * policy of the register. */ 1149 uint32_t fFlags; 1150 /** Read callback. */ 1151 int (*pfnRead)(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value); 1152 /** Write callback. */ 1153 int (*pfnWrite)(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value); 1154 /** Index into the register storage array. */ 1155 uint32_t mem_idx; 1156 /** Abbreviated name. */ 1157 const char *abbrev; 1158 /** Descripton. */ 1159 const char *desc; 1160 } g_aHdaRegMap[HDA_NUM_REGS] = 1161 328 const HDAREGDESC g_aHdaRegMap[HDA_NUM_REGS] = 1162 329 { 1163 330 /* offset size read mask write mask flags read callback write callback index + abbrev */ … … 1209 376 }; 1210 377 1211 /** 1212 * HDA register aliases (HDA spec 3.3.45). 1213 * @remarks Sorted by offReg. 1214 */ 1215 static const struct 1216 { 1217 /** The alias register offset. */ 1218 uint32_t offReg; 1219 /** The register index. */ 1220 int idxAlias; 1221 } g_aHdaRegAliases[] = 378 const HDAREGALIAS g_aHdaRegAliases[] = 1222 379 { 1223 380 { 0x2084, HDA_REG_SD0LPIB }, … … 1228 385 { 0x2124, HDA_REG_SD5LPIB }, 1229 386 { 0x2144, HDA_REG_SD6LPIB }, 1230 { 0x2164, HDA_REG_SD7LPIB } ,387 { 0x2164, HDA_REG_SD7LPIB } 1231 388 }; 1232 389 … … 1321 478 } 1322 479 1323 /**1324 * Updates an HDA stream's current read or write buffer position (depending on the stream type) by1325 * updating its associated LPIB register and DMA position buffer (if enabled).1326 *1327 * @returns Set LPIB value.1328 * @param pStream HDA stream to update read / write position for.1329 * @param u32LPIB New LPIB (position) value to set.1330 */1331 DECLINLINE(uint32_t) hdaStreamUpdateLPIB(PHDASTREAM pStream, uint32_t u32LPIB)1332 {1333 AssertPtrReturn(pStream, 0);1334 1335 AssertMsg(u32LPIB <= pStream->u32CBL,1336 ("[SD%RU8] New LPIB (%RU32) exceeds CBL (%RU32)\n", pStream->u8SD, u32LPIB, pStream->u32CBL));1337 1338 const PHDASTATE pThis = pStream->pHDAState;1339 1340 u32LPIB = RT_MIN(u32LPIB, pStream->u32CBL);1341 1342 LogFlowFunc(("[SD%RU8]: LPIB=%RU32 (DMA Position Buffer Enabled: %RTbool)\n",1343 pStream->u8SD, u32LPIB, pThis->fDMAPosition));1344 1345 /* Update LPIB in any case. */1346 HDA_STREAM_REG(pThis, LPIB, pStream->u8SD) = u32LPIB;1347 1348 /* Do we need to tell the current DMA position? */1349 if (pThis->fDMAPosition)1350 {1351 int rc2 = PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns),1352 pThis->u64DPBase + (pStream->u8SD * 2 * sizeof(uint32_t)),1353 (void *)&u32LPIB, sizeof(uint32_t));1354 AssertRC(rc2);1355 }1356 1357 return u32LPIB;1358 }1359 1360 1361 /**1362 * Locks an HDA stream for serialized access.1363 *1364 * @returns IPRT status code.1365 * @param pStream HDA stream to lock.1366 */1367 static void hdaStreamLock(PHDASTREAM pStream)1368 {1369 AssertPtrReturnVoid(pStream);1370 int rc2 = RTCritSectEnter(&pStream->State.CritSect);1371 AssertRC(rc2);1372 }1373 1374 1375 /**1376 * Unlocks a formerly locked HDA stream.1377 *1378 * @returns IPRT status code.1379 * @param pStream HDA stream to unlock.1380 */1381 static void hdaStreamUnlock(PHDASTREAM pStream)1382 {1383 AssertPtrReturnVoid(pStream);1384 int rc2 = RTCritSectLeave(&pStream->State.CritSect);1385 AssertRC(rc2);1386 }1387 1388 1389 /**1390 * Returns the HDA stream of specified stream descriptor number.1391 *1392 * @return Pointer to HDA stream, or NULL if none found.1393 */1394 DECLINLINE(PHDASTREAM) hdaStreamGetFromSD(PHDASTATE pThis, uint8_t uSD)1395 {1396 AssertPtrReturn(pThis, NULL);1397 AssertReturn(uSD < HDA_MAX_STREAMS, NULL);1398 1399 if (uSD >= HDA_MAX_STREAMS)1400 {1401 AssertMsgFailed(("Invalid / non-handled SD%RU8\n", uSD));1402 return NULL;1403 }1404 1405 return &pThis->aStreams[uSD];1406 }1407 1408 1409 /**1410 * Returns the HDA stream of specified HDA sink.1411 *1412 * @return Pointer to HDA stream, or NULL if none found.1413 */1414 DECLINLINE(PHDASTREAM) hdaSinkGetStream(PHDASTATE pThis, PHDAMIXERSINK pSink)1415 {1416 AssertPtrReturn(pThis, NULL);1417 AssertPtrReturn(pSink, NULL);1418 1419 /** @todo Do something with the channel mapping here? */1420 return hdaStreamGetFromSD(pThis, pSink->uSD);1421 }1422 1423 1424 /**1425 * Returns the audio direction of a specified stream descriptor.1426 *1427 * The register layout specifies that input streams (SDI) come first,1428 * followed by the output streams (SDO). So every stream ID below HDA_MAX_SDI1429 * is an input stream, whereas everything >= HDA_MAX_SDI is an output stream.1430 *1431 * Note: SDnFMT register does not provide that information, so we have to judge1432 * for ourselves.1433 *1434 * @return Audio direction.1435 */1436 DECLINLINE(PDMAUDIODIR) hdaGetDirFromSD(uint8_t uSD)1437 {1438 AssertReturn(uSD < HDA_MAX_STREAMS, PDMAUDIODIR_UNKNOWN);1439 1440 if (uSD < HDA_MAX_SDI)1441 return PDMAUDIODIR_IN;1442 1443 return PDMAUDIODIR_OUT;1444 }1445 #endif /* IN_RING3 */1446 1447 static uint32_t hdaGetINTSTS(PHDASTATE pThis)1448 {1449 uint32_t intSts = 0;1450 1451 /* Check controller interrupts (RIRB, STATEST). */1452 if ( (HDA_REG(pThis, RIRBSTS) & HDA_REG(pThis, RIRBCTL) & (HDA_RIRBCTL_ROIC | HDA_RIRBCTL_RINTCTL))1453 /* SDIN State Change Status Flags (SCSF). */1454 || (HDA_REG(pThis, STATESTS) & HDA_STATESTS_SCSF_MASK))1455 {1456 intSts |= HDA_INTSTS_CIS; /* Set the Controller Interrupt Status (CIS). */1457 }1458 1459 if (HDA_REG(pThis, STATESTS) & HDA_REG(pThis, WAKEEN))1460 {1461 intSts |= HDA_INTSTS_CIS; /* Touch Controller Interrupt Status (CIS). */1462 }1463 1464 /* For each stream, check if any interrupt status bit is set and enabled. */1465 for (uint8_t iStrm = 0; iStrm < HDA_MAX_STREAMS; ++iStrm)1466 {1467 if (HDA_STREAM_REG(pThis, STS, iStrm) & HDA_STREAM_REG(pThis, CTL, iStrm) & (HDA_SDCTL_DEIE | HDA_SDCTL_FEIE | HDA_SDCTL_IOCE))1468 {1469 Log3Func(("[SD%d] interrupt status set\n", iStrm));1470 intSts |= RT_BIT(iStrm);1471 }1472 }1473 1474 if (intSts)1475 intSts |= HDA_INTSTS_GIS; /* Set the Global Interrupt Status (GIS). */1476 1477 Log3Func(("-> 0x%x\n", intSts));1478 1479 return intSts;1480 }1481 1482 #ifndef DEBUG1483 /**1484 * Processes (de/asserts) the interrupt according to the HDA's current state.1485 *1486 * @returns IPRT status code.1487 * @param pThis HDA state.1488 */1489 static int hdaProcessInterrupt(PHDASTATE pThis)1490 #else1491 /**1492 * Processes (de/asserts) the interrupt according to the HDA's current state.1493 * Debug version.1494 *1495 * @returns IPRT status code.1496 * @param pThis HDA state.1497 * @param pszSource Caller information.1498 */1499 static int hdaProcessInterrupt(PHDASTATE pThis, const char *pszSource)1500 #endif1501 {1502 HDA_REG(pThis, INTSTS) = hdaGetINTSTS(pThis);1503 1504 Log3Func(("IRQL=%RU8\n", pThis->u8IRQL));1505 1506 /* NB: It is possible to have GIS set even when CIE/SIEn are all zero; the GIS bit does1507 * not control the interrupt signal. See Figure 4 on page 54 of the HDA 1.0a spec.1508 */1509 1510 /* If global interrupt enable (GIE) is set, check if any enabled interrupts are set. */1511 if ( (HDA_REG(pThis, INTCTL) & HDA_INTCTL_GIE)1512 && (HDA_REG(pThis, INTSTS) & HDA_REG(pThis, INTCTL) & (HDA_INTCTL_CIE | HDA_STRMINT_MASK)))1513 {1514 if (!pThis->u8IRQL)1515 {1516 #ifdef DEBUG1517 if (!pThis->Dbg.IRQ.tsProcessedLastNs)1518 pThis->Dbg.IRQ.tsProcessedLastNs = RTTimeNanoTS();1519 1520 const uint64_t tsLastElapsedNs = RTTimeNanoTS() - pThis->Dbg.IRQ.tsProcessedLastNs;1521 1522 if (!pThis->Dbg.IRQ.tsAssertedNs)1523 pThis->Dbg.IRQ.tsAssertedNs = RTTimeNanoTS();1524 1525 const uint64_t tsAssertedElapsedNs = RTTimeNanoTS() - pThis->Dbg.IRQ.tsAssertedNs;1526 1527 pThis->Dbg.IRQ.cAsserted++;1528 pThis->Dbg.IRQ.tsAssertedTotalNs += tsAssertedElapsedNs;1529 1530 const uint64_t avgAssertedUs = (pThis->Dbg.IRQ.tsAssertedTotalNs / pThis->Dbg.IRQ.cAsserted) / 1000;1531 1532 if (avgAssertedUs > (1000 / HDA_TIMER_HZ) /* ms */ * 1000) /* Exceeds time slot? */1533 Log3Func(("Asserted (%s): %zuus elapsed (%zuus on average) -- %zuus alternation delay\n",1534 pszSource, tsAssertedElapsedNs / 1000,1535 avgAssertedUs,1536 (pThis->Dbg.IRQ.tsDeassertedNs - pThis->Dbg.IRQ.tsAssertedNs) / 1000));1537 #endif1538 Log3Func(("Asserted (%s): %RU64us between alternation (WALCLK=%RU64)\n",1539 pszSource, tsLastElapsedNs / 1000, pThis->u64WalClk));1540 1541 PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0, 1 /* Assert */);1542 pThis->u8IRQL = 1;1543 1544 #ifdef DEBUG1545 pThis->Dbg.IRQ.tsAssertedNs = RTTimeNanoTS();1546 pThis->Dbg.IRQ.tsProcessedLastNs = pThis->Dbg.IRQ.tsAssertedNs;1547 #endif1548 }1549 }1550 else1551 {1552 if (pThis->u8IRQL)1553 {1554 #ifdef DEBUG1555 if (!pThis->Dbg.IRQ.tsProcessedLastNs)1556 pThis->Dbg.IRQ.tsProcessedLastNs = RTTimeNanoTS();1557 1558 const uint64_t tsLastElapsedNs = RTTimeNanoTS() - pThis->Dbg.IRQ.tsProcessedLastNs;1559 1560 if (!pThis->Dbg.IRQ.tsDeassertedNs)1561 pThis->Dbg.IRQ.tsDeassertedNs = RTTimeNanoTS();1562 1563 const uint64_t tsDeassertedElapsedNs = RTTimeNanoTS() - pThis->Dbg.IRQ.tsDeassertedNs;1564 1565 pThis->Dbg.IRQ.cDeasserted++;1566 pThis->Dbg.IRQ.tsDeassertedTotalNs += tsDeassertedElapsedNs;1567 1568 const uint64_t avgDeassertedUs = (pThis->Dbg.IRQ.tsDeassertedTotalNs / pThis->Dbg.IRQ.cDeasserted) / 1000;1569 1570 if (avgDeassertedUs > (1000 / HDA_TIMER_HZ) /* ms */ * 1000) /* Exceeds time slot? */1571 Log3Func(("Deasserted (%s): %zuus elapsed (%zuus on average)\n",1572 pszSource, tsDeassertedElapsedNs / 1000, avgDeassertedUs));1573 1574 Log3Func(("Deasserted (%s): %RU64us between alternation (WALCLK=%RU64)\n",1575 pszSource, tsLastElapsedNs / 1000, pThis->u64WalClk));1576 #endif1577 PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0, 0 /* Deassert */);1578 pThis->u8IRQL = 0;1579 1580 #ifdef DEBUG1581 pThis->Dbg.IRQ.tsDeassertedNs = RTTimeNanoTS();1582 pThis->Dbg.IRQ.tsProcessedLastNs = pThis->Dbg.IRQ.tsDeassertedNs;1583 #endif1584 }1585 }1586 1587 return VINF_SUCCESS;1588 }1589 1590 #ifdef IN_RING31591 480 /** 1592 481 * Reschedules pending interrupts for all audio streams which have complete … … 1878 767 return rc; 1879 768 } 1880 1881 /**1882 * Creates an HDA stream.1883 *1884 * @returns IPRT status code.1885 * @param pStream HDA stream to create.1886 * @param pThis HDA state to assign the HDA stream to.1887 */1888 static int hdaStreamCreate(PHDASTREAM pStream, PHDASTATE pThis)1889 {1890 RT_NOREF(pThis);1891 AssertPtrReturn(pStream, VERR_INVALID_POINTER);1892 1893 pStream->u8SD = UINT8_MAX;1894 pStream->pMixSink = NULL;1895 pStream->pHDAState = pThis;1896 1897 pStream->State.fInReset = false;1898 #ifdef HDA_USE_DMA_ACCESS_HANDLER1899 RTListInit(&pStream->State.lstDMAHandlers);1900 #endif1901 1902 int rc = RTCircBufCreate(&pStream->State.pCircBuf, _64K); /** @todo Make this configurable. */1903 if (RT_SUCCESS(rc))1904 {1905 rc = hdaStreamPeriodCreate(&pStream->State.Period);1906 if (RT_SUCCESS(rc))1907 rc = RTCritSectInit(&pStream->State.CritSect);1908 }1909 1910 #ifdef DEBUG1911 int rc2 = RTCritSectInit(&pStream->Dbg.CritSect);1912 AssertRC(rc2);1913 #endif1914 1915 return rc;1916 }1917 1918 /**1919 * Destroys an HDA stream.1920 *1921 * @param pStream HDA stream to destroy.1922 */1923 static void hdaStreamDestroy(PHDASTREAM pStream)1924 {1925 AssertPtrReturnVoid(pStream);1926 1927 LogFlowFunc(("[SD%RU8]: Destroying ...\n", pStream->u8SD));1928 1929 hdaStreamMapDestroy(&pStream->State.Mapping);1930 1931 int rc2;1932 1933 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO1934 rc2 = hdaStreamAsyncIODestroy(pStream);1935 AssertRC(rc2);1936 #else1937 RT_NOREF(pThis);1938 #endif1939 1940 rc2 = RTCritSectDelete(&pStream->State.CritSect);1941 AssertRC(rc2);1942 1943 if (pStream->State.pCircBuf)1944 {1945 RTCircBufDestroy(pStream->State.pCircBuf);1946 pStream->State.pCircBuf = NULL;1947 }1948 1949 hdaStreamPeriodDestroy(&pStream->State.Period);1950 1951 #ifdef DEBUG1952 rc2 = RTCritSectDelete(&pStream->Dbg.CritSect);1953 AssertRC(rc2);1954 #endif1955 1956 LogFlowFuncLeave();1957 }1958 1959 /**1960 * Initializes an HDA stream.1961 *1962 * @returns IPRT status code.1963 * @param pStream HDA stream to initialize.1964 * @param uSD SD (stream descriptor) number to assign the HDA stream to.1965 */1966 static int hdaStreamInit(PHDASTREAM pStream, uint8_t uSD)1967 {1968 AssertPtrReturn(pStream, VERR_INVALID_POINTER);1969 1970 PHDASTATE pThis = pStream->pHDAState;1971 AssertPtr(pThis);1972 1973 pStream->u8SD = uSD;1974 pStream->u64BDLBase = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, pStream->u8SD),1975 HDA_STREAM_REG(pThis, BDPU, pStream->u8SD));1976 pStream->u16LVI = HDA_STREAM_REG(pThis, LVI, pStream->u8SD);1977 pStream->u32CBL = HDA_STREAM_REG(pThis, CBL, pStream->u8SD);1978 pStream->u16FIFOS = HDA_STREAM_REG(pThis, FIFOS, pStream->u8SD) + 1;1979 1980 /* Make sure to also update the stream's DMA counter (based on its current LPIB value). */1981 hdaStreamUpdateLPIB(pStream, HDA_STREAM_REG(pThis, LPIB, pStream->u8SD));1982 1983 PPDMAUDIOSTREAMCFG pCfg = &pStream->State.strmCfg;1984 1985 int rc = hdaSDFMTToPCMProps(HDA_STREAM_REG(pThis, FMT, uSD), &pCfg->Props);1986 if (RT_FAILURE(rc))1987 {1988 LogRel(("HDA: Warning: Format 0x%x for stream #%RU8 not supported\n", HDA_STREAM_REG(pThis, FMT, uSD), uSD));1989 return rc;1990 }1991 1992 /* Set the stream's direction. */1993 pCfg->enmDir = hdaGetDirFromSD(pStream->u8SD);1994 1995 /* The the stream's name, based on the direction. */1996 switch (pCfg->enmDir)1997 {1998 case PDMAUDIODIR_IN:1999 # ifdef VBOX_WITH_AUDIO_HDA_MIC_IN2000 # error "Implement me!"2001 # else2002 pCfg->DestSource.Source = PDMAUDIORECSOURCE_LINE;2003 pCfg->enmLayout = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED;2004 RTStrCopy(pCfg->szName, sizeof(pCfg->szName), "Line In");2005 # endif2006 break;2007 2008 case PDMAUDIODIR_OUT:2009 /* Destination(s) will be set in hdaAddStreamOut(),2010 * based on the channels / stream layout. */2011 break;2012 2013 default:2014 rc = VERR_NOT_SUPPORTED;2015 break;2016 }2017 2018 /*2019 * Initialize the stream mapping in any case, regardless if2020 * we support surround audio or not. This is needed to handle2021 * the supported channels within a single audio stream, e.g. mono/stereo.2022 *2023 * In other words, the stream mapping *always* knows the real2024 * number of channels in a single audio stream.2025 */2026 rc = hdaStreamMapInit(&pStream->State.Mapping, &pCfg->Props);2027 AssertRCReturn(rc, rc);2028 2029 LogFunc(("[SD%RU8] DMA @ 0x%x (%RU32 bytes), LVI=%RU16, FIFOS=%RU16, rc=%Rrc\n",2030 pStream->u8SD, pStream->u64BDLBase, pStream->u32CBL, pStream->u16LVI, pStream->u16FIFOS, rc));2031 2032 return rc;2033 }2034 2035 /**2036 * Resets an HDA stream.2037 *2038 * @param pThis HDA state.2039 * @param pStream HDA stream to reset.2040 * @param uSD Stream descriptor (SD) number to use for this stream.2041 */2042 static void hdaStreamReset(PHDASTATE pThis, PHDASTREAM pStream, uint8_t uSD)2043 {2044 AssertPtrReturnVoid(pThis);2045 AssertPtrReturnVoid(pStream);2046 AssertReturnVoid(uSD < HDA_MAX_STREAMS);2047 2048 # ifdef VBOX_STRICT2049 AssertReleaseMsg(!RT_BOOL(HDA_STREAM_REG(pThis, CTL, uSD) & HDA_SDCTL_RUN),2050 ("[SD%RU8] Cannot reset stream while in running state\n", uSD));2051 # endif2052 2053 LogFunc(("[SD%RU8]: Reset\n", uSD));2054 2055 /*2056 * Set reset state.2057 */2058 Assert(ASMAtomicReadBool(&pStream->State.fInReset) == false); /* No nested calls. */2059 ASMAtomicXchgBool(&pStream->State.fInReset, true);2060 2061 /*2062 * Second, initialize the registers.2063 */2064 HDA_STREAM_REG(pThis, STS, uSD) = HDA_SDSTS_FIFORDY;2065 /* According to the ICH6 datasheet, 0x40000 is the default value for stream descriptor register 23:202066 * bits are reserved for stream number 18.2.33, resets SDnCTL except SRST bit. */2067 HDA_STREAM_REG(pThis, CTL, uSD) = 0x40000 | (HDA_STREAM_REG(pThis, CTL, uSD) & HDA_SDCTL_SRST);2068 /* ICH6 defines default values (120 bytes for input and 192 bytes for output descriptors) of FIFO size. 18.2.39. */2069 HDA_STREAM_REG(pThis, FIFOS, uSD) = hdaGetDirFromSD(uSD) == PDMAUDIODIR_IN ? HDA_SDIFIFO_120B : HDA_SDOFIFO_192B;2070 /* See 18.2.38: Always defaults to 0x4 (32 bytes). */2071 HDA_STREAM_REG(pThis, FIFOW, uSD) = HDA_SDFIFOW_32B;2072 HDA_STREAM_REG(pThis, LPIB, uSD) = 0;2073 HDA_STREAM_REG(pThis, CBL, uSD) = 0;2074 HDA_STREAM_REG(pThis, LVI, uSD) = 0;2075 HDA_STREAM_REG(pThis, FMT, uSD) = 0;2076 HDA_STREAM_REG(pThis, BDPU, uSD) = 0;2077 HDA_STREAM_REG(pThis, BDPL, uSD) = 0;2078 2079 #ifdef HDA_USE_DMA_ACCESS_HANDLER2080 hdaStreamUnregisterDMAHandlers(pThis, pStream);2081 #endif2082 2083 RT_ZERO(pStream->State.BDLE);2084 pStream->State.uCurBDLE = 0;2085 2086 if (pStream->State.pCircBuf)2087 RTCircBufReset(pStream->State.pCircBuf);2088 2089 /* Reset stream map. */2090 hdaStreamMapReset(&pStream->State.Mapping);2091 2092 /* (Re-)initialize the stream with current values. */2093 int rc2 = hdaStreamInit(pStream, uSD);2094 AssertRC(rc2);2095 2096 /* Reset the stream's period. */2097 hdaStreamPeriodReset(&pStream->State.Period);2098 2099 #ifdef DEBUG2100 pStream->Dbg.cReadsTotal = 0;2101 pStream->Dbg.cbReadTotal = 0;2102 pStream->Dbg.tsLastReadNs = 0;2103 pStream->Dbg.cWritesTotal = 0;2104 pStream->Dbg.cbWrittenTotal = 0;2105 pStream->Dbg.cWritesHz = 0;2106 pStream->Dbg.cbWrittenHz = 0;2107 pStream->Dbg.tsWriteSlotBegin = 0;2108 #endif2109 2110 /* Report that we're done resetting this stream. */2111 HDA_STREAM_REG(pThis, CTL, uSD) = 0;2112 2113 LogFunc(("[SD%RU8] Reset\n", uSD));2114 2115 /* Exit reset mode. */2116 ASMAtomicXchgBool(&pStream->State.fInReset, false);2117 }2118 2119 /**2120 * Enables or disables an HDA audio stream.2121 *2122 * @returns IPRT status code.2123 * @param pStream HDA stream to enable or disable.2124 * @param fEnable Whether to enable or disble the stream.2125 */2126 static int hdaStreamEnable(PHDASTREAM pStream, bool fEnable)2127 {2128 AssertPtrReturn(pStream, VERR_INVALID_POINTER);2129 2130 LogFunc(("[SD%RU8]: fEnable=%RTbool, pMixSink=%p\n", pStream->u8SD, fEnable, pStream->pMixSink));2131 2132 int rc = VINF_SUCCESS;2133 2134 if (pStream->pMixSink) /* Stream attached to a sink? */2135 {2136 AUDMIXSINKCMD enmCmd = fEnable2137 ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE;2138 2139 /* First, enable or disable the stream and the stream's sink, if any. */2140 if (pStream->pMixSink->pMixSink)2141 rc = AudioMixerSinkCtl(pStream->pMixSink->pMixSink, enmCmd);2142 }2143 2144 LogFunc(("[SD%RU8] rc=%Rrc\n", pStream->u8SD, rc));2145 return rc;2146 }2147 769 #endif /* IN_RING3 */ 2148 770 … … 2278 900 *pu32Value = u32LPIB; 2279 901 return VINF_SUCCESS; 2280 }2281 2282 /**2283 * Retrieves the currently set value for the wall clock.2284 *2285 * @return IPRT status code.2286 * @return Currently set wall clock value.2287 * @param pThis HDA state.2288 *2289 * @remark Operation is atomic.2290 */2291 uint64_t hdaWalClkGetCurrent(PHDASTATE pThis)2292 {2293 return ASMAtomicReadU64(&pThis->u64WalClk);2294 902 } 2295 903 … … 2329 937 2330 938 return u64WalClkNew; 2331 }2332 2333 /**2334 * Sets the actual WALCLK register to the specified wall clock value.2335 * The specified wall clock value only will be set (unless fForce is set to true) if all2336 * handled HDA streams have passed (in time) that value. This guarantees that the WALCLK2337 * register stays in sync with all handled HDA streams.2338 *2339 * @return true if the WALCLK register has been updated, false if not.2340 * @param pThis HDA state.2341 * @param u64WalClk Wall clock value to set WALCLK register to.2342 * @param fForce Whether to force setting the wall clock value or not.2343 */2344 bool hdaWalClkSet(PHDASTATE pThis, uint64_t u64WalClk, bool fForce)2345 {2346 const bool fFrontPassed = hdaStreamPeriodHasPassedAbsWalClk (&hdaSinkGetStream(pThis, &pThis->SinkFront)->State.Period,2347 u64WalClk);2348 const uint64_t u64FrontAbsWalClk = hdaStreamPeriodGetAbsElapsedWalClk(&hdaSinkGetStream(pThis, &pThis->SinkFront)->State.Period);2349 #ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND2350 # error "Implement me!"2351 #endif2352 2353 const bool fLineInPassed = hdaStreamPeriodHasPassedAbsWalClk (&hdaSinkGetStream(pThis, &pThis->SinkLineIn)->State.Period, u64WalClk);2354 const uint64_t u64LineInAbsWalClk = hdaStreamPeriodGetAbsElapsedWalClk(&hdaSinkGetStream(pThis, &pThis->SinkLineIn)->State.Period);2355 #ifdef VBOX_WITH_HDA_MIC_IN2356 const bool fMicInPassed = hdaStreamPeriodHasPassedAbsWalClk (&hdaSinkGetStream(pThis, &pThis->SinkMicIn)->State.Period, u64WalClk);2357 const uint64_t u64MicInAbsWalClk = hdaStreamPeriodGetAbsElapsedWalClk(&hdaSinkGetStream(pThis, &pThis->SinkMicIn)->State.Period);2358 #endif2359 2360 #ifdef VBOX_STRICT2361 const uint64_t u64WalClkCur = ASMAtomicReadU64(&pThis->u64WalClk);2362 #endif2363 uint64_t u64WalClkSet = u64WalClk;2364 2365 /* Only drive the WALCLK register forward if all (active) stream periods have passed2366 * the specified point in time given by u64WalClk. */2367 if ( ( fFrontPassed2368 #ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND2369 # error "Implement me!"2370 #endif2371 && fLineInPassed2372 #ifdef VBOX_WITH_HDA_MIC_IN2373 && fMicInPassed2374 #endif2375 )2376 || fForce)2377 {2378 if (!fForce)2379 {2380 /* Get the maximum value of all periods we need to handle.2381 * Not the most elegant solution, but works for now ... */2382 u64WalClk = RT_MAX(u64WalClkSet, u64FrontAbsWalClk);2383 #ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND2384 # error "Implement me!"2385 #endif2386 u64WalClk = RT_MAX(u64WalClkSet, u64LineInAbsWalClk);2387 #ifdef VBOX_WITH_HDA_MIC_IN2388 u64WalClk = RT_MAX(u64WalClkSet, u64MicInAbsWalClk);2389 #endif2390 AssertMsg(u64WalClkSet > u64WalClkCur,2391 ("Setting WALCLK to a stale or backward value (%RU64 -> %RU64) isn't a good idea really. "2392 "Good luck with stuck audio stuff.\n", u64WalClkCur, u64WalClkSet));2393 }2394 2395 /* Set the new WALCLK value. */2396 ASMAtomicWriteU64(&pThis->u64WalClk, u64WalClkSet);2397 }2398 2399 const uint64_t u64WalClkNew = hdaWalClkGetCurrent(pThis);2400 2401 Log3Func(("Cur: %RU64, New: %RU64 (force %RTbool) -> %RU64 %s\n",2402 u64WalClkCur, u64WalClk, fForce,2403 u64WalClkNew, u64WalClkNew == u64WalClk ? "[OK]" : "[DELAYED]"));2404 2405 return (u64WalClkNew == u64WalClk);2406 939 } 2407 940 #endif /* IN_RING3 */ … … 2859 1392 2860 1393 #ifdef IN_RING3 2861 /**2862 * Converts an HDA stream's SDFMT register into a given PCM properties structure.2863 *2864 * @return IPRT status code.2865 * @param u32SDFMT The HDA stream's SDFMT value to convert.2866 * @param pProps PCM properties structure to hold converted result on success.2867 */2868 static int hdaSDFMTToPCMProps(uint32_t u32SDFMT, PPDMAUDIOPCMPROPS pProps)2869 {2870 AssertPtrReturn(pProps, VERR_INVALID_POINTER);2871 2872 # define EXTRACT_VALUE(v, mask, shift) ((v & ((mask) << (shift))) >> (shift))2873 2874 int rc = VINF_SUCCESS;2875 2876 uint32_t u32Hz = EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_BASE_RATE_MASK, HDA_SDFMT_BASE_RATE_SHIFT)2877 ? 44100 : 48000;2878 uint32_t u32HzMult = 1;2879 uint32_t u32HzDiv = 1;2880 2881 switch (EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_MULT_MASK, HDA_SDFMT_MULT_SHIFT))2882 {2883 case 0: u32HzMult = 1; break;2884 case 1: u32HzMult = 2; break;2885 case 2: u32HzMult = 3; break;2886 case 3: u32HzMult = 4; break;2887 default:2888 LogFunc(("Unsupported multiplier %x\n",2889 EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_MULT_MASK, HDA_SDFMT_MULT_SHIFT)));2890 rc = VERR_NOT_SUPPORTED;2891 break;2892 }2893 switch (EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_DIV_MASK, HDA_SDFMT_DIV_SHIFT))2894 {2895 case 0: u32HzDiv = 1; break;2896 case 1: u32HzDiv = 2; break;2897 case 2: u32HzDiv = 3; break;2898 case 3: u32HzDiv = 4; break;2899 case 4: u32HzDiv = 5; break;2900 case 5: u32HzDiv = 6; break;2901 case 6: u32HzDiv = 7; break;2902 case 7: u32HzDiv = 8; break;2903 default:2904 LogFunc(("Unsupported divisor %x\n",2905 EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_DIV_MASK, HDA_SDFMT_DIV_SHIFT)));2906 rc = VERR_NOT_SUPPORTED;2907 break;2908 }2909 2910 uint8_t cBits = 0;2911 switch (EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_BITS_MASK, HDA_SDFMT_BITS_SHIFT))2912 {2913 case 0:2914 cBits = 8;2915 break;2916 case 1:2917 cBits = 16;2918 break;2919 case 4:2920 cBits = 32;2921 break;2922 default:2923 AssertMsgFailed(("Unsupported bits per sample %x\n",2924 EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_BITS_MASK, HDA_SDFMT_BITS_SHIFT)));2925 rc = VERR_NOT_SUPPORTED;2926 break;2927 }2928 2929 if (RT_SUCCESS(rc))2930 {2931 RT_BZERO(pProps, sizeof(PDMAUDIOPCMPROPS));2932 2933 pProps->cBits = cBits;2934 pProps->fSigned = true;2935 pProps->cChannels = (u32SDFMT & 0xf) + 1;2936 pProps->uHz = u32Hz * u32HzMult / u32HzDiv;2937 pProps->cShift = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pProps->cBits, pProps->cChannels);2938 }2939 2940 # undef EXTRACT_VALUE2941 return rc;2942 }2943 2944 1394 /** 2945 1395 * Adds an audio output stream to the device setup using the given configuration. … … 3395 1845 #ifdef IN_RING3 3396 1846 3397 # ifdef HDA_USE_DMA_ACCESS_HANDLER3398 /**3399 * Registers access handlers for a stream's BDLE DMA accesses.3400 *3401 * @returns true if registration was successful, false if not.3402 * @param pStream HDA stream to register BDLE access handlers for.3403 */3404 static bool hdaStreamRegisterDMAHandlers(PHDASTREAM pStream)3405 {3406 /* At least LVI and the BDL base must be set. */3407 if ( !pStream->u16LVI3408 || !pStream->u64BDLBase)3409 {3410 return false;3411 }3412 3413 hdaStreamUnregisterDMAHandlers(pStream);3414 3415 LogFunc(("Registering ...\n"));3416 3417 int rc = VINF_SUCCESS;3418 3419 /*3420 * Create BDLE ranges.3421 */3422 3423 struct BDLERANGE3424 {3425 RTGCPHYS uAddr;3426 uint32_t uSize;3427 } arrRanges[16]; /** @todo Use a define. */3428 3429 size_t cRanges = 0;3430 3431 for (uint16_t i = 0; i < pStream->u16LVI + 1; i++)3432 {3433 HDABDLE BDLE;3434 rc = hdaBDLEFetch(pThis, &BDLE, pStream->u64BDLBase, i /* Index */);3435 if (RT_FAILURE(rc))3436 break;3437 3438 bool fAddRange = true;3439 BDLERANGE *pRange;3440 3441 if (cRanges)3442 {3443 pRange = &arrRanges[cRanges - 1];3444 3445 /* Is the current range a direct neighbor of the current BLDE? */3446 if ((pRange->uAddr + pRange->uSize) == BDLE.Desc.u64BufAdr)3447 {3448 /* Expand the current range by the current BDLE's size. */3449 pRange->uSize += BDLE.Desc.u32BufSize;3450 3451 /* Adding a new range in this case is not needed anymore. */3452 fAddRange = false;3453 3454 LogFunc(("Expanding range %zu by %RU32 (%RU32 total now)\n", cRanges - 1, BDLE.Desc.u32BufSize, pRange->uSize));3455 }3456 }3457 3458 /* Do we need to add a new range? */3459 if ( fAddRange3460 && cRanges < RT_ELEMENTS(arrRanges))3461 {3462 pRange = &arrRanges[cRanges];3463 3464 pRange->uAddr = BDLE.Desc.u64BufAdr;3465 pRange->uSize = BDLE.Desc.u32BufSize;3466 3467 LogFunc(("Adding range %zu - 0x%x (%RU32)\n", cRanges, pRange->uAddr, pRange->uSize));3468 3469 cRanges++;3470 }3471 }3472 3473 LogFunc(("%zu ranges total\n", cRanges));3474 3475 /*3476 * Register all ranges as DMA access handlers.3477 */3478 3479 for (size_t i = 0; i < cRanges; i++)3480 {3481 BDLERANGE *pRange = &arrRanges[i];3482 3483 PHDADMAACCESSHANDLER pHandler = (PHDADMAACCESSHANDLER)RTMemAllocZ(sizeof(HDADMAACCESSHANDLER));3484 if (!pHandler)3485 {3486 rc = VERR_NO_MEMORY;3487 break;3488 }3489 3490 RTListAppend(&pStream->State.lstDMAHandlers, &pHandler->Node);3491 3492 pHandler->pStream = pStream; /* Save a back reference to the owner. */3493 3494 char szDesc[32];3495 RTStrPrintf(szDesc, sizeof(szDesc), "HDA[SD%RU8 - RANGE%02zu]", pStream->u8SD, i);3496 3497 int rc2 = PGMR3HandlerPhysicalTypeRegister(PDMDevHlpGetVM(pStream->pHDAState->pDevInsR3), PGMPHYSHANDLERKIND_WRITE,3498 hdaDMAAccessHandler,3499 NULL, NULL, NULL,3500 NULL, NULL, NULL,3501 szDesc, &pHandler->hAccessHandlerType);3502 AssertRCBreak(rc2);3503 3504 pHandler->BDLEAddr = pRange->uAddr;3505 pHandler->BDLESize = pRange->uSize;3506 3507 /* Get first and last pages of the BDLE range. */3508 RTGCPHYS pgFirst = pRange->uAddr & ~PAGE_OFFSET_MASK;3509 RTGCPHYS pgLast = RT_ALIGN(pgFirst + pRange->uSize, PAGE_SIZE);3510 3511 /* Calculate the region size (in pages). */3512 RTGCPHYS regionSize = RT_ALIGN(pgLast - pgFirst, PAGE_SIZE);3513 3514 pHandler->GCPhysFirst = pgFirst;3515 pHandler->GCPhysLast = pHandler->GCPhysFirst + (regionSize - 1);3516 3517 LogFunc(("\tRegistering region '%s': 0x%x - 0x%x (region size: %zu)\n",3518 szDesc, pHandler->GCPhysFirst, pHandler->GCPhysLast, regionSize));3519 LogFunc(("\tBDLE @ 0x%x - 0x%x (%RU32)\n",3520 pHandler->BDLEAddr, pHandler->BDLEAddr + pHandler->BDLESize, pHandler->BDLESize));3521 3522 rc2 = PGMHandlerPhysicalRegister(PDMDevHlpGetVM(pStream->pHDAState->pDevInsR3),3523 pHandler->GCPhysFirst, pHandler->GCPhysLast,3524 pHandler->hAccessHandlerType, pHandler, NIL_RTR0PTR, NIL_RTRCPTR,3525 szDesc);3526 AssertRCBreak(rc2);3527 3528 pHandler->fRegistered = true;3529 }3530 3531 LogFunc(("Registration ended with rc=%Rrc\n", rc));3532 3533 return RT_SUCCESS(rc);3534 }3535 3536 /**3537 * Unregisters access handlers of a stream's BDLEs.3538 *3539 * @param pStream HDA stream to unregister BDLE access handlers for.3540 */3541 static void hdaStreamUnregisterDMAHandlers(PHDASTREAM pStream)3542 {3543 LogFunc(("\n"));3544 3545 PHDADMAACCESSHANDLER pHandler, pHandlerNext;3546 RTListForEachSafe(&pStream->State.lstDMAHandlers, pHandler, pHandlerNext, HDADMAACCESSHANDLER, Node)3547 {3548 if (!pHandler->fRegistered) /* Handler not registered? Skip. */3549 continue;3550 3551 LogFunc(("Unregistering 0x%x - 0x%x (%zu)\n",3552 pHandler->GCPhysFirst, pHandler->GCPhysLast, pHandler->GCPhysLast - pHandler->GCPhysFirst));3553 3554 int rc2 = PGMHandlerPhysicalDeregister(PDMDevHlpGetVM(pStream->pHDAState->pDevInsR3),3555 pHandler->GCPhysFirst);3556 AssertRC(rc2);3557 3558 RTListNodeRemove(&pHandler->Node);3559 3560 RTMemFree(pHandler);3561 pHandler = NULL;3562 }3563 3564 Assert(RTListIsEmpty(&pStream->State.lstDMAHandlers));3565 }3566 # endif /* HDA_USE_DMA_ACCESS_HANDLER */3567 3568 1847 #ifdef LOG_ENABLED 3569 1848 static void hdaBDLEDumpAll(PHDASTATE pThis, uint64_t u64BDLBase, uint16_t cBDLE) … … 3602 1881 } 3603 1882 #endif /* LOG_ENABLED */ 3604 3605 /**3606 * Fetches a Bundle Descriptor List Entry (BDLE) from the DMA engine.3607 *3608 * @param pThis Pointer to HDA state.3609 * @param pBDLE Where to store the fetched result.3610 * @param u64BaseDMA Address base of DMA engine to use.3611 * @param u16Entry BDLE entry to fetch.3612 */3613 static int hdaBDLEFetch(PHDASTATE pThis, PHDABDLE pBDLE, uint64_t u64BaseDMA, uint16_t u16Entry)3614 {3615 AssertPtrReturn(pThis, VERR_INVALID_POINTER);3616 AssertPtrReturn(pBDLE, VERR_INVALID_POINTER);3617 AssertReturn(u64BaseDMA, VERR_INVALID_PARAMETER);3618 3619 if (!u64BaseDMA)3620 {3621 LogRel2(("HDA: Unable to fetch BDLE #%RU16 - no base DMA address set (yet)\n", u16Entry));3622 return VERR_NOT_FOUND;3623 }3624 /** @todo Compare u16Entry with LVI. */3625 3626 int rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), u64BaseDMA + (u16Entry * sizeof(HDABDLEDESC)),3627 &pBDLE->Desc, sizeof(pBDLE->Desc));3628 3629 if (RT_SUCCESS(rc))3630 {3631 /* Reset internal state. */3632 RT_ZERO(pBDLE->State);3633 pBDLE->State.u32BDLIndex = u16Entry;3634 }3635 3636 Log3Func(("Entry #%d @ 0x%x: %R[bdle], rc=%Rrc\n", u16Entry, u64BaseDMA + (u16Entry * sizeof(HDABDLEDESC)), pBDLE, rc));3637 3638 3639 return VINF_SUCCESS;3640 }3641 3642 /**3643 * Returns the number of outstanding stream data bytes which need to be processed3644 * by the DMA engine assigned to this stream.3645 *3646 * @return Number of bytes for the DMA engine to process.3647 */3648 DECLINLINE(uint32_t) hdaStreamGetTransferSize(PHDASTATE pThis, PHDASTREAM pStream)3649 {3650 AssertPtrReturn(pThis, 0);3651 AssertPtrReturn(pStream, 0);3652 3653 if (!RT_BOOL(HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_SDCTL_RUN))3654 {3655 AssertFailed(); /* Should never happen. */3656 return 0;3657 }3658 3659 /* Determine how much for the current BDL entry we have left to transfer. */3660 PHDABDLE pBDLE = &pStream->State.BDLE;3661 const uint32_t cbBDLE = RT_MIN(pBDLE->Desc.u32BufSize, pBDLE->Desc.u32BufSize - pBDLE->State.u32BufOff);3662 3663 /* Determine how much we (still) can stuff in the stream's internal FIFO. */3664 const uint32_t cbCircBuf = (uint32_t)RTCircBufFree(pStream->State.pCircBuf);3665 3666 uint32_t cbToTransfer = cbBDLE;3667 3668 /* Make sure that we don't transfer more than our FIFO can hold at the moment.3669 * As the host sets the overall pace it needs to process some of the FIFO data first before3670 * we can issue a new DMA data transfer. */3671 if (cbToTransfer > cbCircBuf)3672 cbToTransfer = cbCircBuf;3673 3674 Log3Func(("[SD%RU8] LPIB=%RU32 CBL=%RU32 cbCircBuf=%RU32, -> cbToTransfer=%RU32 %R[bdle]\n", pStream->u8SD,3675 HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), pStream->u32CBL, cbCircBuf, cbToTransfer, pBDLE));3676 return cbToTransfer;3677 }3678 3679 /**3680 * Increases the amount of transferred (audio) data of an HDA stream and3681 * reports this as needed to the guest.3682 *3683 * @param pStream HDA stream to increase amount for.3684 * @param cbInc Amount (in bytes) to increase.3685 */3686 DECLINLINE(void) hdaStreamTransferInc(PHDASTREAM pStream, uint32_t cbInc)3687 {3688 AssertPtrReturnVoid(pStream);3689 3690 if (!cbInc)3691 return;3692 3693 const PHDASTATE pThis = pStream->pHDAState;3694 3695 const uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStream->u8SD);3696 3697 Log3Func(("[SD%RU8] %RU32 + %RU32 -> %RU32, CBL=%RU32\n",3698 pStream->u8SD, u32LPIB, cbInc, u32LPIB + cbInc, pStream->u32CBL));3699 3700 hdaStreamUpdateLPIB(pStream, u32LPIB + cbInc);3701 }3702 1883 3703 1884 /** … … 4334 2515 } 4335 2516 #endif /* HDA_USE_DMA_ACCESS_HANDLER */ 4336 4337 /**4338 * Reads DMA data from a given HDA output stream into its associated FIFO buffer.4339 *4340 * @return IPRT status code.4341 * @param pThis HDA state.4342 * @param pStream HDA output stream to read DMA data from.4343 * @param cbToRead How much (in bytes) to read from DMA.4344 * @param pcbRead Returns read bytes from DMA. Optional.4345 */4346 static int hdaDMARead(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToRead, uint32_t *pcbRead)4347 {4348 AssertPtrReturn(pThis, VERR_INVALID_POINTER);4349 AssertPtrReturn(pStream, VERR_INVALID_POINTER);4350 /* pcbRead is optional. */4351 4352 int rc = VINF_SUCCESS;4353 4354 uint32_t cbReadTotal = 0;4355 4356 PHDABDLE pBDLE = &pStream->State.BDLE;4357 PRTCIRCBUF pCircBuf = pStream->State.pCircBuf;4358 AssertPtr(pCircBuf);4359 4360 #ifdef HDA_DEBUG_SILENCE4361 uint64_t csSilence = 0;4362 4363 pStream->Dbg.cSilenceThreshold = 100;4364 pStream->Dbg.cbSilenceReadMin = _1M;4365 #endif4366 4367 while (cbToRead)4368 {4369 /* Make sure we only copy as much as the stream's FIFO can hold (SDFIFOS, 18.2.39). */4370 void *pvBuf;4371 size_t cbBuf;4372 RTCircBufAcquireWriteBlock(pCircBuf, RT_MIN(cbToRead, pStream->u16FIFOS), &pvBuf, &cbBuf);4373 4374 if (cbBuf)4375 {4376 /*4377 * Read from the current BDLE's DMA buffer.4378 */4379 int rc2 = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns),4380 pBDLE->Desc.u64BufAdr + pBDLE->State.u32BufOff + cbReadTotal, pvBuf, cbBuf);4381 AssertRC(rc2);4382 4383 #ifdef HDA_DEBUG_SILENCE4384 uint16_t *pu16Buf = (uint16_t *)pvBuf;4385 for (size_t i = 0; i < cbBuf / sizeof(uint16_t); i++)4386 {4387 if (*pu16Buf == 0)4388 {4389 csSilence++;4390 }4391 else4392 break;4393 pu16Buf++;4394 }4395 #endif4396 4397 #ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA4398 if (cbBuf)4399 {4400 RTFILE fh;4401 rc2 = RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaDMARead.pcm",4402 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);4403 if (RT_SUCCESS(rc2))4404 {4405 RTFileWrite(fh, pvBuf, cbBuf, NULL);4406 RTFileClose(fh);4407 }4408 else4409 AssertRC(rc2);4410 }4411 #endif4412 4413 #if 04414 pStream->Dbg.cbReadTotal += cbBuf;4415 const uint64_t cbWritten = ASMAtomicReadU64(&pStream->Dbg.cbWrittenTotal);4416 Log3Func(("cbRead=%RU64, cbWritten=%RU64 -> %RU64 bytes %s\n",4417 pStream->Dbg.cbReadTotal, cbWritten,4418 pStream->Dbg.cbReadTotal >= cbWritten ? pStream->Dbg.cbReadTotal - cbWritten : cbWritten - pStream->Dbg.cbReadTotal,4419 pStream->Dbg.cbReadTotal > cbWritten ? "too much" : "too little"));4420 #endif4421 4422 #ifdef VBOX_WITH_STATISTICS4423 STAM_COUNTER_ADD(&pThis->StatBytesRead, cbBuf);4424 #endif4425 }4426 4427 RTCircBufReleaseWriteBlock(pCircBuf, cbBuf);4428 4429 if (!cbBuf)4430 {4431 rc = VERR_BUFFER_OVERFLOW;4432 break;4433 }4434 4435 cbReadTotal += (uint32_t)cbBuf;4436 Assert(pBDLE->State.u32BufOff + cbReadTotal <= pBDLE->Desc.u32BufSize);4437 4438 Assert(cbToRead >= cbBuf);4439 cbToRead -= (uint32_t)cbBuf;4440 }4441 4442 #ifdef HDA_DEBUG_SILENCE4443 4444 if (csSilence)4445 pStream->Dbg.csSilence += csSilence;4446 4447 if ( csSilence == 04448 && pStream->Dbg.csSilence > pStream->Dbg.cSilenceThreshold4449 && pStream->Dbg.cbReadTotal >= pStream->Dbg.cbSilenceReadMin)4450 {4451 LogFunc(("Silent block detected: %RU64 audio samples\n", pStream->Dbg.csSilence));4452 pStream->Dbg.csSilence = 0;4453 }4454 #endif4455 4456 if (RT_SUCCESS(rc))4457 {4458 if (pcbRead)4459 *pcbRead = cbReadTotal;4460 }4461 4462 return rc;4463 }4464 4465 /**4466 * Tells whether a given BDLE is complete or not.4467 *4468 * @return true if BDLE is complete, false if not.4469 * @param pBDLE BDLE to retrieve status for.4470 */4471 static bool hdaBDLEIsComplete(PHDABDLE pBDLE)4472 {4473 bool fIsComplete = false;4474 4475 if ( !pBDLE->Desc.u32BufSize /* There can be BDLEs with 0 size. */4476 || (pBDLE->State.u32BufOff >= pBDLE->Desc.u32BufSize))4477 {4478 Assert(pBDLE->State.u32BufOff == pBDLE->Desc.u32BufSize);4479 fIsComplete = true;4480 }4481 4482 Log3Func(("%R[bdle] => %s\n", pBDLE, fIsComplete ? "COMPLETE" : "INCOMPLETE"));4483 4484 return fIsComplete;4485 }4486 4487 4488 /**4489 * Tells whether a given BDLE needs an interrupt or not.4490 *4491 * @return true if BDLE needs an interrupt, false if not.4492 * @param pBDLE BDLE to retrieve status for.4493 */4494 static bool hdaBDLENeedsInterrupt(PHDABDLE pBDLE)4495 {4496 return (pBDLE->Desc.fFlags & HDA_BDLE_FLAG_IOC);4497 }4498 4499 /**4500 * Writes audio data from an HDA input stream's FIFO to its associated DMA area.4501 *4502 * @return IPRT status code.4503 * @param pThis HDA state.4504 * @param pStream HDA input stream to write audio data to.4505 * @param cbToWrite How much (in bytes) to write.4506 * @param pcbWritten Returns written bytes on success. Optional.4507 */4508 static int hdaDMAWrite(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToWrite, uint32_t *pcbWritten)4509 {4510 AssertPtrReturn(pThis, VERR_INVALID_POINTER);4511 AssertPtrReturn(pStream, VERR_INVALID_POINTER);4512 /* pcbWritten is optional. */4513 4514 PHDABDLE pBDLE = &pStream->State.BDLE;4515 PRTCIRCBUF pCircBuf = pStream->State.pCircBuf;4516 AssertPtr(pCircBuf);4517 4518 int rc = VINF_SUCCESS;4519 4520 uint32_t cbWrittenTotal = 0;4521 4522 void *pvBuf = NULL;4523 size_t cbBuf = 0;4524 4525 uint8_t abSilence[HDA_FIFO_MAX + 1] = { 0 };4526 4527 while (cbToWrite)4528 {4529 size_t cbChunk = RT_MIN(cbToWrite, pStream->u16FIFOS);4530 4531 size_t cbBlock = 0;4532 RTCircBufAcquireReadBlock(pCircBuf, cbChunk, &pvBuf, &cbBlock);4533 4534 if (cbBlock)4535 {4536 cbBuf = cbBlock;4537 }4538 else /* No audio data available? Send silence. */4539 {4540 pvBuf = &abSilence;4541 cbBuf = cbChunk;4542 }4543 4544 /* Sanity checks. */4545 Assert(cbBuf <= pBDLE->Desc.u32BufSize - pBDLE->State.u32BufOff);4546 Assert(cbBuf % HDA_FRAME_SIZE == 0);4547 Assert((cbBuf >> 1) >= 1);4548 4549 #ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA4550 RTFILE fh;4551 RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaDMAWrite.pcm",4552 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);4553 RTFileWrite(fh, pvBuf, cbBuf, NULL);4554 RTFileClose(fh);4555 #endif4556 int rc2 = PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns),4557 pBDLE->Desc.u64BufAdr + pBDLE->State.u32BufOff + cbWrittenTotal,4558 pvBuf, cbBuf);4559 AssertRC(rc2);4560 4561 #ifdef VBOX_WITH_STATISTICS4562 STAM_COUNTER_ADD(&pThis->StatBytesWritten, cbBuf);4563 #endif4564 if (cbBlock)4565 RTCircBufReleaseReadBlock(pCircBuf, cbBlock);4566 4567 Assert(cbToWrite >= cbBuf);4568 cbToWrite -= (uint32_t)cbBuf;4569 4570 cbWrittenTotal += (uint32_t)cbBuf;4571 }4572 4573 if (RT_SUCCESS(rc))4574 {4575 if (pcbWritten)4576 *pcbWritten = cbWrittenTotal;4577 }4578 else4579 LogFunc(("Failed with %Rrc\n", rc));4580 4581 return rc;4582 }4583 2517 4584 2518 /** … … 4789 2723 #endif 4790 2724 4791 /**4792 * Retrieves the available size of (buffered) audio data (in bytes) of a given HDA stream.4793 *4794 * @returns Available data (in bytes).4795 * @param pStream HDA stream to retrieve size for.4796 */4797 static uint32_t hdaStreamGetUsed(PHDASTREAM pStream)4798 {4799 AssertPtrReturn(pStream, 0);4800 4801 if (!pStream->State.pCircBuf)4802 return 0;4803 4804 return (uint32_t)RTCircBufUsed(pStream->State.pCircBuf);4805 }4806 4807 /**4808 * Retrieves the free size of audio data (in bytes) of a given HDA stream.4809 *4810 * @returns Free data (in bytes).4811 * @param pStream HDA stream to retrieve size for.4812 */4813 static uint32_t hdaStreamGetFree(PHDASTREAM pStream)4814 {4815 AssertPtrReturn(pStream, 0);4816 4817 if (!pStream->State.pCircBuf)4818 return 0;4819 4820 return (uint32_t)RTCircBufFree(pStream->State.pCircBuf);4821 }4822 4823 4824 /**4825 * Writes audio data from a mixer sink into an HDA stream's DMA buffer.4826 *4827 * @returns IPRT status code.4828 * @param pStream HDA stream to write to.4829 * @param cbToWrite Number of bytes to write.4830 * @param pcbWritten Number of bytes written. Optional.4831 */4832 static int hdaStreamWrite(PHDASTREAM pStream, uint32_t cbToWrite, uint32_t *pcbWritten)4833 {4834 AssertPtrReturn(pStream, VERR_INVALID_POINTER);4835 AssertReturn(cbToWrite, VERR_INVALID_PARAMETER);4836 /* pcbWritten is optional. */4837 4838 PHDAMIXERSINK pSink = pStream->pMixSink;4839 if (!pSink)4840 {4841 AssertMsgFailed(("[SD%RU8]: Can't write to a stream with no sink attached\n", pStream->u8SD));4842 4843 if (pcbWritten)4844 *pcbWritten = 0;4845 return VINF_SUCCESS;4846 }4847 4848 PRTCIRCBUF pCircBuf = pStream->State.pCircBuf;4849 AssertPtr(pCircBuf);4850 4851 int rc = VINF_SUCCESS;4852 4853 uint32_t cbWrittenTotal = 0;4854 uint32_t cbLeft = RT_MIN(cbToWrite, (uint32_t)RTCircBufFree(pCircBuf));4855 4856 while (cbLeft)4857 {4858 void *pvDst;4859 size_t cbDst;4860 4861 uint32_t cbRead = 0;4862 4863 RTCircBufAcquireWriteBlock(pCircBuf, cbToWrite, &pvDst, &cbDst);4864 4865 if (cbDst)4866 {4867 rc = AudioMixerSinkRead(pSink->pMixSink, AUDMIXOP_COPY, pvDst, (uint32_t)cbDst, &cbRead);4868 AssertRC(rc);4869 4870 Assert(cbDst >= cbRead);4871 Log2Func(("[SD%RU8]: %zu/%zu bytes read\n", pStream->u8SD, cbRead, cbDst));4872 4873 #ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA4874 RTFILE fh;4875 RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaStreamWrite.pcm",4876 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);4877 RTFileWrite(fh, pvDst, cbRead, NULL);4878 RTFileClose(fh);4879 #endif4880 }4881 4882 RTCircBufReleaseWriteBlock(pCircBuf, cbRead);4883 4884 if (RT_FAILURE(rc))4885 break;4886 4887 Assert(cbLeft >= cbRead);4888 cbLeft -= cbRead;4889 4890 cbWrittenTotal += cbRead;4891 }4892 4893 if (pcbWritten)4894 *pcbWritten = cbWrittenTotal;4895 4896 return rc;4897 }4898 4899 4900 /**4901 * Reads audio data from an HDA stream's DMA buffer and writes into a specified mixer sink.4902 *4903 * @returns IPRT status code.4904 * @param pStream HDA stream to read audio data from.4905 * @param cbToRead Number of bytes to read.4906 * @param pcbRead Number of bytes read. Optional.4907 */4908 static int hdaStreamRead(PHDASTREAM pStream, uint32_t cbToRead, uint32_t *pcbRead)4909 {4910 AssertPtrReturn(pStream, VERR_INVALID_POINTER);4911 AssertReturn(cbToRead, VERR_INVALID_PARAMETER);4912 /* pcbWritten is optional. */4913 4914 PHDAMIXERSINK pSink = pStream->pMixSink;4915 if (!pSink)4916 {4917 AssertMsgFailed(("[SD%RU8]: Can't read from a stream with no sink attached\n", pStream->u8SD));4918 4919 if (pcbRead)4920 *pcbRead = 0;4921 return VINF_SUCCESS;4922 }4923 4924 PRTCIRCBUF pCircBuf = pStream->State.pCircBuf;4925 AssertPtr(pCircBuf);4926 4927 int rc = VINF_SUCCESS;4928 4929 uint32_t cbReadTotal = 0;4930 uint32_t cbLeft = RT_MIN(cbToRead, (uint32_t)RTCircBufUsed(pCircBuf));4931 4932 while (cbLeft)4933 {4934 void *pvSrc;4935 size_t cbSrc;4936 4937 uint32_t cbWritten = 0;4938 4939 RTCircBufAcquireReadBlock(pCircBuf, cbLeft, &pvSrc, &cbSrc);4940 4941 if (cbSrc)4942 {4943 #ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA4944 RTFILE fh;4945 RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaStreamRead.pcm",4946 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);4947 RTFileWrite(fh, pvSrc, cbSrc, NULL);4948 RTFileClose(fh);4949 #endif4950 rc = AudioMixerSinkWrite(pSink->pMixSink, AUDMIXOP_COPY, pvSrc, (uint32_t)cbSrc, &cbWritten);4951 AssertRC(rc);4952 4953 Assert(cbSrc >= cbWritten);4954 Log2Func(("[SD%RU8]: %zu/%zu bytes read\n", pStream->u8SD, cbWritten, cbSrc));4955 }4956 4957 RTCircBufReleaseReadBlock(pCircBuf, cbWritten);4958 4959 if (RT_FAILURE(rc))4960 break;4961 4962 Assert(cbLeft >= cbWritten);4963 cbLeft -= cbWritten;4964 4965 cbReadTotal += cbWritten;4966 }4967 4968 if (pcbRead)4969 *pcbRead = cbReadTotal;4970 4971 return rc;4972 }4973 4974 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO4975 /**4976 * Asynchronous I/O thread for a HDA stream.4977 * This will do the heavy lifting work for us as soon as it's getting notified by another thread.4978 *4979 * @returns IPRT status code.4980 * @param hThreadSelf Thread handle.4981 * @param pvUser User argument. Must be of type PHDASTREAMTHREADCTX.4982 */4983 static DECLCALLBACK(int) hdaStreamAsyncIOThread(RTTHREAD hThreadSelf, void *pvUser)4984 {4985 PHDASTREAMTHREADCTX pCtx = (PHDASTREAMTHREADCTX)pvUser;4986 AssertPtr(pCtx);4987 4988 PHDASTREAM pStream = pCtx->pStream;4989 AssertPtr(pStream);4990 4991 PHDASTREAMSTATEAIO pAIO = &pCtx->pStream->State.AIO;4992 4993 ASMAtomicXchgBool(&pAIO->fStarted, true);4994 4995 RTThreadUserSignal(hThreadSelf);4996 4997 LogFunc(("[SD%RU8]: Started\n", pStream->u8SD));4998 4999 for (;;)5000 {5001 int rc2 = RTSemEventWait(pAIO->Event, RT_INDEFINITE_WAIT);5002 if (RT_FAILURE(rc2))5003 break;5004 5005 if (ASMAtomicReadBool(&pAIO->fShutdown))5006 break;5007 5008 rc2 = RTCritSectEnter(&pAIO->CritSect);5009 if (RT_SUCCESS(rc2))5010 {5011 if (!pAIO->fEnabled)5012 {5013 RTCritSectLeave(&pAIO->CritSect);5014 continue;5015 }5016 5017 hdaStreamUpdate(pStream, false /* fInTimer */);5018 5019 int rc3 = RTCritSectLeave(&pAIO->CritSect);5020 AssertRC(rc3);5021 }5022 5023 AssertRC(rc2);5024 }5025 5026 LogFunc(("[SD%RU8]: Ended\n", pStream->u8SD));5027 5028 ASMAtomicXchgBool(&pAIO->fStarted, false);5029 5030 return VINF_SUCCESS;5031 }5032 5033 /**5034 * Creates the async I/O thread for a specific HDA audio stream.5035 *5036 * @returns IPRT status code.5037 * @param pStream HDA audio stream to create the async I/O thread for.5038 */5039 static int hdaStreamAsyncIOCreate(PHDASTREAM pStream)5040 {5041 PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;5042 5043 int rc;5044 5045 if (!ASMAtomicReadBool(&pAIO->fStarted))5046 {5047 pAIO->fShutdown = false;5048 5049 rc = RTSemEventCreate(&pAIO->Event);5050 if (RT_SUCCESS(rc))5051 {5052 rc = RTCritSectInit(&pAIO->CritSect);5053 if (RT_SUCCESS(rc))5054 {5055 HDASTREAMTHREADCTX Ctx = { pStream->pHDAState, pStream };5056 5057 char szThreadName[64];5058 RTStrPrintf2(szThreadName, sizeof(szThreadName), "hdaAIO%RU8", pStream->u8SD);5059 5060 rc = RTThreadCreate(&pAIO->Thread, hdaStreamAsyncIOThread, &Ctx,5061 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, szThreadName);5062 if (RT_SUCCESS(rc))5063 rc = RTThreadUserWait(pAIO->Thread, 10 * 1000 /* 10s timeout */);5064 }5065 }5066 }5067 else5068 rc = VINF_SUCCESS;5069 5070 LogFunc(("[SD%RU8]: Returning %Rrc\n", pStream->u8SD, rc));5071 return rc;5072 }5073 5074 /**5075 * Destroys the async I/O thread of a specific HDA audio stream.5076 *5077 * @returns IPRT status code.5078 * @param pStream HDA audio stream to destroy the async I/O thread for.5079 */5080 static int hdaStreamAsyncIODestroy(PHDASTREAM pStream)5081 {5082 PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;5083 5084 if (!ASMAtomicReadBool(&pAIO->fStarted))5085 return VINF_SUCCESS;5086 5087 ASMAtomicWriteBool(&pAIO->fShutdown, true);5088 5089 int rc = hdaStreamAsyncIONotify(pStream);5090 AssertRC(rc);5091 5092 int rcThread;5093 rc = RTThreadWait(pAIO->Thread, 30 * 1000 /* 30s timeout */, &rcThread);5094 LogFunc(("Async I/O thread ended with %Rrc (%Rrc)\n", rc, rcThread));5095 5096 if (RT_SUCCESS(rc))5097 {5098 rc = RTCritSectDelete(&pAIO->CritSect);5099 AssertRC(rc);5100 5101 rc = RTSemEventDestroy(pAIO->Event);5102 AssertRC(rc);5103 5104 pAIO->fStarted = false;5105 pAIO->fShutdown = false;5106 pAIO->fEnabled = false;5107 }5108 5109 LogFunc(("[SD%RU8]: Returning %Rrc\n", pStream->u8SD, rc));5110 return rc;5111 }5112 5113 /**5114 * Lets the stream's async I/O thread know that there is some data to process.5115 *5116 * @returns IPRT status code.5117 * @param pStream HDA stream to notify async I/O thread for.5118 */5119 static int hdaStreamAsyncIONotify(PHDASTREAM pStream)5120 {5121 return RTSemEventSignal(pStream->State.AIO.Event);5122 }5123 5124 /**5125 * Locks the async I/O thread of a specific HDA audio stream.5126 *5127 * @param pStream HDA stream to lock async I/O thread for.5128 */5129 static void hdaStreamAsyncIOLock(PHDASTREAM pStream)5130 {5131 PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;5132 5133 if (!ASMAtomicReadBool(&pAIO->fStarted))5134 return;5135 5136 int rc2 = RTCritSectEnter(&pAIO->CritSect);5137 AssertRC(rc2);5138 }5139 5140 /**5141 * Unlocks the async I/O thread of a specific HDA audio stream.5142 *5143 * @param pStream HDA stream to unlock async I/O thread for.5144 */5145 static void hdaStreamAsyncIOUnlock(PHDASTREAM pStream)5146 {5147 PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;5148 5149 if (!ASMAtomicReadBool(&pAIO->fStarted))5150 return;5151 5152 int rc2 = RTCritSectLeave(&pAIO->CritSect);5153 AssertRC(rc2);5154 }5155 5156 /**5157 * Enables (resumes) or disables (pauses) the async I/O thread.5158 *5159 * @param pStream HDA stream to enable/disable async I/O thread for.5160 * @param fEnable Whether to enable or disable the I/O thread.5161 *5162 * @remarks Does not do locking.5163 */5164 static void hdaStreamAsyncIOEnable(PHDASTREAM pStream, bool fEnable)5165 {5166 PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;5167 ASMAtomicXchgBool(&pAIO->fEnabled, fEnable);5168 }5169 #endif /* VBOX_WITH_AUDIO_HDA_ASYNC_IO */5170 5171 static uint32_t hdaStreamTransferGetElapsed(PHDASTREAM pStream)5172 {5173 AssertPtr(pStream->pHDAState->pTimer);5174 const uint64_t cTicksNow = TMTimerGet(pStream->pHDAState->pTimer);5175 const uint64_t cTicksPerSec = TMTimerGetFreq(pStream->pHDAState->pTimer);5176 5177 const uint64_t cTicksElapsed = cTicksNow - pStream->State.uTimerTS;5178 #ifdef DEBUG5179 const uint64_t cMsElapsed = cTicksElapsed / (cTicksPerSec / 1000);5180 #endif5181 5182 AssertPtr(pStream->pHDAState->pCodec);5183 5184 PPDMAUDIOSTREAMCFG pCfg = &pStream->State.strmCfg;5185 5186 /* A stream *always* runs with 48 kHz device-wise, regardless of the actual stream input/output format (Hz) being set. */5187 uint32_t csPerPeriod = (int)((pCfg->Props.cChannels * cTicksElapsed * 48000 /* Hz */ + cTicksPerSec) / cTicksPerSec / 2);5188 uint32_t cbPerPeriod = csPerPeriod << pCfg->Props.cShift;5189 5190 Log3Func(("[SD%RU8] %RU64ms (%zu samples, %zu bytes) elapsed\n", pStream->u8SD, cMsElapsed, csPerPeriod, cbPerPeriod));5191 5192 return cbPerPeriod;5193 }5194 5195 /**5196 * Transfers data of an HDA stream according to its usage (input / output).5197 *5198 * For an SDO (output) stream this means reading DMA data from the device to5199 * the HDA stream's internal FIFO buffer.5200 *5201 * For an SDI (input) stream this is reading audio data from the HDA stream's5202 * internal FIFO buffer and writing it as DMA data to the device.5203 *5204 * @returns IPRT status code.5205 * @param pStream HDA stream to update.5206 * @param cbToProcessMax Maximum of data (in bytes) to process.5207 */5208 static int hdaStreamTransfer(PHDASTREAM pStream, uint32_t cbToProcessMax)5209 {5210 AssertPtrReturn(pStream, VERR_INVALID_POINTER);5211 AssertReturn(cbToProcessMax, VERR_INVALID_PARAMETER);5212 5213 hdaStreamLock(pStream);5214 5215 PHDASTATE pThis = pStream->pHDAState;5216 AssertPtr(pThis);5217 5218 PHDASTREAMPERIOD pPeriod = &pStream->State.Period;5219 int rc = hdaStreamPeriodLock(pPeriod);5220 AssertRC(rc);5221 5222 bool fProceed = true;5223 5224 /* Stream not running? */5225 if (!(HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_SDCTL_RUN))5226 {5227 Log3Func(("[SD%RU8] RUN bit not set\n", pStream->u8SD));5228 fProceed = false;5229 }5230 /* Period complete? */5231 else if (hdaStreamPeriodIsComplete(pPeriod))5232 {5233 Log3Func(("[SD%RU8] Period is complete, nothing to do\n", pStream->u8SD));5234 fProceed = false;5235 }5236 5237 if (!fProceed)5238 {5239 hdaStreamPeriodUnlock(pPeriod);5240 hdaStreamUnlock(pStream);5241 return VINF_SUCCESS;5242 }5243 5244 /* Sanity checks. */5245 Assert(pStream->u8SD < HDA_MAX_STREAMS);5246 Assert(pStream->u64BDLBase);5247 Assert(pStream->u32CBL);5248 5249 /* State sanity checks. */5250 Assert(ASMAtomicReadBool(&pStream->State.fInReset) == false);5251 5252 /* Fetch first / next BDL entry. */5253 PHDABDLE pBDLE = &pStream->State.BDLE;5254 if (hdaBDLEIsComplete(pBDLE))5255 {5256 rc = hdaBDLEFetch(pThis, pBDLE, pStream->u64BDLBase, pStream->State.uCurBDLE);5257 AssertRC(rc);5258 }5259 5260 const uint32_t cbPeriodRemaining = hdaStreamPeriodGetRemainingFrames(pPeriod) * HDA_FRAME_SIZE;5261 Assert(cbPeriodRemaining); /* Paranoia. */5262 5263 const uint32_t cbElapsed = hdaStreamTransferGetElapsed(pStream);5264 Assert(cbElapsed); /* Paranoia. */5265 5266 /* Limit the data to read, as this routine could be delayed and therefore5267 * report wrong (e.g. too much) cbElapsed bytes. */5268 uint32_t cbLeft = RT_MIN(RT_MIN(cbPeriodRemaining, cbElapsed), cbToProcessMax);5269 5270 Log3Func(("[SD%RU8] cbPeriodRemaining=%RU32, cbElapsed=%RU32, cbToProcessMax=%RU32 -> cbLeft=%RU32\n",5271 pStream->u8SD, cbPeriodRemaining, cbElapsed, cbToProcessMax, cbLeft));5272 5273 Assert(cbLeft % HDA_FRAME_SIZE == 0); /* Paranoia. */5274 5275 while (cbLeft)5276 {5277 uint32_t cbChunk = RT_MIN(hdaStreamGetTransferSize(pThis, pStream), cbLeft);5278 if (!cbChunk)5279 break;5280 5281 uint32_t cbDMA = 0;5282 5283 if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT) /* Output (SDO). */5284 {5285 STAM_PROFILE_START(&pThis->StatOut, a);5286 5287 rc = hdaDMARead(pThis, pStream, cbChunk, &cbDMA /* pcbRead */);5288 if (RT_FAILURE(rc))5289 LogRel(("HDA: Reading from stream #%RU8 DMA failed with %Rrc\n", pStream->u8SD, rc));5290 5291 STAM_PROFILE_STOP(&pThis->StatOut, a);5292 }5293 else if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_IN) /* Input (SDI). */5294 {5295 STAM_PROFILE_START(&pThis->StatIn, a);5296 5297 rc = hdaDMAWrite(pThis, pStream, cbChunk, &cbDMA /* pcbWritten */);5298 if (RT_FAILURE(rc))5299 LogRel(("HDA: Writing to stream #%RU8 DMA failed with %Rrc\n", pStream->u8SD, rc));5300 5301 STAM_PROFILE_STOP(&pThis->StatIn, a);5302 }5303 else /** @todo Handle duplex streams? */5304 AssertFailed();5305 5306 if (cbDMA)5307 {5308 Assert(cbDMA % HDA_FRAME_SIZE == 0);5309 5310 /* We always increment the position of DMA buffer counter because we're always reading5311 * into an intermediate buffer. */5312 pBDLE->State.u32BufOff += (uint32_t)cbDMA;5313 Assert(pBDLE->State.u32BufOff <= pBDLE->Desc.u32BufSize);5314 5315 hdaStreamTransferInc(pStream, cbDMA);5316 5317 uint32_t framesDMA = cbDMA / HDA_FRAME_SIZE;5318 5319 /* Add the transferred frames to the period. */5320 hdaStreamPeriodInc(pPeriod, framesDMA);5321 5322 /* Save the timestamp of when the last successful DMA transfer has been for this stream. */5323 pStream->State.uTimerTS = TMTimerGet(pThis->pTimer);5324 5325 Assert(cbLeft >= cbDMA);5326 cbLeft -= cbDMA;5327 }5328 5329 if (hdaBDLEIsComplete(pBDLE))5330 {5331 Log3Func(("[SD%RU8] Complete: %R[bdle]\n", pStream->u8SD, pBDLE));5332 5333 if (hdaBDLENeedsInterrupt(pBDLE))5334 {5335 /* If the IOCE ("Interrupt On Completion Enable") bit of the SDCTL register is set5336 * we need to generate an interrupt.5337 */5338 if (HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_SDCTL_IOCE)5339 hdaStreamPeriodAcquireInterrupt(pPeriod);5340 }5341 5342 if (pStream->State.uCurBDLE == pStream->u16LVI)5343 {5344 Assert(pStream->u32CBL == HDA_STREAM_REG(pThis, LPIB, pStream->u8SD));5345 5346 pStream->State.uCurBDLE = 0;5347 hdaStreamUpdateLPIB(pStream, 0 /* LPIB */);5348 }5349 else5350 pStream->State.uCurBDLE++;5351 5352 hdaBDLEFetch(pThis, pBDLE, pStream->u64BDLBase, pStream->State.uCurBDLE);5353 5354 Log3Func(("[SD%RU8] Fetching: %R[bdle]\n", pStream->u8SD, pBDLE));5355 }5356 5357 if (RT_FAILURE(rc))5358 break;5359 }5360 5361 if (hdaStreamPeriodIsComplete(pPeriod))5362 {5363 Log3Func(("[SD%RU8] Period complete -- Current: %R[bdle]\n", pStream->u8SD, &pStream->State.BDLE));5364 5365 /* Set the stream's BCIS bit.5366 *5367 * Note: This only must be done if the whole period is complete, and not if only5368 * one specific BDL entry is complete (if it has the IOC bit set).5369 *5370 * This will otherwise confuses the guest when it 1) deasserts the interrupt,5371 * 2) reads SDSTS (with BCIS set) and then 3) too early reads a (wrong) WALCLK value.5372 *5373 * snd_hda_intel on Linux will tell. */5374 HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_SDSTS_BCIS;5375 5376 /* Try updating the wall clock. */5377 const uint64_t u64WalClk = hdaStreamPeriodGetAbsElapsedWalClk(pPeriod);5378 const bool fWalClkSet = hdaWalClkSet(pThis, u64WalClk, false /* fForce */);5379 5380 /* Does the period have any interrupts outstanding? */5381 if (hdaStreamPeriodNeedsInterrupt(pPeriod))5382 {5383 if (fWalClkSet)5384 {5385 Log3Func(("[SD%RU8] Set WALCLK to %RU64, triggering interrupt\n", pStream->u8SD, u64WalClk));5386 5387 /* Trigger an interrupt first and let hdaRegWriteSDSTS() deal with5388 * ending / beginning a period. */5389 #ifndef DEBUG5390 hdaProcessInterrupt(pThis);5391 #else5392 hdaProcessInterrupt(pThis, __FUNCTION__);5393 #endif5394 }5395 }5396 else5397 {5398 /* End the period first ... */5399 hdaStreamPeriodEnd(pPeriod);5400 5401 /* ... and immediately begin the next one. */5402 hdaStreamPeriodBegin(pPeriod, hdaWalClkGetCurrent(pThis));5403 }5404 }5405 5406 hdaStreamPeriodUnlock(pPeriod);5407 5408 Log3Func(("[SD%RU8] Returning %Rrc ==========================================\n", pStream->u8SD, rc));5409 5410 if (RT_FAILURE(rc))5411 LogFunc(("[SD%RU8] Failed with rc=%Rrcc\n", pStream->u8SD, rc));5412 5413 hdaStreamUnlock(pStream);5414 5415 return VINF_SUCCESS;5416 }5417 5418 /**5419 * Updates a HDA stream by doing its required data transfers.5420 * The host sink(s) set the overall pace.5421 *5422 * This routine is called by both, the synchronous and the asynchronous, implementations.5423 *5424 * @param pStream HDA stream to update.5425 * @param fInTimer Whether to this function was called from the timer5426 * context or an asynchronous I/O stream thread (if supported).5427 */5428 static void hdaStreamUpdate(PHDASTREAM pStream, bool fInTimer)5429 {5430 PAUDMIXSINK pSink = NULL;5431 if ( pStream->pMixSink5432 && pStream->pMixSink->pMixSink)5433 {5434 pSink = pStream->pMixSink->pMixSink;5435 }5436 5437 if (!AudioMixerSinkIsActive(pSink)) /* No sink available? Bail out. */5438 return;5439 5440 int rc2;5441 5442 if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT) /* Output (SDO). */5443 {5444 /* Is the HDA stream ready to be written (guest output data) to? If so, by how much? */5445 const uint32_t cbFree = hdaStreamGetFree(pStream);5446 5447 if ( fInTimer5448 && cbFree)5449 {5450 Log3Func(("[SD%RU8] cbFree=%RU32\n", pStream->u8SD, cbFree));5451 5452 /* Do the DMA transfer. */5453 rc2 = hdaStreamTransfer(pStream, cbFree);5454 AssertRC(rc2);5455 }5456 5457 /* How much (guest output) data is available at the moment for the HDA stream? */5458 uint32_t cbUsed = hdaStreamGetUsed(pStream);5459 5460 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO5461 if ( fInTimer5462 && cbUsed)5463 {5464 rc2 = hdaStreamAsyncIONotify(pStream);5465 AssertRC(rc2);5466 }5467 else5468 {5469 #endif5470 const uint32_t cbSinkWritable = AudioMixerSinkGetWritable(pSink);5471 5472 /* Do not write more than the sink can hold at the moment.5473 * The host sets the overall pace. */5474 if (cbUsed > cbSinkWritable)5475 cbUsed = cbSinkWritable;5476 5477 if (cbUsed)5478 {5479 /* Read (guest output) data and write it to the stream's sink. */5480 rc2 = hdaStreamRead(pStream, cbUsed, NULL /* pcbRead */);5481 AssertRC(rc2);5482 }5483 5484 /* When running synchronously, update the associated sink here.5485 * Otherwise this will be done in the device timer. */5486 rc2 = AudioMixerSinkUpdate(pSink);5487 AssertRC(rc2);5488 5489 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO5490 }5491 #endif5492 }5493 else /* Input (SDI). */5494 {5495 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO5496 if (fInTimer)5497 {5498 rc2 = hdaStreamAsyncIONotify(pStream);5499 AssertRC(rc2);5500 }5501 else5502 {5503 #endif5504 rc2 = AudioMixerSinkUpdate(pSink);5505 AssertRC(rc2);5506 5507 /* Is the sink ready to be read (host input data) from? If so, by how much? */5508 const uint32_t cbReadable = AudioMixerSinkGetReadable(pSink);5509 5510 /* How much (guest input) data is free at the moment? */5511 uint32_t cbFree = hdaStreamGetFree(pStream);5512 5513 Log3Func(("[SD%RU8] cbReadable=%RU32, cbFree=%RU32\n", pStream->u8SD, cbReadable, cbFree));5514 5515 /* Do not read more than the sink can provide at the moment.5516 * The host sets the overall pace. */5517 if (cbFree > cbReadable)5518 cbFree = cbReadable;5519 5520 if (cbFree)5521 {5522 /* Write (guest input) data to the stream which was read from stream's sink before. */5523 rc2 = hdaStreamWrite(pStream, cbFree, NULL /* pcbWritten */);5524 AssertRC(rc2);5525 }5526 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO5527 }5528 #endif5529 5530 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO5531 if (fInTimer)5532 {5533 #endif5534 const uint32_t cbToTransfer = hdaStreamGetUsed(pStream);5535 if (cbToTransfer)5536 {5537 /* When running synchronously, do the DMA data transfers here.5538 * Otherwise this will be done in the stream's async I/O thread. */5539 rc2 = hdaStreamTransfer(pStream, cbToTransfer);5540 AssertRC(rc2);5541 }5542 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO5543 }5544 #endif5545 }5546 }5547 2725 #endif /* IN_RING3 */ 5548 2726 -
trunk/src/VBox/Devices/Audio/DevHDACommon.h
r64351 r67899 1 1 /* $Id$ */ 2 2 /** @file 3 * DevHDACommon.h - Shared defines / functions between HDA controller and codec.3 * DevHDACommon.h - Shared HDA device defines / functions. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 2016 Oracle Corporation7 * Copyright (C) 2016-2017 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 18 18 #ifndef DEV_HDA_COMMON_H 19 19 #define DEV_HDA_COMMON_H 20 21 #include "AudioMixer.h" 22 23 /** See 302349 p 6.2. */ 24 typedef struct HDAREGDESC 25 { 26 /** Register offset in the register space. */ 27 uint32_t offset; 28 /** Size in bytes. Registers of size > 4 are in fact tables. */ 29 uint32_t size; 30 /** Readable bits. */ 31 uint32_t readable; 32 /** Writable bits. */ 33 uint32_t writable; 34 /** Register descriptor (RD) flags of type HDA_RD_FLAG_. 35 * These are used to specify the handling (read/write) 36 * policy of the register. */ 37 uint32_t fFlags; 38 /** Read callback. */ 39 int (*pfnRead)(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value); 40 /** Write callback. */ 41 int (*pfnWrite)(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value); 42 /** Index into the register storage array. */ 43 uint32_t mem_idx; 44 /** Abbreviated name. */ 45 const char *abbrev; 46 /** Descripton. */ 47 const char *desc; 48 } HDAREGDESC, *PHDAREGDESC; 49 50 /** 51 * HDA register aliases (HDA spec 3.3.45). 52 * @remarks Sorted by offReg. 53 */ 54 typedef struct HDAREGALIAS 55 { 56 /** The alias register offset. */ 57 uint32_t offReg; 58 /** The register index. */ 59 int idxAlias; 60 } HDAREGALIAS, *PHDAREGALIAS; 61 62 /** 63 * At the moment we support 4 input + 4 output streams max, which is 8 in total. 64 * Bidirectional streams are currently *not* supported. 65 * 66 * Note: When changing any of those values, be prepared for some saved state 67 * fixups / trouble! 68 */ 69 #define HDA_MAX_SDI 4 70 #define HDA_MAX_SDO 4 71 #define HDA_MAX_STREAMS (HDA_MAX_SDI + HDA_MAX_SDO) 72 73 /** Number of general registers. */ 74 #define HDA_NUM_GENERAL_REGS 34 75 /** Number of total registers in the HDA's register map. */ 76 #define HDA_NUM_REGS (HDA_NUM_GENERAL_REGS + (HDA_MAX_STREAMS * 10 /* Each stream descriptor has 10 registers */)) 77 /** Total number of stream tags (channels). Index 0 is reserved / invalid. */ 78 #define HDA_MAX_TAGS 16 79 80 /* 81 * ICH6 datasheet defines limits for FIFOS registers (18.2.39) 82 * formula: size - 1 83 * Other values not listed are not supported. 84 */ 85 /** Maximum FIFO size (in bytes). */ 86 #define HDA_FIFO_MAX 256 87 88 /** Default timer frequency (in Hz). 89 * 90 * Note: Keep in mind that the Hz rate has nothing to do with samples rates 91 * or DMA / interrupt timing -- it's purely needed in order to drive 92 * the data flow at a constant (and sufficient) rate. 93 * 94 * Lowering this value can ask for trouble, as backends then can run 95 * into data underruns. */ 96 #define HDA_TIMER_HZ 200 97 98 /** HDA's (fixed) audio frame size in bytes. 99 * We only support 16-bit stereo frames at the moment. */ 100 #define HDA_FRAME_SIZE 4 101 102 /** Offset of the SD0 register map. */ 103 #define HDA_REG_DESC_SD0_BASE 0x80 104 105 /** Turn a short global register name into an memory index and a stringized name. */ 106 #define HDA_REG_IDX(abbrev) HDA_MEM_IND_NAME(abbrev), #abbrev 107 108 /** Turns a short stream register name into an memory index and a stringized name. */ 109 #define HDA_REG_IDX_STRM(reg, suff) HDA_MEM_IND_NAME(reg ## suff), #reg #suff 110 111 /** Same as above for a register *not* stored in memory. */ 112 #define HDA_REG_IDX_NOMEM(abbrev) 0, #abbrev 113 114 extern const HDAREGDESC g_aHdaRegMap[HDA_NUM_REGS]; 115 116 /** 117 * NB: Register values stored in memory (au32Regs[]) are indexed through 118 * the HDA_RMX_xxx macros (also HDA_MEM_IND_NAME()). On the other hand, the 119 * register descriptors in g_aHdaRegMap[] are indexed through the 120 * HDA_REG_xxx macros (also HDA_REG_IND_NAME()). 121 * 122 * The au32Regs[] layout is kept unchanged for saved state 123 * compatibility. 124 */ 125 126 /* Registers */ 127 #define HDA_REG_IND_NAME(x) HDA_REG_##x 128 #define HDA_MEM_IND_NAME(x) HDA_RMX_##x 129 #define HDA_REG_IND(pThis, x) ((pThis)->au32Regs[g_aHdaRegMap[x].mem_idx]) 130 #define HDA_REG(pThis, x) (HDA_REG_IND((pThis), HDA_REG_IND_NAME(x))) 131 132 133 #define HDA_REG_GCAP 0 /* range 0x00-0x01*/ 134 #define HDA_RMX_GCAP 0 135 /* GCAP HDASpec 3.3.2 This macro encodes the following information about HDA in a compact manner: 136 * oss (15:12) - number of output streams supported 137 * iss (11:8) - number of input streams supported 138 * bss (7:3) - number of bidirectional streams supported 139 * bds (2:1) - number of serial data out (SDO) signals supported 140 * b64sup (0) - 64 bit addressing supported. 141 */ 142 #define HDA_MAKE_GCAP(oss, iss, bss, bds, b64sup) \ 143 ( (((oss) & 0xF) << 12) \ 144 | (((iss) & 0xF) << 8) \ 145 | (((bss) & 0x1F) << 3) \ 146 | (((bds) & 0x3) << 2) \ 147 | ((b64sup) & 1)) 148 149 #define HDA_REG_VMIN 1 /* 0x02 */ 150 #define HDA_RMX_VMIN 1 151 152 #define HDA_REG_VMAJ 2 /* 0x03 */ 153 #define HDA_RMX_VMAJ 2 154 155 #define HDA_REG_OUTPAY 3 /* 0x04-0x05 */ 156 #define HDA_RMX_OUTPAY 3 157 158 #define HDA_REG_INPAY 4 /* 0x06-0x07 */ 159 #define HDA_RMX_INPAY 4 160 161 #define HDA_REG_GCTL 5 /* 0x08-0x0B */ 162 #define HDA_RMX_GCTL 5 163 #define HDA_GCTL_UNSOL RT_BIT(8) /* Accept Unsolicited Response Enable */ 164 #define HDA_GCTL_FCNTRL RT_BIT(1) /* Flush Control */ 165 #define HDA_GCTL_CRST RT_BIT(0) /* Controller Reset */ 166 167 #define HDA_REG_WAKEEN 6 /* 0x0C */ 168 #define HDA_RMX_WAKEEN 6 169 170 #define HDA_REG_STATESTS 7 /* 0x0E */ 171 #define HDA_RMX_STATESTS 7 172 #define HDA_STATESTS_SCSF_MASK 0x7 /* State Change Status Flags (6.2.8). */ 173 174 #define HDA_REG_GSTS 8 /* 0x10-0x11*/ 175 #define HDA_RMX_GSTS 8 176 #define HDA_GSTS_FSTS RT_BIT(1) /* Flush Status */ 177 178 #define HDA_REG_OUTSTRMPAY 9 /* 0x18 */ 179 #define HDA_RMX_OUTSTRMPAY 112 180 181 #define HDA_REG_INSTRMPAY 10 /* 0x1a */ 182 #define HDA_RMX_INSTRMPAY 113 183 184 #define HDA_REG_INTCTL 11 /* 0x20 */ 185 #define HDA_RMX_INTCTL 9 186 #define HDA_INTCTL_GIE RT_BIT(31) /* Global Interrupt Enable */ 187 #define HDA_INTCTL_CIE RT_BIT(30) /* Controller Interrupt Enable */ 188 /* Bits 0-29 correspond to streams 0-29. */ 189 #define HDA_STRMINT_MASK 0xFF /* Streams 0-7 implemented. Applies to INTCTL and INTSTS. */ 190 191 #define HDA_REG_INTSTS 12 /* 0x24 */ 192 #define HDA_RMX_INTSTS 10 193 #define HDA_INTSTS_GIS RT_BIT(31) /* Global Interrupt Status */ 194 #define HDA_INTSTS_CIS RT_BIT(30) /* Controller Interrupt Status */ 195 /* Bits 0-29 correspond to streams 0-29. */ 196 197 #define HDA_REG_WALCLK 13 /* 0x30 */ 198 /* NB: HDA_RMX_WALCLK is not defined because the register is not stored in memory. */ 199 200 /* Note: The HDA specification defines a SSYNC register at offset 0x38. The 201 * ICH6/ICH9 datahseet defines SSYNC at offset 0x34. The Linux HDA driver matches 202 * the datasheet. 203 */ 204 #define HDA_REG_SSYNC 14 /* 0x34 */ 205 #define HDA_RMX_SSYNC 12 206 207 #define HDA_REG_CORBLBASE 15 /* 0x40 */ 208 #define HDA_RMX_CORBLBASE 13 209 210 #define HDA_REG_CORBUBASE 16 /* 0x44 */ 211 #define HDA_RMX_CORBUBASE 14 212 213 #define HDA_REG_CORBWP 17 /* 0x48 */ 214 #define HDA_RMX_CORBWP 15 215 216 #define HDA_REG_CORBRP 18 /* 0x4A */ 217 #define HDA_RMX_CORBRP 16 218 #define HDA_CORBRP_RST RT_BIT(15) /* CORB Read Pointer Reset */ 219 220 #define HDA_REG_CORBCTL 19 /* 0x4C */ 221 #define HDA_RMX_CORBCTL 17 222 #define HDA_CORBCTL_DMA RT_BIT(1) /* Enable CORB DMA Engine */ 223 #define HDA_CORBCTL_CMEIE RT_BIT(0) /* CORB Memory Error Interrupt Enable */ 224 225 #define HDA_REG_CORBSTS 20 /* 0x4D */ 226 #define HDA_RMX_CORBSTS 18 227 228 #define HDA_REG_CORBSIZE 21 /* 0x4E */ 229 #define HDA_RMX_CORBSIZE 19 230 /* NB: Up to and including ICH 10, sizes of CORB and RIRB are fixed at 256 entries. */ 231 232 #define HDA_REG_RIRBLBASE 22 /* 0x50 */ 233 #define HDA_RMX_RIRBLBASE 20 234 235 #define HDA_REG_RIRBUBASE 23 /* 0x54 */ 236 #define HDA_RMX_RIRBUBASE 21 237 238 #define HDA_REG_RIRBWP 24 /* 0x58 */ 239 #define HDA_RMX_RIRBWP 22 240 #define HDA_RIRBWP_RST RT_BIT(15) /* RIRB Write Pointer Reset */ 241 242 #define HDA_REG_RINTCNT 25 /* 0x5A */ 243 #define HDA_RMX_RINTCNT 23 244 #define RINTCNT_N(pThis) (HDA_REG(pThis, RINTCNT) & 0xff) 245 246 #define HDA_REG_RIRBCTL 26 /* 0x5C */ 247 #define HDA_RMX_RIRBCTL 24 248 #define HDA_RIRBCTL_ROIC RT_BIT(2) /* Response Overrun Interrupt Control */ 249 #define HDA_RIRBCTL_RDMAEN RT_BIT(1) /* RIRB DMA Enable */ 250 #define HDA_RIRBCTL_RINTCTL RT_BIT(0) /* Response Interrupt Control */ 251 252 #define HDA_REG_RIRBSTS 27 /* 0x5D */ 253 #define HDA_RMX_RIRBSTS 25 254 #define HDA_RIRBSTS_RIRBOIS RT_BIT(2) /* Response Overrun Interrupt Status */ 255 #define HDA_RIRBSTS_RINTFL RT_BIT(0) /* Response Interrupt Flag */ 256 257 #define HDA_REG_RIRBSIZE 28 /* 0x5E */ 258 #define HDA_RMX_RIRBSIZE 26 259 260 #define HDA_REG_IC 29 /* 0x60 */ 261 #define HDA_RMX_IC 27 262 263 #define HDA_REG_IR 30 /* 0x64 */ 264 #define HDA_RMX_IR 28 265 266 #define HDA_REG_IRS 31 /* 0x68 */ 267 #define HDA_RMX_IRS 29 268 #define HDA_IRS_IRV RT_BIT(1) /* Immediate Result Valid */ 269 #define HDA_IRS_ICB RT_BIT(0) /* Immediate Command Busy */ 270 271 #define HDA_REG_DPLBASE 32 /* 0x70 */ 272 #define HDA_RMX_DPLBASE 30 273 274 #define HDA_REG_DPUBASE 33 /* 0x74 */ 275 #define HDA_RMX_DPUBASE 31 276 277 #define DPBASE_ADDR_MASK (~(uint64_t)0x7f) 278 279 #define HDA_STREAM_REG_DEF(name, num) (HDA_REG_SD##num##name) 280 #define HDA_STREAM_RMX_DEF(name, num) (HDA_RMX_SD##num##name) 281 /* Note: sdnum here _MUST_ be stream reg number [0,7]. */ 282 #define HDA_STREAM_REG(pThis, name, sdnum) (HDA_REG_IND((pThis), HDA_REG_SD0##name + (sdnum) * 10)) 283 284 #define HDA_SD_NUM_FROM_REG(pThis, func, reg) ((reg - HDA_STREAM_REG_DEF(func, 0)) / 10) 285 286 /** @todo Condense marcos! */ 287 288 #define HDA_REG_SD0CTL HDA_NUM_GENERAL_REGS /* 0x80; other streams offset by 0x20 */ 289 #define HDA_RMX_SD0CTL 32 290 #define HDA_RMX_SD1CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 10) 291 #define HDA_RMX_SD2CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 20) 292 #define HDA_RMX_SD3CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 30) 293 #define HDA_RMX_SD4CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 40) 294 #define HDA_RMX_SD5CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 50) 295 #define HDA_RMX_SD6CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 60) 296 #define HDA_RMX_SD7CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 70) 297 298 #define HDA_SDCTL_NUM_MASK 0xF 299 #define HDA_SDCTL_NUM_SHIFT 20 300 #define HDA_SDCTL_DIR RT_BIT(19) /* Direction (Bidirectional streams only!) */ 301 #define HDA_SDCTL_TP RT_BIT(18) /* Traffic Priority (PCI Express) */ 302 #define HDA_SDCTL_STRIPE_MASK 0x3 303 #define HDA_SDCTL_STRIPE_SHIFT 16 304 #define HDA_SDCTL_DEIE RT_BIT(4) /* Descriptor Error Interrupt Enable */ 305 #define HDA_SDCTL_FEIE RT_BIT(3) /* FIFO Error Interrupt Enable */ 306 #define HDA_SDCTL_IOCE RT_BIT(2) /* Interrupt On Completion Enable */ 307 #define HDA_SDCTL_RUN RT_BIT(1) /* Stream Run */ 308 #define HDA_SDCTL_SRST RT_BIT(0) /* Stream Reset */ 309 310 #define HDA_REG_SD0STS 35 /* 0x83; other streams offset by 0x20 */ 311 #define HDA_RMX_SD0STS 33 312 #define HDA_RMX_SD1STS (HDA_STREAM_RMX_DEF(STS, 0) + 10) 313 #define HDA_RMX_SD2STS (HDA_STREAM_RMX_DEF(STS, 0) + 20) 314 #define HDA_RMX_SD3STS (HDA_STREAM_RMX_DEF(STS, 0) + 30) 315 #define HDA_RMX_SD4STS (HDA_STREAM_RMX_DEF(STS, 0) + 40) 316 #define HDA_RMX_SD5STS (HDA_STREAM_RMX_DEF(STS, 0) + 50) 317 #define HDA_RMX_SD6STS (HDA_STREAM_RMX_DEF(STS, 0) + 60) 318 #define HDA_RMX_SD7STS (HDA_STREAM_RMX_DEF(STS, 0) + 70) 319 320 #define HDA_SDSTS_FIFORDY RT_BIT(5) /* FIFO Ready */ 321 #define HDA_SDSTS_DESE RT_BIT(4) /* Descriptor Error */ 322 #define HDA_SDSTS_FIFOE RT_BIT(3) /* FIFO Error */ 323 #define HDA_SDSTS_BCIS RT_BIT(2) /* Buffer Completion Interrupt Status */ 324 325 #define HDA_REG_SD0LPIB 36 /* 0x84; other streams offset by 0x20 */ 326 #define HDA_REG_SD1LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 10) /* 0xA4 */ 327 #define HDA_REG_SD2LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 20) /* 0xC4 */ 328 #define HDA_REG_SD3LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 30) /* 0xE4 */ 329 #define HDA_REG_SD4LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 40) /* 0x104 */ 330 #define HDA_REG_SD5LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 50) /* 0x124 */ 331 #define HDA_REG_SD6LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 60) /* 0x144 */ 332 #define HDA_REG_SD7LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 70) /* 0x164 */ 333 #define HDA_RMX_SD0LPIB 34 334 #define HDA_RMX_SD1LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 10) 335 #define HDA_RMX_SD2LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 20) 336 #define HDA_RMX_SD3LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 30) 337 #define HDA_RMX_SD4LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 40) 338 #define HDA_RMX_SD5LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 50) 339 #define HDA_RMX_SD6LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 60) 340 #define HDA_RMX_SD7LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 70) 341 342 #define HDA_REG_SD0CBL 37 /* 0x88; other streams offset by 0x20 */ 343 #define HDA_RMX_SD0CBL 35 344 #define HDA_RMX_SD1CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 10) 345 #define HDA_RMX_SD2CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 20) 346 #define HDA_RMX_SD3CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 30) 347 #define HDA_RMX_SD4CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 40) 348 #define HDA_RMX_SD5CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 50) 349 #define HDA_RMX_SD6CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 60) 350 #define HDA_RMX_SD7CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 70) 351 352 #define HDA_REG_SD0LVI 38 /* 0x8C; other streams offset by 0x20 */ 353 #define HDA_RMX_SD0LVI 36 354 #define HDA_RMX_SD1LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 10) 355 #define HDA_RMX_SD2LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 20) 356 #define HDA_RMX_SD3LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 30) 357 #define HDA_RMX_SD4LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 40) 358 #define HDA_RMX_SD5LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 50) 359 #define HDA_RMX_SD6LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 60) 360 #define HDA_RMX_SD7LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 70) 361 362 #define HDA_REG_SD0FIFOW 39 /* 0x8E; other streams offset by 0x20 */ 363 #define HDA_RMX_SD0FIFOW 37 364 #define HDA_RMX_SD1FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 10) 365 #define HDA_RMX_SD2FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 20) 366 #define HDA_RMX_SD3FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 30) 367 #define HDA_RMX_SD4FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 40) 368 #define HDA_RMX_SD5FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 50) 369 #define HDA_RMX_SD6FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 60) 370 #define HDA_RMX_SD7FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 70) 371 372 /* 373 * ICH6 datasheet defined limits for FIFOW values (18.2.38). 374 */ 375 #define HDA_SDFIFOW_8B 0x2 376 #define HDA_SDFIFOW_16B 0x3 377 #define HDA_SDFIFOW_32B 0x4 378 379 #define HDA_REG_SD0FIFOS 40 /* 0x90; other streams offset by 0x20 */ 380 #define HDA_RMX_SD0FIFOS 38 381 #define HDA_RMX_SD1FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 10) 382 #define HDA_RMX_SD2FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 20) 383 #define HDA_RMX_SD3FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 30) 384 #define HDA_RMX_SD4FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 40) 385 #define HDA_RMX_SD5FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 50) 386 #define HDA_RMX_SD6FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 60) 387 #define HDA_RMX_SD7FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 70) 388 389 #define HDA_SDIFIFO_120B 0x77 /* 8-, 16-, 20-, 24-, 32-bit Input Streams */ 390 #define HDA_SDIFIFO_160B 0x9F /* 20-, 24-bit Input Streams Streams */ 391 392 #define HDA_SDOFIFO_16B 0x0F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */ 393 #define HDA_SDOFIFO_32B 0x1F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */ 394 #define HDA_SDOFIFO_64B 0x3F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */ 395 #define HDA_SDOFIFO_128B 0x7F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */ 396 #define HDA_SDOFIFO_192B 0xBF /* 8-, 16-, 20-, 24-, 32-bit Output Streams */ 397 #define HDA_SDOFIFO_256B 0xFF /* 20-, 24-bit Output Streams */ 398 399 #define HDA_REG_SD0FMT 41 /* 0x92; other streams offset by 0x20 */ 400 #define HDA_RMX_SD0FMT 39 401 #define HDA_RMX_SD1FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 10) 402 #define HDA_RMX_SD2FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 20) 403 #define HDA_RMX_SD3FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 30) 404 #define HDA_RMX_SD4FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 40) 405 #define HDA_RMX_SD5FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 50) 406 #define HDA_RMX_SD6FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 60) 407 #define HDA_RMX_SD7FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 70) 408 409 #define HDA_REG_SD0BDPL 42 /* 0x98; other streams offset by 0x20 */ 410 #define HDA_RMX_SD0BDPL 40 411 #define HDA_RMX_SD1BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 10) 412 #define HDA_RMX_SD2BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 20) 413 #define HDA_RMX_SD3BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 30) 414 #define HDA_RMX_SD4BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 40) 415 #define HDA_RMX_SD5BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 50) 416 #define HDA_RMX_SD6BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 60) 417 #define HDA_RMX_SD7BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 70) 418 419 #define HDA_REG_SD0BDPU 43 /* 0x9C; other streams offset by 0x20 */ 420 #define HDA_RMX_SD0BDPU 41 421 #define HDA_RMX_SD1BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 10) 422 #define HDA_RMX_SD2BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 20) 423 #define HDA_RMX_SD3BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 30) 424 #define HDA_RMX_SD4BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 40) 425 #define HDA_RMX_SD5BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 50) 426 #define HDA_RMX_SD6BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 60) 427 #define HDA_RMX_SD7BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 70) 428 429 #define HDA_CODEC_CAD_SHIFT 28 430 /* Encodes the (required) LUN into a codec command. */ 431 #define HDA_CODEC_CMD(cmd, lun) ((cmd) | (lun << HDA_CODEC_CAD_SHIFT)) 20 432 21 433 #define HDA_SDFMT_NON_PCM_SHIFT 15 … … 72 484 | ( (_aChan) & HDA_SDFMT_CHANNELS_MASK)) 73 485 74 #endif /* DEV_HDA_COMMON_H */ 75 486 /** Interrupt on completion (IOC) flag. */ 487 #define HDA_BDLE_FLAG_IOC RT_BIT(0) 488 489 /********************************************************************************************************************************* 490 * Prototypes * 491 *********************************************************************************************************************************/ 492 493 /** The HDA controller. */ 494 typedef struct HDASTATE *PHDASTATE; 495 /** The HDA stream. */ 496 typedef struct HDASTREAM *PHDASTREAM; 497 498 typedef struct HDAMIXERSINK *PHDAMIXERSINK; 499 500 501 /** 502 * Internal state of a Buffer Descriptor List Entry (BDLE), 503 * needed to keep track of the data needed for the actual device 504 * emulation. 505 */ 506 typedef struct HDABDLESTATE 507 { 508 /** Own index within the BDL (Buffer Descriptor List). */ 509 uint32_t u32BDLIndex; 510 /** Number of bytes below the stream's FIFO watermark (SDFIFOW). 511 * Used to check if we need fill up the FIFO again. */ 512 uint32_t cbBelowFIFOW; 513 /** Current offset in DMA buffer (in bytes).*/ 514 uint32_t u32BufOff; 515 uint32_t Padding; 516 } HDABDLESTATE, *PHDABDLESTATE; 517 518 /** 519 * BDL description structure. 520 * Do not touch this, as this must match to the HDA specs. 521 */ 522 typedef struct HDABDLEDESC 523 { 524 /** Starting address of the actual buffer. Must be 128-bit aligned. */ 525 uint64_t u64BufAdr; 526 /** Size of the actual buffer (in bytes). */ 527 uint32_t u32BufSize; 528 /** Bit 0: Interrupt on completion; the controller will generate 529 * an interrupt when the last byte of the buffer has been 530 * fetched by the DMA engine. 531 * 532 * Rest is reserved for further use and must be 0. */ 533 uint32_t fFlags; 534 } HDABDLEDESC, *PHDABDLEDESC; 535 536 /** 537 * Buffer Descriptor List Entry (BDLE) (3.6.3). 538 */ 539 typedef struct HDABDLE 540 { 541 /** The actual BDL description. */ 542 HDABDLEDESC Desc; 543 /** Internal state of this BDLE. 544 * Not part of the actual BDLE registers. */ 545 HDABDLESTATE State; 546 } HDABDLE, *PHDABDLE; 547 548 /** @name Object lookup functions. 549 * @{ 550 */ 551 PDMAUDIODIR hdaGetDirFromSD(uint8_t uSD); 552 PHDASTREAM hdaStreamGetFromSD(PHDASTATE pThis, uint8_t uSD); 553 PHDASTREAM hdaSinkGetStream(PHDASTATE pThis, PHDAMIXERSINK pSink); 554 /** @} */ 555 556 /** @name Interrupt functions. 557 * @{ 558 */ 559 #ifdef DEBUG 560 int hdaProcessInterrupt(PHDASTATE pThis, const char *pszSource); 561 #else 562 int hdaProcessInterrupt(PHDASTATE pThis); 563 #endif 564 /** @} */ 565 566 /** @name Wall clock (WALCLK) functions. 567 * @{ 568 */ 569 uint64_t hdaWalClkGetCurrent(PHDASTATE pThis); 570 #ifdef IN_RING3 571 bool hdaWalClkSet(PHDASTATE pThis, uint64_t u64WalClk, bool fForce); 572 #endif 573 /** @} */ 574 575 /** @name DMA utility functions. 576 * @{ 577 */ 578 int hdaDMARead(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToRead, uint32_t *pcbRead); 579 int hdaDMAWrite(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToWrite, uint32_t *pcbWritten); 580 /** @} */ 581 582 /** @name Register functions. 583 * @{ 584 */ 585 uint32_t hdaGetINTSTS(PHDASTATE pThis); 586 #ifdef IN_RING3 587 int hdaSDFMTToPCMProps(uint32_t u32SDFMT, PPDMAUDIOPCMPROPS pProps); 588 #endif /* IN_RING3 */ 589 /** @} */ 590 591 /** @name BDLE (Buffer Descriptor List Entry) functions. 592 * @{ 593 */ 594 #ifdef IN_RING3 595 int hdaBDLEFetch(PHDASTATE pThis, PHDABDLE pBDLE, uint64_t u64BaseDMA, uint16_t u16Entry); 596 bool hdaBDLEIsComplete(PHDABDLE pBDLE); 597 bool hdaBDLENeedsInterrupt(PHDABDLE pBDLE); 598 #endif /* IN_RING3 */ 599 /** @} */ 600 601 #endif /* DEV_HDA_H_COMMON */ 602 -
trunk/src/VBox/Devices/Audio/HDACodec.h
r67534 r67899 18 18 #ifndef DEV_HDA_CODEC_H 19 19 #define DEV_HDA_CODEC_H 20 21 #include <iprt/list.h> 22 23 #include "AudioMixer.h" 20 24 21 25 /** The ICH HDA (Intel) controller. */ -
trunk/src/VBox/Devices/Makefile.kmk
r67699 r67899 596 596 Audio/DevSB16.cpp \ 597 597 Audio/DevHDA.cpp \ 598 Audio/DevHDACommon.cpp \ 598 599 Audio/HDACodec.cpp \ 600 Audio/HDAStream.cpp \ 599 601 Audio/HDAStreamChannel.cpp \ 600 602 Audio/HDAStreamMap.cpp \
Note:
See TracChangeset
for help on using the changeset viewer.

