Changeset 64875 in vbox
- Timestamp:
- Dec 14, 2016 4:13:17 PM (8 years ago)
- File:
-
- 1 edited
-
trunk/src/VBox/Devices/Audio/DevHDA.cpp (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DevHDA.cpp
r64861 r64875 103 103 # define VBOX_WITH_HDA_AUDIO_INTERLEAVING_STREAMS_SUPPORT 104 104 #endif 105 106 /** Default timer frequency (in Hz). */ 107 #define HDA_TIMER_HZ 100 105 108 106 109 /** … … 743 746 744 747 /** 745 * Structure defining an HDA mixer stream. 746 * This is being used together with an audio mixer instance. 747 */ 748 typedef struct HDAMIXERSTREAM 748 * Structure defining a (host backend) driver stream. 749 * Each driver has its own instances of audio mixer streams, which then 750 * can go into the same (or even different) audio mixer sinks. 751 */ 752 typedef struct HDADRIVERSTREAM 749 753 { 750 754 union … … 758 762 /** Associated mixer handle. */ 759 763 R3PTRTYPE(PAUDMIXSTREAM) pMixStrm; 760 } HDA MIXERSTREAM, *PHDAMIXERSTREAM;764 } HDADRIVERSTREAM, *PHDADRIVERSTREAM; 761 765 762 766 /** … … 787 791 R3PTRTYPE(PPDMIAUDIOCONNECTOR) pConnector; 788 792 /** Mixer stream for line input. */ 789 HDA MIXERSTREAM LineIn;793 HDADRIVERSTREAM LineIn; 790 794 #ifdef VBOX_WITH_AUDIO_HDA_MIC_IN 791 795 /** Mixer stream for mic input. */ 792 HDA MIXERSTREAM MicIn;796 HDADRIVERSTREAM MicIn; 793 797 #endif 794 798 /** Mixer stream for front output. */ 795 HDA MIXERSTREAM Front;799 HDADRIVERSTREAM Front; 796 800 #ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND 797 801 /** Mixer stream for center/LFE output. */ 798 HDA MIXERSTREAM CenterLFE;802 HDADRIVERSTREAM CenterLFE; 799 803 /** Mixer stream for rear output. */ 800 HDA MIXERSTREAM Rear;804 HDADRIVERSTREAM Rear; 801 805 #endif 802 806 } HDADRIVER; … … 1824 1828 if (pStream->State.pCircBuf) 1825 1829 RTCircBufReset(pStream->State.pCircBuf); 1826 #if 01827 RT_ZERO(pStream->State.abFIFO);1828 pStream->State.cbFIFOUsed = 0;1829 pStream->State.cbFIFOOff = 0;1830 #endif1831 1830 1832 1831 /* … … 3531 3530 } 3532 3531 3533 #if 03534 /**3535 * hdaReadAudio - copies samples from audio backend to DMA.3536 * Note: This function writes to the DMA buffer immediately,3537 * but "reports bytes" when all conditions are met (FIFOW).3538 */3539 static int hdaReadAudio(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToRead, uint32_t *pcbRead)3540 {3541 AssertPtrReturn(pThis, VERR_INVALID_POINTER);3542 AssertPtrReturn(pStream, VERR_INVALID_POINTER);3543 /* pcbRead is optional. */3544 3545 int rc;3546 uint32_t cbRead = 0;3547 3548 do3549 {3550 PHDABDLE pBDLE = &pStream->State.BDLE;3551 3552 if (!cbToRead)3553 {3554 rc = VINF_EOF;3555 break;3556 }3557 3558 AssertPtr(pStream->pMixSink);3559 AssertPtr(pStream->pMixSink->pMixSink);3560 rc = AudioMixerSinkRead(pStream->pMixSink->pMixSink, AUDMIXOP_BLEND, pBDLE->State.au8FIFO, cbToRead, &cbRead);3561 if (RT_FAILURE(rc))3562 break;3563 3564 if (!cbRead)3565 {3566 rc = VINF_EOF;3567 break;3568 }3569 3570 /* Sanity checks. */3571 Assert(cbRead <= cbToRead);3572 Assert(cbRead <= sizeof(pBDLE->State.au8FIFO));3573 Assert(cbRead <= pBDLE->Desc.u32BufSize - pBDLE->State.u32BufOff);3574 3575 /*3576 * Write to the BDLE's DMA buffer.3577 */3578 rc = PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns),3579 pBDLE->Desc.u64BufAdr + pBDLE->State.u32BufOff,3580 pBDLE->State.au8FIFO, cbRead);3581 AssertRC(rc);3582 3583 #ifdef HDA_DEBUG_DUMP_PCM_DATA3584 RTFILE fh;3585 RTFileOpen(&fh, HDA_DEBUG_DUMP_PCM_DATA_PATH "hdaReadAudio.pcm",3586 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);3587 RTFileWrite(fh, pBDLE->State.au8FIFO, cbRead, NULL);3588 RTFileClose(fh);3589 #endif3590 if (pBDLE->State.cbBelowFIFOW + cbRead > hdaStreamGetFIFOW(pThis, pStream))3591 {3592 Assert(pBDLE->State.u32BufOff + cbRead <= pBDLE->Desc.u32BufSize);3593 pBDLE->State.u32BufOff += cbRead;3594 pBDLE->State.cbBelowFIFOW = 0;3595 //hdaBackendReadTransferReported(pBDLE, cbDMAData, cbRead, &cbRead, pcbAvail);3596 }3597 else3598 {3599 Assert(pBDLE->State.u32BufOff + cbRead <= pBDLE->Desc.u32BufSize);3600 pBDLE->State.u32BufOff += cbRead;3601 pBDLE->State.cbBelowFIFOW += cbRead;3602 Assert(pBDLE->State.cbBelowFIFOW <= hdaStreamGetFIFOW(pThis, pStream));3603 //hdaBackendTransferUnreported(pThis, pBDLE, pStreamDesc, cbRead, pcbAvail);3604 3605 rc = VERR_NO_DATA;3606 }3607 3608 } while (0);3609 3610 if (RT_SUCCESS(rc))3611 {3612 if (pcbRead)3613 *pcbRead = cbRead;3614 }3615 3616 if (RT_FAILURE(rc))3617 LogFlowFunc(("Failed with %Rrc\n", rc));3618 3619 return rc;3620 }3621 3622 static int hdaWriteAudio(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToWrite, uint32_t *pcbWritten)3623 {3624 AssertPtrReturn(pThis, VERR_INVALID_POINTER);3625 AssertPtrReturn(pStream, VERR_INVALID_POINTER);3626 /* pcbWritten is optional. */3627 3628 PHDABDLE pBDLE = &pStream->State.BDLE;3629 3630 uint32_t cbWritten = 0;3631 3632 /*3633 * Copy from DMA to the corresponding stream buffer (if there are any bytes from the3634 * previous unreported transfer we write at offset 'pBDLE->State.cbUnderFifoW').3635 */3636 int rc;3637 if (!cbToWrite)3638 {3639 rc = VINF_EOF;3640 }3641 else3642 {3643 void *pvBuf = pBDLE->State.au8FIFO + pBDLE->State.cbBelowFIFOW;3644 Assert(cbToWrite >= pBDLE->State.cbBelowFIFOW);3645 uint32_t cbBuf = cbToWrite - pBDLE->State.cbBelowFIFOW;3646 3647 /*3648 * Read from the current BDLE's DMA buffer.3649 */3650 rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns),3651 pBDLE->Desc.u64BufAdr + pBDLE->State.u32BufOff,3652 pvBuf, cbBuf);3653 AssertRC(rc);3654 3655 #ifdef HDA_DEBUG_DUMP_PCM_DATA3656 RTFILE fh;3657 RTFileOpen(&fh, HDA_DEBUG_DUMP_PCM_DATA_PATH "hdaWriteAudio.pcm",3658 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);3659 RTFileWrite(fh, pvBuf, cbBuf, NULL);3660 RTFileClose(fh);3661 #endif3662 3663 #ifdef VBOX_WITH_STATISTICS3664 STAM_COUNTER_ADD(&pThis->StatBytesRead, cbBuf);3665 #endif3666 /*3667 * Write to audio backend. We should ensure that we have enough bytes to copy to the backend.3668 */3669 if (cbBuf >= hdaStreamGetFIFOW(pThis, pStream))3670 {3671 #if defined(VBOX_WITH_HDA_AUDIO_INTERLEAVING_STREAMS_SUPPORT) || defined(VBOX_WITH_AUDIO_HDA_51_SURROUND)3672 PHDASTREAMMAPPING pMapping = &pStream->State.Mapping;3673 #endif3674 3675 /** @todo Which channel is which? */3676 #ifdef VBOX_WITH_HDA_AUDIO_INTERLEAVING_STREAMS_SUPPORT3677 PPDMAUDIOSTREAMCHANNEL pChanFront = &pMapping->paChannels[0];3678 #endif3679 #ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND3680 PPDMAUDIOSTREAMCHANNEL pChanCenterLFE = &pMapping->paChannels[2]; /** @todo FIX! */3681 PPDMAUDIOSTREAMCHANNEL pChanRear = &pMapping->paChannels[4]; /** @todo FIX! */3682 #endif3683 int rc2;3684 3685 void *pvDataFront = NULL;3686 size_t cbDataFront;3687 #ifdef VBOX_WITH_HDA_AUDIO_INTERLEAVING_STREAMS_SUPPORT3688 rc2 = hdaStreamChannelExtract(pChanFront, pvBuf, cbBuf);3689 AssertRC(rc2);3690 3691 rc2 = hdaStreamChannelAcquireData(&pChanFront->Data, pvDataFront, &cbDataFront);3692 AssertRC(rc2);3693 #else3694 /* Use stuff in the whole FIFO to use for the channel data. */3695 pvDataFront = pvBuf;3696 cbDataFront = cbBuf;3697 #endif3698 #ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND3699 void *pvDataCenterLFE;3700 size_t cbDataCenterLFE;3701 rc2 = hdaStreamChannelExtract(pChanCenterLFE, pvBuf, cbBuf);3702 AssertRC(rc2);3703 3704 rc2 = hdaStreamChannelAcquireData(&pChanCenterLFE->Data, pvDataCenterLFE, &cbDataCenterLFE);3705 AssertRC(rc2);3706 3707 void *pvDataRear;3708 size_t cbDataRear;3709 rc2 = hdaStreamChannelExtract(pChanRear, pvBuf, cbBuf);3710 AssertRC(rc2);3711 3712 rc2 = hdaStreamChannelAcquireData(&pChanRear->Data, pvDataRear, &cbDataRear);3713 AssertRC(rc2);3714 #endif3715 3716 /*3717 * Write data to according mixer sinks.3718 */3719 rc2 = AudioMixerSinkWrite(pThis->SinkFront.pMixSink, AUDMIXOP_COPY, pvDataFront, (uint32_t)cbDataFront,3720 NULL /* pcbWritten */);3721 AssertRC(rc2);3722 #ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND3723 rc2 = AudioMixerSinkWrite(pThis->SinkCenterLFE, AUDMIXOP_COPY, pvDataCenterLFE, (uint32_t)cbDataCenterLFE,3724 NULL /* pcbWritten */);3725 AssertRC(rc2);3726 rc2 = AudioMixerSinkWrite(pThis->SinkRear, AUDMIXOP_COPY, pvDataRear, (uint32_t)cbDataRear,3727 NULL /* pcbWritten */);3728 AssertRC(rc2);3729 #endif3730 3731 #ifdef VBOX_WITH_HDA_AUDIO_INTERLEAVING_STREAMS_SUPPORT3732 hdaStreamChannelReleaseData(&pChanFront->Data);3733 #endif3734 #ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND3735 hdaStreamChannelReleaseData(&pChanCenterLFE->Data);3736 hdaStreamChannelReleaseData(&pChanRear->Data);3737 #endif3738 3739 /* Always report all data as being written;3740 * backends who were not able to catch up have to deal with it themselves. */3741 cbWritten = cbToWrite;3742 3743 hdaBDLEUpdate(pBDLE, cbToWrite, cbWritten);3744 }3745 else3746 {3747 AssertFailed();3748 3749 Assert(pBDLE->State.u32BufOff + cbWritten <= pBDLE->Desc.u32BufSize);3750 pBDLE->State.u32BufOff += cbWritten;3751 pBDLE->State.cbBelowFIFOW += cbWritten;3752 Assert(pBDLE->State.cbBelowFIFOW <= hdaStreamGetFIFOW(pThis, pStream));3753 3754 /* Not enough bytes to be processed and reported, we'll try our luck next time around. */3755 //hdaBackendTransferUnreported(pThis, pBDLE, pStreamDesc, cbAvail, NULL);3756 rc = VINF_EOF;3757 }3758 }3759 3760 Assert(cbWritten <= pStream->u16FIFOS);3761 3762 if (RT_SUCCESS(rc))3763 {3764 if (pcbWritten)3765 *pcbWritten = cbWritten;3766 }3767 3768 if (RT_FAILURE(rc))3769 LogFlowFunc(("Failed with %Rrc\n", rc));3770 3771 return rc;3772 }3773 #endif3774 3775 3532 /** 3776 3533 * Retrieves a corresponding sink for a given mixer control. … … 3838 3595 { 3839 3596 int rc2 = VINF_SUCCESS; 3840 PHDA MIXERSTREAM pStream = NULL;3597 PHDADRIVERSTREAM pDrvStream = NULL; 3841 3598 3842 3599 PPDMAUDIOSTREAMCFG pStreamCfg = (PPDMAUDIOSTREAMCFG)RTMemDup(pCfg, sizeof(PDMAUDIOSTREAMCFG)); … … 3857 3614 { 3858 3615 case PDMAUDIORECSOURCE_LINE: 3859 p Stream = &pDrv->LineIn;3616 pDrvStream = &pDrv->LineIn; 3860 3617 break; 3861 3618 #ifdef VBOX_WITH_AUDIO_HDA_MIC_IN 3862 3619 case PDMAUDIORECSOURCE_MIC: 3863 p Stream = &pDrv->MicIn;3620 pDrvStream = &pDrv->MicIn; 3864 3621 break; 3865 3622 #endif … … 3876 3633 { 3877 3634 case PDMAUDIOPLAYBACKDEST_FRONT: 3878 p Stream = &pDrv->Front;3635 pDrvStream = &pDrv->Front; 3879 3636 break; 3880 3637 #ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND 3881 3638 case PDMAUDIOPLAYBACKDEST_CENTER_LFE: 3882 p Stream = &pDrv->CenterLFE;3639 pDrvStream = &pDrv->CenterLFE; 3883 3640 break; 3884 3641 case PDMAUDIOPLAYBACKDEST_REAR: 3885 p Stream = &pDrv->Rear;3642 pDrvStream = &pDrv->Rear; 3886 3643 break; 3887 3644 #endif … … 3896 3653 if (RT_SUCCESS(rc2)) 3897 3654 { 3898 AssertPtr(p Stream);3899 3900 AudioMixerSinkRemoveStream(pSink->pMixSink, p Stream->pMixStrm);3901 3902 AudioMixerStreamDestroy(p Stream->pMixStrm);3903 p Stream->pMixStrm = NULL;3655 AssertPtr(pDrvStream); 3656 3657 AudioMixerSinkRemoveStream(pSink->pMixSink, pDrvStream->pMixStrm); 3658 3659 AudioMixerStreamDestroy(pDrvStream->pMixStrm); 3660 pDrvStream->pMixStrm = NULL; 3904 3661 3905 3662 PAUDMIXSTREAM pMixStrm; … … 3912 3669 3913 3670 if (RT_SUCCESS(rc2)) 3914 p Stream->pMixStrm = pMixStrm;3671 pDrvStream->pMixStrm = pMixStrm; 3915 3672 } 3916 3673 … … 6166 5923 #ifndef VBOX_WITH_AUDIO_HDA_CALLBACKS 6167 5924 uint16_t uTimerHz; 6168 rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, 100 /* Hz*/);5925 rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, HDA_TIMER_HZ /* Default value, if not set. */); 6169 5926 if (RT_FAILURE(rc)) 6170 5927 return PDMDEV_SET_ERROR(pDevIns, rc,
Note:
See TracChangeset
for help on using the changeset viewer.

