hwctxt.cpp

来自「SAMSUNG S3C6410 CPU BSP for winmobile6」· C++ 代码 · 共 2,027 行 · 第 1/4 页

CPP
2,027
字号
						StopOutputDMA();
						StopInputDMA();

						Unlock();

						PowerDown();
					}
					break;
				}

				// return our state
				*(PCEDEVICE_POWER_STATE)pBufOut = m_Dx;

				WAV_INF((_T("[WAV:INF] IOCTL_POWER_SET -> [D%d]\n\r"), m_Dx));

				*pdwActualOut = sizeof(CEDEVICE_POWER_STATE);
			}
			else
			{
				bRc = FALSE;
				dwErr = ERROR_INVALID_PARAMETER;
			}
		}
		break;

	case IOCTL_POWER_GET:
		if ( !pdwActualOut || !pBufOut || (dwLenOut < sizeof(CEDEVICE_POWER_STATE)) )
		{
			bRc = FALSE;
			dwErr = ERROR_INVALID_PARAMETER;
			break;
		}

		*(PCEDEVICE_POWER_STATE)pBufOut = m_Dx;

		RETAILMSG(1, (TEXT("WAVEDEV: IOCTL_POWER_GET: D%u \r\n"), m_Dx));

		*pdwActualOut = sizeof(CEDEVICE_POWER_STATE);
		break;

	default:
		bRc = FALSE;
		dwErr = ERROR_INVALID_FUNCTION;
		DEBUGMSG (ZONE_FUNCTION, (TEXT(" Unsupported ioctl 0x%X\r\n"), dwCode));
		break;
	}

	if (!bRc)
	{
		SetLastError(dwErr);
	}

	return(bRc);
}


BOOL
HardwareContext::StartOutputDMA()
{
	ULONG OutputTransferred;

	//WAV_MSG((_T("[WAV] StartOutputDMA()\r\n")));

	if((m_bOutputDMARunning == FALSE) && (m_Dx == D0))
	{
		m_bOutputDMARunning = TRUE;
		m_nOutByte[OUTPUT_DMA_BUFFER0] = 0;
		m_nOutByte[OUTPUT_DMA_BUFFER1] = 0;

		m_nOutputBufferInUse = OUTPUT_DMA_BUFFER0;	// Start DMA with Buffer 0
		m_OutputDMAStatus = (DMA_DONEA | DMA_DONEB) & ~DMA_BIU;
		OutputTransferred = TransferOutputBuffer(m_OutputDMAStatus);

		if(OutputTransferred)
		{
			CodecPowerControl();					// Turn Output Channel
			CodecMuteControl(DMA_CH_OUT, FALSE);	// Unmute Output Channel

			// IIS PCM output enable
			IIS_set_tx_mode_control(IIS_TRANSFER_NOPAUSE);

			// Output DMA Start
			DMA_set_channel_source(&g_OutputDMA, m_OutputDMABufferPhyPage[OUTPUT_DMA_BUFFER0], WORD_UNIT, BURST_1, INCREASE);
#if		(CPU_NAME == S3C6410)
			DMA_set_channel_destination(&g_OutputDMA, IIS_get_output_physical_buffer_address(IIS_CH_2), WORD_UNIT, BURST_1, FIXED);
#elif	(CPU_NAME == S3C6400)
			DMA_set_channel_destination(&g_OutputDMA, IIS_get_output_physical_buffer_address(IIS_CH_0), WORD_UNIT, BURST_1, FIXED);
#endif
			DMA_set_channel_transfer_size(&g_OutputDMA, AUDIO_DMA_PAGE_SIZE);
			DMA_set_initial_LLI(&g_OutputDMA, 1);
			DMA_channel_start(&g_OutputDMA);

			IIS_set_active_on();
		}
		else
		{
			WAV_ERR((_T("[WAV:ERR] StartOutputDMA() : There is no data to transfer\r\n")));
			m_bOutputDMARunning = FALSE;
		}
	}
	else
	{
		//WAV_ERR((_T("[WAV:ERR] StartOutputDMA() : Output DMA is already running or m_Dx[%d] is not D0\r\n"), m_Dx));
		return FALSE;
	}

	return TRUE;
}


