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

📄 hwctxt.cpp

📁 Samsung公司S3C6400芯片的BSP源码包
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	// WM9713 Need This !!!!
	WriteCodecRegister(WM9713_POWER_CONTROL, 0x1000);

	AC97_enable_codec_ready_interrupt();

	AC97_enable_ACLink_data_transfer();

	AC97_wait_for_codec_ready();

	AC97_disable_all_interrupt();
	AC97_clear_all_interrupt();

	AC97_set_pcmout_transfer_mode(AC97_CH_OFF);
	AC97_set_pcmin_transfer_mode(AC97_CH_OFF);

	WAV_MSG((_T("[WAV] --InitAC97() \n\r")));

	return TRUE;
}


BOOL
HardwareContext::InitCodec()
{
	USHORT CodecVendorID0, CodecVendorID1;
	BOOL bRet = TRUE;

	WAV_MSG((_T("[WAV] ++InitCodec()\n\r")));

	WriteCodecRegister(WM9713_POWER_CONTROL, 0x0000);
	WriteCodecRegister(WM9713_POWERDOWN1, 0x0000);
	WriteCodecRegister(WM9713_POWERDOWN2, 0x0000);
	WriteCodecRegister(WM9713_MCLK_PLL_CTRL0, 0x0b80);

	WriteCodecRegister(WM9713_HEADPHONE_VOL, 0x0808);			// Unmute HPL, HPR
	WriteCodecRegister(WM9713_DAC_VOL_ROUTING, 0x6404);		// Unmute DAC to HPMix, SPKMix, MONOMix, 0 dB
	WriteCodecRegister(WM9713_OUTPUT_MUX, 0x00a0);			// Output HPL, HPR is HPMix, All others is Vmid

	WriteCodecRegister(WM9713_RECORD_ROUTING_MUX, 0xd652);	// Record Mux Source is LineIn, +20dB
	WriteCodecRegister(WM9713_RECORD_VOL, 0x0000);			// Unmute ADC input

	WriteCodecRegister(WM9713_ADDITIONAL_FUNC2, 0x0080);		// AC97_ADDITIONAL_FUNC2	// Set DAC Auto-Mute, bit[1:0]=00, ADC Slot(L/R=3/4)
	WriteCodecRegister(WM9713_EXTED_AUDIOCTRL, 0x0031); 		// bit[5:4]=11, SPDIF Output Slot(L/R=10/11), VRA Enabled

	//------------------------------------------------------------------------------
	// If using sampling rate other than 48KHz you must enable VRA before set sampling rate !!!!!
	//------------------------------------------------------------------------------
	WriteCodecRegister(WM9713_AUDIO_DAC_RATE, SAMPLERATE);		// 2Ch DAC Sample rate
	WriteCodecRegister(WM9713_AUDIO_ADC_RATE, SAMPLERATE);		// 32h ADC Sample rate
	WriteCodecRegister(WM9713_AUX_DAC_RATE, SAMPLERATE);		 // AC97_AUXDAC_RATE	// 2Eh AUXDAC Sample rate

	CodecMuteControl(DMA_CH_OUT | DMA_CH_IN, FALSE);	// output, Input Mute
	CodecPowerControl();								// ADC, DAC Power Off

	CodecVendorID0 = ReadCodecRegister(WM9713_VENDOR_ID1);
	CodecVendorID1 = ReadCodecRegister(WM9713_VENDOR_ID2);

	if (CodecVendorID0 != 0x574d || CodecVendorID1 != 0x4c13)
	{
		// 0x574D4C13 is VenderID of WM9713 Codec
		WAV_ERR((_T("[WAV:ERR] InitCodec() : VenderID Mismatch\n\r")));
		bRet = FALSE;
	}

	WAV_INF((_T("[WAV:INF] InitCodec() : VenderID = 0x%08x\n\r"), ((CodecVendorID0<<16) | CodecVendorID1)));

	WAV_MSG((_T("[WAV] --InitCodec()\n\r")));

	return bRet;
}


