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

📄 hwctxt.cpp

📁 Samsung公司S3C6400芯片的BSP源码包
💻 CPP
📖 第 1 页 / 共 3 页
字号:


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);
		BytesTransferred += FillOutputBuffer(OUTPUT_DMA_BUFFER1);
		break;
	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)
{
	// WM8753
	// SFR[B15..B9], DATA[B8..B0]
	// +------------------------+
	// | B15...B9 B8.........B0 |
	// +------------------------+
	//
	UCHAR command0, command1;

	m_WM8753_SFR_Table[Reg] = Val;

	WAV_MSG((_T("[WAV] WriteCodecRegister(0x%02x, 0x%x)\n\r"), Reg, Val));

	command0 = (UCHAR)(Reg<<1)|(UCHAR)((Val>>8)&1);
	command1 = (UCHAR)(Val&0xFF);

	HW_WriteRegisters((PUCHAR)&command1, command0, 1);
}


DWORD
HardwareContext::WriteCodecRegister2(UCHAR Reg, USHORT Val)
{
	DWORD nReturned=0, bytes=0;
	BOOL  bRet = FALSE;

	UCHAR buff[2];
	IIC_IO_DESC IIC_Data;



	// WM8753
	// SFR[B15..B9], DATA[B8..B0]
	// +------------------------+
	// | B15...B9 B8.........B0 |
	// +------------------------+
	//
	UCHAR command0, command1;

	m_WM8753_SFR_Table[Reg] = Val;

	WAV_MSG((_T("[WAV] WriteCodecRegister2(0x%02x, 0x%x)\n\r"), Reg, Val));

	buff[0] = command0 = (UCHAR)(Reg<<1)|(UCHAR)((Val>>8)&1);
	buff[1] = command1 = (UCHAR)(Val&0xFF);

	IIC_Data.SlaveAddress = CHIP_ID;
	IIC_Data.Data = buff;
	IIC_Data.Count = 2;

	bRet = DeviceIoControl(m_hI2C,
						IOCTL_IIC_WRITE,
						&IIC_Data, sizeof(IIC_IO_DESC),
						NULL, 0,
						&bytes, NULL);

	if (bRet == 0)
	{
		RETAILMSG(1, (TEXT("[HWCTXT] ERROR: Device I/O Control Request FAIL, 0x%08X\r\n"), GetLastError()));
		nReturned = -1;
	}

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

	return nReturned;
}

USHORT
HardwareContext::ReadCodecRegister(UCHAR Reg)
{
	USHORT RegValue = 0;

	//-----------------------------------------------------------------------------------------------------
	// !!!!! Caution !!!!!
	// WM8753 support write operation only.
	// I write sfr data value onto internal table(m_WM8753_SFR_Table), on every write operation for backup.
	// And To support read operation, I just return some value from internal table(m_WM8753_SFR_Table).
	//-----------------------------------------------------------------------------------------------------

	RegValue = m_WM8753_SFR_Table[(int)Reg];

	WAV_MSG((_T("[WAV] ReadCodecRegister(0x%02x) = 0x%03x\n\r"), Reg, RegValue));

	return (USHORT)RegValue;
}

