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.
6 * Copyright for ali5451 support:
7 * (c) 2009, Krzysztof Ćwiertnia (krzysiek.bmkx_gmail_com).
16 #include "Registers.h"
20 Stream::Stream(Device
*device
, bool isInput
)
26 fHWChannel(isInput
? 0 : 1),
29 fBufferSamplesCount(0),
31 fBuffersPhysAddress(0),
34 fBufferCycle(fIsInput
? 1 :0)
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_
));
52 return fDevice
->HardwareId();
62 fHWChannel
= fIsInput
? 0 : 1;
64 if (_HWId() == SiS7018
)
65 fHWChannel
+= 0x20; // bank B optimized for PCM
66 else if (_HWId() == ALi5451
&& fIsInput
)
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
;
84 physical_entry PhysEntry
;
85 get_memory_map(fBuffersAddress
, fBuffersAreaSize
, &PhysEntry
, 1);
87 fBuffersPhysAddress
= PhysEntry
.address
;
89 TRACE("Created area id %d with size: %#x at address %#x[phys:%#lx]\n",
90 fBuffersArea
, fBuffersAreaSize
, fBuffersAddress
, fBuffersPhysAddress
);
92 // back to samples - half of buffer for 16-bit stereo data
93 fBufferSamplesCount
= fBuffersAreaSize
/ (2 * 2 * 2);
103 delete_area(fBuffersArea
);
109 Stream::_DecodeRate(uint32 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;
123 ERROR("Rate:%x is not supported. Fall to default 48000\n", rate
);
129 Stream::GetFormat(multi_format_info
*Format
)
132 Format
->input_latency
= 0;
133 Format
->input
= fFormat
;
135 Format
->output_latency
= 0;
136 Format
->output
= fFormat
;
142 Stream::SetFormat(_multi_format
& format
, uint32 formats
, uint32 rates
)
144 if (fFormat
.rate
== format
.rate
&& fFormat
.format
== format
.format
)
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
);
154 fFormat
.cvsr
= _DecodeRate(fFormat
.rate
);
156 fBufferSamplesCount
= fBuffersAreaSize
/ (2 * 2);
157 switch (fFormat
.format
) {
159 ERROR("Unsupported data format:%x. 16 bit assumed.\n", fFormat
.format
);
161 fBufferSamplesCount
/= 2;
168 TRACE("Format:%#x;Rate:%#x;cvsr:%.2f\n",
169 fFormat
.format
, fFormat
.rate
, fFormat
.cvsr
);
171 // stop the stream - it will be rewaked during next exchnage buffers call
179 Stream::GetBuffers(uint32
& Flags
, int32
& BuffersCount
, int32
& ChannelsCount
,
180 uint32
& BufferSize
, buffer_desc
** Buffers
)
182 Flags
|= fIsInput
? B_MULTI_BUFFER_RECORD
: B_MULTI_BUFFER_PLAYBACK
;
185 BufferSize
= fBufferSamplesCount
;
188 if (fFormat
.format
== B_FMT_8BIT_S
|| fFormat
.format
== B_FMT_8BIT_U
) {
191 // [b][c] init buffers
195 = Buffers
[1][1].base
= (char*)fBuffersAddress
;
198 = Buffers
[1][0].stride
199 = Buffers
[0][1].stride
200 = Buffers
[1][1].stride
= stride
;
202 // shift pair of second part of buffers
203 Buffers
[1][0].base
+= BufferSize
* stride
;
204 Buffers
[1][1].base
+= BufferSize
* stride
;
206 // shift right channel buffers
207 Buffers
[0][1].base
+= stride
/ 2;
208 Buffers
[1][1].base
+= stride
/ 2;
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
);
220 fDevice
->Mixer().SetOutputRate(fFormat
.cvsr
);
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
231 switch (fFormat
.format
) {
233 ControlEtc
|= (1 << 15); // 16 bit
235 ControlEtc
|= (1 << 13); // signed
241 FMControlEtc
|= (0x7f << 7) < 0x7f;
245 DeltaESO
= ((Delta
<< 16) & 0xff000000) | (ESO
& 0x00ffffff);
246 FMControlEtc
|= (0x7f << 7) < 0x7f;
249 FMControlEtc
= fIsInput
? (0x8a80 << 16) : FMControlEtc
;
253 cpu_status cst
= fDevice
->Lock();
255 // select used channel
256 uint32 ChIntReg
= fDevice
->ReadPCI32(RegChIndex
) & ~0x3f;
257 ChIntReg
|= (fHWChannel
& 0x3f);
258 fDevice
->WritePCI32(RegChIndex
, ChIntReg
);
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);
272 reg
= fDevice
->ReadPCI32(RegALiDigiMixer
);
273 fDevice
->WritePCI32(RegALiDigiMixer
, reg
| (1 << _HWVoice()));
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());
283 reg
= fDevice
->ReadPCI16(RegMiscINT
);
284 fDevice
->WritePCI8(RegMiscINT
, reg
| 0x1000);
285 // enable and set record channel
286 fDevice
->WritePCI8(RegRecChannel
, 0x80 | _HWVoice());
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
);
297 // start current channel
298 fDevice
->WritePCI32(_UseBankB() ? RegStartB
: RegStartA
, 1 << _HWVoice());
301 fDevice
->Unlock(cst
);
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
);
317 cpu_status cst
= fDevice
->Lock();
319 // stop current channel
320 fDevice
->WritePCI32(_UseBankB() ? RegStopB
: RegStopA
, 1 << _HWVoice());
323 if (_HWId() == ALi5451
&& fIsInput
) {
324 uint32 reg
= fDevice
->ReadPCI32(RegALiDigiMixer
);
325 fDevice
->WritePCI32(RegALiDigiMixer
, reg
& ~(1 << _HWVoice()));
328 fDevice
->Unlock(cst
);
330 TRACE("%s:OK\n", fIsInput
? "Rec" : "Play");
332 fBufferCycle
= fIsInput
? 1 : 0;
339 Stream::InterruptHandler()
341 uint32 SignaledMask
= fDevice
->ReadPCI32(
342 _UseBankB() ? RegAddrINTB
: RegAddrINTA
);
343 uint32 ChannelMask
= 1 << _HWVoice();
344 if ((SignaledMask
& ChannelMask
) == 0) {
348 // first clear signalled channel bit
349 fDevice
->WritePCI32(_UseBankB() ? RegAddrINTB
: RegAddrINTA
, ChannelMask
);
351 fRealTime
= system_time();
352 fFramesCount
+= fBufferSamplesCount
;
353 fBufferCycle
= (fBufferCycle
+ 1) % 2;
355 fDevice
->SignalReadyBuffers();
362 Stream::ExchangeBuffers(bigtime_t
& RealTime
,
363 bigtime_t
& FramesCount
, int32
& BufferCycle
)
365 RealTime
= fRealTime
;
366 FramesCount
= fFramesCount
;
367 BufferCycle
= fBufferCycle
;