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