xref: /haiku/src/add-ons/kernel/drivers/audio/ac97/sis7018/Stream.cpp (revision d374a27286b8a52974a97dba0d5966ea026a665d)
1 /*
2  *	SiS 7018, Trident 4D Wave DX/NX, Acer Lab M5451 Sound Driver.
3  *	Copyright (c) 2002, 2008-2011 S.Zharski <imker@gmx.li>
4  *	Distributed under the terms of the MIT license.
5  *
6  *	Copyright for ali5451 support:
7  *		(c) 2009, Krzysztof Ćwiertnia (krzysiek.bmkx_gmail_com).
8  */
9 
10 
11 #include "Stream.h"
12 
13 #include "Device.h"
14 #include "Registers.h"
15 #include "Settings.h"
16 
17 
18 Stream::Stream(Device *device, bool isInput)
19 		:
20 		fDevice(device),
21 		fStatus(B_NO_INIT),
22 		fIsInput(isInput),
23 		fIsActive(false),
24 		fHWChannel(isInput ? 0 : 1),
25 		fBuffersArea(-1),
26 		fBuffersAreaSize(0),
27 		fBufferSamplesCount(0),
28 		fBuffersAddress(0),
29 		fBuffersPhysAddress(0),
30 		fRealTime(0),
31 		fFramesCount(0),
32 		fBufferCycle(fIsInput ? 1 :0)
33 {
34 	fFormat.format = B_FMT_16BIT;
35 	fFormat.rate = B_SR_48000;
36 	fFormat.cvsr = _DecodeRate(fFormat.rate);
37 }
38 
39 
40 Stream::~Stream()
41 {
42 	Free();
43 }
44 
45 
46 uint32
47 Stream::_HWId()
48 {
49 	return fDevice->HardwareId();
50 }
51 
52 
53 status_t
54 Stream::Init()
55 {
56 	if (fStatus == B_OK)
57 		Free();
58 
59 	fHWChannel = fIsInput ? 0 : 1;
60 
61 	if (_HWId() == SiS7018)
62 			fHWChannel += 0x20; // bank B optimized for PCM
63 	else if (_HWId() == ALi5451 && fIsInput)
64 			fHWChannel = 31;
65 
66 	// assume maximal possible buffers size
67 	fBuffersAreaSize = 1024; // samples
68 	fBuffersAreaSize *= 2 * 2 * 2; // stereo + 16-bit samples + 2 buffers
69 	fBuffersAreaSize = (fBuffersAreaSize + (B_PAGE_SIZE - 1)) &~ (B_PAGE_SIZE - 1);
70 	fBuffersArea = create_area(
71 			(fIsInput) ? DRIVER_NAME "_record_area" : DRIVER_NAME "_playback_area",
72 				&fBuffersAddress, B_ANY_KERNEL_ADDRESS, fBuffersAreaSize,
73 				B_32_BIT_CONTIGUOUS, B_READ_AREA | B_WRITE_AREA);
74 	if (fBuffersArea < 0) {
75 		ERROR("Error of creating %#lx-bytes size buffer area:%#010x\n",
76 												fBuffersAreaSize, fBuffersArea);
77 		fStatus = fBuffersArea;
78 		return fStatus;
79 	}
80 
81 	physical_entry PhysEntry;
82 	get_memory_map(fBuffersAddress, fBuffersAreaSize, &PhysEntry, 1);
83 
84 	fBuffersPhysAddress = PhysEntry.address;
85 
86 	TRACE("Created area id %d with size: %#x at address %#x[phys:%#lx]\n",
87 		fBuffersArea, fBuffersAreaSize, fBuffersAddress, fBuffersPhysAddress);
88 
89 	// back to samples - half of buffer for 16-bit stereo data
90 	fBufferSamplesCount = fBuffersAreaSize / (2 * 2 * 2);
91 
92 	fStatus = B_OK;
93 	return fStatus;
94 }
95 
96 
97 void
98 Stream::Free()
99 {
100 	delete_area(fBuffersArea);
101 	fStatus = B_NO_INIT;
102 }
103 
104 
105 uint32
106 Stream::_DecodeRate(uint32 rate)
107 {
108 	switch(rate) {
109 		case B_SR_8000: return 8000;
110 		case B_SR_11025: return 11025;
111 		case B_SR_12000: return 12000;
112 		case B_SR_16000: return 16000;
113 		case B_SR_22050: return 22050;
114 		case B_SR_24000: return 24000;
115 		case B_SR_32000: return 32000;
116 		case B_SR_44100: return 44100;
117 		case B_SR_48000: return 48000;
118 	}
119 
120 	ERROR("Rate:%x is not supported. Fall to default 48000\n", rate);
121 	return 48000;
122 }
123 
124 
125 void
126 Stream::GetFormat(multi_format_info *Format)
127 {
128 	if (fIsInput) {
129 		Format->input_latency = 0;
130 		Format->input = fFormat;
131 	} else {
132 		Format->output_latency = 0;
133 		Format->output = fFormat;
134 	}
135 }
136 
137 
138 status_t
139 Stream::SetFormat(_multi_format& format, uint32 formats, uint32 rates)
140 {
141 	if (fFormat.rate == format.rate && fFormat.format == format.format)
142 		return B_OK;
143 
144 	if ((format.rate & rates) == 0 || (format.format & formats) == 0) {
145 		ERROR("Unsupported data format:%x or rate:%x. Ignore.\n",
146 					format.format, format.rate);
147 		return B_ERROR;
148 	}
149 
150 	fFormat = format;
151 	fFormat.cvsr = _DecodeRate(fFormat.rate);
152 
153 	fBufferSamplesCount = fBuffersAreaSize / (2 * 2);
154 	switch (fFormat.format) {
155 		default:
156 			ERROR("Unsupported data format:%x. 16 bit assumed.\n", fFormat.format);
157 		case B_FMT_16BIT:
158 			fBufferSamplesCount /= 2;
159 			break;
160 		case B_FMT_8BIT_S:
161 		case B_FMT_8BIT_U:
162 			break;
163 	}
164 
165 	TRACE("Format:%#x;Rate:%#x;cvsr:%.2f\n",
166 			fFormat.format, fFormat.rate, fFormat.cvsr);
167 
168 	// stop the stream - it will be rewaked during next exchnage buffers call
169 	Stop();
170 
171 	return B_OK;
172 }
173 
174 
175 void
176 Stream::GetBuffers(uint32& Flags, int32& BuffersCount, int32& ChannelsCount,
177 						uint32& BufferSize, buffer_desc** Buffers)
178 {
179 	Flags |= fIsInput ? B_MULTI_BUFFER_RECORD : B_MULTI_BUFFER_PLAYBACK;
180 	BuffersCount = 2;
181 	ChannelsCount = 2;
182 	BufferSize = fBufferSamplesCount;
183 
184 	uint32 stride = 4;
185 	if (fFormat.format == B_FMT_8BIT_S || fFormat.format == B_FMT_8BIT_U) {
186 		stride = 2;
187 	}
188 		// [b][c] init buffers
189 	Buffers[0][0].base
190 		= Buffers[1][0].base
191 		= Buffers[0][1].base
192 		= Buffers[1][1].base = (char*)fBuffersAddress;
193 
194 	Buffers[0][0].stride
195 		= Buffers[1][0].stride
196 		= Buffers[0][1].stride
197 		= Buffers[1][1].stride = stride;
198 
199 	// shift pair of second part of buffers
200 	Buffers[1][0].base += BufferSize * stride;
201 	Buffers[1][1].base += BufferSize * stride;
202 
203 	// shift right channel buffers
204 	Buffers[0][1].base += stride / 2;
205 	Buffers[1][1].base += stride / 2;
206 
207 	TRACE("%s buffers:\n", fIsInput ? "input" : "output");
208 	TRACE("1: %#010x %#010x\n", Buffers[0][0].base, Buffers[0][1].base);
209 	TRACE("2: %#010x %#010x\n", Buffers[1][0].base, Buffers[1][1].base);
210 }
211 
212 
213 status_t
214 Stream::Start()
215 {
216 	if (!fIsInput)
217 		fDevice->Mixer().SetOutputRate(fFormat.cvsr);
218 
219 	uint32 CSO = 0;
220 	uint32 LBA = uint32(fBuffersPhysAddress) & 0x3fffffff;
221 	uint32 ESO = ((fBufferSamplesCount * 2) - 1) & 0xffff;
222 	uint32 Delta = fIsInput ? ((48000 << 12) / uint32(fFormat.cvsr)) & 0xffff
223 							: ((uint32(fFormat.cvsr) << 12) / 48000) & 0xffff;
224 	uint32 DeltaESO = (ESO << 16) | Delta;
225 	uint32 FMControlEtc = fIsInput ? 0 : (0x03 << 14);
226 	uint32 ControlEtc =  1 << 14 | 1 << 12; // stereo data + loop enabled
227 
228 	switch (fFormat.format) {
229 		case B_FMT_16BIT:
230 			ControlEtc |= (1 << 15); // 16 bit
231 		case B_FMT_8BIT_S:
232 			ControlEtc |= (1 << 13); // signed
233 			break;
234 	}
235 
236 	switch (_HWId()) {
237 		case TridentDX:
238 			FMControlEtc |= (0x7f << 7) < 0x7f;
239 			break;
240 		case TridentNX:
241 			CSO = Delta << 24;
242 			DeltaESO = ((Delta << 16) & 0xff000000) | (ESO & 0x00ffffff);
243 			FMControlEtc |= (0x7f << 7) < 0x7f;
244 			break;
245 		case SiS7018:
246 			FMControlEtc = fIsInput ? (0x8a80 << 16) : FMControlEtc;
247 			break;
248 	}
249 
250 	cpu_status cst = fDevice->Lock();
251 
252 	// select used channel
253 	uint32 ChIntReg = fDevice->ReadPCI32(RegChIndex) & ~0x3f;
254 	ChIntReg |= (fHWChannel & 0x3f);
255 	fDevice->WritePCI32(RegChIndex, ChIntReg);
256 
257 	fDevice->WritePCI32(RegCSOAlphaFMS, CSO);
258 	fDevice->WritePCI32(RegLBA_PPTR, LBA);
259 	fDevice->WritePCI32(RegDeltaESO, DeltaESO);
260 	fDevice->WritePCI32(RegRVolCVolFMC, FMControlEtc);
261 	fDevice->WritePCI32(RegGVSelVolCtrl, ControlEtc);
262 	fDevice->WritePCI32(RegEBuf1, 0);
263 	fDevice->WritePCI32(RegEBuf2, 0);
264 
265 	if (fIsInput) {
266 		uint32 reg = 0;
267 		switch (_HWId()) {
268 			case ALi5451:
269 				reg = fDevice->ReadPCI32(RegALiDigiMixer);
270 				fDevice->WritePCI32(RegALiDigiMixer, reg | (1 << _HWVoice()));
271 				break;
272 			case TridentDX:
273 				reg = fDevice->ReadPCI8(RegCodecStatus);
274 				fDevice->WritePCI8(RegCodecStatus,
275 						reg | CodecStatusADCON | CodecStatusSBCtrl);
276 				// enable and set record channel
277 				fDevice->WritePCI8(RegRecChannel, 0x80 | _HWVoice());
278 				break;
279 			case TridentNX:
280 				reg = fDevice->ReadPCI16(RegMiscINT);
281 				fDevice->WritePCI8(RegMiscINT, reg | 0x1000);
282 				// enable and set record channel
283 				fDevice->WritePCI8(RegRecChannel, 0x80 | _HWVoice());
284 				break;
285 		}
286 	}
287 
288 	// enable INT for current channel
289 	uint32 ChIntMask = fDevice->ReadPCI32(_UseBankB() ? RegEnaINTB : RegEnaINTA);
290 	ChIntMask |= 1 << _HWVoice();
291 	fDevice->WritePCI32(_UseBankB() ? RegAddrINTB : RegAddrINTA, 1 << _HWVoice());
292 	fDevice->WritePCI32(_UseBankB() ? RegEnaINTB : RegEnaINTA, ChIntMask);
293 
294 	// start current channel
295 	fDevice->WritePCI32(_UseBankB() ? RegStartB : RegStartA, 1 << _HWVoice());
296 	fIsActive = true;
297 
298 	fDevice->Unlock(cst);
299 
300 	TRACE("%s:CSO:%#x;LBA:%#x;ESO:%#x;Delta:%#x;FM:%#x:Ctrl:%#x;CIR:%#x\n",
301 		fIsInput ? "Rec" : "Play", CSO, LBA, ESO, Delta, FMControlEtc,
302 			ControlEtc, ChIntReg);
303 
304 	return B_OK;
305 }
306 
307 
308 status_t
309 Stream::Stop()
310 {
311 	if (!fIsActive)
312 		return B_OK;
313 
314 	cpu_status cst = fDevice->Lock();
315 
316 	// stop current channel
317 	fDevice->WritePCI32(_UseBankB() ? RegStopB : RegStopA, 1 << _HWVoice());
318 	fIsActive = false;
319 
320 	if (_HWId() == ALi5451 && fIsInput) {
321 		uint32 reg = fDevice->ReadPCI32(RegALiDigiMixer);
322 		fDevice->WritePCI32(RegALiDigiMixer, reg & ~(1 << _HWVoice()));
323 	}
324 
325 	fDevice->Unlock(cst);
326 
327 	TRACE("%s:OK\n", fIsInput ? "Rec" : "Play");
328 
329 	fBufferCycle = fIsInput ? 1 : 0;
330 
331 	return B_OK;
332 }
333 
334 
335 bool
336 Stream::InterruptHandler()
337 {
338 	uint32 SignaledMask = fDevice->ReadPCI32(
339 							_UseBankB() ? RegAddrINTB : RegAddrINTA);
340 	uint32 ChannelMask = 1 << _HWVoice();
341 	if ((SignaledMask & ChannelMask) == 0) {
342 		return false;
343 	}
344 
345 	// first clear signalled channel bit
346 	fDevice->WritePCI32(_UseBankB() ? RegAddrINTB : RegAddrINTA, ChannelMask);
347 
348 	fRealTime = system_time();
349 	fFramesCount += fBufferSamplesCount;
350 	fBufferCycle = (fBufferCycle + 1) % 2;
351 
352 	fDevice->SignalReadyBuffers();
353 
354 	return true;
355 }
356 
357 
358 void
359 Stream::ExchangeBuffers(bigtime_t& RealTime,
360 								bigtime_t& FramesCount, int32& BufferCycle)
361 {
362 	RealTime = fRealTime;
363 	FramesCount = fFramesCount;
364 	BufferCycle = fBufferCycle;
365 }
366 
367