Changeset 60941 in vbox for trunk/src/VBox/Devices/Audio
- Timestamp:
- May 12, 2016 1:12:20 PM (9 years ago)
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/AudioMixer.cpp
r60934 r60941 312 312 } 313 313 314 LogFlowFunc((" Sink=%s,Cmd=%ld, rc=%Rrc\n", pSink->pszName, enmCmd, rc));314 LogFlowFunc(("%s: enmCmd=%ld, rc=%Rrc\n", pSink->pszName, enmCmd, rc)); 315 315 return rc; 316 316 } … … 342 342 343 343 RTMemFree(pSink); 344 } 345 346 /** 347 * Returns the sink's mixing direction. 348 * 349 * @returns Mixing direction. 350 * @param pSink Sink to return direction for. 351 * 352 * @remark 353 */ 354 AUDMIXSINKDIR AudioMixerSinkGetDir(PAUDMIXSINK pSink) 355 { 356 AssertPtrReturn(pSink, AUDMIXSINKDIR_UNKNOWN); 357 return pSink->enmDir; 344 358 } 345 359 … … 519 533 void AudioMixerSinkTimerUpdate(PAUDMIXSINK pSink, uint64_t cTicksPerSec, uint64_t cTicksElapsed, uint32_t *pcbData) 520 534 { 535 AssertPtrReturnVoid(pSink); 536 /* pcbData is optional. */ 537 521 538 uint32_t cSamplesMin = (uint32_t)((2 * cTicksElapsed * pSink->PCMProps.uHz + cTicksPerSec) / cTicksPerSec / 2); 522 539 uint32_t cbSamplesMin = cSamplesMin << pSink->PCMProps.cShift; -
trunk/src/VBox/Devices/Audio/AudioMixer.h
r60934 r60941 156 156 int AudioMixerSinkCtl(PAUDMIXSINK pSink, AUDMIXSINKCMD enmCmd); 157 157 void AudioMixerSinkDestroy(PAUDMIXSINK pSink); 158 AUDMIXSINKDIR AudioMixerSinkGetDir(PAUDMIXSINK pSink); 158 159 PAUDMIXSTREAM AudioMixerSinkGetStream(PAUDMIXSINK pSink, uint8_t uIndex); 159 160 uint8_t AudioMixerSinkGetStreamCount(PAUDMIXSINK pSink); -
trunk/src/VBox/Devices/Audio/DevIchHda.cpp
r60925 r60941 629 629 630 630 /** 631 * Structure defining an HDA mixer sink. 632 * Its purpose is to know which audio mixer sink is bound to 633 * which SDn (SDI/SDO) device stream. 634 * 635 * This is needed in order to handle interleaved streams 636 * (that is, multiple channels in one stream) or non-interleaved 637 * streams (each channel has a dedicated stream). 638 * 639 * This is only known to the actual device emulation level. 640 */ 641 typedef struct HDAMIXERSINK 642 { 643 /** SDn ID this sink is assigned to. 0 if not assigned. */ 644 uint8_t uSD; 645 /** Channel ID of SDn ID. Only valid if SDn ID is valid. */ 646 uint8_t uChannel; 647 uint8_t Padding[3]; 648 /** Pointer to the actual audio mixer sink. */ 649 R3PTRTYPE(PAUDMIXSINK) pMixSink; 650 } HDAMIXERSINK, *PHDAMIXERSINK; 651 652 /** 631 653 * Structure for keeping a HDA stream state. 632 654 * … … 637 659 { 638 660 /** Stream descriptor number (SDn). */ 639 uint8_t u8SD;640 uint8_t Padding0[7];661 uint8_t u8SD; 662 uint8_t Padding0[7]; 641 663 /** DMA base address (SDnBDPU - SDnBDPL). */ 642 uint64_t u64BDLBase;664 uint64_t u64BDLBase; 643 665 /** Cyclic Buffer Length (SDnCBL). 644 666 * Represents the size of the ring buffer. */ 645 uint32_t u32CBL;667 uint32_t u32CBL; 646 668 /** Format (SDnFMT). */ 647 uint16_t u16FMT;669 uint16_t u16FMT; 648 670 /** FIFO Size (FIFOS). 649 671 * Maximum number of bytes that may have been DMA'd into … … 651 673 * 652 674 * Must be a power of two. */ 653 uint16_t u16FIFOS;675 uint16_t u16FIFOS; 654 676 /** Last Valid Index (SDnLVI). */ 655 uint16_t u16LVI;656 uint16_t Padding1[3];657 /** Pointer to mixersink this stream is attached to. */658 R3PTRTYPE(P AUDMIXSINK) pSink;677 uint16_t u16LVI; 678 uint16_t Padding1[3]; 679 /** Pointer to HDA sink this stream is attached to. */ 680 R3PTRTYPE(PHDAMIXERSINK) pMixSink; 659 681 /** Internal state of this stream. */ 660 HDASTREAMSTATE State;682 HDASTREAMSTATE State; 661 683 } HDASTREAM, *PHDASTREAM; 662 684 663 685 /** 664 * Structure for mapping a stream tag to 665 * an internal stream state. 686 * Structure for mapping a stream tag to an HDA stream. 666 687 */ 667 688 typedef struct HDATAG 668 689 { 669 /** Own Tag. */690 /** Own stream tag. */ 670 691 uint8_t uTag; 671 692 uint8_t Padding[7]; … … 785 806 /** Flag whether the RC part is enabled. */ 786 807 bool fRCEnabled; 808 /** Number of active (running) SDn streams. */ 809 uint8_t cStreamsActive; 787 810 #ifndef VBOX_WITH_AUDIO_CALLBACKS 788 811 /** The timer for pumping data thru the attached LUN drivers. */ … … 807 830 /** The device' software mixer. */ 808 831 R3PTRTYPE(PAUDIOMIXER) pMixer; 809 /** Audio sink for PCMoutput. */810 R3PTRTYPE(PAUDMIXSINK) pSinkFront;832 /** HDA sink for (front) output. */ 833 HDAMIXERSINK SinkFront; 811 834 #ifdef VBOX_WITH_HDA_51_SURROUND 812 R3PTRTYPE(PAUDMIXSINK) pSinkCenterLFE; 813 R3PTRTYPE(PAUDMIXSINK) pSinkRear; 814 #endif 815 /** Audio mixer sink for line input. */ 816 R3PTRTYPE(PAUDMIXSINK) pSinkLineIn; 835 /** HDA sink for center / LFE output. */ 836 HDAMIXERSINK SinkCenterLFE; 837 /** HDA sink for rear output. */ 838 HDAMIXERSINK SinkRear; 839 #endif 840 /** HDA mixer sink for line input. */ 841 HDAMIXERSINK SinkLineIn; 817 842 #ifdef VBOX_WITH_HDA_MIC_IN 818 843 /** Audio mixer sink for microphone input. */ 819 R3PTRTYPE(PAUDMIXSINK) pSinkMicIn;844 HDAMIXERSINK SinkMicIn; 820 845 #endif 821 846 uint64_t u64BaseTS; … … 898 923 #ifdef IN_RING3 899 924 static void hdaStreamDestroy(PHDASTREAM pStrmSt); 925 static int hdaStreamSetActive(PHDASTATE pThis, PHDASTREAM pStream, bool fActive); 900 926 static int hdaStreamStart(PHDASTREAM pStrmSt); 901 927 static int hdaStreamStop(PHDASTREAM pStrmSt); … … 919 945 static int hdaProcessInterrupt(PHDASTATE pThis); 920 946 947 /* 948 * Timer routines. 949 */ 950 #ifndef VBOX_WITH_AUDIO_CALLBACKS 951 static void hdaTimerMaybeStart(PHDASTATE pThis); 952 static void hdaTimerMaybeStop(PHDASTATE pThis); 953 static DECLCALLBACK(void) hdaTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser); 954 #endif 921 955 922 956 /********************************************************************************************************************************* … … 1251 1285 } 1252 1286 1287 /** 1288 * Returns the HDA stream of specified stream descriptor number. 1289 * 1290 * @return Pointer to HDA stream, or NULL if none found. 1291 */ 1253 1292 DECLINLINE(PHDASTREAM) hdaStreamFromSD(PHDASTATE pThis, uint8_t uSD) 1254 1293 { 1255 1294 AssertPtrReturn(pThis, NULL); 1256 1295 AssertReturn(uSD <= HDA_MAX_STREAMS, NULL); 1296 1297 if (uSD >= HDA_MAX_STREAMS) 1298 return NULL; 1299 1257 1300 return &pThis->aStreams[uSD]; 1301 } 1302 1303 /** 1304 * Returns the HDA stream of specified HDA sink. 1305 * 1306 * @return Pointer to HDA stream, or NULL if none found. 1307 */ 1308 DECLINLINE(PHDASTREAM) hdaGetStreamFromSink(PHDASTATE pThis, PHDAMIXERSINK pSink) 1309 { 1310 AssertPtrReturn(pThis, NULL); 1311 AssertPtrReturn(pSink, NULL); 1312 1313 /** @todo Do something with the channel mapping here? */ 1314 return hdaStreamFromSD(pThis, pSink->uSD); 1258 1315 } 1259 1316 … … 1556 1613 { 1557 1614 pStrmSt->u8SD = uSD; 1558 pStrmSt->p Sink= NULL;1615 pStrmSt->pMixSink = NULL; 1559 1616 1560 1617 pStrmSt->State.fActive = false; … … 1685 1742 } 1686 1743 1744 static int hdaStreamSetActive(PHDASTATE pThis, PHDASTREAM pStream, bool fActive) 1745 { 1746 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1747 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1748 1749 AUDMIXSINKCMD enmCmd = fActive 1750 ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE; 1751 1752 /* First, enable or disable the stream's sink, if any. */ 1753 AssertPtr(pStream->pMixSink); 1754 if (pStream->pMixSink->pMixSink) 1755 AudioMixerSinkCtl(pStream->pMixSink->pMixSink, enmCmd); 1756 1757 /* Second, see if we need to start or stop the timer. */ 1758 if (!fActive) 1759 { 1760 if (pThis->cStreamsActive) /* Disable can be called mupltiple times. */ 1761 pThis->cStreamsActive--; 1762 1763 #ifndef VBOX_WITH_AUDIO_CALLBACKS 1764 hdaTimerMaybeStop(pThis); 1765 #endif 1766 } 1767 else 1768 { 1769 pThis->cStreamsActive++; 1770 #ifndef VBOX_WITH_AUDIO_CALLBACKS 1771 hdaTimerMaybeStart(pThis); 1772 #endif 1773 } 1774 1775 LogFlowFunc(("u8Strm=%RU8, fActive=%RTbool, cStreamsActive=%RU8\n", pStream->u8SD, fActive, pThis->cStreamsActive)); 1776 1777 return VINF_SUCCESS; 1778 } 1779 1780 static void hdaStreamAssignToSink(PHDASTREAM pStrmSt, PHDAMIXERSINK pMixSink) 1781 { 1782 AssertPtrReturnVoid(pStrmSt); 1783 1784 int rc2 = RTSemMutexRequest(pStrmSt->State.hMtx, RT_INDEFINITE_WAIT); 1785 if (RT_SUCCESS(rc2)) 1786 { 1787 pStrmSt->pMixSink = pMixSink; 1788 1789 rc2 = RTSemMutexRelease(pStrmSt->State.hMtx); 1790 AssertRC(rc2); 1791 } 1792 } 1793 1687 1794 static int hdaStreamStart(PHDASTREAM pStrmSt) 1688 1795 { … … 2150 2257 */ 2151 2258 uint8_t uTag = (u32Value >> HDA_SDCTL_NUM_SHIFT) & HDA_SDCTL_NUM_MASK; 2152 2153 /* Tag 0 is reserved for software / invalid, just skip. */ 2154 if ( !uTag 2155 || (uTag > HDA_MAX_TAGS)) 2259 if (uTag > HDA_MAX_TAGS) 2156 2260 { 2157 2261 LogFunc(("[SD%RU8]: Warning: Invalid stream tag %RU8 specified!\n", uSD, uTag)); … … 2163 2267 AssertPtr(pTag); 2164 2268 2165 if (pTag->uTag) 2166 LogFunc(("[SD%RU8]: Warning: Tag %RU8 already assigned to %RU8 (pStrm=%p)\n", uSD, uTag, pTag->uTag, pTag->pStrm)); 2269 LogFunc(("[SD%RU8]: Using stream tag=%RU8\n", uSD, uTag)); 2167 2270 2168 2271 /* Assign new values. */ 2169 2272 pTag->uTag = uTag; 2170 2273 pTag->pStrm = hdaStreamFromSD(pThis, uSD); 2171 2172 LogFunc(("[SD%RU8]: Using stream tag=%RU8\n", uSD, uTag));2173 2274 2174 2275 PHDASTREAM pStrmSt = pTag->pStrm; … … 2214 2315 LogFunc(("[SD%RU8]: fRun=%RTbool\n", pStrmSt->u8SD, fRun)); 2215 2316 2216 AUDMIXSINKCMD enmCmd = fRun 2217 ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE; 2218 2219 if (hdaGetDirFromSD(uSD) == PDMAUDIODIR_IN) 2220 { 2221 # ifdef VBOX_WITH_HDA_MIC_IN 2222 AudioMixerSinkCtl(pThis->pSinkMicIn, enmCmd); 2223 # endif 2224 AudioMixerSinkCtl(pThis->pSinkLineIn, enmCmd); 2225 } 2226 else 2227 { 2228 AudioMixerSinkCtl(pThis->pSinkFront, enmCmd); 2229 # ifdef VBOX_WITH_HDA_51_SURROUND 2230 AudioMixerSinkCtl(pThis->pSinkCenterLFE, enmCmd); 2231 AudioMixerSinkCtl(pThis->pSinkRear, enmCmd); 2232 # endif 2233 } 2317 hdaStreamSetActive(pThis, pStrmSt, fRun); 2234 2318 2235 2319 if (fRun) … … 2630 2714 { 2631 2715 #ifdef IN_RING3 2632 if (HDA_REG_IND(pThis, iReg) == u32Value) /* Value already set? */2633 return VINF_SUCCESS;2634 2635 2716 PDMAUDIOSTREAMCFG strmCfg; 2636 2717 RT_ZERO(strmCfg); … … 3333 3414 } 3334 3415 3335 rc = AudioMixerSinkRead(pStrmSt->pSink, AUDMIXOP_BLEND, pBDLE->State.au8FIFO, cbBuf, &cbRead); 3416 AssertPtr(pStrmSt->pMixSink); 3417 AssertPtr(pStrmSt->pMixSink->pMixSink); 3418 rc = AudioMixerSinkRead(pStrmSt->pMixSink->pMixSink, AUDMIXOP_BLEND, pBDLE->State.au8FIFO, cbBuf, &cbRead); 3336 3419 if (RT_FAILURE(rc)) 3337 3420 break; … … 3481 3564 * Write data to according mixer sinks. 3482 3565 */ 3483 rc2 = AudioMixerSinkWrite(pThis-> pSinkFront,AUDMIXOP_COPY, pvDataFront, cbDataFront,3566 rc2 = AudioMixerSinkWrite(pThis->SinkFront.pMixSink, AUDMIXOP_COPY, pvDataFront, cbDataFront, 3484 3567 NULL /* pcbWritten */); 3485 3568 AssertRC(rc2); 3486 3569 #ifdef VBOX_WITH_HDA_51_SURROUND 3487 rc2 = AudioMixerSinkWrite(pThis-> pSinkCenterLFE,AUDMIXOP_COPY, pvDataCenterLFE, cbDataCenterLFE,3570 rc2 = AudioMixerSinkWrite(pThis->SinkCenterLFE, AUDMIXOP_COPY, pvDataCenterLFE, cbDataCenterLFE, 3488 3571 NULL /* pcbWritten */); 3489 3572 AssertRC(rc2); 3490 rc2 = AudioMixerSinkWrite(pThis-> pSinkRear,AUDMIXOP_COPY, pvDataRear, cbDataRear,3573 rc2 = AudioMixerSinkWrite(pThis->SinkRear, AUDMIXOP_COPY, pvDataRear, cbDataRear, 3491 3574 NULL /* pcbWritten */); 3492 3575 AssertRC(rc2); … … 3545 3628 * Returns NULL if no sink is found. 3546 3629 * 3547 * @return P AUDMIXSINK3630 * @return PHDAMIXERSINK 3548 3631 * @param pThis HDA state. 3549 3632 * @param enmMixerCtl Mixer control to get the corresponding sink for. 3550 3633 */ 3551 static P AUDMIXSINK hdaMixerControlToSink(PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl)3552 { 3553 P AUDMIXSINK pSink;3634 static PHDAMIXERSINK hdaMixerControlToSink(PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl) 3635 { 3636 PHDAMIXERSINK pSink; 3554 3637 3555 3638 switch (enmMixerCtl) … … 3558 3641 /* Fall through is intentional. */ 3559 3642 case PDMAUDIOMIXERCTL_FRONT: 3560 pSink = pThis->pSinkFront;3643 pSink = &pThis->SinkFront; 3561 3644 break; 3562 3645 #ifdef VBOX_WITH_HDA_51_SURROUND 3563 3646 case PDMAUDIOMIXERCTL_CENTER_LFE: 3564 pSink = pThis->pSinkCenterLFE;3647 pSink = &pThis->SinkCenterLFE; 3565 3648 break; 3566 3649 case PDMAUDIOMIXERCTL_REAR: 3567 pSink = pThis->pSinkRear;3650 pSink = &pThis->SinkRear; 3568 3651 break; 3569 3652 #endif 3570 3653 case PDMAUDIOMIXERCTL_LINE_IN: 3571 pSink = pThis->pSinkLineIn;3654 pSink = &pThis->SinkLineIn; 3572 3655 break; 3573 3656 #ifdef VBOX_WITH_HDA_MIC_IN 3574 3657 case PDMAUDIOMIXERCTL_MIC_IN: 3575 pSink = pThis->pSinkMicIn;3658 pSink = &pThis->SinkMicIn; 3576 3659 break; 3577 3660 #endif … … 3585 3668 } 3586 3669 3587 static DECLCALLBACK(int) hdaMixerAddStream(PHDASTATE pThis, P AUDMIXSINK pSink, PPDMAUDIOSTREAMCFG pCfg)3670 static DECLCALLBACK(int) hdaMixerAddStream(PHDASTATE pThis, PHDAMIXERSINK pSink, PPDMAUDIOSTREAMCFG pCfg) 3588 3671 { 3589 3672 AssertPtrReturn(pThis, VERR_INVALID_POINTER); … … 3591 3674 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 3592 3675 3593 LogFunc(("Sink=%s, Stream=%s\n", pSink->pszName, pCfg->szName)); 3594 3595 int rc = VINF_SUCCESS; 3676 LogFunc(("Sink=%s, Stream=%s\n", pSink->pMixSink->pszName, pCfg->szName)); 3677 3678 /* Update the sink's format. */ 3679 PDMPCMPROPS PCMProps; 3680 int rc = DrvAudioStreamCfgToProps(pCfg, &PCMProps); 3681 if (RT_SUCCESS(rc)) 3682 rc = AudioMixerSinkSetFormat(pSink->pMixSink, &PCMProps); 3596 3683 3597 3684 PHDADRIVER pDrv; … … 3643 3730 if (RT_SUCCESS(rc2)) 3644 3731 { 3732 AudioMixerSinkRemoveStream(pSink->pMixSink, pStream->pMixStrm); 3733 3734 AudioMixerStreamDestroy(pStream->pMixStrm); 3735 pStream->pMixStrm = NULL; 3736 3645 3737 PAUDMIXSTREAM pMixStrm; 3646 3738 rc2 = AudioMixerStreamCreate(pDrv->pConnector, pCfg, 0 /* fFlags */, &pMixStrm); 3647 3739 if (RT_SUCCESS(rc2)) 3648 3740 { 3649 rc2 = AudioMixerSinkAddStream(pSink , pMixStrm);3741 rc2 = AudioMixerSinkAddStream(pSink->pMixSink, pMixStrm); 3650 3742 LogFlowFunc(("LUN#%RU8: Added \"%s\" to sink, rc=%Rrc\n", pDrv->uLUN, pCfg->szName , rc2)); 3651 3743 } … … 3680 3772 int rc; 3681 3773 3682 P AUDMIXSINK pSink = hdaMixerControlToSink(pThis, enmMixerCtl);3774 PHDAMIXERSINK pSink = hdaMixerControlToSink(pThis, enmMixerCtl); 3683 3775 if (pSink) 3684 3776 { … … 3688 3780 rc = VERR_NOT_FOUND; 3689 3781 3690 LogFlowFunc(("Sink=%s, enmMixerCtl=%ld, rc=%Rrc\n", pSink->p szName, enmMixerCtl, rc));3782 LogFlowFunc(("Sink=%s, enmMixerCtl=%ld, rc=%Rrc\n", pSink->pMixSink->pszName, enmMixerCtl, rc)); 3691 3783 return rc; 3692 3784 } … … 3705 3797 int rc; 3706 3798 3707 P AUDMIXSINK pSink = hdaMixerControlToSink(pThis, enmMixerCtl);3799 PHDAMIXERSINK pSink = hdaMixerControlToSink(pThis, enmMixerCtl); 3708 3800 if (pSink) 3709 3801 { 3710 AudioMixerSinkRemoveAllStreams(pSink); 3802 PHDADRIVER pDrv; 3803 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node) 3804 { 3805 PAUDMIXSTREAM pMixStream; 3806 switch (enmMixerCtl) 3807 { 3808 /* 3809 * Input. 3810 */ 3811 case PDMAUDIOMIXERCTL_LINE_IN: 3812 pMixStream = pDrv->LineIn.pMixStrm; 3813 pDrv->LineIn.pMixStrm = NULL; 3814 break; 3815 #ifdef VBOX_WITH_HDA_MIC_IN 3816 case PDMAUDIOMIXERCTL_MIC_IN: 3817 pMixStream = pDrv->MicIn.pMixStrm; 3818 pDrv->MicIn.pMixStrm = NULL; 3819 break; 3820 #endif 3821 /* 3822 * Output. 3823 */ 3824 case PDMAUDIOMIXERCTL_FRONT: 3825 pMixStream = pDrv->Front.pMixStrm; 3826 pDrv->Front.pMixStrm = NULL; 3827 break; 3828 #ifdef VBOX_WITH_HDA_51_SURROUND 3829 case PDMAUDIOMIXERCTL_CENTER_LFE: 3830 pMixStream = pDrv->CenterLFE.pMixStrm; 3831 pDrv->CenterLFE.pMixStrm = NULL; 3832 break; 3833 case PDMAUDIOMIXERCTL_REAR: 3834 pMixStream = pDrv->Rear.pMixStrm; 3835 pDrv->Rear.pMixStrm = NULL; 3836 break; 3837 #endif 3838 default: 3839 AssertMsgFailed(("Mixer control %ld not implemented\n", enmMixerCtl)); 3840 break; 3841 } 3842 3843 AudioMixerSinkRemoveStream(pSink->pMixSink, pMixStream); 3844 AudioMixerStreamDestroy(pMixStream); 3845 } 3846 3847 AudioMixerSinkRemoveAllStreams(pSink->pMixSink); 3711 3848 rc = VINF_SUCCESS; 3712 3849 } … … 3715 3852 3716 3853 LogFlowFunc(("enmMixerCtl=%ld, rc=%Rrc\n", enmMixerCtl, rc)); 3854 return rc; 3855 } 3856 3857 /** 3858 * Sets a SDn stream number and channel to a particular mixer control. 3859 * 3860 * @returns IPRT status code. 3861 * @param pThis HDA State. 3862 * @param enmMixerCtl Mixer control to set SD stream number and channel for. 3863 * @param uSD SD stream number (number + 1) to set. Set to 0 for unassign. 3864 * @param uChannel Channel to set. Only valid if a valid SD stream number is specified. 3865 */ 3866 static DECLCALLBACK(int) hdaMixerSetStream(PHDASTATE pThis, 3867 PDMAUDIOMIXERCTL enmMixerCtl, uint8_t uSD, uint8_t uChannel) 3868 { 3869 LogFlowFunc(("enmMixerCtl=%RU32, uSD=%RU8, uChannel=%RU8\n", enmMixerCtl, uSD, uChannel)); 3870 3871 if (uSD == 0) /* Stream number 0 is reserved. */ 3872 { 3873 LogFlowFunc(("Invalid SDn (%RU8) number for mixer control %ld, ignoring\n", uSD, enmMixerCtl)); 3874 return VINF_SUCCESS; 3875 } 3876 /* uChannel is optional. */ 3877 3878 /* SDn0 starts as 1. */ 3879 Assert(uSD); 3880 uSD--; 3881 3882 int rc; 3883 3884 PHDAMIXERSINK pSink = hdaMixerControlToSink(pThis, enmMixerCtl); 3885 if (pSink) 3886 { 3887 if ( (uSD < HDA_MAX_SDI) 3888 && AudioMixerSinkGetDir(pSink->pMixSink) == AUDMIXSINKDIR_OUTPUT) 3889 { 3890 uSD += HDA_MAX_SDI; 3891 } 3892 3893 LogFlowFunc(("%s: Setting to stream ID=%RU8, channel=%RU8, enmMixerCtl=%RU32\n", 3894 pSink->pMixSink->pszName, uSD, uChannel, enmMixerCtl)); 3895 3896 Assert(uSD < HDA_MAX_STREAMS); 3897 3898 PHDASTREAM pStream = hdaStreamFromSD(pThis, pSink->uSD); 3899 if (pStream) 3900 { 3901 pSink->uSD = uSD; 3902 pSink->uChannel = uChannel; 3903 3904 /* Make sure that the stream also has this sink set. */ 3905 hdaStreamAssignToSink(pStream, pSink); 3906 3907 rc = VINF_SUCCESS; 3908 } 3909 else 3910 { 3911 LogRel(("HDA: Guest wanted to assign invalid stream ID=%RU8 (channel %RU8) to mixer control %RU32, skipping\n", 3912 uSD, uChannel, enmMixerCtl)); 3913 rc = VERR_INVALID_PARAMETER; 3914 } 3915 } 3916 else 3917 rc = VERR_NOT_FOUND; 3918 3919 LogFlowFuncLeaveRC(rc); 3717 3920 return rc; 3718 3921 } … … 3731 3934 int rc; 3732 3935 3733 P AUDMIXSINK pSink = hdaMixerControlToSink(pThis, enmMixerCtl);3936 PHDAMIXERSINK pSink = hdaMixerControlToSink(pThis, enmMixerCtl); 3734 3937 if (pSink) 3735 3938 { 3736 3939 /* Set the volume. 3737 3940 * We assume that the codec already converted it to the correct range. */ 3738 rc = AudioMixerSinkSetVolume(pSink , pVol);3941 rc = AudioMixerSinkSetVolume(pSink->pMixSink, pVol); 3739 3942 } 3740 3943 else … … 3746 3949 3747 3950 #ifndef VBOX_WITH_AUDIO_CALLBACKS 3951 3952 static void hdaTimerMaybeStart(PHDASTATE pThis) 3953 { 3954 if (pThis->cStreamsActive == 0) /* Only start the timer if there are no active streams. */ 3955 return; 3956 3957 if (!pThis->pTimer) 3958 return; 3959 3960 LogFlowFuncEnter(); 3961 3962 /* Fire off timer. */ 3963 TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->cTimerTicks); 3964 } 3965 3966 static void hdaTimerMaybeStop(PHDASTATE pThis) 3967 { 3968 if (pThis->cStreamsActive) /* Some streams still active? Bail out. */ 3969 return; 3970 3971 if (!pThis->pTimer) 3972 return; 3973 3974 LogFlowFuncEnter(); 3975 3976 int rc2 = TMTimerStop(pThis->pTimer); 3977 AssertRC(rc2); 3978 } 3748 3979 3749 3980 static DECLCALLBACK(void) hdaTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser) … … 3764 3995 pThis->uTimerTS = cTicksNow; 3765 3996 3766 /* 3767 * Calculate the codec's (fixed) sampling rate. 3768 */ 3769 AssertPtr(pThis->pCodec); 3770 3771 /* Since the codec always runs at a fixed delivery rate (48 kHz), calculate the sample processing rate based 3772 * on the clock ticks elapsed (the clock itself runs at 24 Mhz). 3773 * A stream itself can have a higher or lower delivery rate, which in turn then results in more or less 3774 * stream samples per frame. */ 3775 uint32_t cCodecSamplesMin = (int)((2 * cTicksElapsed * 48000 /* Hz */ + cTicksPerSec) / cTicksPerSec / 2); 3776 /* We always use 32-bit as containers to make sure all data is being pumped if we need to. */ 3777 uint32_t cbCodecSamplesMin = cCodecSamplesMin << 1; 3778 3779 #if 0 3780 /* 3781 * Process all driver nodes. 3782 */ 3783 PHDADRIVER pDrv; 3784 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node) 3785 { 3786 uint32_t cbIn = 0; 3787 uint32_t cbOut = 0; 3788 3789 rc = pDrv->pConnector->pfnQueryStatus(pDrv->pConnector, &cbIn, &cbOut, NULL /* pcSamplesLive */); 3790 if (RT_SUCCESS(rc)) 3791 rc = pDrv->pConnector->pfnPlayOut(pDrv->pConnector, NULL /* pcSamplesPlayed */); 3792 3793 #ifdef DEBUG_TIMER 3794 LogFlowFunc(("LUN#%RU8: rc=%Rrc, cbIn=%RU32, cbOut=%RU32\n", pDrv->uLUN, rc, cbIn, cbOut)); 3795 #endif 3796 /* If we there was an error handling (available) output or there simply is no output available, 3797 * then calculate the minimum data rate which must be processed by the device emulation in order 3798 * to function correctly. 3799 * 3800 * This is not the optimal solution, but as we have to deal with this on a timer-based approach 3801 * (until we have the audio callbacks) we need to have device' DMA engines running. */ 3802 if (!AudioMixerStreamIsValid(pDrv->Front.pMixStrm)) 3803 { 3804 /* Use the codec's (fixed) sampling rate. */ 3805 cbOut = RT_MAX(cbOut, cbCodecSamplesMin); 3806 continue; 3807 } 3808 3809 const bool fIsActiveOut = pDrv->pConnector->pfnIsActiveOut(pDrv->pConnector, pDrv->Front.pMixStrm->InOut.pOut); 3810 if ( RT_FAILURE(rc) 3811 || !fIsActiveOut) 3812 { 3813 uint32_t cSamplesMin = (int)((2 * cTicksElapsed * pDrv->Front.pMixStrm->InOut.pOut->Props.uHz + cTicksPerSec) / cTicksPerSec / 2); 3814 uint32_t cbSamplesMin = AUDIOMIXBUF_S2B(&pDrv->Front.pMixStrm->InOut.pOut->MixBuf, cSamplesMin); 3815 3816 #ifdef DEBUG_TIMER 3817 LogFlowFunc(("\trc=%Rrc, cSamplesMin=%RU32, cbSamplesMin=%RU32\n", rc, cSamplesMin, cbSamplesMin)); 3818 #endif 3819 cbOut = RT_MAX(cbOut, cbSamplesMin); 3820 } 3821 3822 cbOutMin = RT_MIN(cbOutMin, cbOut); 3823 cbInMax = RT_MAX(cbInMax, cbIn); 3824 } 3825 #else 3826 AudioMixerSinkUpdate(pThis->pSinkFront); 3827 cbOutMin = _4K; //cbCodecSamplesMin; 3828 cbInMax = _4K; 3829 #endif 3830 3831 #ifdef DEBUG_TIMER 3832 LogFlowFunc(("cbInMax=%RU32, cbOutMin=%RU32\n", cbInMax, cbOutMin)); 3833 #endif 3834 3835 if (cbOutMin == UINT32_MAX) 3836 cbOutMin = 0; 3837 3838 /** @todo Determine the streams to be handled. */ 3839 PHDASTREAM pStreamLineIn = &pThis->aStreams[0]; 3997 PHDASTREAM pStreamLineIn = hdaGetStreamFromSink(pThis, &pThis->SinkLineIn); 3840 3998 #ifdef VBOX_WITH_HDA_MIC_IN 3841 /** @todo Anything to do for mic-in? */ 3842 #endif 3843 PHDASTREAM pStreamOut = &pThis->aStreams[4]; 3844 3845 /* Do the actual device transfers. */ 3846 hdaTransfer(pThis, pStreamOut, cbOutMin /* cbToProcess */, NULL /* pcbProcessed */); 3847 hdaTransfer(pThis, pStreamLineIn, cbInMax /* cbToProcess */, NULL /* pcbProcessed */); 3999 PHDASTREAM pStreamMicIn = hdaGetStreamFromSink(pThis, &pThis->SinkMicIn); 4000 #endif 4001 PHDASTREAM pStreamFront = hdaGetStreamFromSink(pThis, &pThis->SinkFront); 4002 4003 uint32_t cbLineIn; 4004 AudioMixerSinkTimerUpdate(pThis->SinkLineIn.pMixSink, cTicksPerSec, cTicksElapsed, &cbLineIn); 4005 if (cbLineIn) 4006 hdaTransfer(pThis, pStreamLineIn, cbLineIn, NULL); /** @todo Add rc! */ 4007 4008 #ifdef VBOX_WITH_HDA_MIC_IN 4009 uint32_t cbMicIn; 4010 AudioMixerSinkTimerUpdate(pThis->SinkMicIn.pMixSink , cTicksPerSec, cTicksElapsed, &cbMicIn); 4011 #endif 4012 4013 uint32_t cbOut; 4014 AudioMixerSinkTimerUpdate(pThis->SinkFront.pMixSink, cTicksPerSec, cTicksElapsed, &cbOut); 4015 if (cbOut) 4016 hdaTransfer(pThis, pStreamFront, cbOut, NULL); /** @todo Add rc! */ 3848 4017 3849 4018 /* Kick the timer again. */ … … 3911 4080 /* pcbProcessed is optional. */ 3912 4081 3913 // 44100 / 200 Hz Timer = cbToProcess = 220,83914 cbToProcess = 440; // FIFO SIZE3915 3916 4082 if (ASMAtomicReadBool(&pThis->fInReset)) /* HDA controller in reset mode? Bail out. */ 3917 4083 { … … 3975 4141 Assert(pStream->State.fInReset == false); 3976 4142 3977 // uint32_t cbLeft = cbToProcess;3978 4143 uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStream->u8SD); 3979 4144 Assert(u32LPIB <= pStream->u32CBL); … … 4039 4204 4040 4205 /* Set the FIFORDY bit on the stream while doing the transfer. */ 4041 //HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);4206 HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY); 4042 4207 4043 4208 uint32_t cbProcessed; … … 4048 4213 4049 4214 /* Remove the FIFORDY bit again. */ 4050 //HDA_STREAM_REG(pThis, STS, pStream->u8SD) &= ~HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);4215 HDA_STREAM_REG(pThis, STS, pStream->u8SD) &= ~HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY); 4051 4216 4052 4217 if (RT_FAILURE(rc)) … … 4854 5019 4855 5020 # ifdef VBOX_WITH_HDA_MIC_IN 4856 AudioMixerSinkCtl(pThis-> pSinkMicIn, enmCmdMicIn);5021 AudioMixerSinkCtl(pThis->SinkMicIn.pMixSink, enmCmdMicIn); 4857 5022 # endif 4858 AudioMixerSinkCtl(pThis-> pSinkLineIn, enmCmdLineIn);4859 AudioMixerSinkCtl(pThis-> pSinkFront, enmCmdOut);5023 AudioMixerSinkCtl(pThis->SinkLineIn.pMixSink, enmCmdLineIn); 5024 AudioMixerSinkCtl(pThis->SinkFront.pMixSink, enmCmdOut); 4860 5025 # ifdef VBOX_WITH_HDA_51_SURROUND 4861 AudioMixerSinkCtl(pThis-> pSinkCenterLFE, enmCmdOut);4862 AudioMixerSinkCtl(pThis-> pSinkRear, enmCmdOut);5026 AudioMixerSinkCtl(pThis->SinkCenterLFE.pMixSink, enmCmdOut); 5027 AudioMixerSinkCtl(pThis->SinkRear.pMixSink, enmCmdOut); 4863 5028 # endif 4864 5029 } … … 5177 5342 * Stop the timer, if any. 5178 5343 */ 5179 int rc2; 5180 if (pThis->pTimer) 5181 { 5182 rc2 = TMTimerStop(pThis->pTimer); 5183 AssertRC(rc2); 5184 } 5344 hdaTimerMaybeStop(pThis); 5185 5345 # endif 5186 5346 … … 5205 5365 * Stop any audio currently playing and/or recording. 5206 5366 */ 5207 AudioMixerSinkCtl(pThis-> pSinkFront, AUDMIXSINKCMD_DISABLE);5367 AudioMixerSinkCtl(pThis->SinkFront.pMixSink, AUDMIXSINKCMD_DISABLE); 5208 5368 # ifdef VBOX_WITH_HDA_MIC_IN 5209 AudioMixerSinkCtl(pThis-> pSinkMicIn, AUDMIXSINKCMD_DISABLE);5369 AudioMixerSinkCtl(pThis->SinkMicIn.pMixSink, AUDMIXSINKCMD_DISABLE); 5210 5370 # endif 5211 AudioMixerSinkCtl(pThis-> pSinkLineIn, AUDMIXSINKCMD_DISABLE);5371 AudioMixerSinkCtl(pThis->SinkLineIn.pMixSink, AUDMIXSINKCMD_DISABLE); 5212 5372 # ifdef VBOX_WITH_HDA_51_SURROUND 5213 AudioMixerSinkCtl(pThis-> pSinkCenterLFE, AUDMIXSINKCMD_DISABLE);5214 AudioMixerSinkCtl(pThis-> pSinkRear, AUDMIXSINKCMD_DISABLE);5373 AudioMixerSinkCtl(pThis->SinkCenterLFE.pMixSink, AUDMIXSINKCMD_DISABLE); 5374 AudioMixerSinkCtl(pThis->SinkRear.pMixSink, AUDMIXSINKCMD_DISABLE); 5215 5375 # endif 5376 5377 /* 5378 * Set some sensible defaults for which HDA sinks 5379 * are connected to which stream number. 5380 * 5381 * We use SD0 for input and SD4 for output by default. 5382 * These stream numbers can be changed by the guest dynamically lateron. 5383 */ 5384 #ifdef VBOX_WITH_HDA_MIC_IN 5385 hdaMixerSetStream(pThis, PDMAUDIOMIXERCTL_MIC_IN , 1 /* SD0 */, 0 /* Channel */); 5386 #endif 5387 hdaMixerSetStream(pThis, PDMAUDIOMIXERCTL_LINE_IN , 1 /* SD0 */, 0 /* Channel */); 5388 5389 hdaMixerSetStream(pThis, PDMAUDIOMIXERCTL_FRONT , 5 /* SD4 */, 0 /* Channel */); 5390 #ifdef VBOX_WITH_HDA_51_SURROUND 5391 hdaMixerSetStream(pThis, PDMAUDIOMIXERCTL_CENTER_LFE, 5 /* SD4 */, 0 /* Channel */); 5392 hdaMixerSetStream(pThis, PDMAUDIOMIXERCTL_REAR , 5 /* SD4 */, 0 /* Channel */); 5393 #endif 5216 5394 5217 5395 pThis->cbCorbBuf = 256 * sizeof(uint32_t); /** @todo Use a define here. */ … … 5244 5422 5245 5423 # ifndef VBOX_WITH_AUDIO_CALLBACKS 5246 /* 5247 * Start timer again, if any. 5248 */ 5249 if (pThis->pTimer) 5250 { 5251 LogFunc(("Restarting timer\n")); 5252 rc2 = TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->cTimerTicks); 5253 AssertRC(rc2); 5254 } 5424 hdaTimerMaybeStart(pThis); 5255 5425 # endif 5256 5426 … … 5405 5575 LogRel2(("HDA: Powering off ...\n")); 5406 5576 5577 /* Ditto goes for the codec, which in turn uses the mixer. */ 5578 hdaCodecPowerOff(pThis->pCodec); 5579 5407 5580 /** 5408 5581 * Note: Destroy the mixer while powering off and *not* in hdaDestruct, … … 5415 5588 pThis->pMixer = NULL; 5416 5589 } 5417 5418 /* Ditto goes for the codec, which in turn uses the mixer. */5419 hdaCodecPowerOff(pThis->pCodec);5420 5590 } 5421 5591 … … 5508 5678 #ifndef VBOX_WITH_AUDIO_CALLBACKS 5509 5679 uint16_t uTimerHz; 5510 rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, 200 /* Hz */);5680 rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, 100 /* Hz */); 5511 5681 if (RT_FAILURE(rc)) 5512 5682 return PDMDEV_SET_ERROR(pDevIns, rc, … … 5675 5845 #ifdef VBOX_WITH_HDA_51_SURROUND 5676 5846 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Front", 5677 AUDMIXSINKDIR_OUTPUT, &pThis-> pSinkFront);5847 AUDMIXSINKDIR_OUTPUT, &pThis->SinkFront.pMixSink); 5678 5848 AssertRC(rc); 5679 5849 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Center / Subwoofer", 5680 AUDMIXSINKDIR_OUTPUT, &pThis-> pSinkCenterLFE);5850 AUDMIXSINKDIR_OUTPUT, &pThis->SinkCenterLFE.pMixSink); 5681 5851 AssertRC(rc); 5682 5852 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Rear", 5683 AUDMIXSINKDIR_OUTPUT, &pThis-> pSinkRear);5853 AUDMIXSINKDIR_OUTPUT, &pThis->SinkRear.pMixSink); 5684 5854 AssertRC(rc); 5685 5855 #else 5686 5856 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] PCM Output", 5687 AUDMIXSINKDIR_OUTPUT, &pThis-> pSinkFront);5857 AUDMIXSINKDIR_OUTPUT, &pThis->SinkFront.pMixSink); 5688 5858 AssertRC(rc); 5689 5859 #endif … … 5692 5862 */ 5693 5863 rc = AudioMixerCreateSink(pThis->pMixer, "[Recording] Line In", 5694 AUDMIXSINKDIR_INPUT, &pThis-> pSinkLineIn);5864 AUDMIXSINKDIR_INPUT, &pThis->SinkLineIn.pMixSink); 5695 5865 AssertRC(rc); 5696 5866 #ifdef VBOX_WITH_HDA_MIC_IN 5697 5867 rc = AudioMixerCreateSink(pThis->pMixer, "[Recording] Microphone In", 5698 AUDMIXSINKDIR_INPUT, &pThis-> pSinkMicIn);5868 AUDMIXSINKDIR_INPUT, &pThis->SinkMicIn.pMixSink); 5699 5869 AssertRC(rc); 5700 5870 #endif … … 5716 5886 pThis->pCodec->pfnMixerAddStream = hdaMixerAddStream; 5717 5887 pThis->pCodec->pfnMixerRemoveStream = hdaMixerRemoveStream; 5888 pThis->pCodec->pfnMixerSetStream = hdaMixerSetStream; 5718 5889 pThis->pCodec->pfnMixerSetVolume = hdaMixerSetVolume; 5719 5890 pThis->pCodec->pfnReset = hdaCodecReset; … … 5744 5915 AssertRC(rc); 5745 5916 } 5746 5747 /*5748 * As we don't have any dynamic stream <-> mixer sink mapping (yet),5749 * hard-wire the associations here.5750 */5751 #ifdef VBOX_WITH_HDA_51_SURROUND5752 # error "Implement me!" /** @todo */5753 #else5754 /* Same goes for the input sink. */5755 for (uint8_t i = 0; i < HDA_MAX_SDI; i++)5756 pThis->aStreams[i].pSink = pThis->pSinkLineIn;5757 # ifdef VBOX_WITH_HDA_MIC_IN5758 # error "Implement me!" /** @todo */5759 # endif5760 /* Assign all output streams to the one-and-only output sink. */5761 for (uint8_t i = HDA_MAX_SDI; i < HDA_MAX_SDO; i++)5762 pThis->aStreams[i].pSink = pThis->pSinkFront;5763 #endif /* VBOX_WITH_HDA_51_SURROUND */5764 5917 5765 5918 /* … … 5969 6122 LogFunc(("Timer ticks=%RU64 (%RU16 Hz)\n", pThis->cTimerTicks, uTimerHz)); 5970 6123 5971 /* Fire off timer. */ 5972 TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->cTimerTicks); 6124 hdaTimerMaybeStart(pThis); 5973 6125 } 5974 6126 } -
trunk/src/VBox/Devices/Audio/DevIchHdaCodec.cpp
r60925 r60941 550 550 typedef struct CODECCOMMONNODE 551 551 { 552 /** Node id - 7 bit format*/553 uint8_t id;554 /** The node name. */552 /** The node's ID. */ 553 uint8_t uID; 554 /** The node's name. */ 555 555 char const *pszName; 556 /** The SDn ID this node is assigned to. 557 * 0 means not assigned, 1 is SDn0. */ 558 uint8_t uSD; 559 /** The SDn's channel to use. 560 * Only valid if a valid SDn ID is set. */ 561 uint8_t uChannel; 556 562 /* PRM 5.3.6 */ 557 563 uint32_t au32F00_param[CODECNODE_F00_PARAM_LENGTH]; … … 839 845 static SSMFIELD const g_aCodecNodeFields[] = 840 846 { 841 SSMFIELD_ENTRY( CODECSAVEDSTATENODE, Core. id),847 SSMFIELD_ENTRY( CODECSAVEDSTATENODE, Core.uID), 842 848 SSMFIELD_ENTRY_PAD_HC_AUTO(3, 3), 843 849 SSMFIELD_ENTRY( CODECSAVEDSTATENODE, Core.au32F00_param), … … 850 856 static SSMFIELD const g_aCodecNodeFieldsV1[] = 851 857 { 852 SSMFIELD_ENTRY( CODECSAVEDSTATENODE, Core. id),858 SSMFIELD_ENTRY( CODECSAVEDSTATENODE, Core.uID), 853 859 SSMFIELD_ENTRY_PAD_HC_AUTO(3, 7), 854 860 SSMFIELD_ENTRY_OLD_HCPTR(Core.name), … … 890 896 891 897 /* Set common parameters across all nodes. */ 892 pNode->node.id = uNID; 898 pNode->node.uID = uNID; 899 pNode->node.uSD = 0; 893 900 894 901 switch (uNID) … … 2051 2058 && pThis->pfnCodecNodeReset) 2052 2059 { 2053 uint8_t i;2054 2060 LogFunc(("Entering reset ...\n")); 2055 2061 2056 //pThis->fInReset = true;2057 2058 for ( i = 0; i < pThis->cTotalNodes; ++i)2062 pThis->fInReset = true; 2063 2064 for (uint8_t i = 0; i < pThis->cTotalNodes; ++i) 2059 2065 pThis->pfnCodecNodeReset(pThis, i, &pThis->paNodes[i]); 2060 2066 2061 //pThis->fInReset = false;2067 pThis->fInReset = false; 2062 2068 2063 2069 LogFunc(("Exited reset\n")); … … 2274 2280 *pResp = 0; 2275 2281 2282 bool fIsOut; 2283 2276 2284 if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd))) 2277 2285 *pResp = pThis->paNodes[CODEC_NID(cmd)].dac.u32F06_param; … … 2287 2295 LogRel2(("HDA: Warning: Unhandled get stream ID command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd)); 2288 2296 2289 /*LogFlowFunc(("[NID0x%02x] Stream ID is 0x%x\n",2290 CODEC_NID(cmd), CODEC_F00_06_GET_STREAM_ID( *pResp)));*/2297 LogFlowFunc(("[NID0x%02x] Stream ID=%RU8, channel=%RU8\n", 2298 CODEC_NID(cmd), CODEC_F00_06_GET_STREAM_ID(cmd), CODEC_F00_06_GET_CHANNEL_ID(cmd))); 2291 2299 2292 2300 return VINF_SUCCESS; … … 2298 2306 *pResp = 0; 2299 2307 2308 PDMAUDIODIR enmDir; 2309 2300 2310 uint32_t *pu32Addr = NULL; 2301 2311 if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd))) 2312 { 2302 2313 pu32Addr = &pThis->paNodes[CODEC_NID(cmd)].dac.u32F06_param; 2314 enmDir = PDMAUDIODIR_OUT; 2315 } 2303 2316 else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd))) 2317 { 2304 2318 pu32Addr = &pThis->paNodes[CODEC_NID(cmd)].adc.u32F06_param; 2319 enmDir = PDMAUDIODIR_IN; 2320 } 2305 2321 else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd))) 2322 { 2306 2323 pu32Addr = &pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F06_param; 2324 enmDir = PDMAUDIODIR_OUT; 2325 } 2307 2326 else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd))) 2327 { 2308 2328 pu32Addr = &pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F06_param; 2309 else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))2310 pu32Addr = &pThis->paNodes[CODEC_NID(cmd)].reserved.u32F06_param;2329 enmDir = PDMAUDIODIR_IN; 2330 } 2311 2331 else 2332 { 2333 enmDir = PDMAUDIODIR_UNKNOWN; 2312 2334 LogRel2(("HDA: Warning: Unhandled set stream ID command for NID0x%02x: 0x%x\n", CODEC_NID(cmd), cmd)); 2313 2314 /* LogFlowFunc(("[NID0x%02x] Setting new stream ID to 0x%x\n", 2315 CODEC_NID(cmd), CODEC_F00_06_GET_STREAM_ID(cmd)));*/ 2335 } 2336 2337 /* Do we (re-)assign our input/output SDn (SDI/SDO) IDs? */ 2338 if (enmDir != PDMAUDIODIR_UNKNOWN) 2339 { 2340 uint8_t uSD = CODEC_F00_06_GET_STREAM_ID(cmd); 2341 uint8_t uChannel = CODEC_F00_06_GET_CHANNEL_ID(cmd); 2342 2343 LogFlowFunc(("[NID0x%02x] Setting to stream ID=%RU8, channel=%RU8, enmDir=%RU32\n", 2344 CODEC_NID(cmd), uSD, uChannel, enmDir)); 2345 2346 pThis->paNodes[CODEC_NID(cmd)].node.uSD = uSD; 2347 pThis->paNodes[CODEC_NID(cmd)].node.uChannel = uChannel; 2348 2349 if (enmDir == PDMAUDIODIR_OUT) 2350 { 2351 /** @todo Check if non-interleaved streams need a different channel / SDn? */ 2352 2353 /* Propagate to the controller. */ 2354 pThis->pfnMixerSetStream(pThis->pHDAState, PDMAUDIOMIXERCTL_FRONT, uSD, uChannel); 2355 #ifdef VBOX_WITH_HDA_51_SURROUND 2356 pThis->pfnMixerSetStream(pThis->pHDAState, PDMAUDIOMIXERCTL_CENTER_LFE, uSD, uChannel); 2357 pThis->pfnMixerSetStream(pThis->pHDAState, PDMAUDIOMIXERCTL_REAR, uSD, uChannel); 2358 #endif 2359 } 2360 else if (enmDir == PDMAUDIODIR_IN) 2361 { 2362 pThis->pfnMixerSetStream(pThis->pHDAState, PDMAUDIOMIXERCTL_LINE_IN, uSD, uChannel); 2363 #ifdef VBOX_WITH_HDA_MIC_IN 2364 pThis->pfnMixerSetStream(pThis->pHDAState, PDMAUDIOMIXERCTL_MIC_IN, uSD, uChannel); 2365 #endif 2366 } 2367 } 2316 2368 2317 2369 if (pu32Addr) … … 2756 2808 static void codecDbgPrintNode(PCODECDBGINFO pInfo, PCODECNODE pNode, bool fRecursive) 2757 2809 { 2758 codecDbgPrintf(pInfo, "Node 0x%02x (%02RU8): ", pNode->node. id, pNode->node.id);2759 2760 if (pNode->node. id== STAC9220_NID_ROOT)2810 codecDbgPrintf(pInfo, "Node 0x%02x (%02RU8): ", pNode->node.uID, pNode->node.uID); 2811 2812 if (pNode->node.uID == STAC9220_NID_ROOT) 2761 2813 { 2762 2814 CODECDBG_PRINT("ROOT\n"); 2763 2815 } 2764 else if (pNode->node. id== STAC9220_NID_AFG)2816 else if (pNode->node.uID == STAC9220_NID_AFG) 2765 2817 { 2766 2818 CODECDBG_PRINT("AFG\n"); … … 2770 2822 CODECDBG_UNINDENT 2771 2823 } 2772 else if (hdaCodecIsPortNode(pInfo->pThis, pNode->node. id))2824 else if (hdaCodecIsPortNode(pInfo->pThis, pNode->node.uID)) 2773 2825 { 2774 2826 CODECDBG_PRINT("PORT\n"); 2775 2827 } 2776 else if (hdaCodecIsDacNode(pInfo->pThis, pNode->node. id))2828 else if (hdaCodecIsDacNode(pInfo->pThis, pNode->node.uID)) 2777 2829 { 2778 2830 CODECDBG_PRINT("DAC\n"); … … 2784 2836 CODECDBG_UNINDENT 2785 2837 } 2786 else if (hdaCodecIsAdcVolNode(pInfo->pThis, pNode->node. id))2838 else if (hdaCodecIsAdcVolNode(pInfo->pThis, pNode->node.uID)) 2787 2839 { 2788 2840 CODECDBG_PRINT("ADC VOLUME\n"); … … 2793 2845 CODECDBG_UNINDENT 2794 2846 } 2795 else if (hdaCodecIsAdcNode(pInfo->pThis, pNode->node. id))2847 else if (hdaCodecIsAdcNode(pInfo->pThis, pNode->node.uID)) 2796 2848 { 2797 2849 CODECDBG_PRINT("ADC\n"); … … 2803 2855 CODECDBG_UNINDENT 2804 2856 } 2805 else if (hdaCodecIsAdcMuxNode(pInfo->pThis, pNode->node. id))2857 else if (hdaCodecIsAdcMuxNode(pInfo->pThis, pNode->node.uID)) 2806 2858 { 2807 2859 CODECDBG_PRINT("ADC MUX\n"); … … 2812 2864 CODECDBG_UNINDENT 2813 2865 } 2814 else if (hdaCodecIsPcbeepNode(pInfo->pThis, pNode->node. id))2866 else if (hdaCodecIsPcbeepNode(pInfo->pThis, pNode->node.uID)) 2815 2867 { 2816 2868 CODECDBG_PRINT("PC BEEP\n"); 2817 2869 } 2818 else if (hdaCodecIsSpdifOutNode(pInfo->pThis, pNode->node. id))2870 else if (hdaCodecIsSpdifOutNode(pInfo->pThis, pNode->node.uID)) 2819 2871 { 2820 2872 CODECDBG_PRINT("SPDIF OUT\n"); 2821 2873 } 2822 else if (hdaCodecIsSpdifInNode(pInfo->pThis, pNode->node. id))2874 else if (hdaCodecIsSpdifInNode(pInfo->pThis, pNode->node.uID)) 2823 2875 { 2824 2876 CODECDBG_PRINT("SPDIF IN\n"); 2825 2877 } 2826 else if (hdaCodecIsDigInPinNode(pInfo->pThis, pNode->node. id))2878 else if (hdaCodecIsDigInPinNode(pInfo->pThis, pNode->node.uID)) 2827 2879 { 2828 2880 CODECDBG_PRINT("DIGITAL IN PIN\n"); 2829 2881 } 2830 else if (hdaCodecIsDigOutPinNode(pInfo->pThis, pNode->node. id))2882 else if (hdaCodecIsDigOutPinNode(pInfo->pThis, pNode->node.uID)) 2831 2883 { 2832 2884 CODECDBG_PRINT("DIGITAL OUT PIN\n"); 2833 2885 } 2834 else if (hdaCodecIsCdNode(pInfo->pThis, pNode->node. id))2886 else if (hdaCodecIsCdNode(pInfo->pThis, pNode->node.uID)) 2835 2887 { 2836 2888 CODECDBG_PRINT("CD\n"); 2837 2889 } 2838 else if (hdaCodecIsVolKnobNode(pInfo->pThis, pNode->node. id))2890 else if (hdaCodecIsVolKnobNode(pInfo->pThis, pNode->node.uID)) 2839 2891 { 2840 2892 CODECDBG_PRINT("VOLUME KNOB\n"); 2841 2893 } 2842 else if (hdaCodecIsReservedNode(pInfo->pThis, pNode->node. id))2894 else if (hdaCodecIsReservedNode(pInfo->pThis, pNode->node.uID)) 2843 2895 { 2844 2896 CODECDBG_PRINT("RESERVED\n"); 2845 2897 } 2846 2898 else 2847 CODECDBG_PRINT("UNKNOWN TYPE 0x%x\n", pNode->node. id);2899 CODECDBG_PRINT("UNKNOWN TYPE 0x%x\n", pNode->node.uID); 2848 2900 2849 2901 if (fRecursive) … … 2853 2905 { \ 2854 2906 const uint8_t uID = RT_BYTE##_aEntry(_aNode->node.au32F02_param[0x0]); \ 2855 if (pNode->node. id== uID) \2907 if (pNode->node.uID == uID) \ 2856 2908 codecDbgPrintNode(pInfo, _aNode, false /* fRecursive */); \ 2857 2909 } … … 2861 2913 { 2862 2914 const PCODECNODE pSubNode = &pInfo->pThis->paNodes[i]; 2863 if (pSubNode->node. id == pNode->node.id)2915 if (pSubNode->node.uID == pNode->node.uID) 2864 2916 continue; 2865 2917 … … 3052 3104 for (unsigned idxNode = 0; idxNode < pThis->cTotalNodes; ++idxNode) 3053 3105 { 3054 uint8_t idOld = pThis->paNodes[idxNode].SavedState.Core. id;3106 uint8_t idOld = pThis->paNodes[idxNode].SavedState.Core.uID; 3055 3107 int rc = SSMR3GetStructEx(pSSM, &pThis->paNodes[idxNode].SavedState, 3056 3108 sizeof(pThis->paNodes[idxNode].SavedState), … … 3058 3110 if (RT_FAILURE(rc)) 3059 3111 return rc; 3060 AssertLogRelMsgReturn(idOld == pThis->paNodes[idxNode].SavedState.Core. id,3061 ("loaded %#x, expected %#x\n", pThis->paNodes[idxNode].SavedState.Core. id, idOld),3112 AssertLogRelMsgReturn(idOld == pThis->paNodes[idxNode].SavedState.Core.uID, 3113 ("loaded %#x, expected %#x\n", pThis->paNodes[idxNode].SavedState.Core.uID, idOld), 3062 3114 VERR_SSM_DATA_UNIT_FORMAT_CHANGED); 3063 3115 } -
trunk/src/VBox/Devices/Audio/DevIchHdaCodec.h
r60925 r60941 97 97 DECLR3CALLBACKMEMBER(int, pfnMixerAddStream, (PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl, PPDMAUDIOSTREAMCFG pCfg)); 98 98 DECLR3CALLBACKMEMBER(int, pfnMixerRemoveStream, (PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl)); 99 DECLR3CALLBACKMEMBER(int, pfnMixerSetStream, (PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl, uint8_t uSD, uint8_t uChannel)); 99 100 DECLR3CALLBACKMEMBER(int, pfnMixerSetVolume, (PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl, PPDMAUDIOVOLUME pVol)); 100 101 /** Callbacks by codec implementation. */
Note:
See TracChangeset
for help on using the changeset viewer.