AudioDxe: Switch from % volume to dB gain

This commit is contained in:
MikeBeaton 2022-01-06 07:45:02 +00:00
parent 6ec644a88d
commit 4c26a2a465
27 changed files with 448 additions and 157 deletions

View File

@ -18,6 +18,8 @@ OpenCore Changelog
- Added VREF handling to support UEFI sound on more Apple hardware
- Updated audio output channel detection to support UEFI sound on more Apple hardware
- Added manual GPIO config (use `--gpio-setup` AudioDxe driver argument for UEFI sound on Apple hardware)
- Switched UEFI audio levels to decibel gain to allow accurate matching of saved macOS volume levels
- Separated settings for minimum audio assist volume and minimum audible volume
#### v0.7.6
- Fixed stack canary support when compiling with GCC

View File

@ -1 +1 @@
7a6403991b9030b2e01127afec27e52f
9d720e65fc51f16dd38ab0a896778571

Binary file not shown.

View File

@ -4877,10 +4877,26 @@ troubleshooting:
\texttt{7C436110-AB2A-4BBB-A880-FE41995C9F82:SystemAudioVolume}
\break
System audio volume level for firmware audio support. 8-bit integer.
The bit of \texttt{0x80} means muted. Lower bits are used to encode
volume range specific to installed audio codec. The value is capped
by \texttt{MaximumBootBeepVolume} AppleHDA layout value to avoid
too loud audio playback in the firmware.
The bit of \texttt{0x80} means muted. The remaining bits are used
to encode the raw amplifier gain setting to be applied to the audio
amplifier in use. Exactly what this value means depends on the codec
(and potentially on the specific amplifier within the codec). This value
is capped by macOS to the \texttt{MaximumBootBeepVolume} AppleHDA layout
value, to avoid over-loud audio playback in the firmware.
\item
\texttt{7C436110-AB2A-4BBB-A880-FE41995C9F82:SystemAudioVolumeDB}
\break
Current system audio volume level in decibels (dB). The value
is a signed byte representing the audio offset (gain if positive,
attentuation if negative) in dB relative to the amplifier reference value
of 0 dB. Exactly which volume level is represented by 0 dB depends on the
codec (and potentially on the specific amplifier within the codec)
but it is normally at or near the maximum available amplifier volume.
Typical values of this variable range from approximately -60 (the exact value
depends on the audio hardware) up to exactly 0. On non-typical audio
hardware, the value may go above zero.
\emph{Note}: Unlike \texttt{SystemAudioVolume}, this value is not capped.
\item
\texttt{5EDDA193-A070-416A-85EB-2A1181F45B18:PEXConf}
\break
@ -7085,15 +7101,54 @@ for known issues.
\texttt{-{}-gpio-setup} driver argument which is dealt with in the
\hyperref[uefiaudio]{AudioDxe} section.
\item
\texttt{MinimumVolume}\\
\item
\texttt{MaximumGain}\\
\textbf{Type}: \texttt{plist\ integer}\\
\textbf{Failsafe}: \texttt{0}\\
\textbf{Description}: Minimal heard volume level from \texttt{0} to \texttt{100}.
\textbf{Failsafe}: \texttt{-15}\\
\textbf{Description}: Maximum gain to use for UEFI audio, specified in decibels (dB) with respect to amplifier
reference level of 0 dB (see note 1).
The screen reader will use this volume level when the calculated volume level is lower
than \texttt{MinimumVolume} and the boot chime will not play if the calculated
volume level is lower than \texttt{MinimumVolume}.
All UEFI audio will use this gain setting when the system amplifier gain read from the \texttt{SystemAudioVolumeDB}
NVRAM variable is higher than this. This is to avoid over-loud UEFI audio when the system volume is set very high,
or the \texttt{SystemAudioVolumeDB} NVRAM value has been misconfigured.
\emph{Note 1}: A typical range of system gain values is from roughly -60 dB to exactly 0 dB, where 0 dB represents the
amplifier maximum volume. However these values depend on the hardware and may be different,
including gain levels above zero (therefore 0 dB is not the amplifier maximum volume) on non-standard hardware.
On any hardware, following the Intel HDA specification, the range will always include 0 dB somewere
(at either end or somewhere in between).
\emph{Note 2}: Values outside $-128$ dB to $+127$ dB (which are well beyond physically plausible decibel values) are not allowed.
\emph{Note 3}: Digital audio output -- which does not have a volume slider in-OS -- ignores this and all other gain settings,
only mute settings are relevant.
\item
\texttt{MinimumAssistGain}\\
\textbf{Type}: \texttt{plist\ integer}\\
\textbf{Failsafe}: \texttt{-30}\\
\textbf{Description}: Minimum gain in decibels (dB) to use for picker audio assist.
The screen reader will use this amplifier gain if the system amplifier gain read from the \texttt{SystemAudioVolumeDB}
NVRAM variable is lower than this.
\emph{Note}: In addition to this setting, because audio assist must be audible to serve its function, audio assist
is not muted even if the OS sound is muted or the \texttt{StartupMute} NVRAM variable is set.
\item
\texttt{MinimumAudibleGain}\\
\textbf{Type}: \texttt{plist\ integer}\\
\textbf{Failsafe}: \texttt{-128}\\
\textbf{Description}: Minimum gain in decibels (dB) at which to attempt to play any sound.
The boot chime will not play if the system amplifier gain level in the
\texttt{SystemAudioVolumeDB} NVRAM variable is lower than this.
\emph{Note}: This setting is designed to save unecessary pauses due to audio setup at inaudible volume
levels, when no sound will be heard anyway. Whether there are inaudible volume levels depends on the
hardware. On some hardware (including Apple) the audio values are well enough matched to the hardware
that the lowest volume levels available are very quiet but audible, whereas on some other hardware combinations,
the lowest part of the volume range may not be audible at all.
\item
\texttt{PlayChime}\\
@ -7102,8 +7157,7 @@ for known issues.
\textbf{Description}: Play chime sound at startup.
Enabling this setting plays the boot chime using the builtin audio support. The volume
level is determined by the \texttt{MinimumVolume} and \texttt{VolumeAmplifier} settings
as well as the \texttt{SystemAudioVolume} NVRAM variable. Possible values include:
level is determined by the \texttt{SystemAudioVolumeDB} NVRAM variable. Supported values are:
\begin{itemize}
\tightlist
@ -7113,9 +7167,12 @@ for known issues.
\item \texttt{Disabled} --- Disables chime unconditionally.
\end{itemize}
\emph{Note}: \texttt{Enabled} can be used in separate from \texttt{StartupMute}
\emph{Note 1}: \texttt{Enabled} can be used separately from the \texttt{StartupMute}
NVRAM variable to avoid conflicts when the firmware is able to play the boot chime.
\emph{Note 2}: Regardless of this setting, the boot chime will not play if system audio is muted,
i.e.~if the \texttt{SystemAudioVolume} NVRAM variable has bit \texttt{0x80} set.
\item
\texttt{ResetTrafficClass}\\
\textbf{Type}: \texttt{plist\ boolean}\\
@ -7139,22 +7196,6 @@ for known issues.
(e.g. volume setting). This option makes it configurable. A typical
delay can be up to 0.5 seconds.
\item
\texttt{VolumeAmplifier}\\
\textbf{Type}: \texttt{plist\ integer}\\
\textbf{Failsafe}: \texttt{0}\\
\textbf{Description}: Multiplication coefficient for system volume to raw volume linear translation
from \texttt{0} to \texttt{1000}.
Volume level range read from \texttt{SystemAudioVolume} varies depending on the codec.
To transform read value in \texttt{[0, 127]} range into raw volume range \texttt{[0, 100]}
the read value is scaled to \texttt{VolumeAmplifier} percents:
\begin{align*}
RawVolume &= MIN(\frac{SystemAudioVolume * VolumeAmplifier}{100}, 100)
\end{align*}
\emph{Note}: the transformation used in macOS is not linear, but it is very close
and this nuance is thus ignored.
\end{enumerate}
\subsection{Drivers Properties}\label{uefidriversprops}