BOOL
HardwareContext::InitOutputDMA()
{
	BOOL bRet = TRUE;

	WAV_MSG((_T("[WAV] ++InitOutputDMA()\n\r")));

	if (!g_PhyDMABufferAddr.LowPart)
	{
		WAV_ERR((_T("[WAV:ERR] InitOutputDMA() : DMA Buffer is Not Allocated Yet\n\r")));
		bRet = FALSE;
		goto CleanUp;
	}

	bRet = DMA_request_channel(&g_OutputDMA, DMA_AC97_PCMOUT);
	if (bRet)
	{
		DMA_initialize_channel(&g_OutputDMA, TRUE);
		DMA_set_channel_source(&g_OutputDMA, m_OutputDMABufferPhyPage[0], WORD_UNIT, BURST_1, INCREASE);
		DMA_set_channel_destination(&g_OutputDMA, AC97_get_pcmout_physical_buffer_address(), WORD_UNIT, BURST_1, FIXED);
		DMA_set_channel_transfer_size(&g_OutputDMA, AUDIO_DMA_PAGE_SIZE);
		DMA_initialize_LLI(&g_OutputDMA, 2);
		DMA_set_LLI_entry(&g_OutputDMA, 0, LLI_NEXT_ENTRY, m_OutputDMABufferPhyPage[0],
							AC97_get_pcmout_physical_buffer_address(), AUDIO_DMA_PAGE_SIZE);
		DMA_set_LLI_entry(&g_OutputDMA, 1, LLI_FIRST_ENTRY, m_OutputDMABufferPhyPage[1],
							AC97_get_pcmout_physical_buffer_address(), AUDIO_DMA_PAGE_SIZE);
		DMA_set_initial_LLI(&g_OutputDMA, 1);
	}

CleanUp:

	WAV_MSG((_T("[WAV] --InitOutputDMA()\n\r")));

	return bRet;
}


BOOL HardwareContext::InitInputDMA()
{
	BOOL bRet = TRUE;

	WAV_MSG((_T("[WAV] ++InitInputDMA()\n\r")));

	if (!g_PhyDMABufferAddr.LowPart)
	{
		WAV_ERR((_T("[WAV:ERR] InitInputDMA() : DMA Buffer is Not Allocated Yet\n\r")));
		bRet = FALSE;
		goto CleanUp;
	}

	bRet = DMA_request_channel(&g_InputDMA, DMA_AC97_PCMIN);
	if (bRet)
	{
		DMA_initialize_channel(&g_InputDMA, TRUE);
		DMA_set_channel_source(&g_InputDMA, AC97_get_pcmin_physical_buffer_address(), WORD_UNIT, BURST_1, FIXED);
		DMA_set_channel_destination(&g_InputDMA, m_InputDMABufferPhyPage[0], WORD_UNIT, BURST_1, INCREASE);
		DMA_set_channel_transfer_size(&g_InputDMA, AUDIO_DMA_PAGE_SIZE);
		DMA_initialize_LLI(&g_InputDMA, 2);
		DMA_set_initial_LLI(&g_InputDMA, 1);
		DMA_set_LLI_entry(&g_InputDMA, 0, LLI_NEXT_ENTRY, AC97_get_pcmin_physical_buffer_address(),
							m_InputDMABufferPhyPage[0], AUDIO_DMA_PAGE_SIZE);
		DMA_set_LLI_entry(&g_InputDMA, 1, LLI_FIRST_ENTRY, AC97_get_pcmin_physical_buffer_address(),
							m_InputDMABufferPhyPage[1], AUDIO_DMA_PAGE_SIZE);
	}

CleanUp:

	WAV_MSG((_T("[WAV] --InitInputDMA()\n\r")));

	return bRet;
}


