⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 minwave.cpp

📁 C-Media8738/8768声卡驱动开发源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
				that->requestedChannelMask =  *(PLONG)PropertyRequest->Value;
				that->requestedChannelCount = 6;
				return STATUS_SUCCESS;
			}
			if ((*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_QUAD) || (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_SURROUND)) {
				that->requestedChannelMask =  *(PLONG)PropertyRequest->Value;
				that->requestedChannelCount = 4;
				return STATUS_SUCCESS;
			}
			if (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_STEREO) {
				that->requestedChannelMask =  *(PLONG)PropertyRequest->Value;
				that->requestedChannelCount = 2;
				return STATUS_SUCCESS;
			}
		} else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) {
			PULONG AccessFlags = PULONG(PropertyRequest->Value);
			*AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET;
			PropertyRequest->ValueSize = sizeof(ULONG);
			return STATUS_SUCCESS;
		}
	}
	return STATUS_INVALID_PARAMETER;
}

///////////////////////////

NTSTATUS CreateMiniportWaveStreamCMI(CMiniportWaveStreamCMI  **MiniportWaveStreamCMI, PUNKNOWN pUnknownOuter, POOL_TYPE PoolType)
{
	PAGED_CODE();
	DBGPRINT(("CreateMiniportWaveStreamCMI"));

#ifdef WAVERT
	*MiniportWaveStreamCMI = new (PoolType, 'gnaa') CMiniportWaveStreamCMI(NULL);
#else
	*MiniportWaveStreamCMI = new (PoolType, 'gnaa') CMiniportWaveStreamCMI(pUnknownOuter);
#endif
	if (*MiniportWaveStreamCMI) {
		(*MiniportWaveStreamCMI)->AddRef();
		return STATUS_SUCCESS;
	}

	return STATUS_INSUFFICIENT_RESOURCES;
}

NTSTATUS CMiniportWaveStreamCMI::prepareStream()
{
	PAGED_CODE();
	DBGPRINT(("CMiniportWaveStreamCMI[%p]::prepareStream()", this));
	DBGPRINT(("---streamIndex: %d, channelNumber: %d", streamIndex, channelNumber));

	NTSTATUS ntStatus;
	UInt8    reg;
	UInt32   val;

	if (state == KSSTATE_RUN) {
		return STATUS_INVALID_DEVICE_REQUEST;
	}

	if (!(Miniport->cm)) {
		DBGPRINT(("Miniport not set"));
		return STATUS_INVALID_DEVICE_REQUEST;
	}

	enableSPDIF = ((currentSampleRate == 44100 || currentSampleRate == 48000 || currentSampleRate == 88200 || currentSampleRate == 96000) &&
		           ((currentResolution == 16) || (currentResolution == 24)) && (currentChannelCount == 2)) &&
		           (Miniport->cm->enableSPDIFOut);

	ntStatus = setupSPDIFPlayback(enableSPDIF);
	if (!NT_SUCCESS(ntStatus)) {
		return ntStatus;
	}

	if (!isCaptureStream) {
		ntStatus = setDACChannels();
		if (!NT_SUCCESS(ntStatus)) {
			return ntStatus;
		}
	}

	KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, false, NULL);

	val = channelNumber ? ADC_CH1 : ADC_CH0;
	if (isCaptureStream) {
		Miniport->cm->regFUNCTRL0 |= val;  // 1->Recording
	} else {
		Miniport->cm->regFUNCTRL0 &= ~val; // 0->Playback
	}
	Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0);

	//set sampling frequency
	val = Miniport->CMIAdapter->readUInt32(REG_FUNCTRL1);
	if ((currentSampleRate == 88200) || (currentSampleRate == 44100)) {
		if (channelNumber) {
			val &= ~SFC_CH1_MASK;
			val |= SFC_44K_CH1;
		} else {
			val &= ~SFC_CH0_MASK;
			val |= SFC_44K_CH0;
		}
	} else if ((currentSampleRate == 96000) || (currentSampleRate == 48000)) {
		if (channelNumber) {
			val &= ~SFC_CH1_MASK;
			val |= SFC_48K_CH1;
		} else {
			val &= ~SFC_CH0_MASK;
			val |= SFC_48K_CH0;
		}
	} else {
			KeReleaseMutex(&Miniport->mutex, FALSE);
			return STATUS_INVALID_DEVICE_REQUEST;
	}
	Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL1, val);

	//set resolution
	val = Miniport->CMIAdapter->readUInt32(REG_CHFORMAT);
	if (channelNumber) {
		val |= FORMAT_CH1;
	} else {
		val |= FORMAT_CH0;
	}
	Miniport->CMIAdapter->writeUInt32(REG_CHFORMAT, val);

	KeReleaseMutex(&Miniport->mutex, false);

	return STATUS_SUCCESS;
}

