Changeset 80681 in vbox
- Timestamp:
- Sep 9, 2019 7:51:22 PM (5 years ago)
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DevHDA.cpp
r80680 r80681 4977 4977 */ 4978 4978 rc = PDMDevHlpPCIRegister(pDevIns, &pThis->PciDev); 4979 if (RT_FAILURE(rc)) 4980 return rc; 4979 AssertRCReturn(rc, rc); 4981 4980 4982 4981 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, 0x4000, PCI_ADDRESS_SPACE_MEM, hdaR3PciIoRegionMap); 4983 if (RT_FAILURE(rc)) 4984 return rc; 4982 AssertRCReturn(rc, rc); 4985 4983 4986 4984 #ifdef VBOX_WITH_MSI_DEVICES … … 4999 4997 5000 4998 rc = PDMDevHlpSSMRegister(pDevIns, HDA_SSM_VERSION, sizeof(*pThis), hdaR3SaveExec, hdaR3LoadExec); 5001 if (RT_FAILURE(rc)) 5002 return rc; 4999 AssertRCReturn(rc, rc); 5003 5000 5004 5001 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO … … 5019 5016 hdaR3ReattachInternal(pThis, NULL /* pDrv */, uLUN, "NullAudio"); 5020 5017 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding", 5021 N_("Host audio backend initialization has failed. Selecting the NULL audio backend"5022 "with the consequence that no sound is audible"));5018 N_("Host audio backend initialization has failed. " 5019 "Selecting the NULL audio backend with the consequence that no sound is audible")); 5023 5020 /* Attaching to the NULL audio backend will never fail. */ 5024 5021 rc = VINF_SUCCESS; 5025 5022 } 5023 else 5024 AssertRCReturn(rc, rc); 5026 5025 break; 5027 5026 } … … 5030 5029 LogFunc(("cLUNs=%RU8, rc=%Rrc\n", uLUN, rc)); 5031 5030 5032 if (RT_SUCCESS(rc)) 5033 { 5034 rc = AudioMixerCreate("HDA Mixer", 0 /* uFlags */, &pThis->pMixer); 5035 if (RT_SUCCESS(rc)) 5036 { 5037 /* 5038 * Add mixer output sinks. 5039 */ 5031 rc = AudioMixerCreate("HDA Mixer", 0 /* uFlags */, &pThis->pMixer); 5032 AssertRCReturn(rc, rc); 5033 5034 /* 5035 * Add mixer output sinks. 5036 */ 5040 5037 #ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND 5041 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Front", 5042 AUDMIXSINKDIR_OUTPUT, &pThis->SinkFront.pMixSink); 5043 AssertRC(rc); 5044 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Center / Subwoofer", 5045 AUDMIXSINKDIR_OUTPUT, &pThis->SinkCenterLFE.pMixSink); 5046 AssertRC(rc); 5047 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Rear", 5048 AUDMIXSINKDIR_OUTPUT, &pThis->SinkRear.pMixSink); 5049 AssertRC(rc); 5038 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Front", AUDMIXSINKDIR_OUTPUT, &pThis->SinkFront.pMixSink); 5039 AssertRCReturn(rc, rc); 5040 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Center / Subwoofer", AUDMIXSINKDIR_OUTPUT, &pThis->SinkCenterLFE.pMixSink); 5041 AssertRCReturn(rc, rc); 5042 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Rear", AUDMIXSINKDIR_OUTPUT, &pThis->SinkRear.pMixSink); 5043 AssertRCReturn(rc, rc); 5050 5044 #else 5051 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] PCM Output", 5052 AUDMIXSINKDIR_OUTPUT, &pThis->SinkFront.pMixSink); 5053 AssertRC(rc); 5045 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] PCM Output", AUDMIXSINKDIR_OUTPUT, &pThis->SinkFront.pMixSink); 5046 AssertRCReturn(rc, rc); 5054 5047 #endif 5055 /* 5056 * Add mixer input sinks.5057 */5058 rc = AudioMixerCreateSink(pThis->pMixer, "[Recording] Line In",5059 5060 AssertRC(rc);5048 5049 /* 5050 * Add mixer input sinks. 5051 */ 5052 rc = AudioMixerCreateSink(pThis->pMixer, "[Recording] Line In", AUDMIXSINKDIR_INPUT, &pThis->SinkLineIn.pMixSink); 5053 AssertRCReturn(rc, rc); 5061 5054 #ifdef VBOX_WITH_AUDIO_HDA_MIC_IN 5062 rc = AudioMixerCreateSink(pThis->pMixer, "[Recording] Microphone In", 5063 AUDMIXSINKDIR_INPUT, &pThis->SinkMicIn.pMixSink); 5064 AssertRC(rc); 5055 rc = AudioMixerCreateSink(pThis->pMixer, "[Recording] Microphone In", AUDMIXSINKDIR_INPUT, &pThis->SinkMicIn.pMixSink); 5056 AssertRCReturn(rc, rc); 5065 5057 #endif 5066 /* There is no master volume control. Set the master to max. */ 5067 PDMAUDIOVOLUME vol = { false, 255, 255 }; 5068 rc = AudioMixerSetMasterVolume(pThis->pMixer, &vol); 5069 AssertRC(rc); 5070 } 5071 } 5072 5073 if (RT_SUCCESS(rc)) 5074 { 5075 /* Allocate CORB buffer. */ 5076 pThis->cbCorbBuf = HDA_CORB_SIZE * HDA_CORB_ELEMENT_SIZE; 5077 pThis->pu32CorbBuf = (uint32_t *)RTMemAllocZ(pThis->cbCorbBuf); 5078 if (pThis->pu32CorbBuf) 5079 { 5080 /* Allocate RIRB buffer. */ 5081 pThis->cbRirbBuf = HDA_RIRB_SIZE * HDA_RIRB_ELEMENT_SIZE; 5082 pThis->pu64RirbBuf = (uint64_t *)RTMemAllocZ(pThis->cbRirbBuf); 5083 if (pThis->pu64RirbBuf) 5058 5059 /* There is no master volume control. Set the master to max. */ 5060 PDMAUDIOVOLUME vol = { false, 255, 255 }; 5061 rc = AudioMixerSetMasterVolume(pThis->pMixer, &vol); 5062 AssertRCReturn(rc, rc); 5063 5064 /* Allocate CORB buffer. */ 5065 pThis->cbCorbBuf = HDA_CORB_SIZE * HDA_CORB_ELEMENT_SIZE; 5066 pThis->pu32CorbBuf = (uint32_t *)RTMemAllocZ(pThis->cbCorbBuf); 5067 AssertReturn(pThis->pu32CorbBuf, VERR_NO_MEMORY); 5068 5069 /* Allocate RIRB buffer. */ 5070 pThis->cbRirbBuf = HDA_RIRB_SIZE * HDA_RIRB_ELEMENT_SIZE; 5071 pThis->pu64RirbBuf = (uint64_t *)RTMemAllocZ(pThis->cbRirbBuf); 5072 AssertReturn(pThis->pu64RirbBuf, VERR_NO_MEMORY); 5073 5074 /* Allocate codec. */ 5075 pThis->pCodec = (PHDACODEC)RTMemAllocZ(sizeof(HDACODEC)); 5076 AssertReturn(pThis->pCodec, VERR_NO_MEMORY); 5077 5078 /* Set codec callbacks to this controller. */ 5079 pThis->pCodec->pfnCbMixerAddStream = hdaR3MixerAddStream; 5080 pThis->pCodec->pfnCbMixerRemoveStream = hdaR3MixerRemoveStream; 5081 pThis->pCodec->pfnCbMixerControl = hdaR3MixerControl; 5082 pThis->pCodec->pfnCbMixerSetVolume = hdaR3MixerSetVolume; 5083 5084 pThis->pCodec->pHDAState = pThis; /* Assign HDA controller state to codec. */ 5085 5086 /* Construct the codec. */ 5087 rc = hdaCodecConstruct(pDevIns, pThis->pCodec, 0 /* Codec index */, pCfg); 5088 AssertRCReturn(rc, rc); 5089 5090 /* ICH6 datasheet defines 0 values for SVID and SID (18.1.14-15), which together with values returned for 5091 verb F20 should provide device/codec recognition. */ 5092 Assert(pThis->pCodec->u16VendorId); 5093 Assert(pThis->pCodec->u16DeviceId); 5094 PCIDevSetSubSystemVendorId(&pThis->PciDev, pThis->pCodec->u16VendorId); /* 2c ro - intel.) */ 5095 PCIDevSetSubSystemId( &pThis->PciDev, pThis->pCodec->u16DeviceId); /* 2e ro. */ 5096 5097 /* 5098 * Create all hardware streams. 5099 */ 5100 static const char * const s_apszNames[] = 5101 { 5102 "HDA SD0", "HDA SD1", "HDA SD2", "HDA SD3", 5103 "HDA SD4", "HDA SD5", "HDA SD6", "HDA SD7", 5104 }; 5105 AssertCompile(RT_ELEMENTS(s_apszNames) == HDA_MAX_STREAMS); 5106 for (uint8_t i = 0; i < HDA_MAX_STREAMS; ++i) 5107 { 5108 /* Create the emulation timer (per stream). 5109 * 5110 * Note: Use TMCLOCK_VIRTUAL_SYNC here, as the guest's HDA driver 5111 * relies on exact (virtual) DMA timing and uses DMA Position Buffers 5112 * instead of the LPIB registers. 5113 */ 5114 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, hdaR3Timer, &pThis->aStreams[i], 5115 TMTIMER_FLAGS_NO_CRIT_SECT, s_apszNames[i], &pThis->pTimer[i]); 5116 AssertRCReturn(rc, rc); 5117 5118 /* Use our own critcal section for the device timer. 5119 * That way we can control more fine-grained when to lock what. */ 5120 rc = TMR3TimerSetCritSect(pThis->pTimer[i], &pThis->CritSect); 5121 AssertRCReturn(rc, rc); 5122 5123 rc = hdaR3StreamCreate(&pThis->aStreams[i], pThis, i /* u8SD */); 5124 AssertRCReturn(rc, rc); 5125 } 5126 5127 #ifdef VBOX_WITH_AUDIO_HDA_ONETIME_INIT 5128 /* 5129 * Initialize the driver chain. 5130 */ 5131 PHDADRIVER pDrv; 5132 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node) 5133 { 5134 /* 5135 * Only primary drivers are critical for the VM to run. Everything else 5136 * might not worth showing an own error message box in the GUI. 5137 */ 5138 if (!(pDrv->fFlags & PDMAUDIODRVFLAGS_PRIMARY)) 5139 continue; 5140 5141 PPDMIAUDIOCONNECTOR pCon = pDrv->pConnector; 5142 AssertPtr(pCon); 5143 5144 bool fValidLineIn = AudioMixerStreamIsValid(pDrv->LineIn.pMixStrm); 5145 # ifdef VBOX_WITH_AUDIO_HDA_MIC_IN 5146 bool fValidMicIn = AudioMixerStreamIsValid(pDrv->MicIn.pMixStrm); 5147 # endif 5148 bool fValidOut = AudioMixerStreamIsValid(pDrv->Front.pMixStrm); 5149 # ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND 5150 /** @todo Anything to do here? */ 5151 # endif 5152 5153 if ( !fValidLineIn 5154 # ifdef VBOX_WITH_AUDIO_HDA_MIC_IN 5155 && !fValidMicIn 5156 # endif 5157 && !fValidOut) 5158 { 5159 LogRel(("HDA: Falling back to NULL backend (no sound audible)\n")); 5160 5161 hdaR3Reset(pDevIns); 5162 hdaR3ReattachInternal(pThis, pDrv, pDrv->uLUN, "NullAudio"); 5163 5164 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding", 5165 N_("No audio devices could be opened. " 5166 "Selecting the NULL audio backend with the consequence that no sound is audible")); 5167 } 5168 else 5169 { 5170 bool fWarn = false; 5171 5172 PDMAUDIOBACKENDCFG BackendCfg; 5173 int rc2 = pCon->pfnGetConfig(pCon, &BackendCfg); 5174 if (RT_SUCCESS(rc2)) 5084 5175 { 5085 /* Allocate codec. */ 5086 pThis->pCodec = (PHDACODEC)RTMemAllocZ(sizeof(HDACODEC)); 5087 if (!pThis->pCodec) 5088 rc = PDMDEV_SET_ERROR(pDevIns, VERR_NO_MEMORY, N_("Out of memory allocating HDA codec state")); 5089 } 5090 else 5091 rc = PDMDEV_SET_ERROR(pDevIns, VERR_NO_MEMORY, N_("Out of memory allocating RIRB")); 5092 } 5093 else 5094 rc = PDMDEV_SET_ERROR(pDevIns, VERR_NO_MEMORY, N_("Out of memory allocating CORB")); 5095 5096 if (RT_SUCCESS(rc)) 5097 { 5098 /* Set codec callbacks to this controller. */ 5099 pThis->pCodec->pfnCbMixerAddStream = hdaR3MixerAddStream; 5100 pThis->pCodec->pfnCbMixerRemoveStream = hdaR3MixerRemoveStream; 5101 pThis->pCodec->pfnCbMixerControl = hdaR3MixerControl; 5102 pThis->pCodec->pfnCbMixerSetVolume = hdaR3MixerSetVolume; 5103 5104 pThis->pCodec->pHDAState = pThis; /* Assign HDA controller state to codec. */ 5105 5106 /* Construct the codec. */ 5107 rc = hdaCodecConstruct(pDevIns, pThis->pCodec, 0 /* Codec index */, pCfg); 5108 if (RT_FAILURE(rc)) 5109 AssertRCReturn(rc, rc); 5110 5111 /* ICH6 datasheet defines 0 values for SVID and SID (18.1.14-15), which together with values returned for 5112 verb F20 should provide device/codec recognition. */ 5113 Assert(pThis->pCodec->u16VendorId); 5114 Assert(pThis->pCodec->u16DeviceId); 5115 PCIDevSetSubSystemVendorId(&pThis->PciDev, pThis->pCodec->u16VendorId); /* 2c ro - intel.) */ 5116 PCIDevSetSubSystemId( &pThis->PciDev, pThis->pCodec->u16DeviceId); /* 2e ro. */ 5117 } 5118 } 5119 5120 if (RT_SUCCESS(rc)) 5121 { 5122 /* 5123 * Create all hardware streams. 5124 */ 5125 static const char * const s_apszNames[] = 5126 { 5127 "HDA SD0", "HDA SD1", "HDA SD2", "HDA SD3", 5128 "HDA SD4", "HDA SD5", "HDA SD6", "HDA SD7", 5129 }; 5130 AssertCompile(RT_ELEMENTS(s_apszNames) == HDA_MAX_STREAMS); 5131 for (uint8_t i = 0; i < HDA_MAX_STREAMS; ++i) 5132 { 5133 /* Create the emulation timer (per stream). 5134 * 5135 * Note: Use TMCLOCK_VIRTUAL_SYNC here, as the guest's HDA driver 5136 * relies on exact (virtual) DMA timing and uses DMA Position Buffers 5137 * instead of the LPIB registers. 5138 */ 5139 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, hdaR3Timer, &pThis->aStreams[i], 5140 TMTIMER_FLAGS_NO_CRIT_SECT, s_apszNames[i], &pThis->pTimer[i]); 5141 AssertRCReturn(rc, rc); 5142 5143 /* Use our own critcal section for the device timer. 5144 * That way we can control more fine-grained when to lock what. */ 5145 rc = TMR3TimerSetCritSect(pThis->pTimer[i], &pThis->CritSect); 5146 AssertRCReturn(rc, rc); 5147 5148 rc = hdaR3StreamCreate(&pThis->aStreams[i], pThis, i /* u8SD */); 5149 AssertRC(rc); 5150 } 5151 5152 #ifdef VBOX_WITH_AUDIO_HDA_ONETIME_INIT 5153 /* 5154 * Initialize the driver chain. 5155 */ 5156 PHDADRIVER pDrv; 5157 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node) 5158 { 5159 /* 5160 * Only primary drivers are critical for the VM to run. Everything else 5161 * might not worth showing an own error message box in the GUI. 5162 */ 5163 if (!(pDrv->fFlags & PDMAUDIODRVFLAGS_PRIMARY)) 5164 continue; 5165 5166 PPDMIAUDIOCONNECTOR pCon = pDrv->pConnector; 5167 AssertPtr(pCon); 5168 5169 bool fValidLineIn = AudioMixerStreamIsValid(pDrv->LineIn.pMixStrm); 5176 if (BackendCfg.cMaxStreamsIn) 5177 { 5170 5178 # ifdef VBOX_WITH_AUDIO_HDA_MIC_IN 5171 bool fValidMicIn = AudioMixerStreamIsValid(pDrv->MicIn.pMixStrm); 5172 # endif 5173 bool fValidOut = AudioMixerStreamIsValid(pDrv->Front.pMixStrm); 5174 # ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND 5175 /** @todo Anything to do here? */ 5176 # endif 5177 5178 if ( !fValidLineIn 5179 # ifdef VBOX_WITH_AUDIO_HDA_MIC_IN 5180 && !fValidMicIn 5181 # endif 5182 && !fValidOut) 5183 { 5184 LogRel(("HDA: Falling back to NULL backend (no sound audible)\n")); 5185 5186 hdaR3Reset(pDevIns); 5187 hdaR3ReattachInternal(pThis, pDrv, pDrv->uLUN, "NullAudio"); 5188 5189 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding", 5190 N_("No audio devices could be opened. Selecting the NULL audio backend " 5191 "with the consequence that no sound is audible")); 5179 /* If the audio backend supports two or more input streams at once, 5180 * warn if one of our two inputs (microphone-in and line-in) failed to initialize. */ 5181 if (BackendCfg.cMaxStreamsIn >= 2) 5182 fWarn = !fValidLineIn || !fValidMicIn; 5183 /* If the audio backend only supports one input stream at once (e.g. pure ALSA, and 5184 * *not* ALSA via PulseAudio plugin!), only warn if both of our inputs failed to initialize. 5185 * One of the two simply is not in use then. */ 5186 else if (BackendCfg.cMaxStreamsIn == 1) 5187 fWarn = !fValidLineIn && !fValidMicIn; 5188 /* Don't warn if our backend is not able of supporting any input streams at all. */ 5189 # else /* !VBOX_WITH_AUDIO_HDA_MIC_IN */ 5190 /* We only have line-in as input source. */ 5191 fWarn = !fValidLineIn; 5192 # endif /* !VBOX_WITH_AUDIO_HDA_MIC_IN */ 5193 } 5194 5195 if ( !fWarn 5196 && BackendCfg.cMaxStreamsOut) 5197 fWarn = !fValidOut; 5192 5198 } 5193 5199 else 5194 5200 { 5195 bool fWarn = false; 5196 5197 PDMAUDIOBACKENDCFG backendCfg; 5198 int rc2 = pCon->pfnGetConfig(pCon, &backendCfg); 5199 if (RT_SUCCESS(rc2)) 5201 LogRel(("HDA: Unable to retrieve audio backend configuration for LUN #%RU8, rc=%Rrc\n", pDrv->uLUN, rc2)); 5202 fWarn = true; 5203 } 5204 5205 if (fWarn) 5206 { 5207 char szMissingStreams[255]; 5208 size_t len = 0; 5209 if (!fValidLineIn) 5200 5210 { 5201 if (backendCfg.cMaxStreamsIn) 5202 { 5211 LogRel(("HDA: WARNING: Unable to open PCM line input for LUN #%RU8!\n", pDrv->uLUN)); 5212 len = RTStrPrintf(szMissingStreams, sizeof(szMissingStreams), "PCM Input"); 5213 } 5203 5214 # ifdef VBOX_WITH_AUDIO_HDA_MIC_IN 5204 /* If the audio backend supports two or more input streams at once, 5205 * warn if one of our two inputs (microphone-in and line-in) failed to initialize. */ 5206 if (backendCfg.cMaxStreamsIn >= 2) 5207 fWarn = !fValidLineIn || !fValidMicIn; 5208 /* If the audio backend only supports one input stream at once (e.g. pure ALSA, and 5209 * *not* ALSA via PulseAudio plugin!), only warn if both of our inputs failed to initialize. 5210 * One of the two simply is not in use then. */ 5211 else if (backendCfg.cMaxStreamsIn == 1) 5212 fWarn = !fValidLineIn && !fValidMicIn; 5213 /* Don't warn if our backend is not able of supporting any input streams at all. */ 5214 # else /* !VBOX_WITH_AUDIO_HDA_MIC_IN */ 5215 /* We only have line-in as input source. */ 5216 fWarn = !fValidLineIn; 5217 # endif /* VBOX_WITH_AUDIO_HDA_MIC_IN */ 5218 } 5219 5220 if ( !fWarn 5221 && backendCfg.cMaxStreamsOut) 5222 { 5223 fWarn = !fValidOut; 5224 } 5215 if (!fValidMicIn) 5216 { 5217 LogRel(("HDA: WARNING: Unable to open PCM microphone input for LUN #%RU8!\n", pDrv->uLUN)); 5218 len += RTStrPrintf(szMissingStreams + len, 5219 sizeof(szMissingStreams) - len, len ? ", PCM Microphone" : "PCM Microphone"); 5225 5220 } 5226 else 5221 # endif 5222 if (!fValidOut) 5227 5223 { 5228 LogRel(("HDA: Unable to retrieve audio backend configuration for LUN #%RU8, rc=%Rrc\n", pDrv->uLUN, rc2)); 5229 fWarn = true; 5224 LogRel(("HDA: WARNING: Unable to open PCM output for LUN #%RU8!\n", pDrv->uLUN)); 5225 len += RTStrPrintf(szMissingStreams + len, 5226 sizeof(szMissingStreams) - len, len ? ", PCM Output" : "PCM Output"); 5230 5227 } 5231 5228 5232 if (fWarn) 5233 { 5234 char szMissingStreams[255]; 5235 size_t len = 0; 5236 if (!fValidLineIn) 5237 { 5238 LogRel(("HDA: WARNING: Unable to open PCM line input for LUN #%RU8!\n", pDrv->uLUN)); 5239 len = RTStrPrintf(szMissingStreams, sizeof(szMissingStreams), "PCM Input"); 5240 } 5241 # ifdef VBOX_WITH_AUDIO_HDA_MIC_IN 5242 if (!fValidMicIn) 5243 { 5244 LogRel(("HDA: WARNING: Unable to open PCM microphone input for LUN #%RU8!\n", pDrv->uLUN)); 5245 len += RTStrPrintf(szMissingStreams + len, 5246 sizeof(szMissingStreams) - len, len ? ", PCM Microphone" : "PCM Microphone"); 5247 } 5248 # endif /* VBOX_WITH_AUDIO_HDA_MIC_IN */ 5249 if (!fValidOut) 5250 { 5251 LogRel(("HDA: WARNING: Unable to open PCM output for LUN #%RU8!\n", pDrv->uLUN)); 5252 len += RTStrPrintf(szMissingStreams + len, 5253 sizeof(szMissingStreams) - len, len ? ", PCM Output" : "PCM Output"); 5254 } 5255 5256 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding", 5257 N_("Some HDA audio streams (%s) could not be opened. Guest applications generating audio " 5258 "output or depending on audio input may hang. Make sure your host audio device " 5259 "is working properly. Check the logfile for error messages of the audio " 5260 "subsystem"), szMissingStreams); 5261 } 5229 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding", 5230 N_("Some HDA audio streams (%s) could not be opened. " 5231 "Guest applications generating audio output or depending on audio input may hang. " 5232 "Make sure your host audio device is working properly. " 5233 "Check the logfile for error messages of the audio subsystem"), szMissingStreams); 5262 5234 } 5263 5235 } 5236 } 5264 5237 #endif /* VBOX_WITH_AUDIO_HDA_ONETIME_INIT */ 5265 } 5266 5267 if (RT_SUCCESS(rc)) 5268 { 5269 hdaR3Reset(pDevIns); 5270 5271 /* 5272 * Debug and string formatter types. 5273 */ 5274 PDMDevHlpDBGFInfoRegister(pDevIns, "hda", "HDA info. (hda [register case-insensitive])", hdaR3DbgInfo); 5275 PDMDevHlpDBGFInfoRegister(pDevIns, "hdabdle", "HDA stream BDLE info. (hdabdle [stream number])", hdaR3DbgInfoBDLE); 5276 PDMDevHlpDBGFInfoRegister(pDevIns, "hdastream", "HDA stream info. (hdastream [stream number])", hdaR3DbgInfoStream); 5277 PDMDevHlpDBGFInfoRegister(pDevIns, "hdcnodes", "HDA codec nodes.", hdaR3DbgInfoCodecNodes); 5278 PDMDevHlpDBGFInfoRegister(pDevIns, "hdcselector", "HDA codec's selector states [node number].", hdaR3DbgInfoCodecSelector); 5279 PDMDevHlpDBGFInfoRegister(pDevIns, "hdamixer", "HDA mixer state.", hdaR3DbgInfoMixer); 5280 5281 rc = RTStrFormatTypeRegister("bdle", hdaR3StrFmtBDLE, NULL); 5282 AssertRC(rc); 5283 rc = RTStrFormatTypeRegister("sdctl", hdaR3StrFmtSDCTL, NULL); 5284 AssertRC(rc); 5285 rc = RTStrFormatTypeRegister("sdsts", hdaR3StrFmtSDSTS, NULL); 5286 AssertRC(rc); 5287 rc = RTStrFormatTypeRegister("sdfifos", hdaR3StrFmtSDFIFOS, NULL); 5288 AssertRC(rc); 5289 rc = RTStrFormatTypeRegister("sdfifow", hdaR3StrFmtSDFIFOW, NULL); 5290 AssertRC(rc); 5291 5292 /* 5293 * Some debug assertions. 5294 */ 5295 for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegMap); i++) 5296 { 5297 struct HDAREGDESC const *pReg = &g_aHdaRegMap[i]; 5298 struct HDAREGDESC const *pNextReg = i + 1 < RT_ELEMENTS(g_aHdaRegMap) ? &g_aHdaRegMap[i + 1] : NULL; 5299 5300 /* binary search order. */ 5301 AssertReleaseMsg(!pNextReg || pReg->offset + pReg->size <= pNextReg->offset, 5302 ("[%#x] = {%#x LB %#x} vs. [%#x] = {%#x LB %#x}\n", 5303 i, pReg->offset, pReg->size, i + 1, pNextReg->offset, pNextReg->size)); 5304 5305 /* alignment. */ 5306 AssertReleaseMsg( pReg->size == 1 5307 || (pReg->size == 2 && (pReg->offset & 1) == 0) 5308 || (pReg->size == 3 && (pReg->offset & 3) == 0) 5309 || (pReg->size == 4 && (pReg->offset & 3) == 0), 5310 ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size)); 5311 5312 /* registers are packed into dwords - with 3 exceptions with gaps at the end of the dword. */ 5313 AssertRelease(((pReg->offset + pReg->size) & 3) == 0 || pNextReg); 5314 if (pReg->offset & 3) 5315 { 5316 struct HDAREGDESC const *pPrevReg = i > 0 ? &g_aHdaRegMap[i - 1] : NULL; 5317 AssertReleaseMsg(pPrevReg, ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size)); 5318 if (pPrevReg) 5319 AssertReleaseMsg(pPrevReg->offset + pPrevReg->size == pReg->offset, 5320 ("[%#x] = {%#x LB %#x} vs. [%#x] = {%#x LB %#x}\n", 5321 i - 1, pPrevReg->offset, pPrevReg->size, i + 1, pReg->offset, pReg->size)); 5322 } 5238 5239 hdaR3Reset(pDevIns); 5240 5241 /* 5242 * Info items and string formatter types. The latter is non-optional as 5243 * the info handles use (at least some of) the custom types and we cannot 5244 * accept screwing formatting. 5245 */ 5246 PDMDevHlpDBGFInfoRegister(pDevIns, "hda", "HDA info. (hda [register case-insensitive])", hdaR3DbgInfo); 5247 PDMDevHlpDBGFInfoRegister(pDevIns, "hdabdle", "HDA stream BDLE info. (hdabdle [stream number])", hdaR3DbgInfoBDLE); 5248 PDMDevHlpDBGFInfoRegister(pDevIns, "hdastream", "HDA stream info. (hdastream [stream number])", hdaR3DbgInfoStream); 5249 PDMDevHlpDBGFInfoRegister(pDevIns, "hdcnodes", "HDA codec nodes.", hdaR3DbgInfoCodecNodes); 5250 PDMDevHlpDBGFInfoRegister(pDevIns, "hdcselector", "HDA codec's selector states [node number].", hdaR3DbgInfoCodecSelector); 5251 PDMDevHlpDBGFInfoRegister(pDevIns, "hdamixer", "HDA mixer state.", hdaR3DbgInfoMixer); 5252 5253 rc = RTStrFormatTypeRegister("bdle", hdaR3StrFmtBDLE, NULL); 5254 AssertMsgReturn(RT_SUCCESS(rc) || rc == VERR_ALREADY_EXISTS, ("%Rrc\n", rc), rc); 5255 rc = RTStrFormatTypeRegister("sdctl", hdaR3StrFmtSDCTL, NULL); 5256 AssertMsgReturn(RT_SUCCESS(rc) || rc == VERR_ALREADY_EXISTS, ("%Rrc\n", rc), rc); 5257 rc = RTStrFormatTypeRegister("sdsts", hdaR3StrFmtSDSTS, NULL); 5258 AssertMsgReturn(RT_SUCCESS(rc) || rc == VERR_ALREADY_EXISTS, ("%Rrc\n", rc), rc); 5259 rc = RTStrFormatTypeRegister("sdfifos", hdaR3StrFmtSDFIFOS, NULL); 5260 AssertMsgReturn(RT_SUCCESS(rc) || rc == VERR_ALREADY_EXISTS, ("%Rrc\n", rc), rc); 5261 rc = RTStrFormatTypeRegister("sdfifow", hdaR3StrFmtSDFIFOW, NULL); 5262 AssertMsgReturn(RT_SUCCESS(rc) || rc == VERR_ALREADY_EXISTS, ("%Rrc\n", rc), rc); 5263 5264 /* 5265 * Asserting sanity. 5266 */ 5267 for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegMap); i++) 5268 { 5269 struct HDAREGDESC const *pReg = &g_aHdaRegMap[i]; 5270 struct HDAREGDESC const *pNextReg = i + 1 < RT_ELEMENTS(g_aHdaRegMap) ? &g_aHdaRegMap[i + 1] : NULL; 5271 5272 /* binary search order. */ 5273 AssertReleaseMsg(!pNextReg || pReg->offset + pReg->size <= pNextReg->offset, 5274 ("[%#x] = {%#x LB %#x} vs. [%#x] = {%#x LB %#x}\n", 5275 i, pReg->offset, pReg->size, i + 1, pNextReg->offset, pNextReg->size)); 5276 5277 /* alignment. */ 5278 AssertReleaseMsg( pReg->size == 1 5279 || (pReg->size == 2 && (pReg->offset & 1) == 0) 5280 || (pReg->size == 3 && (pReg->offset & 3) == 0) 5281 || (pReg->size == 4 && (pReg->offset & 3) == 0), 5282 ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size)); 5283 5284 /* registers are packed into dwords - with 3 exceptions with gaps at the end of the dword. */ 5285 AssertRelease(((pReg->offset + pReg->size) & 3) == 0 || pNextReg); 5286 if (pReg->offset & 3) 5287 { 5288 struct HDAREGDESC const *pPrevReg = i > 0 ? &g_aHdaRegMap[i - 1] : NULL; 5289 AssertReleaseMsg(pPrevReg, ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size)); 5290 if (pPrevReg) 5291 AssertReleaseMsg(pPrevReg->offset + pPrevReg->size == pReg->offset, 5292 ("[%#x] = {%#x LB %#x} vs. [%#x] = {%#x LB %#x}\n", 5293 i - 1, pPrevReg->offset, pPrevReg->size, i + 1, pReg->offset, pReg->size)); 5294 } 5323 5295 #if 0 5324 5325 5326 5327 5328 5329 5330 5331 5296 if ((pReg->offset + pReg->size) & 3) 5297 { 5298 AssertReleaseMsg(pNextReg, ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size)); 5299 if (pNextReg) 5300 AssertReleaseMsg(pReg->offset + pReg->size == pNextReg->offset, 5301 ("[%#x] = {%#x LB %#x} vs. [%#x] = {%#x LB %#x}\n", 5302 i, pReg->offset, pReg->size, i + 1, pNextReg->offset, pNextReg->size)); 5303 } 5332 5304 #endif 5333 /* The final entry is a full DWORD, no gaps! Allows shortcuts. */ 5334 AssertReleaseMsg(pNextReg || ((pReg->offset + pReg->size) & 3) == 0, 5335 ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size)); 5336 } 5305 /* The final entry is a full DWORD, no gaps! Allows shortcuts. */ 5306 AssertReleaseMsg(pNextReg || ((pReg->offset + pReg->size) & 3) == 0, 5307 ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size)); 5337 5308 } 5338 5309 5339 5310 # ifdef VBOX_WITH_STATISTICS 5340 if (RT_SUCCESS(rc)) 5341 { 5342 /* 5343 * Register statistics. 5344 */ 5345 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatTimer, STAMTYPE_PROFILE, "/Devices/HDA/Timer", STAMUNIT_TICKS_PER_CALL, "Profiling hdaR3Timer."); 5346 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatIn, STAMTYPE_PROFILE, "/Devices/HDA/Input", STAMUNIT_TICKS_PER_CALL, "Profiling input."); 5347 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatOut, STAMTYPE_PROFILE, "/Devices/HDA/Output", STAMUNIT_TICKS_PER_CALL, "Profiling output."); 5348 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatBytesRead, STAMTYPE_COUNTER, "/Devices/HDA/BytesRead" , STAMUNIT_BYTES, "Bytes read from HDA emulation."); 5349 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatBytesWritten, STAMTYPE_COUNTER, "/Devices/HDA/BytesWritten", STAMUNIT_BYTES, "Bytes written to HDA emulation."); 5350 } 5311 /* 5312 * Register statistics. 5313 */ 5314 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatTimer, STAMTYPE_PROFILE, "/Devices/HDA/Timer", STAMUNIT_TICKS_PER_CALL, "Profiling hdaR3Timer."); 5315 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatIn, STAMTYPE_PROFILE, "/Devices/HDA/Input", STAMUNIT_TICKS_PER_CALL, "Profiling input."); 5316 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatOut, STAMTYPE_PROFILE, "/Devices/HDA/Output", STAMUNIT_TICKS_PER_CALL, "Profiling output."); 5317 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatBytesRead, STAMTYPE_COUNTER, "/Devices/HDA/BytesRead" , STAMUNIT_BYTES, "Bytes read from HDA emulation."); 5318 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatBytesWritten, STAMTYPE_COUNTER, "/Devices/HDA/BytesWritten", STAMUNIT_BYTES, "Bytes written to HDA emulation."); 5351 5319 # endif 5352 5320 5353 LogFlowFuncLeaveRC(rc); 5354 return rc; 5321 return VINF_SUCCESS; 5355 5322 } 5356 5323 -
trunk/src/VBox/Devices/Audio/HDACodec.h
r76565 r80681 101 101 const uint8_t u8DacLineOut; 102 102 103 /** Public codec functions. */ 103 /** @name Public codec functions. 104 * @{ */ 104 105 DECLR3CALLBACKMEMBER(int, pfnLookup, (PHDACODEC pThis, uint32_t uVerb, uint64_t *puResp)); 105 106 DECLR3CALLBACKMEMBER(void, pfnReset, (PHDACODEC pThis)); 106 107 DECLR3CALLBACKMEMBER(int, pfnNodeReset, (PHDACODEC pThis, uint8_t, PCODECNODE)); 108 /** @} */ 107 109 108 /** Callbacks to the HDA controller, mostly used for multiplexing to the various host backends. */ 110 /** @name Callbacks to the HDA controller, mostly used for multiplexing to the 111 * various host backends. 112 * @{ */ 109 113 DECLR3CALLBACKMEMBER(int, pfnCbMixerAddStream, (PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl, PPDMAUDIOSTREAMCFG pCfg)); 110 114 DECLR3CALLBACKMEMBER(int, pfnCbMixerRemoveStream, (PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl)); 111 115 DECLR3CALLBACKMEMBER(int, pfnCbMixerControl, (PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl, uint8_t uSD, uint8_t uChannel)); 112 116 DECLR3CALLBACKMEMBER(int, pfnCbMixerSetVolume, (PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl, PPDMAUDIOVOLUME pVol)); 117 /** @} */ 113 118 114 /** These callbacks are set by codec implementation to answer debugger requests. */ 119 /** @name These callbacks are set by codec implementation to answer debugger requests. 120 * @{ */ 115 121 DECLR3CALLBACKMEMBER(void, pfnDbgListNodes, (PHDACODEC pThis, PCDBGFINFOHLP pHlp, const char *pszArgs)); 116 122 DECLR3CALLBACKMEMBER(void, pfnDbgSelector, (PHDACODEC pThis, PCDBGFINFOHLP pHlp, const char *pszArgs)); 123 /** @} */ 117 124 } HDACODEC; 118 125
Note:
See TracChangeset
for help on using the changeset viewer.