BOOL
HardwareContext::InitInterruptThread()
{
	DWORD Irq;
	DWORD dwPriority;

	Irq = g_OutputDMA.dwIRQ;
	if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &Irq, sizeof(DWORD), &m_dwSysintrOutput, sizeof(DWORD), NULL))
	{
		WAV_ERR((_T("[WAV:ERR] InitInterruptThread() : Output DMA IOCTL_HAL_REQUEST_SYSINTR Failed \n\r")));
		return FALSE;
	}

	Irq = g_InputDMA.dwIRQ;
	if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &Irq, sizeof(DWORD), &m_dwSysintrInput, sizeof(DWORD), NULL))
	{
		WAV_ERR((_T("[WAV:ERR] InitInterruptThread() : Input DMA IOCTL_HAL_REQUEST_SYSINTR Failed \n\r")));
		return FALSE;
	}

	m_hOutputDMAInterrupt = CreateEvent(NULL, FALSE, FALSE, NULL);
	if (m_hOutputDMAInterrupt == NULL)
	{
		WAV_ERR((_T("[WAV:ERR] InitInterruptThread() : Output DMA CreateEvent() Failed \n\r")));
		return(FALSE);
	}

	m_hInputDMAInterrupt = CreateEvent(NULL, FALSE, FALSE, NULL);
	if (m_hInputDMAInterrupt == NULL)
	{
		WAV_ERR((_T("[WAV:ERR] InitInterruptThread() : Input DMA CreateEvent() Failed \n\r")));
		return(FALSE);
	}

	if (!InterruptInitialize(m_dwSysintrOutput, m_hOutputDMAInterrupt, NULL, 0))
	{
		WAV_ERR((_T("[WAV:ERR] InitInterruptThread() : Output DMA InterruptInitialize() Failed \n\r")));
		return FALSE;
	}

	if (! InterruptInitialize(m_dwSysintrInput, m_hInputDMAInterrupt, NULL, 0))
	{
		WAV_ERR((_T("[WAV:ERR] InitInterruptThread() : Input DMA InterruptInitialize() Failed \n\r")));
		return FALSE;
	}


	m_hOutputDMAInterruptThread = CreateThread((LPSECURITY_ATTRIBUTES)NULL, 0,
							(LPTHREAD_START_ROUTINE)CallInterruptThreadOutputDMA, this, 0, NULL);

	if (m_hOutputDMAInterruptThread == NULL)
	{
		WAV_ERR((_T("[WAV:ERR] InitInterruptThread() : Output DMA CreateThread() Failed \n\r")));
		return FALSE;
	}

	m_hInputDMAInterruptThread = CreateThread((LPSECURITY_ATTRIBUTES)NULL, 0,
							(LPTHREAD_START_ROUTINE)CallInterruptThreadInputDMA, this, 0, NULL);

	if (m_hInputDMAInterruptThread == NULL)
	{
		WAV_ERR((_T("[WAV:ERR] InitInterruptThread() : Input DMA CreateThread() Failed \n\r")));
		return FALSE;
	}

	dwPriority = GetInterruptThreadPriority();

	// Bump up the priority since the interrupt must be serviced immediately.
	CeSetThreadPriority(m_hOutputDMAInterruptThread, dwPriority);
	CeSetThreadPriority(m_hInputDMAInterruptThread, dwPriority);
	WAV_INF((_T("[WAV:INF] InitInterruptThread() : IST Priority = %d\n\r"), dwPriority));

	return(TRUE);
}

BOOL
HardwareContext::DeinitInterruptThread()
{
	return TRUE;
}


DWORD
HardwareContext::GetInterruptThreadPriority()
{
	HKEY hDevKey;
	DWORD dwValType;
	DWORD dwValLen;
	DWORD dwPrio = INTERRUPT_THREAD_PRIORITY_DEFAULT;
	LONG lResult;

	hDevKey = OpenDeviceKey((LPWSTR)m_DriverIndex);
	if (hDevKey)
	{
		dwValLen = sizeof(DWORD);
		lResult = RegQueryValueEx(hDevKey, TEXT("Priority256"), NULL, &dwValType, (PUCHAR)&dwPrio, &dwValLen);
		RegCloseKey(hDevKey);
	}
	else
	{
		WAV_ERR((_T("[WAV:ERR] GetInterruptThreadPriority() : OpenDeviceKey() Failed\n\r")));
	}

	return dwPrio;
}


ULONG
HardwareContext::TransferOutputBuffer(DWORD dwStatus)
{
	ULONG BytesTransferred = 0;
	ULONG BytesTotal = 0;

	dwStatus &= (DMA_DONEA|DMA_DONEB|DMA_BIU);

	//WAV_MSG((_T("[WAV] TransferOutputBuffer(0x%08x)\n\r"), dwStatus));

	switch (dwStatus)
	{
	case 0:
	case DMA_BIU:
		// No done bits set- must not be my interrupt
		return 0;
	case DMA_DONEA|DMA_DONEB|DMA_BIU:
		// Load B, then A
		BytesTransferred = FillOutputBuffer(OUTPUT_DMA_BUFFER1);
		// fall through
	case DMA_DONEA: // This should never happen!
	case DMA_DONEA|DMA_BIU:
		BytesTransferred += FillOutputBuffer(OUTPUT_DMA_BUFFER0);		// charlie, A => B
		break;
	case DMA_DONEA|DMA_DONEB:
		// Load A, then B
		BytesTransferred = FillOutputBuffer(OUTPUT_DMA_BUFFER0);
		// charlie
		BytesTransferred += FillOutputBuffer(OUTPUT_DMA_BUFFER1);
		break;		// charlie
	case DMA_DONEB|DMA_BIU: // This should never happen!
	case DMA_DONEB:
		// Load B
		BytesTransferred += FillOutputBuffer(OUTPUT_DMA_BUFFER1);		// charlie, B => A
		break;
	}

	// If it was our interrupt, but we weren't able to transfer any bytes
	// (e.g. no full buffers ready to be emptied)
	// and all the output DMA buffers are now empty, then stop the output DMA
	BytesTotal = m_nOutByte[OUTPUT_DMA_BUFFER0]+m_nOutByte[OUTPUT_DMA_BUFFER1];

	if (BytesTotal == 0)
	{
		StopOutputDMA();
	}
	else
	{
		StartOutputDMA();		// for DMA resume when wake up
	}

	return BytesTransferred;
}


