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:
@@ -175,7 +175,6 @@ Device::Open(uint32 flags)
|
|||||||
ERROR("Error of starting playback stream:%#010x\n", status);
|
ERROR("Error of starting playback stream:%#010x\n", status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,8 @@ public:
|
|||||||
static int32 InterruptHandler(void *interruptParam);
|
static int32 InterruptHandler(void *interruptParam);
|
||||||
void SignalReadyBuffers();
|
void SignalReadyBuffers();
|
||||||
|
|
||||||
|
class Mixer& Mixer() { return fMixer; }
|
||||||
|
|
||||||
cpu_status Lock();
|
cpu_status Lock();
|
||||||
void Unlock(cpu_status st);
|
void Unlock(cpu_status st);
|
||||||
|
|
||||||
@@ -90,7 +92,7 @@ private:
|
|||||||
int32 fInterruptsNest;
|
int32 fInterruptsNest;
|
||||||
sem_id fBuffersReadySem;
|
sem_id fBuffersReadySem;
|
||||||
|
|
||||||
Mixer fMixer;
|
class Mixer fMixer;
|
||||||
Stream fPlaybackStream;
|
Stream fPlaybackStream;
|
||||||
Stream fRecordStream;
|
Stream fRecordStream;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
#define MAX_DEVICES 3
|
#define MAX_DEVICES 3
|
||||||
|
|
||||||
|
|
||||||
const char* const kVersion = "ver.2.0.0";
|
const char* const kVersion = "2.0.2";
|
||||||
|
|
||||||
extern pci_module_info *gPCI;
|
extern pci_module_info *gPCI;
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ Mixer::Mixer(Device *device)
|
|||||||
fMaskRW(1 << 15),
|
fMaskRW(1 << 15),
|
||||||
fMaskRD(1 << 15),
|
fMaskRD(1 << 15),
|
||||||
fMaskWD(1 << 15),
|
fMaskWD(1 << 15),
|
||||||
|
fHasVRA(false),
|
||||||
fInputRates(0),
|
fInputRates(0),
|
||||||
fOutputRates(0),
|
fOutputRates(0),
|
||||||
fInputFormats(0),
|
fInputFormats(0),
|
||||||
@@ -69,6 +70,25 @@ Mixer::Init()
|
|||||||
void
|
void
|
||||||
Mixer::_ReadSupportedFormats()
|
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 {
|
struct _Cap {
|
||||||
ac97_capability fCap;
|
ac97_capability fCap;
|
||||||
uint32 fRate;
|
uint32 fRate;
|
||||||
@@ -89,9 +109,12 @@ Mixer::_ReadSupportedFormats()
|
|||||||
fOutputRates |= caps[i].fRate;
|
fOutputRates |= caps[i].fRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
fInputRates = B_SR_48000;
|
if(fOutputRates == 0) {
|
||||||
fInputFormats = B_FMT_16BIT;
|
ERROR("Output rates are not guessed. Force to 48 kHz.\n");
|
||||||
fOutputFormats = B_FMT_16BIT;
|
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:
|
// Control ids are encoded in the following way:
|
||||||
// GGBBRRTT --
|
// GGBBRRTT --
|
||||||
// GG - in gain controls: 10th of granularity. Signed!
|
// GG - in gain controls: 10th of granularity. Signed!
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ public:
|
|||||||
uint32 InputFormats() { return fInputFormats; }
|
uint32 InputFormats() { return fInputFormats; }
|
||||||
uint32 OutputFormats() { return fOutputFormats; }
|
uint32 OutputFormats() { return fOutputFormats; }
|
||||||
|
|
||||||
|
void SetOutputRate(uint32 rate);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _ReadSupportedFormats();
|
void _ReadSupportedFormats();
|
||||||
bool _WaitPortReady(uint8 reg, uint32 mask, uint32* result = NULL);
|
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 fMaskRD;
|
||||||
uint32 fMaskWD;
|
uint32 fMaskWD;
|
||||||
|
|
||||||
|
bool fHasVRA;
|
||||||
uint32 fInputRates;
|
uint32 fInputRates;
|
||||||
uint32 fOutputRates;
|
uint32 fOutputRates;
|
||||||
uint32 fInputFormats;
|
uint32 fInputFormats;
|
||||||
|
|||||||
@@ -213,6 +213,9 @@ Stream::GetBuffers(uint32& Flags, int32& BuffersCount, int32& ChannelsCount,
|
|||||||
status_t
|
status_t
|
||||||
Stream::Start()
|
Stream::Start()
|
||||||
{
|
{
|
||||||
|
if (!fIsInput)
|
||||||
|
fDevice->Mixer().SetOutputRate(fFormat.cvsr);
|
||||||
|
|
||||||
uint32 CSO = 0;
|
uint32 CSO = 0;
|
||||||
uint32 LBA = uint32(fBuffersPhysAddress) & 0x3fffffff;
|
uint32 LBA = uint32(fBuffersPhysAddress) & 0x3fffffff;
|
||||||
uint32 ESO = ((fBufferSamplesCount * 2) - 1) & 0xffff;
|
uint32 ESO = ((fBufferSamplesCount * 2) - 1) & 0xffff;
|
||||||
@@ -290,6 +293,7 @@ Stream::Start()
|
|||||||
|
|
||||||
// start current channel
|
// start current channel
|
||||||
fDevice->WritePCI32(_UseBankB() ? RegStartB : RegStartA, 1 << _HWVoice());
|
fDevice->WritePCI32(_UseBankB() ? RegStartB : RegStartA, 1 << _HWVoice());
|
||||||
|
fIsActive = true;
|
||||||
|
|
||||||
fDevice->Unlock(cst);
|
fDevice->Unlock(cst);
|
||||||
|
|
||||||
@@ -297,8 +301,6 @@ Stream::Start()
|
|||||||
fIsInput ? "Rec" : "Play", CSO, LBA, ESO, Delta, FMControlEtc,
|
fIsInput ? "Rec" : "Play", CSO, LBA, ESO, Delta, FMControlEtc,
|
||||||
ControlEtc, ChIntReg);
|
ControlEtc, ChIntReg);
|
||||||
|
|
||||||
fIsActive = true;
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,11 +308,15 @@ Stream::Start()
|
|||||||
status_t
|
status_t
|
||||||
Stream::Stop()
|
Stream::Stop()
|
||||||
{
|
{
|
||||||
|
if (!fIsActive)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
cpu_status cst = fDevice->Lock();
|
cpu_status cst = fDevice->Lock();
|
||||||
|
|
||||||
// stop current channel
|
// stop current channel
|
||||||
fDevice->WritePCI32(_UseBankB() ? RegStopB : RegStopA, 1 << _HWVoice());
|
fDevice->WritePCI32(_UseBankB() ? RegStopB : RegStopA, 1 << _HWVoice());
|
||||||
|
fIsActive = false;
|
||||||
|
|
||||||
if (_HWId() == ALi5451 && fIsInput) {
|
if (_HWId() == ALi5451 && fIsInput) {
|
||||||
uint32 reg = fDevice->ReadPCI32(RegALiDigiMixer);
|
uint32 reg = fDevice->ReadPCI32(RegALiDigiMixer);
|
||||||
fDevice->WritePCI32(RegALiDigiMixer, reg & ~(1 << _HWVoice()));
|
fDevice->WritePCI32(RegALiDigiMixer, reg & ~(1 << _HWVoice()));
|
||||||
@@ -320,8 +326,6 @@ Stream::Stop()
|
|||||||
|
|
||||||
TRACE("%s:OK\n", fIsInput ? "Rec" : "Play");
|
TRACE("%s:OK\n", fIsInput ? "Rec" : "Play");
|
||||||
|
|
||||||
fIsActive = false;
|
|
||||||
|
|
||||||
fBufferCycle = fIsInput ? 1 : 0;
|
fBufferCycle = fIsInput ? 1 : 0;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ public:
|
|||||||
void ExchangeBuffers(bigtime_t& RealTime,
|
void ExchangeBuffers(bigtime_t& RealTime,
|
||||||
bigtime_t& FramesCount,
|
bigtime_t& FramesCount,
|
||||||
int32& BufferCycle);
|
int32& BufferCycle);
|
||||||
|
|
||||||
void GetFormat(multi_format_info *Format);
|
void GetFormat(multi_format_info *Format);
|
||||||
status_t SetFormat(_multi_format& format,
|
status_t SetFormat(_multi_format& format,
|
||||||
uint32 formats, uint32 rates);
|
uint32 formats, uint32 rates);
|
||||||
|
|||||||
Reference in New Issue
Block a user