From a4f1824882aa1e69f4daab3ccbaeeda6a80d300d Mon Sep 17 00:00:00 2001 From: Siarzhuk Zharski Date: Sun, 30 Jan 2011 19:59:30 +0000 Subject: [PATCH] 1) Improved detecting and handling AC97 VRA possibilites. Thanks to Maxim for testing; 2) Functionality of the handling the rate for AC97 Front PCM DAC added. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@40327 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../drivers/audio/ac97/sis7018/Device.cpp | 1 - .../drivers/audio/ac97/sis7018/Device.h | 4 +- .../drivers/audio/ac97/sis7018/Driver.h | 2 +- .../drivers/audio/ac97/sis7018/Mixer.cpp | 51 +++++++++++++++++-- .../kernel/drivers/audio/ac97/sis7018/Mixer.h | 3 ++ .../drivers/audio/ac97/sis7018/Stream.cpp | 14 +++-- .../drivers/audio/ac97/sis7018/Stream.h | 1 + 7 files changed, 65 insertions(+), 11 deletions(-) diff --git a/src/add-ons/kernel/drivers/audio/ac97/sis7018/Device.cpp b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Device.cpp index 6ba828766e..816c81a44e 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/sis7018/Device.cpp +++ b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Device.cpp @@ -175,7 +175,6 @@ Device::Open(uint32 flags) ERROR("Error of starting playback stream:%#010x\n", status); } - return B_OK; } diff --git a/src/add-ons/kernel/drivers/audio/ac97/sis7018/Device.h b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Device.h index fd18e7bb03..399161a33d 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/sis7018/Device.h +++ b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Device.h @@ -57,6 +57,8 @@ public: static int32 InterruptHandler(void *interruptParam); void SignalReadyBuffers(); + class Mixer& Mixer() { return fMixer; } + cpu_status Lock(); void Unlock(cpu_status st); @@ -90,7 +92,7 @@ private: int32 fInterruptsNest; sem_id fBuffersReadySem; - Mixer fMixer; + class Mixer fMixer; Stream fPlaybackStream; Stream fRecordStream; }; diff --git a/src/add-ons/kernel/drivers/audio/ac97/sis7018/Driver.h b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Driver.h index 1f4e9a16dd..c8d41f735a 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/sis7018/Driver.h +++ b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Driver.h @@ -16,7 +16,7 @@ #define MAX_DEVICES 3 -const char* const kVersion = "ver.2.0.0"; +const char* const kVersion = "2.0.2"; extern pci_module_info *gPCI; diff --git a/src/add-ons/kernel/drivers/audio/ac97/sis7018/Mixer.cpp b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Mixer.cpp index 19566af5c2..66f12cdea4 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/sis7018/Mixer.cpp +++ b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Mixer.cpp @@ -26,6 +26,7 @@ Mixer::Mixer(Device *device) fMaskRW(1 << 15), fMaskRD(1 << 15), fMaskWD(1 << 15), + fHasVRA(false), fInputRates(0), fOutputRates(0), fInputFormats(0), @@ -69,6 +70,25 @@ Mixer::Init() void Mixer::_ReadSupportedFormats() { + fInputRates = B_SR_48000; + fOutputRates = 0; + fInputFormats = B_FMT_16BIT; + fOutputFormats = B_FMT_16BIT; + + uint16 extId = ac97_reg_cached_read(fAC97Dev, AC97_EXTENDED_ID); + uint16 extCtrl = ac97_reg_cached_read(fAC97Dev, AC97_EXTENDED_STAT_CTRL); + TRACE("Ext.ID:%#010x %#010x\n", extId, extCtrl); + + fHasVRA = ((extId & EXID_VRA) == EXID_VRA); + if (!fHasVRA) { + fOutputRates = B_SR_8000 | B_SR_11025 | B_SR_12000 + | B_SR_16000 | B_SR_22050 | B_SR_24000 + | B_SR_32000 | B_SR_44100 | B_SR_48000; + TRACE("VRA is not supported. Assume all rates are ok:%#010x\n", + fOutputRates); + return; + } + struct _Cap { ac97_capability fCap; uint32 fRate; @@ -89,9 +109,12 @@ Mixer::_ReadSupportedFormats() fOutputRates |= caps[i].fRate; } - fInputRates = B_SR_48000; - fInputFormats = B_FMT_16BIT; - fOutputFormats = B_FMT_16BIT; + if(fOutputRates == 0) { + ERROR("Output rates are not guessed. Force to 48 kHz.\n"); + fOutputRates = B_SR_48000; + } + + TRACE("Output rates are:%#010x\n", fOutputRates); } @@ -195,6 +218,28 @@ Mixer::_WriteAC97(uint8 reg, uint16 data) } +void +Mixer::SetOutputRate(uint32 outputRate) +{ + if (!fHasVRA) + return; + + uint32 rate = 0; + if (!ac97_get_rate(fAC97Dev, AC97_PCM_FRONT_DAC_RATE, &rate)) { + ERROR("Failed to read PCM Front DAC Rate. Force to %d.\n", outputRate); + } else + if (rate == outputRate) { + TRACE("AC97 PCM Front DAC rate not set to %d\n", outputRate); + return; + } + + if (!ac97_set_rate(fAC97Dev, AC97_PCM_FRONT_DAC_RATE, rate)) + ERROR("Failed to set AC97 PCM Front DAC rate\n"); + else + TRACE("AC97 PCM Front DAC rate set to %d\n", outputRate); +} + + // Control ids are encoded in the following way: // GGBBRRTT -- // GG - in gain controls: 10th of granularity. Signed! diff --git a/src/add-ons/kernel/drivers/audio/ac97/sis7018/Mixer.h b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Mixer.h index 559a0b689f..aadd1b0e6b 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/sis7018/Mixer.h +++ b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Mixer.h @@ -35,6 +35,8 @@ public: uint32 InputFormats() { return fInputFormats; } uint32 OutputFormats() { return fOutputFormats; } + void SetOutputRate(uint32 rate); + private: void _ReadSupportedFormats(); bool _WaitPortReady(uint8 reg, uint32 mask, uint32* result = NULL); @@ -57,6 +59,7 @@ static void _WriteAC97(void* cookie, uint8 reg, uint16 data); uint32 fMaskRD; uint32 fMaskWD; + bool fHasVRA; uint32 fInputRates; uint32 fOutputRates; uint32 fInputFormats; diff --git a/src/add-ons/kernel/drivers/audio/ac97/sis7018/Stream.cpp b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Stream.cpp index f4064a8d92..e377fadae2 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/sis7018/Stream.cpp +++ b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Stream.cpp @@ -213,6 +213,9 @@ Stream::GetBuffers(uint32& Flags, int32& BuffersCount, int32& ChannelsCount, status_t Stream::Start() { + if (!fIsInput) + fDevice->Mixer().SetOutputRate(fFormat.cvsr); + uint32 CSO = 0; uint32 LBA = uint32(fBuffersPhysAddress) & 0x3fffffff; uint32 ESO = ((fBufferSamplesCount * 2) - 1) & 0xffff; @@ -290,6 +293,7 @@ Stream::Start() // start current channel fDevice->WritePCI32(_UseBankB() ? RegStartB : RegStartA, 1 << _HWVoice()); + fIsActive = true; fDevice->Unlock(cst); @@ -297,8 +301,6 @@ Stream::Start() fIsInput ? "Rec" : "Play", CSO, LBA, ESO, Delta, FMControlEtc, ControlEtc, ChIntReg); - fIsActive = true; - return B_OK; } @@ -306,11 +308,15 @@ Stream::Start() status_t Stream::Stop() { + if (!fIsActive) + return B_OK; + cpu_status cst = fDevice->Lock(); // stop current channel fDevice->WritePCI32(_UseBankB() ? RegStopB : RegStopA, 1 << _HWVoice()); - + fIsActive = false; + if (_HWId() == ALi5451 && fIsInput) { uint32 reg = fDevice->ReadPCI32(RegALiDigiMixer); fDevice->WritePCI32(RegALiDigiMixer, reg & ~(1 << _HWVoice())); @@ -320,8 +326,6 @@ Stream::Stop() TRACE("%s:OK\n", fIsInput ? "Rec" : "Play"); - fIsActive = false; - fBufferCycle = fIsInput ? 1 : 0; return B_OK; diff --git a/src/add-ons/kernel/drivers/audio/ac97/sis7018/Stream.h b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Stream.h index 50257a120c..de0341b556 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/sis7018/Stream.h +++ b/src/add-ons/kernel/drivers/audio/ac97/sis7018/Stream.h @@ -35,6 +35,7 @@ public: void ExchangeBuffers(bigtime_t& RealTime, bigtime_t& FramesCount, int32& BufferCycle); + void GetFormat(multi_format_info *Format); status_t SetFormat(_multi_format& format, uint32 formats, uint32 rates);