BOOL
HardwareContext::CodecPowerControl()
{
	USHORT mRegValue;
#if 1
	if( (m_bInputDMARunning == FALSE) && (m_bOutputDMARunning == FALSE) ) // Input / Output Off
	{
		WAV_MSG((_T("[WAV] CodecPowerControl() : CodecPowerControl() ADC & DAC All Off\n\r")));
		mRegValue = ReadCodecRegister(WM8753_PWR_MGMT_1);
		mRegValue = mRegValue & ~(WM8753_PWR1_VMIDSEL_MASK) | (WM8753_PWR1_VMIDSEL_DISABLE);
		mRegValue |= (WM8753_PWR1_DIGENB); // MCLK is disabled
		WriteCodecRegister(WM8753_PWR_MGMT_1, mRegValue);	// Vmid/VREF power down
	}
	else
	{
		WAV_MSG((_T("[WAV] CodecPowerControl() : CodecPowerControl() ADC and/or DAC is On\n\r")));
		mRegValue = ReadCodecRegister(WM8753_PWR_MGMT_1);
		mRegValue = mRegValue & ~(WM8753_PWR1_VMIDSEL_MASK) | (WM8753_PWR1_VMIDSEL_50KOHM);
		mRegValue &= ~(WM8753_PWR1_DIGENB); // MCLK is enabled
		WriteCodecRegister(WM8753_PWR_MGMT_1, mRegValue);	// Vmid/VREF power up
	}

	if( m_bOutputDMARunning ) // Output On
	{
		WAV_MSG((_T("[WAV] CodecPowerControl() : CodecPowerControl() DAC On\n\r")));
		mRegValue = ReadCodecRegister(WM8753_PWR_MGMT_3);
		mRegValue |= (WM8753_PWR3_LOUT1|WM8753_PWR3_ROUT1);
		WriteCodecRegister(WM8753_PWR_MGMT_3, mRegValue);	// DAC power up
	}
	else // Output Off
	{
		WAV_MSG((_T("[WAV] CodecPowerControl() : CodecPowerControl() DAC Off\n\r")));
		mRegValue = ReadCodecRegister(WM8753_PWR_MGMT_3);
		mRegValue &= ~(WM8753_PWR3_LOUT1|WM8753_PWR3_ROUT1);
		WriteCodecRegister(WM8753_PWR_MGMT_3, mRegValue);	// DAC power down
	}

	if( m_bInputDMARunning ) // Input On
	{
		WAV_MSG((_T("[WAV] CodecPowerControl() : CodecPowerControl() ADC On\n\r")));
		m_shInputVolumeL = ReadCodecRegister(WM8753_LEFT_ADC_VOLUME);
		m_shInputVolumeR = ReadCodecRegister(WM8753_RIGHT_ADC_VOLUME);
		WriteCodecRegister(WM8753_LEFT_ADC_VOLUME, WM8753_ADCVOL_MUTE);	// DAC power down
		WriteCodecRegister(WM8753_RIGHT_ADC_VOLUME, WM8753_ADCVOL_MUTE);	// DAC power down
	}
	else // Input Off
	{
		WAV_MSG((_T("[WAV] CodecPowerControl() : CodecPowerControl() ADC Off\n\r")));
		WriteCodecRegister(WM8753_LEFT_ADC_VOLUME, m_shInputVolumeL);	// DAC power down
		WriteCodecRegister(WM8753_RIGHT_ADC_VOLUME, m_shInputVolumeR);	// DAC power down
	}
#endif
	return(TRUE);
}


BOOL
HardwareContext::CodecMuteControl(DWORD channel, BOOL bMute)
{
	USHORT volume;
#if 1
	if((channel & DMA_CH_OUT ))// && !m_bOutputDMARunning )
	{
		if(bMute)
		{
			WAV_MSG((_T("[WAV] CodecMuteControl() : CH_OUT is muted\n\r")));
			volume = ReadCodecRegister(WM8753_DAC_CONTROL);
			volume |= WM8753_DAC_SOFT_MUTE;
   			WriteCodecRegister(WM8753_DAC_CONTROL, volume);
		}
		else
		{
			WAV_MSG((_T("[WAV] CodecMuteControl() : CH_OUT is un-muted\n\r")));
			volume = ReadCodecRegister(WM8753_DAC_CONTROL);
			volume &= ~WM8753_DAC_SOFT_MUTE;
   			WriteCodecRegister(WM8753_DAC_CONTROL, volume);
		}
	}

	if( (channel & DMA_CH_IN))// && !m_bInputDMARunning )
	{
		if(bMute)
		{
			WAV_MSG((_T("[WAV] CodecMuteControl() : CH_IN is muted\n\r")));
			volume = ReadCodecRegister(WM8753_LEFT_INPUT_VOLUME);
			WriteCodecRegister(WM8753_LEFT_INPUT_VOLUME, volume|WM8753_INVOL_MUTE);

			volume = ReadCodecRegister(WM8753_RIGHT_INPUT_VOLUME);
			WriteCodecRegister(WM8753_RIGHT_INPUT_VOLUME, volume|WM8753_INVOL_MUTE);
		}
		else
		{
			WAV_MSG((_T("[WAV] CodecMuteControl() : CH_IN is un-muted\n\r")));
			volume = ReadCodecRegister(WM8753_LEFT_INPUT_VOLUME);
			WriteCodecRegister(WM8753_LEFT_INPUT_VOLUME, volume&~WM8753_INVOL_MUTE);

			volume = ReadCodecRegister(WM8753_RIGHT_INPUT_VOLUME);
			WriteCodecRegister(WM8753_RIGHT_INPUT_VOLUME, volume&~WM8753_INVOL_MUTE);
		}
	}
#endif
	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();
}


//
// Write WM8753 IIS Codec registers directly from our cache
//
DWORD HardwareContext::HW_WriteRegisters(
	PUCHAR pBuff,   	// Optional buffer
	UCHAR StartReg, 	// start register
	DWORD nRegs     	// number of registers
	)
{
	DWORD dwErr=0,bytes;
	UCHAR buff[2];
	IIC_IO_DESC IIC_Data;


	buff[0] = StartReg;
	buff[1] = pBuff[0];
	IIC_Data.SlaveAddress = WM8753_WRITE;
	IIC_Data.Data = buff;
	IIC_Data.Count = 2;

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

	// use iocontrol to write
	if ( !DeviceIoControl(m_hI2C,
						IOCTL_IIC_WRITE,
						&IIC_Data, sizeof(IIC_IO_DESC),
						NULL, 0,
						&bytes, NULL) )
	{
		dwErr = GetLastError();
	}

	if ( dwErr )
	{
		WAV_ERR((_T("[WAV::ERR]I2CWrite ERROR: %u \r\n"), dwErr));
	}

	return dwErr;
}

DWORD HardwareContext::HW_ReadRegisters(
	PUCHAR pBuff,   	// Optional buffer
	UCHAR StartReg, 	// start register
	DWORD nRegs     	// number of registers
	)
{
	DWORD dwErr=0;
	DWORD bytes;
	IIC_IO_DESC IIC_AddressData, IIC_Data;
	IIC_AddressData.SlaveAddress = WM8753_READ;
	IIC_AddressData.Data = &StartReg;
	IIC_AddressData.Count = 1;

	IIC_Data.SlaveAddress = WM8753_READ;
	IIC_Data.Data = pBuff;
	IIC_Data.Count = 1;

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

	// use iocontrol to read
	if ( !DeviceIoControl(m_hI2C,
						IOCTL_IIC_READ,
						&IIC_AddressData, sizeof(IIC_IO_DESC),
						&IIC_Data, sizeof(IIC_IO_DESC),
						&bytes, NULL) )
	{
		dwErr = GetLastError();
	}

	if ( dwErr )
	{
		WAV_ERR((_T("[WAV::ERR]I2CRead ERROR: %u \r\n"), dwErr));
	}

	return dwErr;
}

void HardwareContext::I2S_Init8753Driver()
{
	int i;

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

	// Initialize WM8753_SFR_Table data
	for (i=0; i<WM8753_MAX_REGISTER_COUNT; i++)
	m_WM8753_SFR_Table[i] = 0;

	// Default setting value
	//for(i=0; i<WM8753_MAX_REGISTER_COUNT; i++)
	for(i=0; i<(sizeof(WM8753_Codec_Init_Table)/sizeof(unsigned int)/2); i++)
	{
		WriteCodecRegister(WM8753_Codec_Init_Table[i][0], WM8753_Codec_Init_Table[i][1]);
	}

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

⌨️ 快捷键说明

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