mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-20 09:49:15 +03:00
Kernel: Implement variable rate audio support for AC97 devices
Previously we `VERIFY()`ed that the device supports variable-rate audio (VRA). Now, we query the VRA bit and if VRA is not supported, we do not enable double-rate audio and disallow setting any sample rate except the fixed 48kHz rate as defined by the AC'97 specification. This should allow the driver to function on a wider array of hardware. Note that in the AC'97 specification, DRA without VRA is allowed when supported: this effectively doubles the sample rate to 96kHZ. For now, we ignore that possibility and let it default to 48kHZ.
This commit is contained in:
parent
377a984905
commit
58bcb93777
Notes:
sideshowbarker
2024-07-18 00:38:56 +09:00
Author: https://github.com/gmta Commit: https://github.com/SerenityOS/serenity/commit/58bcb937775 Pull-request: https://github.com/SerenityOS/serenity/pull/11073
@ -13,6 +13,9 @@ namespace Kernel {
|
||||
|
||||
static constexpr int buffer_descriptor_list_max_entries = 32;
|
||||
|
||||
static constexpr u16 pcm_default_sample_rate = 44100;
|
||||
static constexpr u16 pcm_fixed_sample_rate = 48000;
|
||||
|
||||
// Valid output range - with double-rate enabled, sample rate can go up to 96kHZ
|
||||
static constexpr u16 pcm_sample_rate_minimum = 8000;
|
||||
static constexpr u16 pcm_sample_rate_maximum = 48000;
|
||||
@ -101,21 +104,25 @@ UNMAP_AFTER_INIT void AC97::initialize()
|
||||
// Reset mixer
|
||||
m_io_mixer_base.offset(NativeAudioMixerRegister::Reset).out<u16>(1);
|
||||
|
||||
// Verify extended capabilities
|
||||
auto extended_audio_id = m_io_mixer_base.offset(NativeAudioMixerRegister::ExtendedAudioID).in<u16>();
|
||||
VERIFY((extended_audio_id & ExtendedAudioMask::VariableRatePCMAudio) > 0);
|
||||
VERIFY((extended_audio_id & ExtendedAudioMask::Revision) >> 10 == AC97Revision::Revision23);
|
||||
|
||||
// Enable double rate PCM audio if supported
|
||||
if ((extended_audio_id & ExtendedAudioMask::DoubleRatePCMAudio) > 0) {
|
||||
auto extended_audio_status_control_register = m_io_mixer_base.offset(NativeAudioMixerRegister::ExtendedAudioStatusControl);
|
||||
auto extended_audio_status = extended_audio_status_control_register.in<u16>();
|
||||
// Enable variable and double rate PCM audio if supported
|
||||
auto extended_audio_status_control_register = m_io_mixer_base.offset(NativeAudioMixerRegister::ExtendedAudioStatusControl);
|
||||
auto extended_audio_status = extended_audio_status_control_register.in<u16>();
|
||||
if ((extended_audio_id & ExtendedAudioMask::VariableRatePCMAudio) > 0) {
|
||||
extended_audio_status |= ExtendedAudioStatusControlFlag::VariableRateAudio;
|
||||
m_variable_rate_pcm_supported = true;
|
||||
}
|
||||
if (!m_variable_rate_pcm_supported) {
|
||||
extended_audio_status &= ~ExtendedAudioStatusControlFlag::DoubleRateAudio;
|
||||
} else if ((extended_audio_id & ExtendedAudioMask::DoubleRatePCMAudio) > 0) {
|
||||
extended_audio_status |= ExtendedAudioStatusControlFlag::DoubleRateAudio;
|
||||
extended_audio_status_control_register.out(extended_audio_status);
|
||||
m_double_rate_pcm_enabled = true;
|
||||
}
|
||||
extended_audio_status_control_register.out(extended_audio_status);
|
||||
|
||||
MUST(set_pcm_output_sample_rate(m_sample_rate));
|
||||
MUST(set_pcm_output_sample_rate(m_variable_rate_pcm_supported ? pcm_default_sample_rate : pcm_fixed_sample_rate));
|
||||
|
||||
// Left and right volume of 0 means attenuation of 0 dB
|
||||
set_master_output_volume(0, 0, Muted::No);
|
||||
@ -134,8 +141,6 @@ ErrorOr<void> AC97::ioctl(OpenFileDescription&, unsigned request, Userspace<void
|
||||
}
|
||||
case SOUNDCARD_IOCTL_SET_SAMPLE_RATE: {
|
||||
auto sample_rate = static_cast<u32>(arg.ptr());
|
||||
if (sample_rate == m_sample_rate)
|
||||
return {};
|
||||
TRY(set_pcm_output_sample_rate(sample_rate));
|
||||
return {};
|
||||
}
|
||||
@ -165,8 +170,13 @@ void AC97::set_master_output_volume(u8 left_channel, u8 right_channel, Muted mut
|
||||
|
||||
ErrorOr<void> AC97::set_pcm_output_sample_rate(u32 sample_rate)
|
||||
{
|
||||
if (m_sample_rate == sample_rate)
|
||||
return {};
|
||||
|
||||
auto const double_rate_shift = m_double_rate_pcm_enabled ? 1 : 0;
|
||||
auto shifted_sample_rate = sample_rate >> double_rate_shift;
|
||||
if (!m_variable_rate_pcm_supported && shifted_sample_rate != pcm_fixed_sample_rate)
|
||||
return ENOTSUP;
|
||||
if (shifted_sample_rate < pcm_sample_rate_minimum || shifted_sample_rate > pcm_sample_rate_maximum)
|
||||
return ENOTSUP;
|
||||
|
||||
|
@ -54,6 +54,7 @@ private:
|
||||
};
|
||||
|
||||
enum ExtendedAudioStatusControlFlag : u16 {
|
||||
VariableRateAudio = 1 << 0,
|
||||
DoubleRateAudio = 1 << 1,
|
||||
};
|
||||
|
||||
@ -170,7 +171,8 @@ private:
|
||||
u8 m_output_buffer_page_count = 4;
|
||||
u8 m_output_buffer_page_index = 0;
|
||||
AC97Channel m_pcm_out_channel;
|
||||
u32 m_sample_rate = 44100;
|
||||
u32 m_sample_rate = 0;
|
||||
bool m_variable_rate_pcm_supported = false;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user