void
HardwareContext::StopOutputDMA()
{
	//WAV_MSG((_T("[WAV] StopOutputDMA()\r\n")));

	if (m_bOutputDMARunning)
	{
		m_OutputDMAStatus = DMA_CLEAR;

		// Stop output DMA
		DMA_channel_stop(&g_OutputDMA);

		// IIS PCM output disable
		IIS_set_tx_mode_control(IIS_TRANSFER_PAUSE);

		if (m_bInputDMARunning == FALSE) IIS_set_active_off();
	}

	m_bOutputDMARunning = FALSE;

	CodecMuteControl(DMA_CH_OUT, TRUE);
	CodecPowerControl();
}


BOOL
HardwareContext::StartInputDMA()
{
	WAV_MSG((_T("[WAV] StartInputDMA()\r\n")));

	if(m_bInputDMARunning == FALSE)
	{
		m_bInputDMARunning = TRUE;

		m_nInByte[INPUT_DMA_BUFFER0] = 0;
		m_nInByte[INPUT_DMA_BUFFER1] = 0;

		m_nInputBufferInUse = INPUT_DMA_BUFFER0;	// Start DMA with Buffer 0
		m_InputDMAStatus = (DMA_DONEA | DMA_DONEB) & ~DMA_BIU;

		CodecPowerControl();					// Turn On Channel
		CodecMuteControl(DMA_CH_IN, FALSE);	// Unmute Input Channel

		// IIS PCM input enable
		IIS_set_rx_mode_control(IIS_TRANSFER_NOPAUSE);

#if		(CPU_NAME == S3C6410)
		DMA_set_channel_source(&g_InputDMA, IIS_get_input_physical_buffer_address(IIS_CH_2), WORD_UNIT, BURST_1, FIXED);
#elif	(CPU_NAME == S3C6400)
		DMA_set_channel_source(&g_InputDMA, IIS_get_input_physical_buffer_address(IIS_CH_0), WORD_UNIT, BURST_1, FIXED);
#endif
		DMA_set_channel_destination(&g_InputDMA, m_InputDMABufferPhyPage[INPUT_DMA_BUFFER0], WORD_UNIT, BURST_1, INCREASE);
		DMA_set_channel_transfer_size(&g_InputDMA, AUDIO_DMA_PAGE_SIZE);
		DMA_set_initial_LLI(&g_InputDMA, 1);
		DMA_channel_start(&g_InputDMA);

		IIS_set_active_on();
	}
	else
	{
		//WAV_ERR((_T("[WAV:ERR] StartInputDMA() : Input DMA is already running\r\n")));
		return FALSE;
	}

	return TRUE;
}


void
HardwareContext::StopInputDMA()
{
	WAV_MSG((_T("[WAV] StopInputDMA()\r\n")));

	if (m_bInputDMARunning)
	{
		DMA_channel_stop(&g_InputDMA);
		// IIS PCM input disable
		IIS_set_rx_mode_control(IIS_TRANSFER_PAUSE);

		m_InputDMAStatus = DMA_CLEAR;

		if (m_bOutputDMARunning == FALSE) IIS_set_active_off();
	}

	m_bInputDMARunning = FALSE;

	CodecMuteControl(DMA_CH_IN, TRUE);
	CodecPowerControl();
}


DWORD
HardwareContext::GetOutputGain (void)
{
    return m_dwOutputGain;
}

MMRESULT
HardwareContext::SetOutputGain (DWORD dwGain)
{
	WAV_MSG((_T("[WAV] SetOutputGain(0x%08x)\r\n"), dwGain));

	m_dwOutputGain = dwGain & 0xffff;	// save off so we can return this from GetGain - but only MONO

	// convert 16-bit gain to 5-bit attenuation
	UCHAR ucGain;
	if (m_dwOutputGain == 0)
	{
		ucGain = 0x3F; // mute: set maximum attenuation
	}
	else
	{
		ucGain = (UCHAR) ((0xffff - m_dwOutputGain) >> 11);	// codec supports 64dB attenuation, we'll only use 32
	}

	//ASSERT((ucGain & 0xC0) == 0); // bits 6,7 clear indicate DATA0 in Volume mode.

	// TODO: When Control HW Volume???

	return MMSYSERR_NOERROR;
}


DWORD
HardwareContext::GetInputGain (void)
{
    return m_dwInputGain;
}

