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
This commit is contained in:
Siarzhuk Zharski 2011-01-30 19:59:30 +00:00
parent 38bda6536f
commit a4f1824882
7 changed files with 65 additions and 11 deletions

View File

@ -175,7 +175,6 @@ Device::Open(uint32 flags)
ERROR("Error of starting playback stream:%#010x\n", status);
}
return B_OK;
}

View File

@ -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;
};

View File

@ -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;

View File

@ -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!

View File

@ -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;

View File

@ -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;

View File

@ -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);