NTSTATUS CMiniportWaveStreamCMI::setDACChannels()
{
	PAGED_CODE();
	DBGPRINT(("CMiniportWaveStreamCMI[%p]::setDACChannels()", this));
	NTSTATUS ntStatus = STATUS_SUCCESS;

	if (currentChannelCount > 2) {
		if (Miniport->cm->maxChannels < currentChannelCount) {
			return STATUS_INVALID_DEVICE_REQUEST;
		}
		if ((currentResolution != 16) || (currentChannelCount < 2)) {
			return STATUS_INVALID_DEVICE_REQUEST;
		}
#if OUT_CHANNEL == 0
		return STATUS_INVALID_DEVICE_REQUEST;
#endif
		KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL);
		Miniport->CMIAdapter->setUInt32Bit(REG_LEGACY, DWORD_MAPPING);
		Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, XCHG_DAC);

		switch (currentChannelCount) {
			case 4:
				Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, EN_4CH_CH1);
				Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_5CH_CH1);
				Miniport->CMIAdapter->clearUInt32Bit(REG_LEGACY, EN_6CH_CH1);
				Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, EN_CENTER);
				break;
			case 6:
				Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_4CH_CH1);
				Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, EN_5CH_CH1);
				Miniport->CMIAdapter->setUInt32Bit(REG_LEGACY, EN_6CH_CH1);
				Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, EN_CENTER);
				break;
			case 8:
				if (Miniport->cm->chipVersion == 68) {
					Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_4CH_CH1);
					Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, EN_5CH_CH1);
					Miniport->CMIAdapter->setUInt32Bit(REG_LEGACY, EN_6CH_CH1);
					Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, EN_CENTER);
					Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL2, EN_8CH_CH1);
					break;
				} else {
					ntStatus = STATUS_INVALID_DEVICE_REQUEST;
				}
			default:
				ntStatus = STATUS_INVALID_DEVICE_REQUEST;
		}
		KeReleaseMutex(&Miniport->mutex, FALSE);
	} else {
		if (Miniport->cm->canMultiChannel) {
			KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL);
			Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_5CH_CH1 | EN_4CH_CH1);
			Miniport->CMIAdapter->clearUInt32Bit(REG_LEGACY, EN_6CH_CH1 | DWORD_MAPPING);
			Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, EN_CENTER);
			Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, XCHG_DAC);
			if (Miniport->cm->chipVersion == 68) {
				Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL2, EN_8CH_CH1);
			}
			KeReleaseMutex(&Miniport->mutex, FALSE);
		}
	}
	return ntStatus;
}

NTSTATUS CMiniportWaveStreamCMI::setupSPDIFPlayback(bool enableSPDIF)
{
	PAGED_CODE();
	DBGPRINT(("CMiniportWaveStreamCMI[%p]::setupSPDIFPlayback(%d)", this, enableSPDIF));

	NTSTATUS ntStatus;

	KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, false, NULL);

	if (enableSPDIF) {
		Miniport->CMIAdapter->setUInt32Bit(REG_LEGACY, EN_SPDIF_OUT);
		Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDO2DAC);
#if OUT_CHANNEL == 0
		Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDF_0);
#else
		Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDF_1);
#endif
		setupAC3Passthru();

		if ( (currentSampleRate == 48000) || (currentSampleRate == 96000) ) {
			Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, EN_SPDIF_48);
		} else {
			Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, EN_SPDIF_48);
		}

		if (currentSampleRate == 96000) {
#if OUT_CHANNEL == 0
			Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD96_CH0);
#else
			Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD96_CH1);
#endif
			Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, DBLSPDS);
		} else if (currentSampleRate == 88200) {
#if OUT_CHANNEL == 0
			Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD88_CH0);
#else
			Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD88_CH1);
#endif
			Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, DBLSPDS);
		} else {
#if OUT_CHANNEL == 0
			Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD88_CH0 | SPD96_CH0);
#else
			Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD88_CH1 | SPD96_CH1);
#endif
			Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, DBLSPDS);
		}

	} else {
		Miniport->CMIAdapter->clearUInt32Bit(REG_LEGACY, EN_SPDIF_OUT);
		Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDO2DAC);
#if OUT_CHANNEL == 0
		Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDF_0);
#else
		Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDF_1);
#endif
#if OUT_CHANNEL == 0
		Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD88_CH0 | SPD96_CH0);
#else
		Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD88_CH1 | SPD96_CH1);
#endif
		Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, DBLSPDS);
		setupAC3Passthru();
	}

	KeReleaseMutex(&Miniport->mutex, false);
	return STATUS_SUCCESS;
}

NTSTATUS CMiniportWaveStreamCMI::setupAC3Passthru()
{
	PAGED_CODE();
	DBGPRINT(("CMiniportWaveStreamCMI[%p]::setupAC3Passthru()"));

	if (enableAC3Passthru) {
		Miniport->CMIAdapter->writeUInt8(REG_MIXER1, Miniport->CMIAdapter->readUInt8(REG_MIXER1) | MUTE_WAVE);

		Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, EN_SPDO_AC3_1);
		Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, EN_SPDO_AC3_2);

		if (Miniport->cm->canAC3HW) {
			Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, EN_SPDO_AC3_3);
			Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, SPD32SEL);
			if (Miniport->cm->chipVersion >= 39) {
				Miniport->CMIAdapter->clearUInt8Bit(REG_MIXER1, EN_SPDI2DAC);
			}
		} else {
			Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, SPD32SEL);
			if (Miniport->cm->chipVersion == 33) {
				if (currentSampleRate >= 48000) {
#if OUT_CHANNEL == 0
					 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD96_CH0);
#else
					 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD96_CH1);