MMRESULT
HardwareContext::SetInputGain (DWORD dwGain)
{
	WAV_MSG((_T("[WAV] SetInputGain(0x%08x)\r\n"), dwGain));

	m_dwInputGain = dwGain;

	if (!m_bInputMute)
	{
		m_InputDeviceContext.SetGain(dwGain);
	}

	return MMSYSERR_NOERROR;
}

BOOL
HardwareContext::GetOutputMute (void)
{
	return m_bOutputMute;
}

MMRESULT
HardwareContext::SetOutputMute (BOOL bMute)
{
#if		(CPU_NAME == S3C6400)
	USHORT CodecReg;
#endif
	WAV_INF((_T("[WAV:INF] ++SetOutputMute(%d)\n\r"), bMute));

	m_bOutputMute = bMute;

#if		(CPU_NAME == S3C6410)
	if (bMute)
	{
		WriteCodecRegister(WM8580_DAC_CONTROL5, 0x010);	
	}
	else
	{
		WriteCodecRegister(WM8580_DAC_CONTROL5, 0x000);
	}

#elif	(CPU_NAME == S3C6400)
	CodecReg = ReadCodecRegister(WM8753_DAC_CONTROL);

	if (bMute)
	{
		CodecReg |= WM8753_DAC_SOFT_MUTE;
	}
	else
	{
		CodecReg &= ~WM8753_DAC_SOFT_MUTE;
	}

	WriteCodecRegister(WM8753_DAC_CONTROL, CodecReg);
#endif

	WAV_INF((_T("[WAV:INF] --SetOutputMute()\n\r")));

	return MMSYSERR_NOERROR;
}


BOOL
HardwareContext::GetInputMute (void)
{
	return m_bInputMute;
}

MMRESULT
HardwareContext::SetInputMute (BOOL bMute)
{
	m_bInputMute = bMute;
	return m_InputDeviceContext.SetGain(bMute ? 0: m_dwInputGain);
}


DWORD
HardwareContext::ForceSpeaker(BOOL bForceSpeaker)
{
	// If m_NumForcedSpeaker is non-zero, audio should be routed to an
	// external speaker (if hw permits).
	if (bForceSpeaker)
	{
		m_NumForcedSpeaker++;
		if (m_NumForcedSpeaker == 1)
		{
			SetSpeakerEnable(TRUE);
		}
	}
	else
	{
		m_NumForcedSpeaker--;
		if (m_NumForcedSpeaker ==0)
		{
			SetSpeakerEnable(FALSE);
		}
	}

	return MMSYSERR_NOERROR;
}


void
HardwareContext::InterruptThreadOutputDMA()
{
	ULONG OutputTransferred;

#if (_WIN32_WCE < 600)
	// Fast way to access embedded pointers in wave headers in other processes.
	SetProcPermissions((DWORD)-1);
#endif

	WAV_INF((_T("[WAV:INF] ++InterruptThreadOutputDMA()\n\r")));

	while(TRUE)
	{
		WaitForSingleObject(m_hOutputDMAInterrupt, INFINITE);

		Lock();

		__try
		{
			DMA_set_interrupt_mask(&g_OutputDMA);
			DMA_clear_interrupt_pending(&g_OutputDMA);

			InterruptDone(m_dwSysintrOutput);

			DMA_clear_interrupt_mask(&g_OutputDMA);

			if ( m_Dx == D0 )
			{
				// DMA Output Buffer is Changed by LLI
				if (m_nOutputBufferInUse == OUTPUT_DMA_BUFFER0)
				{
					// Buffer0 DMA finished
					// DMA start with Buffer 1
					m_nOutputBufferInUse = OUTPUT_DMA_BUFFER1;
				}
				else
				{
					// Buffer 1 DMA finished
					// DMA start with Buffer 0
					m_nOutputBufferInUse = OUTPUT_DMA_BUFFER0;
				}

				if(m_OutputDMAStatus & DMA_BIU)
				{
					m_OutputDMAStatus &= ~DMA_STRTB;	// Buffer B just completed...
					m_OutputDMAStatus |= DMA_DONEB;
					m_OutputDMAStatus &= ~DMA_BIU;		// Buffer A is in use
				}
				else
				{
					m_OutputDMAStatus &= ~DMA_STRTA;	// Buffer A just completed...
					m_OutputDMAStatus |= DMA_DONEA;
					m_OutputDMAStatus |= DMA_BIU;		// Buffer B is in use
				}

				OutputTransferred = TransferOutputBuffer(m_OutputDMAStatus);
			}
		}
		__except(EXCEPTION_EXECUTE_HANDLER)
		{
			DEBUGMSG(ZONE_ERROR, (TEXT("WAVDEV2.DLL:InterruptThreadOutputDMA() - EXCEPTION: %d"), GetExceptionCode()));
		}

		Unlock();
	}

	WAV_INF((_T("[WAV:INF] --InterruptThreadOutputDMA()\n\r")));
}