ULONG
HardwareContext::FillOutputBuffer(int nBufferNumber)
{
	ULONG BytesTransferred = 0;
	PBYTE pBufferStart = m_OutputDMABufferVirPage[nBufferNumber];
	PBYTE pBufferEnd = pBufferStart + AUDIO_DMA_PAGE_SIZE;
	PBYTE pBufferLast;

	//WAV_MSG((_T("[WAV] FillOutputBuffer(%d)\n\r"), nBufferNumber));

	__try
	{
		pBufferLast = m_OutputDeviceContext.TransferBuffer(pBufferStart, pBufferEnd, NULL);

		BytesTransferred = pBufferLast-pBufferStart;
		m_nOutByte[nBufferNumber] = BytesTransferred;

		// Enable if you need to clear the rest of the DMA buffer
		StreamContext::ClearBuffer(pBufferLast, pBufferEnd);

		if(nBufferNumber == OUTPUT_DMA_BUFFER0)			// Output Buffer A
		{
			m_OutputDMAStatus &= ~DMA_DONEA;
			m_OutputDMAStatus |= DMA_STRTA;
		}
		else								// Output Buffer B
		{
			m_OutputDMAStatus &= ~DMA_DONEB;
			m_OutputDMAStatus |= DMA_STRTB;
		}
	}
	__except(EXCEPTION_EXECUTE_HANDLER)
	{
		WAV_ERR((_T("[WAV:ERR] FillOutputBuffer() : Exception ccurs [%d]\n\r"), GetExceptionCode()));
		DEBUGMSG(ZONE_ERROR, (TEXT("WAVDEV2.DLL:TransferOutputBuffer() - EXCEPTION: %d"), GetExceptionCode()));
	}

	return BytesTransferred;
}


ULONG
HardwareContext::TransferInputBuffers(DWORD dwStatus)
{
	ULONG BytesTransferred=0;

	dwStatus &= (DMA_DONEA|DMA_DONEB|DMA_BIU);

	//WAV_MSG((_T("[WAV] TransferInputBuffers(0x%08x)\n\r"), dwStatus));

	switch (dwStatus)
	{
	case 0:
	case DMA_BIU:
		// No done bits set- must not be my interrupt
		return 0;
	case DMA_DONEA|DMA_DONEB|DMA_BIU:
		// Load B, then A
		BytesTransferred = FillInputBuffer(INPUT_DMA_BUFFER1);
		// fall through
	case DMA_DONEA: // This should never happen!
	case DMA_DONEA|DMA_BIU:
		// Load A
		BytesTransferred += FillInputBuffer(INPUT_DMA_BUFFER0);
		break;
	case DMA_DONEA|DMA_DONEB:
		// Load A, then B
		BytesTransferred = FillInputBuffer(INPUT_DMA_BUFFER0);
		BytesTransferred += FillInputBuffer(INPUT_DMA_BUFFER1);
		break;
	case DMA_DONEB|DMA_BIU: // This should never happen!
	case DMA_DONEB:
		// Load B
		BytesTransferred += FillInputBuffer(INPUT_DMA_BUFFER1);
		break;
	}

	// If it was our interrupt, but we weren't able to transfer any bytes
	// (e.g. no empty buffers ready to be filled)
	// Then stop the input DMA
	if (BytesTransferred==0)
	{
		StopInputDMA();
	}
	else
	{
		StartInputDMA();		// for DMA resume when wake up
	}

	return BytesTransferred;
}