Binary file not shown.

View File

@ -1,7 +1,7 @@
\documentclass[]{article}
%DIF LATEXDIFF DIFFERENCE FILE
%DIF DEL PreviousConfiguration.tex Wed Jan 5 23:59:13 2022
%DIF ADD ../Configuration.tex Thu Jan 6 09:12:56 2022
%DIF DEL PreviousConfiguration.tex Sun Jan 9 22:59:35 2022
%DIF ADD ../Configuration.tex Mon Jan 10 09:58:30 2022
\usepackage{lmodern}
\usepackage{amssymb,amsmath}
@ -4945,12 +4945,31 @@ troubleshooting:
\texttt{7C436110-AB2A-4BBB-A880-FE41995C9F82:SystemAudioVolume}
\break
System audio volume level for firmware audio support. 8-bit integer.
The bit of \texttt{0x80} means muted. Lower bits are used to encode
volume range specific to installed audio codec. The value is capped
by \texttt{MaximumBootBeepVolume} AppleHDA layout value to avoid
too loud audio playback in the firmware.
\item
\texttt{5EDDA193-A070-416A-85EB-2A1181F45B18:PEXConf}
The bit of \texttt{0x80} means muted. \DIFdelbegin \DIFdel{Lower }\DIFdelend \DIFaddbegin \DIFadd{The remaining }\DIFaddend bits are used
to encode \DIFdelbegin \DIFdel{volume range specific to installed audio
codec. The }\DIFdelend \DIFaddbegin \DIFadd{the raw amplifier gain setting to be applied to the audio
amplifier in use. Exactly what this value means depends on the codec
(and potentially on the specific amplifier within the codec). This }\DIFaddend value
is capped by \DIFaddbegin \DIFadd{macOS to the }\DIFaddend \texttt{MaximumBootBeepVolume} AppleHDA layout
value\DIFdelbegin \DIFdel{to avoid
too loud }\DIFdelend \DIFaddbegin \DIFadd{, to avoid over-loud }\DIFaddend audio playback in the firmware.
\item
\DIFaddbegin \texttt{\DIFadd{7C436110-AB2A-4BBB-A880-FE41995C9F82:SystemAudioVolumeDB}}
\break
\DIFadd{Current system audio volume level in decibels (dB). The value
is a signed byte representing the audio offset (gain if positive,
attentuation if negative) in dB relative to the amplifier reference value
of 0 dB. Exactly which volume level is represented by 0 dB depends on the
codec (and potentially on the specific amplifier within the codec)
but it is normally at or near the maximum available amplifier volume.
Typical values of this variable range from approximately -60 (the exact value
depends on the audio hardware) up to exactly 0. On non-typical audio
hardware, the value may go above zero.
}
\emph{\DIFadd{Note}}\DIFadd{: Unlike }\texttt{\DIFadd{SystemAudioVolume}}\DIFadd{, this value is not capped.
}\item
\DIFaddend \texttt{5EDDA193-A070-416A-85EB-2A1181F45B18:PEXConf}
\break
PCI expansion slot configuration for \texttt{MacPro7,1}.
8-byte sequence describing default PCI slot configuration.
@ -7171,8 +7190,8 @@ on most Apple hardware, and possibly some others) may be specified in }\texttt{\
}\DIFaddend located on the \DIFaddbegin \DIFadd{specified }\DIFaddend audio controller (\texttt{AudioDevice}).
\item
\DIFaddbegin \texttt{\DIFadd{DisconnectHda}}\\
\textbf{\DIFadd{Type}}\DIFadd{: }\texttt{\DIFadd{plist\ boolean}}\\
\texttt{\DIFdelbegin \DIFdel{MinimumVolume}\DIFdelend \DIFaddbegin \DIFadd{DisconnectHda}\DIFaddend }\\
\textbf{Type}: \DIFaddbegin \texttt{\DIFadd{plist\ boolean}}\\
\textbf{\DIFadd{Failsafe}}\DIFadd{: }\texttt{\DIFadd{false}}\\
\textbf{\DIFadd{Description}}\DIFadd{: Disconnect HDA controller before loading drivers.
}
@ -7186,25 +7205,80 @@ on most Apple hardware, and possibly some others) may be specified in }\texttt{\
}\hyperref[uefiaudio]{AudioDxe} \DIFadd{section.
}
\item
\DIFaddend \texttt{MinimumVolume}\\
\textbf{Type}: \texttt{plist\ integer}\\
\textbf{Failsafe}: \texttt{0}\\
\textbf{Description}: Minimal heard volume level from \texttt{0} to \texttt{100}.
\item
\texttt{\DIFadd{MaximumGain}}\\
\textbf{\DIFadd{Type}}\DIFadd{: }\DIFaddend \texttt{plist\ integer}\\
\textbf{Failsafe}: \texttt{\DIFdelbegin \DIFdel{0}\DIFdelend \DIFaddbegin \DIFadd{-15}\DIFaddend }\\
\textbf{Description}: \DIFdelbegin \DIFdel{Minimal heard volume level from }%DIFDELCMD < \texttt{%%%
\DIFdelend \DIFaddbegin \DIFadd{Maximum gain to use for UEFI audio, specified in decibels (dB) with respect to amplifier
reference level of }\DIFaddend 0 \DIFdelbegin %DIFDELCMD < \MBLOCKRIGHTBRACE %%%
\DIFdel{to }\DIFdelend \DIFaddbegin \DIFadd{dB (see note 1).
}
The screen reader will use this volume level when the calculated volume level is lower
than \texttt{MinimumVolume} and the boot chime will not play if the calculated
volume level is lower than \texttt{MinimumVolume}.
\DIFadd{All UEFI audio will use this gain setting when the system amplifier gain read from the }\DIFaddend \texttt{\DIFdelbegin \DIFdel{100}\DIFdelend \DIFaddbegin \DIFadd{SystemAudioVolumeDB}\DIFaddend }
\DIFaddbegin \DIFadd{NVRAM variable is higher than this. This is to avoid over-loud UEFI audio when the system volume is set very high,
or the }\texttt{\DIFadd{SystemAudioVolumeDB}} \DIFadd{NVRAM value has been misconfigured}\DIFaddend .
\item
\DIFaddbegin \emph{\DIFadd{Note 1}}\DIFadd{: A typical range of system gain values is from roughly -60 dB to exactly 0 dB, where 0 dB represents the
amplifier maximum volume. However these values depend on the hardware and may be different,
including gain levels above zero (therefore 0 dB is not the amplifier maximum volume) on non-standard hardware.
On any hardware, following the Intel HDA specification, the range will always include 0 dB somewere
(at either end or somewhere in between).
}
\emph{\DIFadd{Note 2}}\DIFadd{: Values outside $-128$ dB to $+127$ dB (which are well beyond physically plausible decibel values) are not allowed.
}
\emph{\DIFadd{Note 3}}\DIFadd{: Digital audio output -- which does not have a volume slider in-OS -- ignores this and all other gain settings,
only mute settings are relevant.
}
\item
\texttt{\DIFadd{MinimumAssistGain}}\\
\textbf{\DIFadd{Type}}\DIFadd{: }\texttt{\DIFadd{plist\ integer}}\\
\textbf{\DIFadd{Failsafe}}\DIFadd{: }\texttt{\DIFadd{-30}}\\
\textbf{\DIFadd{Description}}\DIFadd{: Minimum gain in decibels (dB) to use for picker audio assist.
}
\DIFaddend The screen reader will use this \DIFdelbegin \DIFdel{volume level when the calculated volume level }\DIFdelend \DIFaddbegin \DIFadd{amplifier gain if the system amplifier gain read from the }\texttt{\DIFadd{SystemAudioVolumeDB}}
\DIFadd{NVRAM variable }\DIFaddend is lower than \DIFdelbegin \texttt{\DIFdel{MinimumVolume}} %DIFAUXCMD
\DIFdel{and the }\DIFdelend \DIFaddbegin \DIFadd{this.
}
\emph{\DIFadd{Note}}\DIFadd{: In addition to this setting, because audio assist must be audible to serve its function, audio assist
is not muted even if the OS sound is muted or the }\texttt{\DIFadd{StartupMute}} \DIFadd{NVRAM variable is set.
}
\item
\texttt{\DIFadd{MinimumAudibleGain}}\\
\textbf{\DIFadd{Type}}\DIFadd{: }\texttt{\DIFadd{plist\ integer}}\\
\textbf{\DIFadd{Failsafe}}\DIFadd{: }\texttt{\DIFadd{-128}}\\
\textbf{\DIFadd{Description}}\DIFadd{: Minimum gain in decibels (dB) at which to attempt to play any sound.
}
\DIFadd{The }\DIFaddend boot chime will not play if the \DIFdelbegin \DIFdel{calculated
volume level }\DIFdelend \DIFaddbegin \DIFadd{system amplifier gain level in the
}\texttt{\DIFadd{SystemAudioVolumeDB}} \DIFadd{NVRAM variable }\DIFaddend is lower than \DIFdelbegin \texttt{\DIFdel{MinimumVolume}}%DIFAUXCMD
\DIFdelend \DIFaddbegin \DIFadd{this}\DIFaddend .
\DIFaddbegin \emph{\DIFadd{Note}}\DIFadd{: This setting is designed to save unecessary pauses due to audio setup at inaudible volume
levels, when no sound will be heard anyway. Whether there are inaudible volume levels depends on the
hardware. On some hardware (including Apple) the audio values are well enough matched to the hardware
that the lowest volume levels available are very quiet but audible, whereas on some other hardware combinations,
the lowest part of the volume range may not be audible at all.
}
\DIFaddend \item
\texttt{PlayChime}\\
\textbf{Type}: \texttt{plist\ string}\\
\textbf{Failsafe}: \texttt{Auto}\\
\textbf{Description}: Play chime sound at startup.
Enabling this setting plays the boot chime using the builtin audio support. The volume
level is determined by the \texttt{MinimumVolume} and \texttt{VolumeAmplifier} settings
as well as the \texttt{SystemAudioVolume} NVRAM variable. Possible values include:
level is determined by the \texttt{\DIFdelbegin \DIFdel{MinimumVolume}\DIFdelend \DIFaddbegin \DIFadd{SystemAudioVolumeDB}\DIFaddend } \DIFdelbegin \DIFdel{and }\texttt{\DIFdel{VolumeAmplifier}} %DIFAUXCMD
\DIFdel{settings
as well as the }\texttt{\DIFdel{SystemAudioVolume}} %DIFAUXCMD
\DIFdelend NVRAM variable. \DIFdelbegin \DIFdel{Possible values include}\DIFdelend \DIFaddbegin \DIFadd{Supported values are}\DIFaddend :
\begin{itemize}
\tightlist
@ -7214,10 +7288,14 @@ on most Apple hardware, and possibly some others) may be specified in }\texttt{\
\item \texttt{Disabled} --- Disables chime unconditionally.
\end{itemize}
\emph{Note}: \texttt{Enabled} can be used in separate from \texttt{StartupMute}
\emph{Note \DIFaddbegin \DIFadd{1}\DIFaddend }: \texttt{Enabled} can be used \DIFdelbegin \DIFdel{in separate from }\DIFdelend \DIFaddbegin \DIFadd{separately from the }\DIFaddend \texttt{StartupMute}
NVRAM variable to avoid conflicts when the firmware is able to play the boot chime.
\item
\DIFaddbegin \emph{\DIFadd{Note 2}}\DIFadd{: Regardless of this setting, the boot chime will not play if system audio is muted,
i.e.~if the }\texttt{\DIFadd{SystemAudioVolume}} \DIFadd{NVRAM variable has bit }\texttt{\DIFadd{0x80}} \DIFadd{set.
}
\DIFaddend \item
\texttt{ResetTrafficClass}\\
\textbf{Type}: \texttt{plist\ boolean}\\
\textbf{Failsafe}: \texttt{false}\\
@ -7240,23 +7318,50 @@ on most Apple hardware, and possibly some others) may be specified in }\texttt{\
(e.g. volume setting). This option makes it configurable. A typical
delay can be up to 0.5 seconds.
\item
\texttt{VolumeAmplifier}\\
\textbf{Type}: \texttt{plist\ integer}\\
\textbf{Failsafe}: \texttt{0}\\
\textbf{Description}: Multiplication coefficient for system volume to raw volume linear translation
from \texttt{0} to \texttt{1000}.
\DIFdelbegin %DIFDELCMD < \item
\item%DIFAUXCMD
%DIFDELCMD < %%%
\texttt{\DIFdel{VolumeAmplifier}}%DIFAUXCMD
%DIFDELCMD < \\
%DIFDELCMD < %%%
\textbf{\DIFdel{Type}}%DIFAUXCMD
\DIFdel{: }\texttt{\DIFdel{plist\ integer}}%DIFAUXCMD
%DIFDELCMD < \\
%DIFDELCMD < %%%
\textbf{\DIFdel{Failsafe}}%DIFAUXCMD
\DIFdel{: }\texttt{\DIFdel{0}}%DIFAUXCMD
%DIFDELCMD < \\
%DIFDELCMD < %%%
\textbf{\DIFdel{Description}}%DIFAUXCMD
\DIFdel{: Multiplication coefficient for system volume to raw volume linear translation
from }\texttt{\DIFdel{0}} %DIFAUXCMD
\DIFdel{to }\texttt{\DIFdel{1000}}%DIFAUXCMD
\DIFdel{.
}%DIFDELCMD <
Volume level range read from \texttt{SystemAudioVolume} varies depending on the codec.
To transform read value in \texttt{[0, 127]} range into raw volume range \texttt{[0, 100]}
the read value is scaled to \texttt{VolumeAmplifier} percents:
\begin{align*}
RawVolume &= MIN(\frac{SystemAudioVolume * VolumeAmplifier}{100}, 100)
\end{align*}
\emph{Note}: the transformation used in macOS is not linear, but it is very close
%DIFDELCMD < %%%
\DIFdel{Volume level range read from }\texttt{\DIFdel{SystemAudioVolume}} %DIFAUXCMD
\DIFdel{varies depending on the codec.
To transform read value in }\texttt{%DIFDELCMD < [%%%
\DIFdel{0, 127}%DIFDELCMD < ]%%%
} %DIFAUXCMD
\DIFdel{range into raw volume range }\texttt{%DIFDELCMD < [%%%
\DIFdel{0, 100}%DIFDELCMD < ]%%%
}
%DIFAUXCMD
\DIFdel{the read value is scaled to }\texttt{\DIFdel{VolumeAmplifier}} %DIFAUXCMD
\DIFdel{percents:
}\begin{align*}
\DIFdel{RawVolume }&\DIFdel{= MIN(\frac{SystemAudioVolume * VolumeAmplifier}{100}, 100)
}\end{align*}%DIFAUXCMD
%DIFDELCMD < %%%
\emph{\DIFdel{Note}}%DIFAUXCMD
\DIFdel{: the transformation used in macOS is not linear, but it is very close
and this nuance is thus ignored.
}%DIFDELCMD <
\end{enumerate}
%DIFDELCMD < %%%
\DIFdelend \end{enumerate}
\subsection{Drivers Properties}\label{uefidriversprops}

Binary file not shown.

View File

@ -1204,6 +1204,8 @@
<integer>0</integer>
<key>SystemAudioVolume</key>
<data>Rg==</data>
<key>SystemAudioVolumeDB</key>
<data>4g==</data>
<key>boot-args</key>
<string>-v keepsyms=1</string>
<key>csr-active-config</key>
@ -1357,16 +1359,18 @@
<false/>
<key>DisconnectHda</key>
<false/>
<key>MinimumVolume</key>
<integer>20</integer>
<key>MaximumGain</key>
<integer>-15</integer>
<key>MinimumAssistGain</key>
<integer>-30</integer>
<key>MinimumAudibleGain</key>
<integer>-55</integer>
<key>PlayChime</key>
<string>Auto</string>
<key>ResetTrafficClass</key>
<false/>
<key>SetupDelay</key>
<integer>0</integer>
<key>VolumeAmplifier</key>
<integer>0</integer>
</dict>
<key>ConnectDrivers</key>
<true/>

View File

@ -1202,6 +1202,8 @@
<dict>
<key>SystemAudioVolume</key>
<data>Rg==</data>
<key>SystemAudioVolumeDB</key>
<data>4g==</data>
<key>boot-args</key>
<string>-v keepsyms=1</string>
<key>csr-active-config</key>
@ -1695,16 +1697,18 @@
<false/>
<key>DisconnectHda</key>
<false/>
<key>MinimumVolume</key>
<integer>20</integer>
<key>MaximumGain</key>
<integer>-15</integer>
<key>MinimumAssistGain</key>
<integer>-30</integer>
<key>MinimumAudibleGain</key>
<integer>-55</integer>
<key>PlayChime</key>
<string>Auto</string>
<key>ResetTrafficClass</key>
<false/>
<key>SetupDelay</key>
<integer>0</integer>
<key>VolumeAmplifier</key>
<integer>0</integer>
</dict>
<key>ConnectDrivers</key>
<true/>

View File

@ -12,7 +12,7 @@
#include <Library/OcFileLib.h>
#include <Protocol/OcAudio.h>
#define OC_AUDIO_DEFAULT_VOLUME_LEVEL 70
#define OC_AUDIO_DEFAULT_GAIN (-30)
/**
Install audio support protocols.
@ -43,16 +43,14 @@ OcLanguageCodeToString (
);
/**
Get system volume level in 0~100 range.
Get system amplifier gain.
@param[in] Amplifier Amplification coefficient 1~999.
@param[out] Muted Whether volume is off.
@param[out] Muted Whether amplifier should be muted.
@retval ASCII string.
**/
UINT8
OcGetVolumeLevel (
IN UINT32 Amplifier,
INT8
OcGetAmplifierGain (
OUT BOOLEAN *Muted
);

View File

@ -618,11 +618,12 @@ typedef enum {
_(OC_STRING , AudioDevice , , OC_STRING_CONSTR ("", _, __) , OC_DESTR (OC_STRING)) \
_(OC_STRING , PlayChime , , OC_STRING_CONSTR ("Auto", _, __) , OC_DESTR (OC_STRING)) \
_(UINT32 , SetupDelay , , 0 , ()) \
_(UINT16 , VolumeAmplifier , , 0 , ()) \
_(BOOLEAN , AudioSupport , , FALSE , ()) \
_(UINT8 , AudioCodec , , 0 , ()) \
_(UINT64 , AudioOutMask , , MAX_UINT64 , ()) \
_(UINT8 , MinimumVolume , , 0 , ()) \
_(UINT8 , AudioCodec , , 0 , ()) \
_(INT8 , MaximumGain , , -15 , ()) \
_(INT8 , MinimumAssistGain , , -30 , ()) \
_(INT8 , MinimumAudibleGain , , -128 , ()) \
_(BOOLEAN , ResetTrafficClass , , FALSE , ()) \
_(BOOLEAN , DisconnectHda , , FALSE , ())
OC_DECLARE (OC_UEFI_AUDIO)

View File

@ -166,7 +166,8 @@ EFI_STATUS
@param[in] This A pointer to the EFI_AUDIO_IO_PROTOCOL instance.
@param[in] OutputIndexMask A mask indicating the desired outputs.
@param[in] Volume The volume (0-100) to use.
@param[in] Gain The amplifier gain (or attentuation if negative) in dB to use, relative to 0 dB level (0 dB
is usually at at or near max available volume, but is not required to be so in the spec).
@param[in] Bits The width in bits of the source data.
@param[in] Freq The frequency of the source data.
@param[in] Channels The number of channels the source data contains.
@ -180,7 +181,7 @@ EFI_STATUS
(EFIAPI *EFI_AUDIO_IO_SETUP_PLAYBACK) (
IN EFI_AUDIO_IO_PROTOCOL *This,
IN UINT64 OutputIndexMask,
IN UINT8 Volume,
IN INT8 Gain,
IN EFI_AUDIO_IO_PROTOCOL_FREQ Freq,
IN EFI_AUDIO_IO_PROTOCOL_BITS Bits,
IN UINT8 Channels,

View File

@ -19,7 +19,7 @@
#include <Protocol/AppleVoiceOver.h>
#include <Protocol/DevicePath.h>
#define OC_AUDIO_PROTOCOL_REVISION 0x030000
#define OC_AUDIO_PROTOCOL_REVISION 0x040000
//
// OC_AUDIO_PROTOCOL_GUID
@ -120,7 +120,8 @@ STATIC_ASSERT (OcVoiceOverAudioFileIndexMax - OcVoiceOverAudioFileIndexBase == 9
@param[in] DevicePath Controller device path, optional.
@param[in] CodecAddress Codec address, optional.
@param[in] OutputIndexMask Output index mask.
@param[in] Volume Raw volume level from 0 to 100.
@param[in] Gain The amplifier gain (or attenuation if negative) in dB to use, relative to 0 dB level (0 dB
is usually at at or near max available volume, but is not required to be so in the spec).
@retval EFI_SUCESS on success.
@retval EFI_NOT_FOUND when missing.
@ -133,7 +134,7 @@ EFI_STATUS
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL,
IN UINT8 CodecAddress OPTIONAL,
IN UINT64 OutputIndexMask,
IN UINT8 Volume
IN INT8 Gain
);
/**
@ -202,6 +203,8 @@ EFI_STATUS
@param[in,out] This Audio protocol instance.
@param[in] File File to play.
@param[in] Gain The amplifier gain (or attenuation if negative) in dB to use, relative to 0 dB level.
@param[in] UseGain If TRUE use provided volume level, otherwise use stored global volume level.
@param[in] Wait Wait for completion of the previous track.
@retval EFI_SUCCESS on successful playback startup.
@ -211,6 +214,8 @@ EFI_STATUS
(EFIAPI* OC_AUDIO_PLAY_FILE) (
IN OUT OC_AUDIO_PROTOCOL *This,
IN UINT32 File,
IN INT8 Gain OPTIONAL,
IN BOOLEAN UseGain,
IN BOOLEAN Wait
);

View File

@ -139,9 +139,12 @@ typedef enum {
#define APPLE_SYSTEM_AUDIO_VOLUME_MUTED BIT7
#define APPLE_SYSTEM_AUDIO_VOLUME_VOLUME_MASK 0x7FU
#define APPLE_SYSTEM_AUDIO_VOLUME_DB_MIN (-128)
#define APPLE_SYSTEM_AUDIO_VOLUME_DB_MAX (127)
///
/// System audio volume.
/// UINT8: APPLE_SYSTEM_AUDIO_VOLUME_VOLUME_MASK | APPLE_SYSTEM_AUDIO_VOLUME_VOLUME_MASK
/// UINT8: APPLE_SYSTEM_AUDIO_VOLUME_MUTED | APPLE_SYSTEM_AUDIO_VOLUME_VOLUME_MASK
/// gAppleBootVariableGuid
///
#define APPLE_SYSTEM_AUDIO_VOLUME_VARIABLE_NAME L"SystemAudioVolume"
@ -155,10 +158,10 @@ typedef enum {
///
/// System audio volume in decibels, created by AppleHDA.kext.
/// UINT8: SystemAudioVolume'
/// UINT8: SystemAudioVolumeDB
/// gAppleBootVariableGuid
///
#define APPLE_SYSTEM_AUDIO_VOLUME_SAVED_VARIABLE_DB_NAME L"SystemAudioVolumeDB"
#define APPLE_SYSTEM_AUDIO_VOLUME_DB_VARIABLE_NAME L"SystemAudioVolumeDB"
///
/// System language.

View File

@ -168,7 +168,7 @@ InternalOcAudioConnect (
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL,
IN UINT8 CodecAddress OPTIONAL,
IN UINT64 OutputIndexMask,
IN UINT8 Volume
IN INT8 Gain
)
{
EFI_STATUS Status;
@ -180,7 +180,7 @@ InternalOcAudioConnect (
Private = OC_AUDIO_PROTOCOL_PRIVATE_FROM_OC_AUDIO (This);
Private->OutputIndexMask = OutputIndexMask;
Private->Volume = Volume;
Private->Gain = Gain;
if (DevicePath == NULL) {
Status = gBS->LocateProtocol (
@ -303,6 +303,8 @@ EFIAPI
InternalOcAudioPlayFile (
IN OUT OC_AUDIO_PROTOCOL *This,
IN UINT32 File,
IN INT8 Gain OPTIONAL,
IN BOOLEAN UseGain,
IN BOOLEAN Wait
)
{
@ -366,7 +368,7 @@ InternalOcAudioPlayFile (
Status = Private->AudioIo->SetupPlayback (
Private->AudioIo,
Private->OutputIndexMask,
Private->Volume,
UseGain ? Gain : Private->Gain,
Frequency,
Bits,
Channels,

View File

@ -132,7 +132,7 @@ InternalOcAudioGenBeep (
Status = Private->AudioIo->SetupPlayback (
Private->AudioIo,
Private->OutputIndexMask,
Private->Volume,
Private->Gain,
OC_BEEP_AUDIO_FREQUENCY,
OC_BEEP_AUDIO_BITS,
OC_BEEP_AUDIO_CHANNELS,

View File

@ -51,7 +51,7 @@ typedef struct {
UINTN PlaybackDelay;
UINT8 Language;
UINT64 OutputIndexMask;
UINT8 Volume;
INT8 Gain;
OC_AUDIO_PROTOCOL OcAudio;
APPLE_BEEP_GEN_PROTOCOL BeepGen;
APPLE_VOICE_OVER_AUDIO_PROTOCOL VoiceOver;
@ -64,7 +64,7 @@ InternalOcAudioConnect (
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL,
IN UINT8 CodecAddress OPTIONAL,
IN UINT64 OutputIndexMask,
IN UINT8 Volume
IN INT8 Gain
);
EFI_STATUS
@ -81,6 +81,8 @@ EFIAPI
InternalOcAudioPlayFile (
IN OUT OC_AUDIO_PROTOCOL *This,
IN UINT32 File,
IN INT8 Gain OPTIONAL,
IN BOOLEAN UseGain,
IN BOOLEAN Wait
);

View File

@ -54,7 +54,7 @@ mAudioProtocol = {
.PlaybackDelay = 0,
.Language = AppleVoiceOverLanguageEn,
.OutputIndexMask = 0,
.Volume = 100,
.Gain = APPLE_SYSTEM_AUDIO_VOLUME_DB_MIN,
.OcAudio = {
.Revision = OC_AUDIO_PROTOCOL_REVISION,
.Connect = InternalOcAudioConnect,
@ -158,51 +158,75 @@ OcAudioInstallProtocols (
return &mAudioProtocol.OcAudio;
}
UINT8
OcGetVolumeLevel (
IN UINT32 Amplifier,
INT8
OcGetAmplifierGain (
OUT BOOLEAN *Muted
)
{
EFI_STATUS Status;
EFI_STATUS AltStatus;
UINTN Size;
UINT8 Value;
UINT8 NewValue;
INT8 DbValue;
*Muted = FALSE;
//
// Check mute initially (only available in raw, amp-specific gain setting).
//
Size = sizeof (Value);
Status = gRT->GetVariable (
AltStatus = gRT->GetVariable (
APPLE_SYSTEM_AUDIO_VOLUME_VARIABLE_NAME,
&gAppleBootVariableGuid,
NULL,
&Size,
&Value
);
if (EFI_ERROR (Status)) {
Value = OC_AUDIO_DEFAULT_VOLUME_LEVEL;
if (EFI_ERROR (AltStatus)) {
Value = 0;
} else if ((Value & APPLE_SYSTEM_AUDIO_VOLUME_MUTED) != 0) {
*Muted = TRUE;
Value &= APPLE_SYSTEM_AUDIO_VOLUME_VOLUME_MASK;
}
if ((Value & APPLE_SYSTEM_AUDIO_VOLUME_MUTED) != 0) {
Value &= APPLE_SYSTEM_AUDIO_VOLUME_VOLUME_MASK;
*Muted = TRUE;
//
// If no mute, use dB gain setting (which can be applied to any amp on any codec).
//
if (*Muted) {
//
// SystemAudioVolumeDB appears not to contain sane values when SystemAudioVolume indicates muted,
// therefore we have to fall back to default gain value for use with audio assist, which never mutes.
//
DbValue = APPLE_SYSTEM_AUDIO_VOLUME_DB_MIN;
Status = EFI_NOT_STARTED;
} else {
*Muted = FALSE;
Size = sizeof (DbValue);
Status = gRT->GetVariable (
APPLE_SYSTEM_AUDIO_VOLUME_DB_VARIABLE_NAME,
&gAppleBootVariableGuid,
NULL,
&Size,
&DbValue
);
if (EFI_ERROR (Status)) {
DbValue = OC_AUDIO_DEFAULT_GAIN;
}
}
if (Amplifier > 0) {
NewValue = (UINT8) (Value * Amplifier / 100);
} else {
NewValue = Value;
}
NewValue = MIN (NewValue, 100);
//
// Log system saved raw gain for debugging purposes. Value derived later from dB gain should
// be the same to within about +/- 1, if applied on an amp with the same amp capabilities.
//
DEBUG ((
DEBUG_INFO,
"OCAU: System volume is %d (calculated from %d) - %r\n",
NewValue,
"OCAU: System amp gain %d dB, saved raw gain 0x%X, system audio mute (for chime) %u - %r/%r\n",
DbValue,
Value,
*Muted,
AltStatus,
Status
));
return NewValue;
return DbValue;
}

View File

@ -129,7 +129,7 @@ InternalOcAudioVoiceOverPlay (
{
OC_AUDIO_PROTOCOL_PRIVATE *Private;
Private = OC_AUDIO_PROTOCOL_PRIVATE_FROM_VOICE_OVER (This);
return Private->OcAudio.PlayFile (&Private->OcAudio, File, TRUE);
return Private->OcAudio.PlayFile (&Private->OcAudio, File, 0, FALSE, TRUE);
}
EFI_STATUS

View File

@ -74,7 +74,7 @@ OcPlayAudioFile (
}
if (Context->OcAudio != NULL) {
Status = Context->OcAudio->PlayFile (Context->OcAudio, File, TRUE);
Status = Context->OcAudio->PlayFile (Context->OcAudio, File, 0, FALSE, TRUE);
}
if (Fallback && EFI_ERROR (Status)) {

View File

@ -756,11 +756,12 @@ mUefiAudioSchema[] = {
OC_SCHEMA_INTEGER_IN ("AudioOutMask", OC_GLOBAL_CONFIG, Uefi.Audio.AudioOutMask),
OC_SCHEMA_BOOLEAN_IN ("AudioSupport", OC_GLOBAL_CONFIG, Uefi.Audio.AudioSupport),
OC_SCHEMA_BOOLEAN_IN ("DisconnectHda", OC_GLOBAL_CONFIG, Uefi.Audio.DisconnectHda),
OC_SCHEMA_INTEGER_IN ("MinimumVolume", OC_GLOBAL_CONFIG, Uefi.Audio.MinimumVolume),
OC_SCHEMA_INTEGER_IN ("MaximumGain", OC_GLOBAL_CONFIG, Uefi.Audio.MaximumGain),
OC_SCHEMA_INTEGER_IN ("MinimumAssistGain", OC_GLOBAL_CONFIG, Uefi.Audio.MinimumAssistGain),
OC_SCHEMA_INTEGER_IN ("MinimumAudibleGain", OC_GLOBAL_CONFIG, Uefi.Audio.MinimumAudibleGain),
OC_SCHEMA_STRING_IN ("PlayChime", OC_GLOBAL_CONFIG, Uefi.Audio.PlayChime),
OC_SCHEMA_BOOLEAN_IN ("ResetTrafficClass", OC_GLOBAL_CONFIG, Uefi.Audio.ResetTrafficClass),
OC_SCHEMA_INTEGER_IN ("SetupDelay", OC_GLOBAL_CONFIG, Uefi.Audio.SetupDelay),
OC_SCHEMA_INTEGER_IN ("VolumeAmplifier", OC_GLOBAL_CONFIG, Uefi.Audio.VolumeAmplifier),
};
STATIC

View File

@ -496,7 +496,7 @@ OcLoadUefiAudioSupport (
CHAR16 *UnicodeDevicePath;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
OC_AUDIO_PROTOCOL *OcAudio;
UINT8 VolumeLevel;
INT8 Gain;
BOOLEAN Muted;
if (Config->Uefi.Audio.ResetTrafficClass) {
@ -518,7 +518,7 @@ OcLoadUefiAudioSupport (
return;
}
VolumeLevel = OcGetVolumeLevel (Config->Uefi.Audio.VolumeAmplifier, &Muted);
Gain = OcGetAmplifierGain (&Muted);
DevicePath = NULL;
AsciiDevicePath = OC_BLOB_GET (&Config->Uefi.Audio.AudioDevice);
@ -549,15 +549,28 @@ OcLoadUefiAudioSupport (
}
//
// Never disable sound completely, as it is vital for accessability.
// Have a max. volume to limit very loud user volume during boot, as Apple do.
//
if (Gain > Config->Uefi.Audio.MaximumGain) {
DEBUG ((
DEBUG_INFO,
"OC: Limiting gain %d dB -> %d dB\n",
Gain,
Config->Uefi.Audio.MaximumGain
));
Gain = Config->Uefi.Audio.MaximumGain;
}
//
// Never disable audio assist sound completely, as it is vital for accessibility.
//
Status = OcAudio->Connect (
OcAudio,
DevicePath,
Config->Uefi.Audio.AudioCodec,
Config->Uefi.Audio.AudioOutMask,
VolumeLevel < Config->Uefi.Audio.MinimumVolume
? Config->Uefi.Audio.MinimumVolume : VolumeLevel
Gain < Config->Uefi.Audio.MinimumAssistGain
? Config->Uefi.Audio.MinimumAssistGain : Gain
);
if (DevicePath != NULL) {
@ -587,12 +600,15 @@ OcLoadUefiAudioSupport (
OcSetVoiceOverLanguage (NULL);
if (OcShouldPlayChime (OC_BLOB_GET (&Config->Uefi.Audio.PlayChime))
&& VolumeLevel >= Config->Uefi.Audio.MinimumVolume && !Muted) {
if (!Muted
&& Gain >= Config->Uefi.Audio.MinimumAudibleGain
&& OcShouldPlayChime (OC_BLOB_GET (&Config->Uefi.Audio.PlayChime))) {
DEBUG ((DEBUG_INFO, "OC: Starting to play chime...\n"));
Status = OcAudio->PlayFile (
OcAudio,
AppleVoiceOverAudioFileVoiceOverBoot,
Gain,
TRUE,
FALSE
);
DEBUG ((DEBUG_INFO, "OC: Play chime started - %r\n", Status));

View File

@ -55,7 +55,7 @@
#include <Protocol/HdaControllerInfo.h>
// Driver version
#define AUDIODXE_VERSION 0xC
#define AUDIODXE_VERSION 0xD
#define AUDIODXE_PKG_VERSION 1
// Driver Bindings.

View File

@ -967,22 +967,27 @@ EFI_STATUS
EFIAPI
HdaCodecEnableWidgetPath(
IN HDA_WIDGET_DEV *HdaWidget,
IN UINT8 Volume,
IN INT8 Gain,
IN UINT8 StreamId,
IN UINT16 StreamFormat
)
{
EFI_STATUS Status;
EFI_STATUS Status;
EFI_HDA_IO_PROTOCOL *HdaIo;
UINT32 Response;
UINT8 VrefCaps;
UINT8 VrefCtrl;
UINT32 Response;
UINT8 VrefCaps;
UINT8 VrefCtrl;
UINT8 Offset;
UINT8 NumSteps;
UINT8 StepSize;
INTN GainParam;
//DEBUG((DEBUG_INFO, "HdaCodecEnableWidgetPath(): start\n"));
// Check if widget is valid.
if ((HdaWidget == NULL) || (Volume > EFI_AUDIO_IO_PROTOCOL_MAX_VOLUME))
if (HdaWidget == NULL) {
return EFI_INVALID_PARAMETER;
}
HdaIo = HdaWidget->FuncGroup->HdaCodecDev->HdaIo;
@ -1064,17 +1069,27 @@ HdaCodecEnableWidgetPath(
// If there is an output amp, unmute.
if (HdaWidget->Capabilities & HDA_PARAMETER_WIDGET_CAPS_OUT_AMP) {
UINT8 offset = HDA_PARAMETER_AMP_CAPS_OFFSET(HdaWidget->AmpOutCapabilities); // TODO set volume.
// If there are no overriden amp capabilities, check function group.
if (!(HdaWidget->AmpOverride))
offset = HDA_PARAMETER_AMP_CAPS_OFFSET(HdaWidget->FuncGroup->AmpOutCapabilities);
if (HdaWidget->AmpOverride) {
Offset = HDA_PARAMETER_AMP_CAPS_OFFSET(HdaWidget->AmpOutCapabilities);
NumSteps = HDA_PARAMETER_AMP_CAPS_NUM_STEPS(HdaWidget->AmpOutCapabilities);
StepSize = HDA_PARAMETER_AMP_CAPS_STEP_SIZE(HdaWidget->AmpOutCapabilities);
} else {
Offset = HDA_PARAMETER_AMP_CAPS_OFFSET(HdaWidget->FuncGroup->AmpOutCapabilities);
NumSteps = HDA_PARAMETER_AMP_CAPS_NUM_STEPS(HdaWidget->FuncGroup->AmpOutCapabilities);
StepSize = HDA_PARAMETER_AMP_CAPS_STEP_SIZE(HdaWidget->FuncGroup->AmpOutCapabilities);
}
// Calculate offset.
offset = (offset * Volume) / EFI_AUDIO_IO_PROTOCOL_MAX_VOLUME;
DEBUG((DEBUG_INFO, "HDA: Amp out offset 0x%X\n", offset));
// Calculate gain param.
GainParam = (Gain * 4 / (StepSize + 1)) + Offset;
if (GainParam > NumSteps) {
GainParam = NumSteps;
} else if (GainParam < 0) {
GainParam = 0;
}
DEBUG((DEBUG_INFO, "HDA: Amp gain 0x%X (from %d dB)\n", GainParam, Gain));
Status = HdaIo->SendCommand(HdaIo, HdaWidget->NodeId, HDA_CODEC_VERB(HDA_VERB_SET_AMP_GAIN_MUTE,
HDA_VERB_SET_AMP_GAIN_MUTE_PAYLOAD(0, offset, FALSE, TRUE, TRUE, FALSE, TRUE)), &Response);
HDA_VERB_SET_AMP_GAIN_MUTE_PAYLOAD(0, GainParam, FALSE, TRUE, TRUE, FALSE, TRUE)), &Response);
if (EFI_ERROR(Status))
return Status;
}

View File

@ -235,7 +235,7 @@ EFIAPI
HdaCodecAudioIoSetupPlayback(
IN EFI_AUDIO_IO_PROTOCOL *This,
IN UINT64 OutputIndexMask,
IN UINT8 Volume,
IN INT8 Gain,
IN EFI_AUDIO_IO_PROTOCOL_FREQ Freq,
IN EFI_AUDIO_IO_PROTOCOL_BITS Bits,
IN UINT8 Channels,
@ -293,7 +293,7 @@ EFI_STATUS
EFIAPI
HdaCodecEnableWidgetPath(
IN HDA_WIDGET_DEV *HdaWidget,
IN UINT8 Volume,
IN INT8 Gain,
IN UINT8 StreamId,
IN UINT16 StreamFormat);

View File

@ -3,6 +3,8 @@
SPDX-License-Identifier: BSD-3-Clause
**/
#include <Guid/AppleVariable.h>
#include "HdaCodec.h"
#include <Protocol/AudioIo.h>
#include <Library/OcMiscLib.h>
@ -12,7 +14,7 @@
// Cache playback setup.
//
STATIC UINT64 mOutputIndexMask = 0;
STATIC UINT8 mVolume = 0;
STATIC INT8 mGain = APPLE_SYSTEM_AUDIO_VOLUME_DB_MIN;
STATIC EFI_AUDIO_IO_PROTOCOL_FREQ mFreq = 0;
STATIC EFI_AUDIO_IO_PROTOCOL_BITS mBits = 0;
STATIC UINT8 mChannels = 0xFFU;
@ -216,7 +218,8 @@ HdaCodecAudioIoGetOutputs(
@param[in] This A pointer to the EFI_AUDIO_IO_PROTOCOL instance.
@param[in] OutputIndexMask A mask indicating the desired outputs.
@param[in] Volume The volume (0-100) to use.
@param[in] Gain The amplifier gain (or attentuation if negative) in dB to use, relative to 0 dB level (0 dB
is usually at at or near max available volume, but is not required to be so in the spec).
@param[in] Bits The width in bits of the source data.
@param[in] Freq The frequency of the source data.
@param[in] Channels The number of channels the source data contains.
@ -230,7 +233,7 @@ EFIAPI
HdaCodecAudioIoSetupPlayback(
IN EFI_AUDIO_IO_PROTOCOL *This,
IN UINT64 OutputIndexMask,
IN UINT8 Volume,
IN INT8 Gain,
IN EFI_AUDIO_IO_PROTOCOL_FREQ Freq,
IN EFI_AUDIO_IO_PROTOCOL_BITS Bits,
IN UINT8 Channels,
@ -264,7 +267,7 @@ HdaCodecAudioIoSetupPlayback(
// Basic settings caching.
if (mOutputIndexMask == OutputIndexMask
&& mVolume == Volume
&& mGain == Gain
&& mFreq == Freq
&& mBits == Bits
&& mChannels == Channels) {
@ -272,14 +275,15 @@ HdaCodecAudioIoSetupPlayback(
}
mOutputIndexMask = OutputIndexMask;
mVolume = Volume;
mGain = Gain;
mFreq = Freq;
mBits = Bits;
mChannels = Channels;
// If a parameter is invalid, return error.
if ((This == NULL) || (Volume > EFI_AUDIO_IO_PROTOCOL_MAX_VOLUME))
if (This == NULL) {
return EFI_INVALID_PARAMETER;
}
// Get private data.
AudioIoPrivateData = AUDIO_IO_PRIVATE_DATA_FROM_THIS(This);
@ -500,7 +504,7 @@ HdaCodecAudioIoSetupPlayback(
if ((OutputIndexMask & IndexMask) == 0) {
continue;
}
Status = HdaCodecEnableWidgetPath(HdaCodecDev->OutputPorts[Index], Volume, HdaStreamId, StreamFmt);
Status = HdaCodecEnableWidgetPath(HdaCodecDev->OutputPorts[Index], Gain, HdaStreamId, StreamFmt);
if (EFI_ERROR(Status))
goto CLOSE_STREAM;
}

View File

@ -182,6 +182,40 @@ CheckUefiAppleInput (
return ErrorCount;
}
STATIC
UINT32
CheckUefiGain (
INT8 Gain,
CHAR8 *GainName,
INT8 GainAbove, OPTIONAL
CHAR8 *GainAboveName OPTIONAL
)
{
UINT32 ErrorCount;
ErrorCount = 0;
//
// Cannot check these as they are already truncated to INT8 before we can validate them.
// TODO: (?) Add check during DEBUG parsing that specified values fit into what they will be cast to.
//
#if 0
if (Gain < -128) {
DEBUG ((DEBUG_WARN, "UEFI->Audio->%a must be greater than or equal to -128!\n", GainName));
++ErrorCount;
} else if (Gain > 127) {
DEBUG ((DEBUG_WARN, "UEFI->Audio->%a must be less than or equal to 127!\n", GainName));
++ErrorCount;
}
#endif
if (GainAboveName != NULL && Gain > GainAbove) {
DEBUG ((DEBUG_WARN, "UEFI->Audio->%a must be less than or equal to UEFI->Audio->%a!\n", GainName, GainAboveName));
++ErrorCount;
}
return ErrorCount;
}
STATIC
UINT32
CheckUefiAudio (
@ -208,6 +242,35 @@ CheckUefiAudio (
++ErrorCount;
}
ErrorCount += CheckUefiGain (
UserUefi->Audio.MaximumGain,
"MaximumGain",
0,
NULL
);
// No operational reason for MinimumAssistGain <= MaximumGain, but is safer to ensure non-deafening sound levels.
ErrorCount += CheckUefiGain (
UserUefi->Audio.MinimumAssistGain,
"MinimumAssistGain",
UserUefi->Audio.MaximumGain,
"MaximumGain"
);
ErrorCount += CheckUefiGain (
UserUefi->Audio.MinimumAudibleGain,
"MinimumAudibleGain",
UserUefi->Audio.MinimumAssistGain,
"MinimumAssistGain"
);
ErrorCount += CheckUefiGain (
UserUefi->Audio.MinimumAudibleGain,
"MinimumAudibleGain",
UserUefi->Audio.MaximumGain,
"MaximumGain"
);
if (!AsciiDevicePathIsLegal (AsciiAudioDevicePath)) {
DEBUG ((DEBUG_WARN, "UEFI->Audio->AudioDevice is borked! Please check the information above!\n"));
++ErrorCount;