void
HardwareContext::InterruptThreadInputDMA()
{
	ULONG InputTransferred;		// How can I use it ???

#if (_WIN32_WCE < 600)
	// Fast way to access embedded pointers in wave headers in other processes.
	SetProcPermissions((DWORD)-1);
#endif

	//WAV_INF((_T("[WAV:INF] ++InterruptThreadInputDMA()\n\r")));

	while(TRUE)
	{
		WaitForSingleObject(m_hInputDMAInterrupt, INFINITE);

		Lock();

		__try
		{
			DMA_set_interrupt_mask(&g_InputDMA);
			DMA_clear_interrupt_pending(&g_InputDMA);

			InterruptDone(m_dwSysintrInput);

			DMA_clear_interrupt_mask(&g_InputDMA);

			if ( m_Dx == D0 )
			{
				if (m_nInputBufferInUse == INPUT_DMA_BUFFER0)
				{
					// Buffer0 DMA finished
					// DMA start with Buffer 1
					m_nInputBufferInUse = INPUT_DMA_BUFFER1;
				}
				else
				{
					// Buffer 1 DMA finished
					// DMA start with Buffer 0
					m_nInputBufferInUse = INPUT_DMA_BUFFER0;
				}

				if(m_InputDMAStatus & DMA_BIU)
				{
					m_InputDMAStatus &= ~DMA_STRTB;		// Buffer B just completed...
					m_InputDMAStatus |= DMA_DONEB;
					m_InputDMAStatus &= ~DMA_BIU;		// Buffer A is in use
				}
				else
				{
					m_InputDMAStatus &= ~DMA_STRTA;		// Buffer A just completed...
					m_InputDMAStatus |= DMA_DONEA;
					m_InputDMAStatus |= DMA_BIU;			// Buffer B is in use
				}

				InputTransferred = TransferInputBuffers(m_InputDMAStatus);
				//WAV_INF((_T("[WAV:INF] InputTransferred = %d\n\r"), InputTransferred));
			}
		}
		__except(EXCEPTION_EXECUTE_HANDLER)
		{
			DEBUGMSG(ZONE_ERROR, (TEXT("WAVDEV2.DLL:InterruptThreadInputDMA() - EXCEPTION: %d"), GetExceptionCode()));
		}

		Unlock();
	}

	//WAV_INF((_T("[WAV:INF] --InterruptThreadInputDMA()\n\r")));
}



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

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

	// Alloc and Map GPIO SFR
	g_pGPIOReg = (S3C6410_GPIO_REG *)DrvLib_MapIoSpace(S3C6410_BASE_REG_PA_GPIO, sizeof(S3C6410_GPIO_REG), FALSE);
	if (g_pGPIOReg == NULL)
	{
		WAV_ERR((_T("[WAV:ERR] MapRegisters() : g_pGPIOReg DrvLib_MapIoSpace() Failed\n\r")));
		bRet = FALSE;
		goto CleanUp;
	}

	// Alloc and Map DMAC0 SFR
	g_pDMAC0Reg = (S3C6410_DMAC_REG *)DrvLib_MapIoSpace(S3C6410_BASE_REG_PA_DMA0, sizeof(S3C6410_DMAC_REG), FALSE);
	if (g_pDMAC0Reg == NULL)
	{
		WAV_ERR((_T("[WAV:ERR] MapRegisters() : g_pDMAC0Reg DrvLib_MapIoSpace() Failed\n\r")));
		bRet = FALSE;
		goto CleanUp;
	}

⌨️ 快捷键说明

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