ULONG
HardwareContext::FillInputBuffer(int nBufferNumber)
{
	ULONG BytesTransferred = 0;

	PBYTE pBufferStart = m_InputDMABufferVirPage[nBufferNumber];
	PBYTE pBufferEnd = pBufferStart + AUDIO_DMA_PAGE_SIZE;
	PBYTE pBufferLast;

	//WAV_MSG((_T("[WAV] FillInputBuffer(%d)\n\r"), nBufferNumber));

	__try
	{
		pBufferLast = m_InputDeviceContext.TransferBuffer(pBufferStart, pBufferEnd, NULL);
		BytesTransferred = m_nInByte[nBufferNumber] = pBufferLast-pBufferStart;

		if(nBufferNumber == INPUT_DMA_BUFFER0)			// Input Buffer A
		{
			m_InputDMAStatus &= ~DMA_DONEA;
			m_InputDMAStatus |= DMA_STRTA;
		}
		else												// Input Buffer B
		{
			m_InputDMAStatus &= ~DMA_DONEB;
			m_InputDMAStatus |= DMA_STRTB;
		}

	}
	__except(EXCEPTION_EXECUTE_HANDLER)
	{
		WAV_ERR((_T("[WAV:ERR] FillInputBuffer() : Exception ccurs [%d]\n\r"), GetExceptionCode()));
	}

	return BytesTransferred;
}


void
HardwareContext::WriteCodecRegister(UCHAR Reg, USHORT Val)
{
	AC97_write_codec(Reg, Val);
}

USHORT
HardwareContext::ReadCodecRegister(UCHAR Reg)
{
	return AC97_read_codec(Reg);
}


BOOL
HardwareContext::CodecPowerControl()
{

	if( m_bInputDMARunning & m_bOutputDMARunning )
	{
		//WAV_MSG((_T("[WAV] CodecPowerControl() : CodecPowerControl() ADC & DAC On\n\r")));
		WriteCodecRegister(WM9713_POWER_CONTROL, AC97_PWR_D0);	// ADC, DAC power up
	}
	else if( m_bInputDMARunning )
	{
		//WAV_MSG((_T("[WAV] CodecPowerControl() : CodecPowerControl() ADC On\n\r")));
		WriteCodecRegister(WM9713_POWER_CONTROL, AC97_PWR_PR1);	// DAC power down
	}
	else if( m_bOutputDMARunning )
	{
		//WAV_MSG((_T("[WAV] CodecPowerControl() : CodecPowerControl() DAC On\n\r")));
		WriteCodecRegister(WM9713_POWER_CONTROL, AC97_PWR_PR0);	// ADC power down
	}
	else
	{
		//WAV_MSG((_T("[WAV] CodecPowerControl() : CodecPowerControl() ADC & DAC Off\n\r")));
		WriteCodecRegister(WM9713_POWER_CONTROL, AC97_PWR_PR1|AC97_PWR_PR0);	// ADC, DAC power down
	}

	return(TRUE);
}


BOOL
HardwareContext::CodecMuteControl(DWORD channel, BOOL bMute)
{
	USHORT volume;

	if((channel & DMA_CH_OUT ))// && !m_bOutputDMARunning )
	{
		if(bMute)
		{
			volume = ReadCodecRegister(WM9713_HEADPHONE_VOL);
   			WriteCodecRegister(WM9713_HEADPHONE_VOL, volume|0x8080);
		}
		else
		{
			volume = ReadCodecRegister(WM9713_HEADPHONE_VOL);
   			WriteCodecRegister(WM9713_HEADPHONE_VOL, volume&~0x8080);
		}
	}

	if( (channel & DMA_CH_IN))// && !m_bInputDMARunning )
	{
		if(bMute)
		{
			volume = ReadCodecRegister(WM9713_RECORD_VOL);
			WriteCodecRegister(WM9713_RECORD_VOL, volume|0x8000);
		}
		else
		{
			volume = ReadCodecRegister(WM9713_RECORD_VOL);
			WriteCodecRegister(WM9713_RECORD_VOL, volume&~0x8000);
		}
	}

	return(TRUE);
}

void HardwareContext::SetSpeakerEnable(BOOL bEnable)
{
	// Code to turn speaker on/off here
	return;
}


void CallInterruptThreadOutputDMA(HardwareContext *pHWContext)
{
    pHWContext->InterruptThreadOutputDMA();
}

void CallInterruptThreadInputDMA(HardwareContext *pHWContext)
{
    pHWContext->InterruptThreadInputDMA();
}


⌨️ 快捷键说明

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