#endif
				} else {
#if OUT_CHANNEL == 0
					 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD96_CH0);
#else
					 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD96_CH1);
#endif
				}
			}
		}
	} else {
		Miniport->CMIAdapter->setUInt8Bit(REG_MIXER1, EN_SPDI2DAC);

		Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_SPDO_AC3_1);
		Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, EN_SPDO_AC3_2);

		if (Miniport->cm->canAC3HW) {
			Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_SPDO_AC3_3);
			if (currentResolution > 16) {
				Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, SPD32SEL);
				Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD24SEL);
			} else {
				Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, SPD32SEL);
				Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD24SEL);
			}
		} else {
			Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, SPD32SEL);
#if OUT_CHANNEL == 0
			Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD96_CH0);
#else
			Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD96_CH1);
#endif
		}
	}
	return STATUS_SUCCESS;
}

CMiniportWaveStreamCMI::~CMiniportWaveStreamCMI(void)
{
	PAGED_CODE();

	DBGPRINT(("CMiniportWaveStreamCMI[%p]::~CMiniportWaveStreamCMI", this));

#ifdef WAVERT
	if (Port) {
		Port->Release();
		Port = NULL;
	}
#else
	if (DMAChannel) {
		DMAChannel->Release();
		DMAChannel = NULL;
	}

	if (ServiceGroup) {
		ServiceGroup->Release();
		ServiceGroup = NULL;
	}
#endif

	Miniport->isStreamRunning[streamIndex] = false;

	if ((streamIndex == AC3_OUT_STREAM) && Miniport->isStreamRunning[PCM_OUT_STREAM]) {
		KSSTATE temp = Miniport->stream[PCM_OUT_STREAM]->state;
		Miniport->stream[PCM_OUT_STREAM]->state = KSSTATE_STOP;
		Miniport->stream[PCM_OUT_STREAM]->prepareStream();
		Miniport->stream[PCM_OUT_STREAM]->SetState(KSSTATE_ACQUIRE);
		Miniport->stream[PCM_OUT_STREAM]->state = temp;
		Miniport->stream[PCM_OUT_STREAM]->SetState(KSSTATE_RUN_AC3);
	}

	if (Miniport) {
		Miniport->Release();
		Miniport = NULL;
    }
}

STDMETHODIMP CMiniportWaveStreamCMI::NonDelegatingQueryInterface(REFIID Interface, PVOID *Object)
{
	PAGED_CODE();
	ASSERT(Object);
	DBGPRINT(("CMiniportWaveStreamCMI[%p]::NonDelegatingQueryInterface(%p, %p)", this, Interface, Object));

	if (IsEqualGUIDAligned(Interface,IID_IUnknown)) {
		*Object = PVOID(PUNKNOWN(PMINIPORTWAVECYCLICSTREAM(this)));
#ifdef WAVERT
	} else if (IsEqualGUIDAligned(Interface,IID_IMiniportWaveRTStream)) {
		*Object = PVOID(PMINIPORTWAVERTSTREAM(this));
#else
	} else if (IsEqualGUIDAligned(Interface,IID_IMiniportWaveCyclicStream)) {
		*Object = PVOID(PMINIPORTWAVECYCLICSTREAM(this));
#endif
	} else if (IsEqualGUIDAligned (Interface, IID_IDrmAudioStream)) {
		*Object = (PVOID)(PDRMAUDIOSTREAM(this));
	} else {
		*Object = NULL;
	}

	if (*Object) {
		PUNKNOWN(*Object)->AddRef();
		return STATUS_SUCCESS;
	}

	return STATUS_INVALID_PARAMETER;
}

#ifdef WAVERT
NTSTATUS CMiniportWaveStreamCMI::Init(CMiniportWaveCMI* Miniport_, UInt32 streamIndex_, bool isCaptureStream_, PKSDATAFORMAT DataFormat, PPORTWAVERTSTREAM Port_)
#else
NTSTATUS CMiniportWaveStreamCMI::Init(CMiniportWaveCMI* Miniport_, UInt32 streamIndex_, bool isCaptureStream_, PKSDATAFORMAT DataFormat, PDMACHANNEL DMAChannel_, PSERVICEGROUP* OutServiceGroup)
#endif
{
	PAGED_CODE();
	ASSERT(Miniport_);
	ASSERT(DataFormat);

	NTSTATUS ntStatus;

#ifdef WAVERT
    ASSERT(Port_);
	DBGPRINT(("CMiniportWaveStreamCMI[%p]::Init(%p, %d, %d, %p, %p)", this, Miniport_, streamIndex_, isCaptureStream_, DataFormat, Port_));
	Port = Port_;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -