xref: /haiku/src/add-ons/kernel/drivers/audio/ac97/sis7018/Stream.cpp (revision 25a7b01d15612846f332751841da3579db313082)
107910542SSiarzhuk Zharski /*
207910542SSiarzhuk Zharski  *	SiS 7018, Trident 4D Wave DX/NX, Acer Lab M5451 Sound Driver.
307910542SSiarzhuk Zharski  *	Copyright (c) 2002, 2008-2011 S.Zharski <imker@gmx.li>
407910542SSiarzhuk Zharski  *	Distributed under the terms of the MIT license.
507910542SSiarzhuk Zharski  *
607910542SSiarzhuk Zharski  *	Copyright for ali5451 support:
707910542SSiarzhuk Zharski  *		(c) 2009, Krzysztof Ćwiertnia (krzysiek.bmkx_gmail_com).
807910542SSiarzhuk Zharski  */
907910542SSiarzhuk Zharski 
1007910542SSiarzhuk Zharski 
1107910542SSiarzhuk Zharski #include "Stream.h"
1207910542SSiarzhuk Zharski 
13*a188dae8SSiarzhuk Zharski #include <memory.h>
14*a188dae8SSiarzhuk Zharski 
1507910542SSiarzhuk Zharski #include "Device.h"
1607910542SSiarzhuk Zharski #include "Registers.h"
1707910542SSiarzhuk Zharski #include "Settings.h"
1807910542SSiarzhuk Zharski 
1907910542SSiarzhuk Zharski 
Stream(Device * device,bool isInput)2007910542SSiarzhuk Zharski Stream::Stream(Device *device, bool isInput)
2107910542SSiarzhuk Zharski 		:
2207910542SSiarzhuk Zharski 		fDevice(device),
2307910542SSiarzhuk Zharski 		fStatus(B_NO_INIT),
2407910542SSiarzhuk Zharski 		fIsInput(isInput),
2507910542SSiarzhuk Zharski 		fIsActive(false),
2607910542SSiarzhuk Zharski 		fHWChannel(isInput ? 0 : 1),
2707910542SSiarzhuk Zharski 		fBuffersArea(-1),
2807910542SSiarzhuk Zharski 		fBuffersAreaSize(0),
2907910542SSiarzhuk Zharski 		fBufferSamplesCount(0),
3007910542SSiarzhuk Zharski 		fBuffersAddress(0),
3107910542SSiarzhuk Zharski 		fBuffersPhysAddress(0),
3207910542SSiarzhuk Zharski 		fRealTime(0),
3307910542SSiarzhuk Zharski 		fFramesCount(0),
3407910542SSiarzhuk Zharski 		fBufferCycle(fIsInput ? 1 :0)
3507910542SSiarzhuk Zharski {
3607910542SSiarzhuk Zharski 	fFormat.format = B_FMT_16BIT;
3707910542SSiarzhuk Zharski 	fFormat.rate = B_SR_48000;
3807910542SSiarzhuk Zharski 	fFormat.cvsr = _DecodeRate(fFormat.rate);
39*a188dae8SSiarzhuk Zharski 	memset(fFormat._reserved_, 0, sizeof(fFormat._reserved_));
4007910542SSiarzhuk Zharski }
4107910542SSiarzhuk Zharski 
4207910542SSiarzhuk Zharski 
~Stream()4307910542SSiarzhuk Zharski Stream::~Stream()
4407910542SSiarzhuk Zharski {
4507910542SSiarzhuk Zharski 	Free();
4607910542SSiarzhuk Zharski }
4707910542SSiarzhuk Zharski 
4807910542SSiarzhuk Zharski 
4907910542SSiarzhuk Zharski uint32
_HWId()5007910542SSiarzhuk Zharski Stream::_HWId()
5107910542SSiarzhuk Zharski {
5207910542SSiarzhuk Zharski 	return fDevice->HardwareId();
5307910542SSiarzhuk Zharski }
5407910542SSiarzhuk Zharski 
5507910542SSiarzhuk Zharski 
5607910542SSiarzhuk Zharski status_t
Init()5707910542SSiarzhuk Zharski Stream::Init()
5807910542SSiarzhuk Zharski {
5907910542SSiarzhuk Zharski 	if (fStatus == B_OK)
6007910542SSiarzhuk Zharski 		Free();
6107910542SSiarzhuk Zharski 
6207910542SSiarzhuk Zharski 	fHWChannel = fIsInput ? 0 : 1;
6307910542SSiarzhuk Zharski 
6407910542SSiarzhuk Zharski 	if (_HWId() == SiS7018)
6507910542SSiarzhuk Zharski 			fHWChannel += 0x20; // bank B optimized for PCM
6607910542SSiarzhuk Zharski 	else if (_HWId() == ALi5451 && fIsInput)
6707910542SSiarzhuk Zharski 			fHWChannel = 31;
6807910542SSiarzhuk Zharski 
6907910542SSiarzhuk Zharski 	// assume maximal possible buffers size
7007910542SSiarzhuk Zharski 	fBuffersAreaSize = 1024; // samples
7107910542SSiarzhuk Zharski 	fBuffersAreaSize *= 2 * 2 * 2; // stereo + 16-bit samples + 2 buffers
7207910542SSiarzhuk Zharski 	fBuffersAreaSize = (fBuffersAreaSize + (B_PAGE_SIZE - 1)) &~ (B_PAGE_SIZE - 1);
7307910542SSiarzhuk Zharski 	fBuffersArea = create_area(
7407910542SSiarzhuk Zharski 			(fIsInput) ? DRIVER_NAME "_record_area" : DRIVER_NAME "_playback_area",
7507910542SSiarzhuk Zharski 				&fBuffersAddress, B_ANY_KERNEL_ADDRESS, fBuffersAreaSize,
7607910542SSiarzhuk Zharski 				B_32_BIT_CONTIGUOUS, B_READ_AREA | B_WRITE_AREA);
7707910542SSiarzhuk Zharski 	if (fBuffersArea < 0) {
7807910542SSiarzhuk Zharski 		ERROR("Error of creating %#lx-bytes size buffer area:%#010x\n",
7907910542SSiarzhuk Zharski 												fBuffersAreaSize, fBuffersArea);
8007910542SSiarzhuk Zharski 		fStatus = fBuffersArea;
8107910542SSiarzhuk Zharski 		return fStatus;
8207910542SSiarzhuk Zharski 	}
8307910542SSiarzhuk Zharski 
8407910542SSiarzhuk Zharski 	physical_entry PhysEntry;
8507910542SSiarzhuk Zharski 	get_memory_map(fBuffersAddress, fBuffersAreaSize, &PhysEntry, 1);
8607910542SSiarzhuk Zharski 
8707910542SSiarzhuk Zharski 	fBuffersPhysAddress = PhysEntry.address;
8807910542SSiarzhuk Zharski 
8907910542SSiarzhuk Zharski 	TRACE("Created area id %d with size: %#x at address %#x[phys:%#lx]\n",
9007910542SSiarzhuk Zharski 		fBuffersArea, fBuffersAreaSize, fBuffersAddress, fBuffersPhysAddress);
9107910542SSiarzhuk Zharski 
9207910542SSiarzhuk Zharski 	// back to samples - half of buffer for 16-bit stereo data
9307910542SSiarzhuk Zharski 	fBufferSamplesCount = fBuffersAreaSize / (2 * 2 * 2);
9407910542SSiarzhuk Zharski 
9507910542SSiarzhuk Zharski 	fStatus = B_OK;
9607910542SSiarzhuk Zharski 	return fStatus;
9707910542SSiarzhuk Zharski }
9807910542SSiarzhuk Zharski 
9907910542SSiarzhuk Zharski 
10007910542SSiarzhuk Zharski void
Free()10107910542SSiarzhuk Zharski Stream::Free()
10207910542SSiarzhuk Zharski {
10307910542SSiarzhuk Zharski 	delete_area(fBuffersArea);
10407910542SSiarzhuk Zharski 	fStatus = B_NO_INIT;
10507910542SSiarzhuk Zharski }
10607910542SSiarzhuk Zharski 
10707910542SSiarzhuk Zharski 
10807910542SSiarzhuk Zharski uint32
_DecodeRate(uint32 rate)10907910542SSiarzhuk Zharski Stream::_DecodeRate(uint32 rate)
11007910542SSiarzhuk Zharski {
11107910542SSiarzhuk Zharski 	switch(rate) {
11207910542SSiarzhuk Zharski 		case B_SR_8000: return 8000;
11307910542SSiarzhuk Zharski 		case B_SR_11025: return 11025;
11407910542SSiarzhuk Zharski 		case B_SR_12000: return 12000;
11507910542SSiarzhuk Zharski 		case B_SR_16000: return 16000;
11607910542SSiarzhuk Zharski 		case B_SR_22050: return 22050;
11707910542SSiarzhuk Zharski 		case B_SR_24000: return 24000;
11807910542SSiarzhuk Zharski 		case B_SR_32000: return 32000;
11907910542SSiarzhuk Zharski 		case B_SR_44100: return 44100;
12007910542SSiarzhuk Zharski 		case B_SR_48000: return 48000;
12107910542SSiarzhuk Zharski 	}
12207910542SSiarzhuk Zharski 
12307910542SSiarzhuk Zharski 	ERROR("Rate:%x is not supported. Fall to default 48000\n", rate);
12407910542SSiarzhuk Zharski 	return 48000;
12507910542SSiarzhuk Zharski }
12607910542SSiarzhuk Zharski 
12707910542SSiarzhuk Zharski 
12807910542SSiarzhuk Zharski void
GetFormat(multi_format_info * Format)12907910542SSiarzhuk Zharski Stream::GetFormat(multi_format_info *Format)
13007910542SSiarzhuk Zharski {
13107910542SSiarzhuk Zharski 	if (fIsInput) {
13207910542SSiarzhuk Zharski 		Format->input_latency = 0;
13307910542SSiarzhuk Zharski 		Format->input = fFormat;
13407910542SSiarzhuk Zharski 	} else {
13507910542SSiarzhuk Zharski 		Format->output_latency = 0;
13607910542SSiarzhuk Zharski 		Format->output = fFormat;
13707910542SSiarzhuk Zharski 	}
13807910542SSiarzhuk Zharski }
13907910542SSiarzhuk Zharski 
14007910542SSiarzhuk Zharski 
14107910542SSiarzhuk Zharski status_t
SetFormat(_multi_format & format,uint32 formats,uint32 rates)14207910542SSiarzhuk Zharski Stream::SetFormat(_multi_format& format, uint32 formats, uint32 rates)
14307910542SSiarzhuk Zharski {
14407910542SSiarzhuk Zharski 	if (fFormat.rate == format.rate && fFormat.format == format.format)
14507910542SSiarzhuk Zharski 		return B_OK;
14607910542SSiarzhuk Zharski 
14707910542SSiarzhuk Zharski 	if ((format.rate & rates) == 0 || (format.format & formats) == 0) {
14807910542SSiarzhuk Zharski 		ERROR("Unsupported data format:%x or rate:%x. Ignore.\n",
14907910542SSiarzhuk Zharski 					format.format, format.rate);
15007910542SSiarzhuk Zharski 		return B_ERROR;
15107910542SSiarzhuk Zharski 	}
15207910542SSiarzhuk Zharski 
15307910542SSiarzhuk Zharski 	fFormat = format;
15407910542SSiarzhuk Zharski 	fFormat.cvsr = _DecodeRate(fFormat.rate);
15507910542SSiarzhuk Zharski 
15607910542SSiarzhuk Zharski 	fBufferSamplesCount = fBuffersAreaSize / (2 * 2);
15707910542SSiarzhuk Zharski 	switch (fFormat.format) {
15807910542SSiarzhuk Zharski 		default:
15907910542SSiarzhuk Zharski 			ERROR("Unsupported data format:%x. 16 bit assumed.\n", fFormat.format);
16007910542SSiarzhuk Zharski 		case B_FMT_16BIT:
16107910542SSiarzhuk Zharski 			fBufferSamplesCount /= 2;
16207910542SSiarzhuk Zharski 			break;
16307910542SSiarzhuk Zharski 		case B_FMT_8BIT_S:
16407910542SSiarzhuk Zharski 		case B_FMT_8BIT_U:
16507910542SSiarzhuk Zharski 			break;
16607910542SSiarzhuk Zharski 	}
16707910542SSiarzhuk Zharski 
16807910542SSiarzhuk Zharski 	TRACE("Format:%#x;Rate:%#x;cvsr:%.2f\n",
16907910542SSiarzhuk Zharski 			fFormat.format, fFormat.rate, fFormat.cvsr);
17007910542SSiarzhuk Zharski 
17107910542SSiarzhuk Zharski 	// stop the stream - it will be rewaked during next exchnage buffers call
17207910542SSiarzhuk Zharski 	Stop();
17307910542SSiarzhuk Zharski 
17407910542SSiarzhuk Zharski 	return B_OK;
17507910542SSiarzhuk Zharski }
17607910542SSiarzhuk Zharski 
17707910542SSiarzhuk Zharski 
17807910542SSiarzhuk Zharski void
GetBuffers(uint32 & Flags,int32 & BuffersCount,int32 & ChannelsCount,uint32 & BufferSize,buffer_desc ** Buffers)17907910542SSiarzhuk Zharski Stream::GetBuffers(uint32& Flags, int32& BuffersCount, int32& ChannelsCount,
18007910542SSiarzhuk Zharski 						uint32& BufferSize, buffer_desc** Buffers)
18107910542SSiarzhuk Zharski {
18207910542SSiarzhuk Zharski 	Flags |= fIsInput ? B_MULTI_BUFFER_RECORD : B_MULTI_BUFFER_PLAYBACK;
18307910542SSiarzhuk Zharski 	BuffersCount = 2;
18407910542SSiarzhuk Zharski 	ChannelsCount = 2;
18507910542SSiarzhuk Zharski 	BufferSize = fBufferSamplesCount;
18607910542SSiarzhuk Zharski 
18707910542SSiarzhuk Zharski 	uint32 stride = 4;
18807910542SSiarzhuk Zharski 	if (fFormat.format == B_FMT_8BIT_S || fFormat.format == B_FMT_8BIT_U) {
18907910542SSiarzhuk Zharski 		stride = 2;
19007910542SSiarzhuk Zharski 	}
19107910542SSiarzhuk Zharski 		// [b][c] init buffers
19207910542SSiarzhuk Zharski 	Buffers[0][0].base
19307910542SSiarzhuk Zharski 		= Buffers[1][0].base
19407910542SSiarzhuk Zharski 		= Buffers[0][1].base
19507910542SSiarzhuk Zharski 		= Buffers[1][1].base = (char*)fBuffersAddress;
19607910542SSiarzhuk Zharski 
19707910542SSiarzhuk Zharski 	Buffers[0][0].stride
19807910542SSiarzhuk Zharski 		= Buffers[1][0].stride
19907910542SSiarzhuk Zharski 		= Buffers[0][1].stride
20007910542SSiarzhuk Zharski 		= Buffers[1][1].stride = stride;
20107910542SSiarzhuk Zharski 
20207910542SSiarzhuk Zharski 	// shift pair of second part of buffers
20307910542SSiarzhuk Zharski 	Buffers[1][0].base += BufferSize * stride;
20407910542SSiarzhuk Zharski 	Buffers[1][1].base += BufferSize * stride;
20507910542SSiarzhuk Zharski 
20607910542SSiarzhuk Zharski 	// shift right channel buffers
20707910542SSiarzhuk Zharski 	Buffers[0][1].base += stride / 2;
20807910542SSiarzhuk Zharski 	Buffers[1][1].base += stride / 2;
20907910542SSiarzhuk Zharski 
21007910542SSiarzhuk Zharski 	TRACE("%s buffers:\n", fIsInput ? "input" : "output");
21107910542SSiarzhuk Zharski 	TRACE("1: %#010x %#010x\n", Buffers[0][0].base, Buffers[0][1].base);
21207910542SSiarzhuk Zharski 	TRACE("2: %#010x %#010x\n", Buffers[1][0].base, Buffers[1][1].base);
21307910542SSiarzhuk Zharski }
21407910542SSiarzhuk Zharski 
21507910542SSiarzhuk Zharski 
21607910542SSiarzhuk Zharski status_t
Start()21707910542SSiarzhuk Zharski Stream::Start()
21807910542SSiarzhuk Zharski {
219a4f18248SSiarzhuk Zharski 	if (!fIsInput)
220a4f18248SSiarzhuk Zharski 		fDevice->Mixer().SetOutputRate(fFormat.cvsr);
221a4f18248SSiarzhuk Zharski 
22207910542SSiarzhuk Zharski 	uint32 CSO = 0;
22307910542SSiarzhuk Zharski 	uint32 LBA = uint32(fBuffersPhysAddress) & 0x3fffffff;
22407910542SSiarzhuk Zharski 	uint32 ESO = ((fBufferSamplesCount * 2) - 1) & 0xffff;
22507910542SSiarzhuk Zharski 	uint32 Delta = fIsInput ? ((48000 << 12) / uint32(fFormat.cvsr)) & 0xffff
22607910542SSiarzhuk Zharski 							: ((uint32(fFormat.cvsr) << 12) / 48000) & 0xffff;
22707910542SSiarzhuk Zharski 	uint32 DeltaESO = (ESO << 16) | Delta;
22807910542SSiarzhuk Zharski 	uint32 FMControlEtc = fIsInput ? 0 : (0x03 << 14);
22907910542SSiarzhuk Zharski 	uint32 ControlEtc =  1 << 14 | 1 << 12; // stereo data + loop enabled
23007910542SSiarzhuk Zharski 
23107910542SSiarzhuk Zharski 	switch (fFormat.format) {
23207910542SSiarzhuk Zharski 		case B_FMT_16BIT:
23307910542SSiarzhuk Zharski 			ControlEtc |= (1 << 15); // 16 bit
23407910542SSiarzhuk Zharski 		case B_FMT_8BIT_S:
23507910542SSiarzhuk Zharski 			ControlEtc |= (1 << 13); // signed
23607910542SSiarzhuk Zharski 			break;
23707910542SSiarzhuk Zharski 	}
23807910542SSiarzhuk Zharski 
23907910542SSiarzhuk Zharski 	switch (_HWId()) {
24007910542SSiarzhuk Zharski 		case TridentDX:
24107910542SSiarzhuk Zharski 			FMControlEtc |= (0x7f << 7) < 0x7f;
24207910542SSiarzhuk Zharski 			break;
24307910542SSiarzhuk Zharski 		case TridentNX:
24407910542SSiarzhuk Zharski 			CSO = Delta << 24;
24507910542SSiarzhuk Zharski 			DeltaESO = ((Delta << 16) & 0xff000000) | (ESO & 0x00ffffff);
24607910542SSiarzhuk Zharski 			FMControlEtc |= (0x7f << 7) < 0x7f;
24707910542SSiarzhuk Zharski 			break;
24807910542SSiarzhuk Zharski 		case SiS7018:
24907910542SSiarzhuk Zharski 			FMControlEtc = fIsInput ? (0x8a80 << 16) : FMControlEtc;
25007910542SSiarzhuk Zharski 			break;
25107910542SSiarzhuk Zharski 	}
25207910542SSiarzhuk Zharski 
25307910542SSiarzhuk Zharski 	cpu_status cst = fDevice->Lock();
25407910542SSiarzhuk Zharski 
25507910542SSiarzhuk Zharski 	// select used channel
25607910542SSiarzhuk Zharski 	uint32 ChIntReg = fDevice->ReadPCI32(RegChIndex) & ~0x3f;
25707910542SSiarzhuk Zharski 	ChIntReg |= (fHWChannel & 0x3f);
25807910542SSiarzhuk Zharski 	fDevice->WritePCI32(RegChIndex, ChIntReg);
25907910542SSiarzhuk Zharski 
26007910542SSiarzhuk Zharski 	fDevice->WritePCI32(RegCSOAlphaFMS, CSO);
26107910542SSiarzhuk Zharski 	fDevice->WritePCI32(RegLBA_PPTR, LBA);
26207910542SSiarzhuk Zharski 	fDevice->WritePCI32(RegDeltaESO, DeltaESO);
26307910542SSiarzhuk Zharski 	fDevice->WritePCI32(RegRVolCVolFMC, FMControlEtc);
26407910542SSiarzhuk Zharski 	fDevice->WritePCI32(RegGVSelVolCtrl, ControlEtc);
26507910542SSiarzhuk Zharski 	fDevice->WritePCI32(RegEBuf1, 0);
26607910542SSiarzhuk Zharski 	fDevice->WritePCI32(RegEBuf2, 0);
26707910542SSiarzhuk Zharski 
26807910542SSiarzhuk Zharski 	if (fIsInput) {
26907910542SSiarzhuk Zharski 		uint32 reg = 0;
27007910542SSiarzhuk Zharski 		switch (_HWId()) {
27107910542SSiarzhuk Zharski 			case ALi5451:
27207910542SSiarzhuk Zharski 				reg = fDevice->ReadPCI32(RegALiDigiMixer);
27307910542SSiarzhuk Zharski 				fDevice->WritePCI32(RegALiDigiMixer, reg | (1 << _HWVoice()));
27407910542SSiarzhuk Zharski 				break;
27507910542SSiarzhuk Zharski 			case TridentDX:
27607910542SSiarzhuk Zharski 				reg = fDevice->ReadPCI8(RegCodecStatus);
27707910542SSiarzhuk Zharski 				fDevice->WritePCI8(RegCodecStatus,
27807910542SSiarzhuk Zharski 						reg | CodecStatusADCON | CodecStatusSBCtrl);
27907910542SSiarzhuk Zharski 				// enable and set record channel
28007910542SSiarzhuk Zharski 				fDevice->WritePCI8(RegRecChannel, 0x80 | _HWVoice());
28107910542SSiarzhuk Zharski 				break;
28207910542SSiarzhuk Zharski 			case TridentNX:
28307910542SSiarzhuk Zharski 				reg = fDevice->ReadPCI16(RegMiscINT);
28407910542SSiarzhuk Zharski 				fDevice->WritePCI8(RegMiscINT, reg | 0x1000);
28507910542SSiarzhuk Zharski 				// enable and set record channel
28607910542SSiarzhuk Zharski 				fDevice->WritePCI8(RegRecChannel, 0x80 | _HWVoice());
28707910542SSiarzhuk Zharski 				break;
28807910542SSiarzhuk Zharski 		}
28907910542SSiarzhuk Zharski 	}
29007910542SSiarzhuk Zharski 
29107910542SSiarzhuk Zharski 	// enable INT for current channel
29207910542SSiarzhuk Zharski 	uint32 ChIntMask = fDevice->ReadPCI32(_UseBankB() ? RegEnaINTB : RegEnaINTA);
29307910542SSiarzhuk Zharski 	ChIntMask |= 1 << _HWVoice();
29407910542SSiarzhuk Zharski 	fDevice->WritePCI32(_UseBankB() ? RegAddrINTB : RegAddrINTA, 1 << _HWVoice());
29507910542SSiarzhuk Zharski 	fDevice->WritePCI32(_UseBankB() ? RegEnaINTB : RegEnaINTA, ChIntMask);
29607910542SSiarzhuk Zharski 
29707910542SSiarzhuk Zharski 	// start current channel
29807910542SSiarzhuk Zharski 	fDevice->WritePCI32(_UseBankB() ? RegStartB : RegStartA, 1 << _HWVoice());
299a4f18248SSiarzhuk Zharski 	fIsActive = true;
30007910542SSiarzhuk Zharski 
30107910542SSiarzhuk Zharski 	fDevice->Unlock(cst);
30207910542SSiarzhuk Zharski 
30307910542SSiarzhuk Zharski 	TRACE("%s:CSO:%#x;LBA:%#x;ESO:%#x;Delta:%#x;FM:%#x:Ctrl:%#x;CIR:%#x\n",
30407910542SSiarzhuk Zharski 		fIsInput ? "Rec" : "Play", CSO, LBA, ESO, Delta, FMControlEtc,
30507910542SSiarzhuk Zharski 			ControlEtc, ChIntReg);
30607910542SSiarzhuk Zharski 
30707910542SSiarzhuk Zharski 	return B_OK;
30807910542SSiarzhuk Zharski }
30907910542SSiarzhuk Zharski 
31007910542SSiarzhuk Zharski 
31107910542SSiarzhuk Zharski status_t
Stop()31207910542SSiarzhuk Zharski Stream::Stop()
31307910542SSiarzhuk Zharski {
314a4f18248SSiarzhuk Zharski 	if (!fIsActive)
315a4f18248SSiarzhuk Zharski 		return B_OK;
316a4f18248SSiarzhuk Zharski 
31707910542SSiarzhuk Zharski 	cpu_status cst = fDevice->Lock();
31807910542SSiarzhuk Zharski 
31907910542SSiarzhuk Zharski 	// stop current channel
32007910542SSiarzhuk Zharski 	fDevice->WritePCI32(_UseBankB() ? RegStopB : RegStopA, 1 << _HWVoice());
321a4f18248SSiarzhuk Zharski 	fIsActive = false;
32207910542SSiarzhuk Zharski 
32307910542SSiarzhuk Zharski 	if (_HWId() == ALi5451 && fIsInput) {
32407910542SSiarzhuk Zharski 		uint32 reg = fDevice->ReadPCI32(RegALiDigiMixer);
32507910542SSiarzhuk Zharski 		fDevice->WritePCI32(RegALiDigiMixer, reg & ~(1 << _HWVoice()));
32607910542SSiarzhuk Zharski 	}
32707910542SSiarzhuk Zharski 
32807910542SSiarzhuk Zharski 	fDevice->Unlock(cst);
32907910542SSiarzhuk Zharski 
33007910542SSiarzhuk Zharski 	TRACE("%s:OK\n", fIsInput ? "Rec" : "Play");
33107910542SSiarzhuk Zharski 
33207910542SSiarzhuk Zharski 	fBufferCycle = fIsInput ? 1 : 0;
33307910542SSiarzhuk Zharski 
33407910542SSiarzhuk Zharski 	return B_OK;
33507910542SSiarzhuk Zharski }
33607910542SSiarzhuk Zharski 
33707910542SSiarzhuk Zharski 
33807910542SSiarzhuk Zharski bool
InterruptHandler()33907910542SSiarzhuk Zharski Stream::InterruptHandler()
34007910542SSiarzhuk Zharski {
34107910542SSiarzhuk Zharski 	uint32 SignaledMask = fDevice->ReadPCI32(
34207910542SSiarzhuk Zharski 							_UseBankB() ? RegAddrINTB : RegAddrINTA);
34307910542SSiarzhuk Zharski 	uint32 ChannelMask = 1 << _HWVoice();
34407910542SSiarzhuk Zharski 	if ((SignaledMask & ChannelMask) == 0) {
34507910542SSiarzhuk Zharski 		return false;
34607910542SSiarzhuk Zharski 	}
34707910542SSiarzhuk Zharski 
34807910542SSiarzhuk Zharski 	// first clear signalled channel bit
34907910542SSiarzhuk Zharski 	fDevice->WritePCI32(_UseBankB() ? RegAddrINTB : RegAddrINTA, ChannelMask);
35007910542SSiarzhuk Zharski 
35107910542SSiarzhuk Zharski 	fRealTime = system_time();
35207910542SSiarzhuk Zharski 	fFramesCount += fBufferSamplesCount;
35307910542SSiarzhuk Zharski 	fBufferCycle = (fBufferCycle + 1) % 2;
35407910542SSiarzhuk Zharski 
35507910542SSiarzhuk Zharski 	fDevice->SignalReadyBuffers();
35607910542SSiarzhuk Zharski 
35707910542SSiarzhuk Zharski 	return true;
35807910542SSiarzhuk Zharski }
35907910542SSiarzhuk Zharski 
36007910542SSiarzhuk Zharski 
36107910542SSiarzhuk Zharski void
ExchangeBuffers(bigtime_t & RealTime,bigtime_t & FramesCount,int32 & BufferCycle)36207910542SSiarzhuk Zharski Stream::ExchangeBuffers(bigtime_t& RealTime,
36307910542SSiarzhuk Zharski 								bigtime_t& FramesCount, int32& BufferCycle)
36407910542SSiarzhuk Zharski {
36507910542SSiarzhuk Zharski 	RealTime = fRealTime;
36607910542SSiarzhuk Zharski 	FramesCount = fFramesCount;
36707910542SSiarzhuk Zharski 	BufferCycle = fBufferCycle;
36807910542SSiarzhuk Zharski }
36907910542SSiarzhuk Zharski 
370