Changeset 34443 in vbox
- Timestamp:
- Nov 29, 2010 7:42:11 AM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DevIchIntelHDA.cpp
r34350 r34443 223 223 #define HDA_STREAM_REG_DEF(name, num) (ICH6_HDA_REG_SD##num##name) 224 224 #define HDA_STREAM_REG(pState, name, num) (HDA_REG((pState), N_(HDA_STREAM_REG_DEF(name, num)))) 225 /* Note: sdnum here _MUST_ be stream reg number [0,7] */ 226 #define HDA_STREAM_REG2(pState, name, sdnum) (HDA_REG_IND((pState), ICH6_HDA_REG_SD0##name + (sdnum) * 10)) 225 227 226 228 #define ICH6_HDA_REG_SD0CTL 32 /* 0x80 */ … … 387 389 uint8_t au8HdaBuffer[HDA_SDONFIFO_256B + 1]; 388 390 } HDABDLEDESC, *PHDABDLEDESC; 391 392 typedef struct HDASTREAMTRANSFERDESC 393 { 394 uint64_t u64BaseDMA; 395 uint32_t u32Ctl; 396 uint32_t *pu32Sts; 397 uint8_t u8Strm; 398 uint32_t *pu32Lpib; 399 uint32_t u32Cbl; 400 uint32_t u32Fifos; 401 } HDASTREAMTRANSFERDESC, *PHDASTREAMTRANSFERDESC; 389 402 390 403 typedef struct INTELHDLinkState … … 420 433 CODECState Codec; 421 434 uint8_t u8Counter; 422 uint8_t u8StreamsInReset; 423 } INTELHDLinkState; 435 } INTELHDLinkState, *PINTELHDLinkState; 424 436 425 437 #define ICH6_HDASTATE_2_DEVINS(pINTELHD) ((pINTELHD)->pDevIns) … … 476 488 DECLCALLBACK(int)hdaRegReadU8(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value); 477 489 DECLCALLBACK(int)hdaRegWriteU8(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t pu32Value); 490 491 static inline void hdaInitTransferDescriptor(PINTELHDLinkState pState, PHDABDLEDESC pBdle, uint8_t u8Strm, PHDASTREAMTRANSFERDESC pStreamDesc); 478 492 static int hdaLookup(INTELHDLinkState* pState, uint32_t u32Offset); 479 static void fetch_bd(INTELHDLinkState *pState, PHDABDLEDESC pBdle, uint64_t u64BaseDMA); 493 static void hdaFetchBdle(INTELHDLinkState *pState, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc); 494 #ifdef LOG_ENABLED 495 static void dump_bd(INTELHDLinkState *pState, PHDABDLEDESC pBdle, uint64_t u64BaseDMA); 496 #endif 480 497 481 498 /* see 302349 p 6.2*/ … … 626 643 }; 627 644 628 static void inline hdaUpdatePosBuf(INTELHDLinkState *pState, uint8_t u8Strm, uint32_t u32Value)645 static void inline hdaUpdatePosBuf(INTELHDLinkState *pState, PHDASTREAMTRANSFERDESC pStreamDesc) 629 646 { 630 647 if (pState->u64DPBase & DPBASE_ENABLED) 631 648 PDMDevHlpPhysWrite(ICH6_HDASTATE_2_DEVINS(pState), 632 (pState->u64DPBase & DPBASE_ADDR_MASK) + u8Strm*8, &u32Value, sizeof(uint32_t)); 633 } 634 static uint32_t inline hdaFifoWToSz(INTELHDLinkState *pState, int iNum) 635 { 636 switch (ICH6_HDA_REG_SD0FIFOW + 10*iNum) 637 { 638 case ICH6_HDA_REG_SD0FIFOW: 639 case ICH6_HDA_REG_SD1FIFOW: 640 case ICH6_HDA_REG_SD2FIFOW: 641 case ICH6_HDA_REG_SD3FIFOW: 642 case ICH6_HDA_REG_SD4FIFOW: 643 case ICH6_HDA_REG_SD5FIFOW: 644 case ICH6_HDA_REG_SD6FIFOW: 645 case ICH6_HDA_REG_SD7FIFOW: 646 switch(HDA_REG_IND(pState, ICH6_HDA_REG_SD0FIFOW + 10*iNum)) 647 { 648 case HDA_SDFIFOW_8B: return 8; 649 case HDA_SDFIFOW_16B: return 16; 650 case HDA_SDFIFOW_32B: return 32; 651 default: 652 AssertMsgFailed(("hda: unsupported value (%x) in SDFIFOW(,%d)\n", HDA_REG_IND(pState, iNum), iNum)); 653 } 649 (pState->u64DPBase & DPBASE_ADDR_MASK) + pStreamDesc->u8Strm*8, pStreamDesc->pu32Lpib, sizeof(uint32_t)); 650 } 651 static uint32_t inline hdaFifoWToSz(INTELHDLinkState *pState, PHDASTREAMTRANSFERDESC pStreamDesc) 652 { 653 switch(HDA_STREAM_REG2(pState, FIFOW, pStreamDesc->u8Strm)) 654 { 655 case HDA_SDFIFOW_8B: return 8; 656 case HDA_SDFIFOW_16B: return 16; 657 case HDA_SDFIFOW_32B: return 32; 654 658 default: 655 AssertMsgFailed(("hda: Not SDnFIFOW register"));656 return 0;657 }659 AssertMsgFailed(("hda: unsupported value (%x) in SDFIFOW(,%d)\n", HDA_REG_IND(pState, pStreamDesc->u8Strm), pStreamDesc->u8Strm)); 660 } 661 return 0; 658 662 } 659 663 … … 837 841 } 838 842 839 static void hdaStreamReset(INTELHDLinkState *pState, uint32_t u32Offset) 840 { 841 Log(("hda: reset of stream (%x) started\n", u32Offset)); 842 Log(("hda: reset of stream (%x) finished\n", u32Offset)); 843 static void hdaStreamReset(INTELHDLinkState *pState, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc, uint8_t u8Strm) 844 { 845 Log(("hda: reset of stream (%d) started\n", u8Strm)); 846 Assert(( pState 847 && pBdle 848 && pStreamDesc 849 && u8Strm <= 7)); 850 memset(pBdle, 0, sizeof(HDABDLEDESC)); 851 *pStreamDesc->pu32Lpib = 0; 852 *pStreamDesc->pu32Sts = 0; 853 /* According to ICH6 datasheet, 0x40000 is default value for stream descriptor register 23:20 854 * bits are reserved for stream number 18.2.33, resets SDnCTL except SRCT bit */ 855 HDA_STREAM_REG2(pState, CTL, u8Strm) = 0x40000 | (HDA_STREAM_REG2(pState, CTL, u8Strm) & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST)); 856 857 /* ICH6 defines default values (0x77 for input and 0xBF for output descriptors) of FIFO size. 18.2.39 */ 858 HDA_STREAM_REG2(pState, FIFOS, u8Strm) = u8Strm < 4 ? HDA_SDINFIFO_120B : HDA_SDONFIFO_192B; 859 HDA_STREAM_REG2(pState, FIFOW, u8Strm) = u8Strm < 4 ? HDA_SDFIFOW_8B : HDA_SDFIFOW_32B; 860 HDA_STREAM_REG2(pState, CBL, u8Strm) = 0; 861 HDA_STREAM_REG2(pState, LVI, u8Strm) = 0; 862 HDA_STREAM_REG2(pState, FMT, u8Strm) = 0; 863 HDA_STREAM_REG2(pState, BDPU, u8Strm) = 0; 864 HDA_STREAM_REG2(pState, BDPL, u8Strm) = 0; 865 Log(("hda: reset of stream (%d) finished\n", u8Strm)); 843 866 } 844 867 … … 944 967 uint32_t v = pState->au32Regs[index]; 945 968 uint32_t nv = u32Value & ICH6_HDA_STATES_SCSF; 946 pState->au32Regs[index] = (v ^ nv) & v; /* write of 1 clears corresponding bit */969 pState->au32Regs[index] &= ~(v & nv); /* write of 1 clears corresponding bit */ 947 970 return VINF_SUCCESS; 948 971 } … … 1001 1024 { 1002 1025 uint32_t v = CORBSTS(pState); 1003 v = (v ^ u32Value) & v; 1004 CORBSTS(pState) = v; 1026 CORBSTS(pState) &= ~(v & u32Value); 1005 1027 return VINF_SUCCESS; 1006 1028 } … … 1024 1046 return hdaRegReadU24(pState, offset, index, pu32Value); 1025 1047 } 1026 #define HDA_STREAM_BITMASK(offset) (1 << (((offset) - 0x80) >> 5)) 1027 #define HDA_IS_STREAM_IN_RESET(pState, offset) ((pState)->u8StreamsInReset & HDA_STREAM_BITMASK((offset))) 1048 1028 1049 DECLCALLBACK(int)hdaRegWriteSDCTL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value) 1029 1050 { 1030 bool fOn = RT_BOOL((u32Value & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN))); 1051 bool fRun = RT_BOOL((u32Value & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN))); 1052 bool fInRun = RT_BOOL((HDA_REG_IND(pState, index) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN))); 1053 bool fReset = RT_BOOL((u32Value & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST))); 1054 bool fInReset = RT_BOOL((HDA_REG_IND(pState, index) & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST))); 1031 1055 int rc = VINF_SUCCESS; 1032 uint64_t u64BaseDMA = 0; 1033 uint8_t u8Strm = 0; 1034 PHDABDLEDESC pBdle = NULL; 1035 uint32_t *pu32Lpib = 0; 1036 if(u32Value & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST)) 1037 { 1038 Log(("hda: guest has initiated hw stream reset\n")); 1039 pState->u8StreamsInReset |= HDA_STREAM_BITMASK(offset); 1040 hdaStreamReset(pState, offset); 1041 HDA_REG_IND(pState, index) &= ~HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST); 1042 } 1043 else if (HDA_IS_STREAM_IN_RESET(pState, offset)) 1044 { 1045 Log(("hda: guest has initiated exit of stream reset\n")); 1046 pState->u8StreamsInReset &= ~HDA_STREAM_BITMASK(offset); 1047 HDA_REG_IND(pState, index) &= ~HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST); 1048 } 1049 /* 1050 * Stopping streams we postpone up to reset exit to let HDA complete the tasks 1051 */ 1052 switch (index) 1053 { 1054 case ICH6_HDA_REG_SD0CTL: 1055 u8Strm = 0; 1056 pBdle = &pState->stInBdle; 1057 pu32Lpib = &SDLPIB(pState, 0); 1058 AUD_set_active_in(ISD0FMT_TO_AUDIO_SELECTOR(pState), fOn); 1059 Log(("hda: DMA SD0CTL switched %s\n", fOn ? "on" : " off")); 1056 if (fInReset) 1057 { 1058 /* Assert!!! Guest is resetting HDA's stream, we're expecting guest will mark stream as exit 1059 * from reset 1060 */ 1061 Assert((!fReset)); 1062 Log(("hda: guest initiate exit of stream reset.\n")); 1063 goto done; 1064 } 1065 else if (fReset) 1066 { 1067 /* 1068 * Assert!!! ICH6 datasheet 18.2.33 says that RUN bit should be cleared before initiation of reset. 1069 */ 1070 uint8_t u8Strm = 0; 1071 PHDABDLEDESC pBdle = NULL; 1072 HDASTREAMTRANSFERDESC stStreamDesc; 1073 Assert((!fInRun && !fRun)); 1074 switch (index) 1075 { 1076 case ICH6_HDA_REG_SD0CTL: 1077 u8Strm = 0; 1078 pBdle = &pState->stInBdle; 1060 1079 break; 1061 case ICH6_HDA_REG_SD4CTL: 1062 u8Strm = 4; 1063 pBdle = &pState->stOutBdle; 1064 1065 pu32Lpib = &SDLPIB(pState, 4); 1066 u64BaseDMA = RT_MAKE_U64(SDBDPL(pState, 4), SDBDPU(pState, 4)); 1067 fOn = fOn && u64BaseDMA; 1068 if (fOn) 1069 SDSTS(pState, 4) &= ~(1<<5); 1070 AUD_set_active_out(OSD0FMT_TO_AUDIO_SELECTOR(pState), fOn); 1071 Log(("hda: DMA SD4CTL switched %s\n", fOn ? "on" : " off")); 1080 case ICH6_HDA_REG_SD4CTL: 1081 u8Strm = 4; 1082 pBdle = &pState->stOutBdle; 1072 1083 break; 1073 default: 1074 Log(("Attempt to modify DMA state on unattached SDI(%s), ignored\n", s_ichIntelHDRegMap[index].abbrev)); 1075 break; 1076 } 1077 if ( !fOn 1078 && pBdle 1079 && pu32Lpib) 1080 { 1081 memset(pBdle, 0, sizeof(HDABDLEDESC)); 1082 *pu32Lpib = 0; 1083 hdaUpdatePosBuf(pState, u8Strm, 0); 1084 } 1084 default: 1085 Log(("hda: changing SRST bit on non-attached stream\n")); 1086 goto done; 1087 } 1088 Log(("hda: guest initiate enter to stream reset.\n")); 1089 hdaInitTransferDescriptor(pState, pBdle, u8Strm, &stStreamDesc); 1090 hdaStreamReset(pState, pBdle, &stStreamDesc, u8Strm); 1091 goto done; 1092 } 1093 1094 /* we enter here to change DMA states only */ 1095 if ( (fInRun && !fRun) 1096 || (fRun && !fInRun)) 1097 { 1098 Assert((!fReset && !fInReset)); 1099 switch (index) 1100 { 1101 case ICH6_HDA_REG_SD0CTL: 1102 AUD_set_active_in(ISD0FMT_TO_AUDIO_SELECTOR(pState), fRun); 1103 break; 1104 case ICH6_HDA_REG_SD4CTL: 1105 AUD_set_active_out(OSD0FMT_TO_AUDIO_SELECTOR(pState), fRun); 1106 break; 1107 default: 1108 Log(("hda: changing RUN bit on non-attached stream\n")); 1109 goto done; 1110 } 1111 } 1112 1113 done: 1085 1114 rc = hdaRegWriteU24(pState, offset, index, u32Value); 1086 1115 if (RT_FAILURE(rc)) … … 1092 1121 { 1093 1122 uint32_t v = HDA_REG_IND(pState, index); 1094 v ^=(u32Value & v);1123 v &= ~(u32Value & v); 1095 1124 HDA_REG_IND(pState, index) = v; 1096 1125 hdaProcessInterrupt(pState); 1097 #if 01098 if ( v != u32Value1099 && (INTCTL_SALL(pState) & (1 << ((offset - 0x83) >> 5))))1100 {1101 int rc;1102 rc = hdaProcessInterrupt(pState);1103 if (RT_FAILURE(rc))1104 AssertRCReturn(rc, rc);1105 }1106 #endif1107 1126 return VINF_SUCCESS; 1108 1127 } 1128 1109 1129 DECLCALLBACK(int)hdaRegWriteSDLVI(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value) 1110 1130 { … … 1292 1312 DECLCALLBACK(int)hdaRegWriteRIRBSTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value) 1293 1313 { 1294 uint8_t nv = u32Value;1295 1314 uint8_t v = RIRBSTS(pState); 1296 RIRBSTS(pState) = (v ^ nv) & v;1315 RIRBSTS(pState) &= ~(v & u32Value); 1297 1316 1298 1317 return hdaProcessInterrupt(pState); … … 1302 1321 static void dump_bd(INTELHDLinkState *pState, PHDABDLEDESC pBdle, uint64_t u64BaseDMA) 1303 1322 { 1323 #if 0 1304 1324 uint64_t addr; 1305 1325 uint32_t len; … … 1326 1346 i , counter)); 1327 1347 } 1328 }1329 1348 #endif 1330 1331 static void fetch_bd(INTELHDLinkState *pState, PHDABDLEDESC pBdle, uint64_t u64BaseDMA) 1349 } 1350 #endif 1351 1352 static void hdaFetchBdle(INTELHDLinkState *pState, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc) 1332 1353 { 1333 1354 uint8_t bdle[16]; 1334 Assert((u64BaseDMA && pBdle && pBdle->u32BdleMaxCvi)); 1335 PDMDevHlpPhysRead(ICH6_HDASTATE_2_DEVINS(pState), u64BaseDMA + pBdle->u32BdleCvi*16, bdle, 16); 1355 Assert(( pStreamDesc->u64BaseDMA 1356 && pBdle 1357 && pBdle->u32BdleMaxCvi)); 1358 PDMDevHlpPhysRead(ICH6_HDASTATE_2_DEVINS(pState), pStreamDesc->u64BaseDMA + pBdle->u32BdleCvi*16, bdle, 16); 1336 1359 pBdle->u64BdleCviAddr = *(uint64_t *)bdle; 1337 1360 pBdle->u32BdleCviLen = *(uint32_t *)&bdle[8]; 1338 1361 pBdle->fBdleCviIoc = (*(uint32_t *)&bdle[12]) & 0x1; 1339 1362 #ifdef LOG_ENABLED 1340 dump_bd(pState, pBdle, u64BaseDMA);1363 dump_bd(pState, pBdle, pStreamDesc->u64BaseDMA); 1341 1364 #endif 1342 1365 } 1343 1366 1344 static inline uint32_t hdaCalculateTransferBufferLength(PHDABDLEDESC pBdle, uint32_t u32SoundBackendBufferBytesAvail, uint32_t u32Fifos, uint32_t u32CblLimit)1367 static inline uint32_t hdaCalculateTransferBufferLength(PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc, uint32_t u32SoundBackendBufferBytesAvail, uint32_t u32CblLimit) 1345 1368 { 1346 1369 uint32_t cb2Copy; 1370 #if 0 1347 1371 if (u32SoundBackendBufferBytesAvail <= u32Fifos + 1) 1348 1372 { … … 1353 1377 return 0; 1354 1378 } 1379 #endif 1355 1380 /* 1356 1381 * Amounts of bytes depends on current position in buffer (u32BdleCviLen-u32BdleCviPos) … … 1361 1386 * we may increase the counter in range of [0, FIFOS + 1] 1362 1387 */ 1363 cb2Copy = RT_MIN(cb2Copy, u32Fifos + 1);1388 cb2Copy = RT_MIN(cb2Copy, pStreamDesc->u32Fifos + 1); 1364 1389 Assert((u32SoundBackendBufferBytesAvail > 0)); 1365 1390 … … 1416 1441 } 1417 1442 1418 static inline void hdaBackendTransferUnreported(INTELHDLinkState *pState, PHDABDLEDESC pBdle, uint8_t u8Strm, uint32_t cbCopied, uint32_t *pu32BackendBufferCapacity)1443 static inline void hdaBackendTransferUnreported(INTELHDLinkState *pState, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc, uint32_t cbCopied, uint32_t *pu32BackendBufferCapacity) 1419 1444 { 1420 1445 Log(("hda:hdaBackendTransferUnreported: CVI (cbUnderFifoW:%d, pos:%d, len:%d)\n", pBdle->cbUnderFifoW, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen)); … … 1425 1450 *pu32BackendBufferCapacity -= cbCopied; 1426 1451 Log(("hda:hdaBackendTransferUnreported: CVI (cbUnderFifoW:%d, pos:%d, len:%d)\n", pBdle->cbUnderFifoW, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen)); 1427 Assert((pBdle->cbUnderFifoW <= hdaFifoWToSz(pState, u8Strm))); 1428 } 1452 Assert((pBdle->cbUnderFifoW <= hdaFifoWToSz(pState, pStreamDesc))); 1453 } 1454 static inline bool hdaIsTransferCountersOverlapped(PINTELHDLinkState pState, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc) 1455 { 1456 bool fOnBufferEdge = ( *pStreamDesc->pu32Lpib == pStreamDesc->u32Cbl 1457 || pBdle->u32BdleCviPos == pBdle->u32BdleCviLen); 1458 Assert((*pStreamDesc->pu32Lpib <= pStreamDesc->u32Cbl)); 1459 if (*pStreamDesc->pu32Lpib == pStreamDesc->u32Cbl) 1460 *pStreamDesc->pu32Lpib -= pStreamDesc->u32Cbl; 1461 hdaUpdatePosBuf(pState, pStreamDesc); 1462 1463 if (pBdle->u32BdleCviPos == pBdle->u32BdleCviLen) 1464 { 1465 pBdle->u32BdleCviPos = 0; 1466 pBdle->u32BdleCvi++; 1467 if (pBdle->u32BdleCvi == pBdle->u32BdleMaxCvi + 1) 1468 pBdle->u32BdleCvi = 0; 1469 } 1470 return fOnBufferEdge; 1471 } 1472 1473 static inline void hdaStreamCounterUpdate(PINTELHDLinkState pState, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc, uint32_t cbInc) 1474 { 1475 /* 1476 * if we're under FIFO Watermark it's expected that HDA doesn't fetch anything. 1477 * (ICH6 datasheet 18.2.38) 1478 */ 1479 if (!pBdle->cbUnderFifoW) 1480 { 1481 *pStreamDesc->pu32Lpib += cbInc; 1482 1483 /* 1484 * Assert. Overlapping of buffer counter shouldn't happen. 1485 */ 1486 Assert((*pStreamDesc->pu32Lpib <= pStreamDesc->u32Cbl)); 1487 1488 hdaUpdatePosBuf(pState, pStreamDesc); 1489 1490 } 1491 } 1492 1493 static inline bool hdaDoNextTransferCycle(PINTELHDLinkState pState, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc) 1494 { 1495 bool fDoNextTransferLoop = true; 1496 if ( pBdle->u32BdleCviPos == pBdle->u32BdleCviLen 1497 || *pStreamDesc->pu32Lpib == pStreamDesc->u32Cbl) 1498 { 1499 if ( !pBdle->cbUnderFifoW 1500 && pBdle->fBdleCviIoc) 1501 { 1502 /* 1503 * @todo - more carefully investigate BCIS flag. 1504 * Speech synthesis works fine on Mac Guest if this bit isn't set 1505 * but in general sound quality becomes lesser. 1506 */ 1507 *pStreamDesc->pu32Sts |= HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS); 1508 /* 1509 * we should generate the interrupt if ICE bit of SDCTL register is set. 1510 */ 1511 if (pStreamDesc->u32Ctl & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE)) 1512 hdaProcessInterrupt(pState); 1513 } 1514 fDoNextTransferLoop = false; 1515 } 1516 return fDoNextTransferLoop; 1517 } 1518 1429 1519 /* 1430 1520 * hdaReadAudio - copies samples from Qemu Sound back-end to DMA. 1431 1521 * Note: this function writes immediately to DMA buffer, but "reports bytes" when all conditions meet (FIFOW) 1432 1522 */ 1433 static uint32_t hdaReadAudio(INTELHDLinkState *pState, uint32_t *pu32Avail, bool *fStop, uint32_t u32CblLimit)1523 static uint32_t hdaReadAudio(INTELHDLinkState *pState, PHDASTREAMTRANSFERDESC pStreamDesc, uint32_t *pu32Avail, bool *fStop, uint32_t u32CblLimit) 1434 1524 { 1435 1525 PHDABDLEDESC pBdle = &pState->stInBdle; … … 1440 1530 Log(("hda:ra: CVI(pos:%d, len:%d)\n", pBdle->u32BdleCviPos, pBdle->u32BdleCviLen)); 1441 1531 1442 cb2Copy = hdaCalculateTransferBufferLength(pBdle, *pu32Avail, SDFIFOS(pState, 0), u32CblLimit);1532 cb2Copy = hdaCalculateTransferBufferLength(pBdle, pStreamDesc, *pu32Avail, u32CblLimit); 1443 1533 if (!cb2Copy) 1444 1534 { … … 1465 1555 else 1466 1556 { 1467 hdaBackendTransferUnreported(pState, pBdle, 0, cbBackendCopy, pu32Avail);1557 hdaBackendTransferUnreported(pState, pBdle, pStreamDesc, cbBackendCopy, pu32Avail); 1468 1558 *fStop = true; 1469 1559 } … … 1474 1564 } 1475 1565 1476 static uint32_t hdaWriteAudio(INTELHDLinkState *pState, uint32_t *pu32Avail, bool *fStop, uint32_t u32CblLimit)1566 static uint32_t hdaWriteAudio(INTELHDLinkState *pState, PHDASTREAMTRANSFERDESC pStreamDesc, uint32_t *pu32Avail, bool *fStop, uint32_t u32CblLimit) 1477 1567 { 1478 1568 PHDABDLEDESC pBdle = &pState->stOutBdle; … … 1483 1573 Log(("hda:wa: CVI(cvi:%d, pos:%d, len:%d)\n", pBdle->u32BdleCvi, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen)); 1484 1574 1485 cb2Copy = hdaCalculateTransferBufferLength(pBdle, *pu32Avail, SDFIFOS(pState, 4), u32CblLimit);1575 cb2Copy = hdaCalculateTransferBufferLength(pBdle, pStreamDesc, *pu32Avail, u32CblLimit); 1486 1576 1487 1577 /* … … 1498 1588 * Write to audio backend. we should be sure whether we have enought bytes to copy to Audio backend. 1499 1589 */ 1500 if (cb2Copy + pBdle->cbUnderFifoW >= hdaFifoWToSz(pState, 4))1590 if (cb2Copy + pBdle->cbUnderFifoW >= hdaFifoWToSz(pState, pStreamDesc)) 1501 1591 { 1502 1592 /* … … 1509 1599 { 1510 1600 /* Not enough bytes to be processed and reported, check luck on next enterence */ 1511 hdaBackendTransferUnreported(pState, pBdle, 4, cb2Copy, NULL);1601 hdaBackendTransferUnreported(pState, pBdle, pStreamDesc, cb2Copy, NULL); 1512 1602 *fStop = true; 1513 1603 } … … 1525 1615 } 1526 1616 1617 static inline void hdaInitTransferDescriptor(PINTELHDLinkState pState, PHDABDLEDESC pBdle, uint8_t u8Strm, PHDASTREAMTRANSFERDESC pStreamDesc) 1618 { 1619 Assert(( pState 1620 && pBdle 1621 && pStreamDesc 1622 && u8Strm <= 7)); 1623 memset(pStreamDesc, 0, sizeof(HDASTREAMTRANSFERDESC)); 1624 pStreamDesc->u8Strm = u8Strm; 1625 pStreamDesc->u32Ctl = HDA_STREAM_REG2(pState, CTL, u8Strm); 1626 pStreamDesc->u64BaseDMA = RT_MAKE_U64(HDA_STREAM_REG2(pState, BDPL, u8Strm), 1627 HDA_STREAM_REG2(pState, BDPU, u8Strm)); 1628 pStreamDesc->pu32Lpib = &HDA_STREAM_REG2(pState, LPIB, u8Strm); 1629 pStreamDesc->pu32Sts = &HDA_STREAM_REG2(pState, STS, u8Strm); 1630 pStreamDesc->u32Cbl = HDA_STREAM_REG2(pState, CBL, u8Strm); 1631 pStreamDesc->u32Fifos = HDA_STREAM_REG2(pState, FIFOS, u8Strm); 1632 1633 pBdle->u32BdleMaxCvi = HDA_STREAM_REG2(pState, LVI, u8Strm); 1634 #ifdef LOG_ENABLED 1635 if ( pBdle 1636 && pBdle->u32BdleMaxCvi) 1637 { 1638 Log(("Initialization of transfer descriptor:\n")); 1639 dump_bd(pState, pBdle, pStreamDesc->u64BaseDMA); 1640 } 1641 #endif 1642 } 1643 1527 1644 DECLCALLBACK(void) hdaTransfer(CODECState *pCodecState, ENMSOUNDSOURCE src, int avail) 1528 1645 { 1529 1646 bool fStop = false; 1530 uint 64_t u64BaseDMA= 0;1647 uint8_t u8Strm = 0; 1531 1648 PHDABDLEDESC pBdle = NULL; 1532 1649 INTELHDLinkState *pState = (INTELHDLinkState *)pCodecState->pHDAState; 1650 HDASTREAMTRANSFERDESC stStreamDesc; 1533 1651 uint32_t nBytes; 1534 uint32_t u32Ctl;1535 uint32_t *pu32Sts;1536 uint8_t u8Strm;1537 uint32_t *pu32Lpib;1538 uint32_t u32Cbl;1539 uint32_t u32Fifos;1540 uint32_t u32Fifow;1541 switch (src)1542 {1543 case PO_INDEX:1544 {1545 u8Strm = 4;1546 u32Ctl = SDCTL(pState, 4);1547 u64BaseDMA = RT_MAKE_U64(SDBDPL(pState, 4), SDBDPU(pState, 4));1548 pu32Lpib = &SDLPIB(pState, 4);1549 pu32Sts = &SDSTS(pState, 4);1550 u32Cbl = SDLCBL(pState, 4);1551 pBdle = &pState->stOutBdle;1552 pBdle->u32BdleMaxCvi = SDLVI(pState, 4);1553 u32Fifos = SDFIFOS(pState, 4);1554 u32Fifow = hdaFifoWToSz(pState, 4);1555 break;1556 }1557 case PI_INDEX:1558 {1559 u8Strm = 0;1560 u32Ctl = SDCTL(pState, 0);1561 pu32Lpib = &SDLPIB(pState, 0);1562 pu32Sts = &SDSTS(pState, 0);1563 u32Cbl = SDLCBL(pState, 0);1564 u64BaseDMA = RT_MAKE_U64(SDBDPL(pState, 0), SDBDPU(pState, 0));1565 pBdle = &pState->stInBdle;1566 pBdle->u32BdleMaxCvi = SDLVI(pState, 0);1567 u32Fifos = SDFIFOS(pState, 0);1568 u32Fifow = hdaFifoWToSz(pState, 0);1569 break;1570 }1571 default:1572 return;1573 }1574 if ( !(u32Ctl & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN))1575 || !avail1576 || !u64BaseDMA)1577 return;1578 /* Fetch the Buffer Descriptor Entry (BDE). */1579 fetch_bd(pState, pBdle, u64BaseDMA);1580 1652 while( avail && !fStop) 1581 1653 { 1582 *pu32Sts |= HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);1583 Assert((avail >= 0 && (u32Cbl >= (*pu32Lpib)))); /* sanity */1584 uint32_t u32CblLimit = u32Cbl - (*pu32Lpib);1585 Assert((u32CblLimit > hdaFifoWToSz(pState, u8Strm)));1586 Log(("hda: CBL=%d, LPIB=%d\n", u32Cbl, *pu32Lpib));1587 1654 switch (src) 1588 1655 { 1589 1656 case PO_INDEX: 1590 nBytes = hdaWriteAudio(pState, (uint32_t *)&avail, &fStop, u32CblLimit); 1657 { 1658 u8Strm = 4; 1659 pBdle = &pState->stOutBdle; 1660 break; 1661 } 1662 case PI_INDEX: 1663 { 1664 u8Strm = 0; 1665 pBdle = &pState->stInBdle; 1666 break; 1667 } 1668 default: 1669 return; 1670 } 1671 hdaInitTransferDescriptor(pState, pBdle, u8Strm, &stStreamDesc); 1672 Assert ( (stStreamDesc.u32Ctl & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)) 1673 && avail 1674 && stStreamDesc.u64BaseDMA); 1675 1676 /* Fetch the Buffer Descriptor Entry (BDE). */ 1677 1678 if (hdaIsTransferCountersOverlapped(pState, pBdle, &stStreamDesc)) 1679 hdaFetchBdle(pState, pBdle, &stStreamDesc); 1680 *stStreamDesc.pu32Sts |= HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY); 1681 Assert((avail >= 0 && (stStreamDesc.u32Cbl >= (*stStreamDesc.pu32Lpib)))); /* sanity */ 1682 uint32_t u32CblLimit = stStreamDesc.u32Cbl - (*stStreamDesc.pu32Lpib); 1683 Assert((u32CblLimit > hdaFifoWToSz(pState, &stStreamDesc))); 1684 Log(("hda: CBL=%d, LPIB=%d\n", stStreamDesc.u32Cbl, *stStreamDesc.pu32Lpib)); 1685 switch (src) 1686 { 1687 case PO_INDEX: 1688 nBytes = hdaWriteAudio(pState, &stStreamDesc, (uint32_t *)&avail, &fStop, u32CblLimit); 1591 1689 break; 1592 1690 case PI_INDEX: 1593 nBytes = hdaReadAudio(pState, (uint32_t *)&avail, &fStop, u32CblLimit);1691 nBytes = hdaReadAudio(pState, &stStreamDesc, (uint32_t *)&avail, &fStop, u32CblLimit); 1594 1692 break; 1595 1693 default: … … 1598 1696 AssertMsgFailed(("Unsupported")); 1599 1697 } 1600 /* 1601 * if we're under FIFO Watermark it's expected that HDA doesn't fetch anything. 1602 * (ICH6 datasheet 18.2.38) 1603 */ 1604 Assert(nBytes <= (u32Fifos + 1)); 1605 *pu32Sts &= ~HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY); 1606 if (!pBdle->cbUnderFifoW) 1607 { 1608 *pu32Lpib += nBytes; 1609 1610 /* 1611 * Assert. Overlapping of buffer counter shouldn't happen. 1612 */ 1613 Assert((*pu32Lpib <= u32Cbl)); 1614 1615 /* Optionally write back the current DMA position. */ 1616 hdaUpdatePosBuf(pState, u8Strm, *pu32Lpib); 1617 1618 } 1698 Assert(nBytes <= (stStreamDesc.u32Fifos + 1)); 1699 *stStreamDesc.pu32Sts &= ~HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY); 1700 1619 1701 /* Process end of buffer condition. */ 1620 if ( pBdle->u32BdleCviPos == pBdle->u32BdleCviLen 1621 || *pu32Lpib == u32Cbl) 1622 { 1623 if ( !pBdle->cbUnderFifoW 1624 && pBdle->fBdleCviIoc) 1625 { 1626 /* 1627 * @todo - more carefully investigate BCIS flag. 1628 * Speech synthesis works fine on Mac Guest if this bit isn't set 1629 * but in general sound quality becomes lesser. 1630 */ 1631 *pu32Sts |= HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS); 1632 /* 1633 * we should generate the interrupt if ICE bit of SDCTL register is set. 1634 */ 1635 if (u32Ctl & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE)) 1636 hdaProcessInterrupt(pState); 1637 } 1638 if (*pu32Lpib == u32Cbl) 1639 *pu32Lpib -= u32Cbl; 1640 hdaUpdatePosBuf(pState, u8Strm, *pu32Lpib); 1641 1642 if (pBdle->u32BdleCviPos == pBdle->u32BdleCviLen) 1643 { 1644 pBdle->u32BdleCviPos = 0; 1645 pBdle->u32BdleCvi++; 1646 if (pBdle->u32BdleCvi == pBdle->u32BdleMaxCvi + 1) 1647 pBdle->u32BdleCvi = 0; 1648 1649 } 1650 fStop = true; 1651 } 1702 hdaStreamCounterUpdate(pState, pBdle, &stStreamDesc, nBytes); 1703 fStop = !hdaDoNextTransferCycle(pState, pBdle, &stStreamDesc); 1652 1704 } 1653 1705 }
Note:
See TracChangeset
for help on using the changeset viewer.