You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'linus' of master.kernel.org:/pub/scm/linux/kernel/git/perex/alsa
* 'linus' of master.kernel.org:/pub/scm/linux/kernel/git/perex/alsa: (212 commits) [PATCH] Fix breakage with CONFIG_SYSFS_DEPRECATED [ALSA] version 1.0.14rc2 [ALSA] ASoC documentation updates [ALSA] ca0106 - Add missing sysfs device assignment [ALSA] aoa i2sbus: Stop Apple i2s DMA gracefully [ALSA] hda-codec - Add support for Fujitsu PI1556 Realtek ALC880 [ALSA] aoa: remove suspend/resume printks [ALSA] Fix possible deadlocks in sequencer at removal of ports [ALSA] emu10k1 - Fix STAC9758 front channel [ALSA] soc - Clean up with kmemdup() [ALSA] snd-ak4114: Fix two array overflows [ALSA] ac97_bus power management [ALSA] usbaudio - Add support for Edirol UA-101 [ALSA] hda-codec - Add ALC861VD/ALC660VD support [ALSA] soc - ASoC 0.13 Sharp poodle machine [ALSA] soc - ASoC 0.13 Sharp tosa machine [ALSA] soc - ASoC 0.13 spitz machine [ALSA] soc - ASoC Sharp corgi machine [ALSA] soc - ASoC 0.13 pxa2xx DMA [ALSA] soc - ASoC 0.13 pxa2xx AC97 driver ...
This commit is contained in:
@@ -242,6 +242,12 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
ac97_clock - AC'97 clock (default = 48000)
|
||||
ac97_quirk - AC'97 workaround for strange hardware
|
||||
See "AC97 Quirk Option" section below.
|
||||
ac97_codec - Workaround to specify which AC'97 codec
|
||||
instead of probing. If this works for you
|
||||
file a bug with your `lspci -vn` output.
|
||||
-2 -- Force probing.
|
||||
-1 -- Default behavior.
|
||||
0-2 -- Use the specified codec.
|
||||
spdif_aclink - S/PDIF transfer over AC-link (default = 1)
|
||||
|
||||
This module supports one card and autoprobe.
|
||||
@@ -779,6 +785,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
asus-dig ASUS with SPDIF out
|
||||
asus-dig2 ASUS with SPDIF out (using GPIO2)
|
||||
uniwill 3-jack
|
||||
fujitsu Fujitsu Laptops (Pi1536)
|
||||
F1734 2-jack
|
||||
lg LG laptop (m1 express dual)
|
||||
lg-lw LG LW20/LW25 laptop
|
||||
@@ -800,14 +807,18 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
ALC262
|
||||
fujitsu Fujitsu Laptop
|
||||
hp-bpc HP xw4400/6400/8400/9400 laptops
|
||||
hp-bpc-d7000 HP BPC D7000
|
||||
benq Benq ED8
|
||||
hippo Hippo (ATI) with jack detection, Sony UX-90s
|
||||
hippo_1 Hippo (Benq) with jack detection
|
||||
basic fixed pin assignment w/o SPDIF
|
||||
auto auto-config reading BIOS (default)
|
||||
|
||||
ALC882/885
|
||||
3stack-dig 3-jack with SPDIF I/O
|
||||
6stck-dig 6-jack digital with SPDIF I/O
|
||||
6stack-dig 6-jack digital with SPDIF I/O
|
||||
arima Arima W820Di1
|
||||
macpro MacPro support
|
||||
auto auto-config reading BIOS (default)
|
||||
|
||||
ALC883/888
|
||||
@@ -817,6 +828,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
3stack-6ch-dig 3-jack 6-channel with SPDIF I/O
|
||||
6stack-dig-demo 6-jack digital for Intel demo board
|
||||
acer Acer laptops (Travelmate 3012WTMi, Aspire 5600, etc)
|
||||
medion Medion Laptops
|
||||
targa-dig Targa/MSI
|
||||
targa-2ch-dig Targs/MSI with 2-channel
|
||||
laptop-eapd 3-jack with SPDIF I/O and EAPD (Clevo M540JE, M550JE)
|
||||
auto auto-config reading BIOS (default)
|
||||
|
||||
ALC861/660
|
||||
@@ -825,6 +840,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
6stack-dig 6-jack with SPDIF I/O
|
||||
3stack-660 3-jack (for ALC660)
|
||||
uniwill-m31 Uniwill M31 laptop
|
||||
toshiba Toshiba laptop support
|
||||
asus Asus laptop support
|
||||
asus-laptop ASUS F2/F3 laptops
|
||||
auto auto-config reading BIOS (default)
|
||||
|
||||
ALC861VD/660VD
|
||||
3stack 3-jack
|
||||
3stack-dig 3-jack with SPDIF OUT
|
||||
6stack-dig 6-jack with SPDIF OUT
|
||||
3stack-660 3-jack (for ALC660VD)
|
||||
auto auto-config reading BIOS (default)
|
||||
|
||||
CMI9880
|
||||
@@ -845,6 +870,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
3stack 3-stack, shared surrounds
|
||||
laptop 2-channel only (FSC V2060, Samsung M50)
|
||||
laptop-eapd 2-channel with EAPD (Samsung R65, ASUS A6J)
|
||||
ultra 2-channel with EAPD (Samsung Ultra tablet PC)
|
||||
|
||||
AD1988
|
||||
6stack 6-jack
|
||||
@@ -855,11 +881,30 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
laptop-dig ditto with SPDIF
|
||||
auto auto-config reading BIOS (default)
|
||||
|
||||
Conexant 5045
|
||||
laptop Laptop config
|
||||
test for testing/debugging purpose, almost all controls
|
||||
can be adjusted. Appearing only when compiled with
|
||||
$CONFIG_SND_DEBUG=y
|
||||
|
||||
Conexant 5047
|
||||
laptop Basic Laptop config
|
||||
laptop-hp Laptop config for some HP models (subdevice 30A5)
|
||||
laptop-eapd Laptop config with EAPD support
|
||||
test for testing/debugging purpose, almost all controls
|
||||
can be adjusted. Appearing only when compiled with
|
||||
$CONFIG_SND_DEBUG=y
|
||||
|
||||
STAC9200/9205/9220/9221/9254
|
||||
ref Reference board
|
||||
3stack D945 3stack
|
||||
5stack D945 5stack + SPDIF
|
||||
|
||||
STAC9202/9250/9251
|
||||
ref Reference board, base config
|
||||
m2-2 Some Gateway MX series laptops
|
||||
m6 Some Gateway NX series laptops
|
||||
|
||||
STAC9227/9228/9229/927x
|
||||
ref Reference board
|
||||
3stack D965 3stack
|
||||
@@ -974,6 +1019,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
Module for Envy24HT (VT/ICE1724), Envy24PT (VT1720) based PCI sound cards.
|
||||
* MidiMan M Audio Revolution 5.1
|
||||
* MidiMan M Audio Revolution 7.1
|
||||
* MidiMan M Audio Audiophile 192
|
||||
* AMP Ltd AUDIO2000
|
||||
* TerraTec Aureon 5.1 Sky
|
||||
* TerraTec Aureon 7.1 Space
|
||||
@@ -993,7 +1039,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
|
||||
model - Use the given board model, one of the following:
|
||||
revo51, revo71, amp2000, prodigy71, prodigy71lt,
|
||||
prodigy192, aureon51, aureon71, universe,
|
||||
prodigy192, aureon51, aureon71, universe, ap192,
|
||||
k8x800, phase22, phase28, ms300, av710
|
||||
|
||||
This module supports multiple cards and autoprobe.
|
||||
@@ -1049,6 +1095,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
buggy_semaphore - Enable workaround for hardwares with buggy
|
||||
semaphores (e.g. on some ASUS laptops)
|
||||
(default off)
|
||||
spdif_aclink - Use S/PDIF over AC-link instead of direct connection
|
||||
from the controller chip
|
||||
(0 = off, 1 = on, -1 = default)
|
||||
|
||||
This module supports one chip and autoprobe.
|
||||
|
||||
@@ -1371,6 +1420,13 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-portman2x4
|
||||
---------------------
|
||||
|
||||
Module for Midiman Portman 2x4 parallel port MIDI interface
|
||||
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-powermac (on ppc only)
|
||||
---------------------------------
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
</bookinfo>
|
||||
|
||||
<chapter><title>Management of Cards and Devices</title>
|
||||
<sect1><title>Card Managment</title>
|
||||
<sect1><title>Card Management</title>
|
||||
!Esound/core/init.c
|
||||
</sect1>
|
||||
<sect1><title>Device Components</title>
|
||||
@@ -59,7 +59,7 @@
|
||||
<sect1><title>PCM Format Helpers</title>
|
||||
!Esound/core/pcm_misc.c
|
||||
</sect1>
|
||||
<sect1><title>PCM Memory Managment</title>
|
||||
<sect1><title>PCM Memory Management</title>
|
||||
!Esound/core/pcm_memory.c
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
||||
@@ -1360,8 +1360,7 @@
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
<![CDATA[
|
||||
static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id,
|
||||
struct pt_regs *regs)
|
||||
static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct mychip *chip = dev_id;
|
||||
....
|
||||
@@ -2127,7 +2126,7 @@
|
||||
accessible via <constant>substream->runtime</constant>.
|
||||
This runtime pointer holds the various information; it holds
|
||||
the copy of hw_params and sw_params configurations, the buffer
|
||||
pointers, mmap records, spinlocks, etc. Almost everyhing you
|
||||
pointers, mmap records, spinlocks, etc. Almost everything you
|
||||
need for controlling the PCM can be found there.
|
||||
</para>
|
||||
|
||||
@@ -2340,7 +2339,7 @@ struct _snd_pcm_runtime {
|
||||
|
||||
<para>
|
||||
When the PCM substreams can be synchronized (typically,
|
||||
synchorinized start/stop of a playback and a capture streams),
|
||||
synchronized start/stop of a playback and a capture streams),
|
||||
you can give <constant>SNDRV_PCM_INFO_SYNC_START</constant>,
|
||||
too. In this case, you'll need to check the linked-list of
|
||||
PCM substreams in the trigger callback. This will be
|
||||
@@ -3062,8 +3061,7 @@ struct _snd_pcm_runtime {
|
||||
<title>Interrupt Handler Case #1</title>
|
||||
<programlisting>
|
||||
<![CDATA[
|
||||
static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id,
|
||||
struct pt_regs *regs)
|
||||
static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct mychip *chip = dev_id;
|
||||
spin_lock(&chip->lock);
|
||||
@@ -3106,8 +3104,7 @@ struct _snd_pcm_runtime {
|
||||
<title>Interrupt Handler Case #2</title>
|
||||
<programlisting>
|
||||
<![CDATA[
|
||||
static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id,
|
||||
struct pt_regs *regs)
|
||||
static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct mychip *chip = dev_id;
|
||||
spin_lock(&chip->lock);
|
||||
@@ -3247,7 +3244,7 @@ struct _snd_pcm_runtime {
|
||||
You can even define your own constraint rules.
|
||||
For example, let's suppose my_chip can manage a substream of 1 channel
|
||||
if and only if the format is S16_LE, otherwise it supports any format
|
||||
specified in the <structname>snd_pcm_hardware</structname> stucture (or in any
|
||||
specified in the <structname>snd_pcm_hardware</structname> structure (or in any
|
||||
other constraint_list). You can build a rule like this:
|
||||
|
||||
<example>
|
||||
@@ -3690,16 +3687,6 @@ struct _snd_pcm_runtime {
|
||||
</example>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Here, the chip instance is retrieved via
|
||||
<function>snd_kcontrol_chip()</function> macro. This macro
|
||||
just accesses to kcontrol->private_data. The
|
||||
kcontrol->private_data field is
|
||||
given as the argument of <function>snd_ctl_new()</function>
|
||||
(see the later subsection
|
||||
<link linkend="control-interface-constructor"><citetitle>Constructor</citetitle></link>).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <structfield>value</structfield> field is depending on
|
||||
the type of control as well as on info callback. For example,
|
||||
@@ -3780,7 +3767,7 @@ struct _snd_pcm_runtime {
|
||||
<para>
|
||||
Like <structfield>get</structfield> callback,
|
||||
when the control has more than one elements,
|
||||
all elemehts must be evaluated in this callback, too.
|
||||
all elements must be evaluated in this callback, too.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
@@ -5541,12 +5528,12 @@ struct _snd_pcm_runtime {
|
||||
#ifdef CONFIG_PM
|
||||
static int snd_my_suspend(struct pci_dev *pci, pm_message_t state)
|
||||
{
|
||||
.... /* do things for suspsend */
|
||||
.... /* do things for suspend */
|
||||
return 0;
|
||||
}
|
||||
static int snd_my_resume(struct pci_dev *pci)
|
||||
{
|
||||
.... /* do things for suspsend */
|
||||
.... /* do things for suspend */
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -6111,7 +6098,7 @@ struct _snd_pcm_runtime {
|
||||
<!-- ****************************************************** -->
|
||||
<!-- Acknowledgments -->
|
||||
<!-- ****************************************************** -->
|
||||
<chapter id="acknowledments">
|
||||
<chapter id="acknowledgments">
|
||||
<title>Acknowledgments</title>
|
||||
<para>
|
||||
I would like to thank Phil Kerr for his help for improvement and
|
||||
|
||||
@@ -277,11 +277,11 @@ Helper Functions
|
||||
snd_hda_get_codec_name() stores the codec name on the given string.
|
||||
|
||||
snd_hda_check_board_config() can be used to obtain the configuration
|
||||
information matching with the device. Define the table with struct
|
||||
hda_board_config entries (zero-terminated), and pass it to the
|
||||
function. The function checks the modelname given as a module
|
||||
parameter, and PCI subsystem IDs. If the matching entry is found, it
|
||||
returns the config field value.
|
||||
information matching with the device. Define the model string table
|
||||
and the table with struct snd_pci_quirk entries (zero-terminated),
|
||||
and pass it to the function. The function checks the modelname given
|
||||
as a module parameter, and PCI subsystem IDs. If the matching entry
|
||||
is found, it returns the config field value.
|
||||
|
||||
snd_hda_add_new_ctls() can be used to create and add control entries.
|
||||
Pass the zero-terminated array of struct snd_kcontrol_new. The same array
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
ASoC currently supports the three main Digital Audio Interfaces (DAI) found on
|
||||
SoC controllers and portable audio CODECS today, namely AC97, I2S and PCM.
|
||||
|
||||
|
||||
AC97
|
||||
====
|
||||
|
||||
AC97 is a five wire interface commonly found on many PC sound cards. It is
|
||||
now also popular in many portable devices. This DAI has a reset line and time
|
||||
multiplexes its data on its SDATA_OUT (playback) and SDATA_IN (capture) lines.
|
||||
The bit clock (BCLK) is always driven by the CODEC (usually 12.288MHz) and the
|
||||
frame (FRAME) (usually 48kHz) is always driven by the controller. Each AC97
|
||||
frame is 21uS long and is divided into 13 time slots.
|
||||
|
||||
The AC97 specification can be found at :-
|
||||
http://www.intel.com/design/chipsets/audio/ac97_r23.pdf
|
||||
|
||||
|
||||
I2S
|
||||
===
|
||||
|
||||
I2S is a common 4 wire DAI used in HiFi, STB and portable devices. The Tx and
|
||||
Rx lines are used for audio transmision, whilst the bit clock (BCLK) and
|
||||
left/right clock (LRC) synchronise the link. I2S is flexible in that either the
|
||||
controller or CODEC can drive (master) the BCLK and LRC clock lines. Bit clock
|
||||
usually varies depending on the sample rate and the master system clock
|
||||
(SYSCLK). LRCLK is the same as the sample rate. A few devices support separate
|
||||
ADC and DAC LRCLK's, this allows for similtanious capture and playback at
|
||||
different sample rates.
|
||||
|
||||
I2S has several different operating modes:-
|
||||
|
||||
o I2S - MSB is transmitted on the falling edge of the first BCLK after LRC
|
||||
transition.
|
||||
|
||||
o Left Justified - MSB is transmitted on transition of LRC.
|
||||
|
||||
o Right Justified - MSB is transmitted sample size BCLK's before LRC
|
||||
transition.
|
||||
|
||||
PCM
|
||||
===
|
||||
|
||||
PCM is another 4 wire interface, very similar to I2S, that can support a more
|
||||
flexible protocol. It has bit clock (BCLK) and sync (SYNC) lines that are used
|
||||
to synchronise the link whilst the Tx and Rx lines are used to transmit and
|
||||
receive the audio data. Bit clock usually varies depending on sample rate
|
||||
whilst sync runs at the sample rate. PCM also supports Time Division
|
||||
Multiplexing (TDM) in that several devices can use the bus similtaniuosly (This
|
||||
is sometimes referred to as network mode).
|
||||
|
||||
Common PCM operating modes:-
|
||||
|
||||
o Mode A - MSB is transmitted on falling edge of first BCLK after FRAME/SYNC.
|
||||
|
||||
o Mode B - MSB is transmitted on rising edge of FRAME/SYNC.
|
||||
@@ -0,0 +1,51 @@
|
||||
Audio Clocking
|
||||
==============
|
||||
|
||||
This text describes the audio clocking terms in ASoC and digital audio in
|
||||
general. Note: Audio clocking can be complex !
|
||||
|
||||
|
||||
Master Clock
|
||||
------------
|
||||
|
||||
Every audio subsystem is driven by a master clock (sometimes refered to as MCLK
|
||||
or SYSCLK). This audio master clock can be derived from a number of sources
|
||||
(e.g. crystal, PLL, CPU clock) and is responsible for producing the correct
|
||||
audio playback and capture sample rates.
|
||||
|
||||
Some master clocks (e.g. PLL's and CPU based clocks) are configuarble in that
|
||||
their speed can be altered by software (depending on the system use and to save
|
||||
power). Other master clocks are fixed at at set frequency (i.e. crystals).
|
||||
|
||||
|
||||
DAI Clocks
|
||||
----------
|
||||
The Digital Audio Interface is usually driven by a Bit Clock (often referred to
|
||||
as BCLK). This clock is used to drive the digital audio data across the link
|
||||
between the codec and CPU.
|
||||
|
||||
The DAI also has a frame clock to signal the start of each audio frame. This
|
||||
clock is sometimes referred to as LRC (left right clock) or FRAME. This clock
|
||||
runs at exactly the sample rate (LRC = Rate).
|
||||
|
||||
Bit Clock can be generated as follows:-
|
||||
|
||||
BCLK = MCLK / x
|
||||
|
||||
or
|
||||
|
||||
BCLK = LRC * x
|
||||
|
||||
or
|
||||
|
||||
BCLK = LRC * Channels * Word Size
|
||||
|
||||
This relationship depends on the codec or SoC CPU in particular. In general
|
||||
it's best to configure BCLK to the lowest possible speed (depending on your
|
||||
rate, number of channels and wordsize) to save on power.
|
||||
|
||||
It's also desireable to use the codec (if possible) to drive (or master) the
|
||||
audio clocks as it's usually gives more accurate sample rates than the CPU.
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
ASoC Codec Driver
|
||||
=================
|
||||
|
||||
The codec driver is generic and hardware independent code that configures the
|
||||
codec to provide audio capture and playback. It should contain no code that is
|
||||
specific to the target platform or machine. All platform and machine specific
|
||||
code should be added to the platform and machine drivers respectively.
|
||||
|
||||
Each codec driver *must* provide the following features:-
|
||||
|
||||
1) Codec DAI and PCM configuration
|
||||
2) Codec control IO - using I2C, 3 Wire(SPI) or both API's
|
||||
3) Mixers and audio controls
|
||||
4) Codec audio operations
|
||||
|
||||
Optionally, codec drivers can also provide:-
|
||||
|
||||
5) DAPM description.
|
||||
6) DAPM event handler.
|
||||
7) DAC Digital mute control.
|
||||
|
||||
It's probably best to use this guide in conjuction with the existing codec
|
||||
driver code in sound/soc/codecs/
|
||||
|
||||
ASoC Codec driver breakdown
|
||||
===========================
|
||||
|
||||
1 - Codec DAI and PCM configuration
|
||||
-----------------------------------
|
||||
Each codec driver must have a struct snd_soc_codec_dai to define it's DAI and
|
||||
PCM's capablities and operations. This struct is exported so that it can be
|
||||
registered with the core by your machine driver.
|
||||
|
||||
e.g.
|
||||
|
||||
struct snd_soc_codec_dai wm8731_dai = {
|
||||
.name = "WM8731",
|
||||
/* playback capabilities */
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = WM8731_RATES,
|
||||
.formats = WM8731_FORMATS,},
|
||||
/* capture capabilities */
|
||||
.capture = {
|
||||
.stream_name = "Capture",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = WM8731_RATES,
|
||||
.formats = WM8731_FORMATS,},
|
||||
/* pcm operations - see section 4 below */
|
||||
.ops = {
|
||||
.prepare = wm8731_pcm_prepare,
|
||||
.hw_params = wm8731_hw_params,
|
||||
.shutdown = wm8731_shutdown,
|
||||
},
|
||||
/* DAI operations - see DAI.txt */
|
||||
.dai_ops = {
|
||||
.digital_mute = wm8731_mute,
|
||||
.set_sysclk = wm8731_set_dai_sysclk,
|
||||
.set_fmt = wm8731_set_dai_fmt,
|
||||
}
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(wm8731_dai);
|
||||
|
||||
|
||||
2 - Codec control IO
|
||||
--------------------
|
||||
The codec can ususally be controlled via an I2C or SPI style interface (AC97
|
||||
combines control with data in the DAI). The codec drivers will have to provide
|
||||
functions to read and write the codec registers along with supplying a register
|
||||
cache:-
|
||||
|
||||
/* IO control data and register cache */
|
||||
void *control_data; /* codec control (i2c/3wire) data */
|
||||
void *reg_cache;
|
||||
|
||||
Codec read/write should do any data formatting and call the hardware read write
|
||||
below to perform the IO. These functions are called by the core and alsa when
|
||||
performing DAPM or changing the mixer:-
|
||||
|
||||
unsigned int (*read)(struct snd_soc_codec *, unsigned int);
|
||||
int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
|
||||
|
||||
Codec hardware IO functions - usually points to either the I2C, SPI or AC97
|
||||
read/write:-
|
||||
|
||||
hw_write_t hw_write;
|
||||
hw_read_t hw_read;
|
||||
|
||||
|
||||
3 - Mixers and audio controls
|
||||
-----------------------------
|
||||
All the codec mixers and audio controls can be defined using the convenience
|
||||
macros defined in soc.h.
|
||||
|
||||
#define SOC_SINGLE(xname, reg, shift, mask, invert)
|
||||
|
||||
Defines a single control as follows:-
|
||||
|
||||
xname = Control name e.g. "Playback Volume"
|
||||
reg = codec register
|
||||
shift = control bit(s) offset in register
|
||||
mask = control bit size(s) e.g. mask of 7 = 3 bits
|
||||
invert = the control is inverted
|
||||
|
||||
Other macros include:-
|
||||
|
||||
#define SOC_DOUBLE(xname, reg, shift_left, shift_right, mask, invert)
|
||||
|
||||
A stereo control
|
||||
|
||||
#define SOC_DOUBLE_R(xname, reg_left, reg_right, shift, mask, invert)
|
||||
|
||||
A stereo control spanning 2 registers
|
||||
|
||||
#define SOC_ENUM_SINGLE(xreg, xshift, xmask, xtexts)
|
||||
|
||||
Defines an single enumerated control as follows:-
|
||||
|
||||
xreg = register
|
||||
xshift = control bit(s) offset in register
|
||||
xmask = control bit(s) size
|
||||
xtexts = pointer to array of strings that describe each setting
|
||||
|
||||
#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts)
|
||||
|
||||
Defines a stereo enumerated control
|
||||
|
||||
|
||||
4 - Codec Audio Operations
|
||||
--------------------------
|
||||
The codec driver also supports the following alsa operations:-
|
||||
|
||||
/* SoC audio ops */
|
||||
struct snd_soc_ops {
|
||||
int (*startup)(struct snd_pcm_substream *);
|
||||
void (*shutdown)(struct snd_pcm_substream *);
|
||||
int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *);
|
||||
int (*hw_free)(struct snd_pcm_substream *);
|
||||
int (*prepare)(struct snd_pcm_substream *);
|
||||
};
|
||||
|
||||
Please refer to the alsa driver PCM documentation for details.
|
||||
http://www.alsa-project.org/~iwai/writing-an-alsa-driver/c436.htm
|
||||
|
||||
|
||||
5 - DAPM description.
|
||||
---------------------
|
||||
The Dynamic Audio Power Management description describes the codec's power
|
||||
components, their relationships and registers to the ASoC core. Please read
|
||||
dapm.txt for details of building the description.
|
||||
|
||||
Please also see the examples in other codec drivers.
|
||||
|
||||
|
||||
6 - DAPM event handler
|
||||
----------------------
|
||||
This function is a callback that handles codec domain PM calls and system
|
||||
domain PM calls (e.g. suspend and resume). It's used to put the codec to sleep
|
||||
when not in use.
|
||||
|
||||
Power states:-
|
||||
|
||||
SNDRV_CTL_POWER_D0: /* full On */
|
||||
/* vref/mid, clk and osc on, active */
|
||||
|
||||
SNDRV_CTL_POWER_D1: /* partial On */
|
||||
SNDRV_CTL_POWER_D2: /* partial On */
|
||||
|
||||
SNDRV_CTL_POWER_D3hot: /* Off, with power */
|
||||
/* everything off except vref/vmid, inactive */
|
||||
|
||||
SNDRV_CTL_POWER_D3cold: /* Everything Off, without power */
|
||||
|
||||
|
||||
7 - Codec DAC digital mute control.
|
||||
------------------------------------
|
||||
Most codecs have a digital mute before the DAC's that can be used to minimise
|
||||
any system noise. The mute stops any digital data from entering the DAC.
|
||||
|
||||
A callback can be created that is called by the core for each codec DAI when the
|
||||
mute is applied or freed.
|
||||
|
||||
i.e.
|
||||
|
||||
static int wm8974_mute(struct snd_soc_codec *codec,
|
||||
struct snd_soc_codec_dai *dai, int mute)
|
||||
{
|
||||
u16 mute_reg = wm8974_read_reg_cache(codec, WM8974_DAC) & 0xffbf;
|
||||
if(mute)
|
||||
wm8974_write(codec, WM8974_DAC, mute_reg | 0x40);
|
||||
else
|
||||
wm8974_write(codec, WM8974_DAC, mute_reg);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,297 @@
|
||||
Dynamic Audio Power Management for Portable Devices
|
||||
===================================================
|
||||
|
||||
1. Description
|
||||
==============
|
||||
|
||||
Dynamic Audio Power Management (DAPM) is designed to allow portable Linux devices
|
||||
to use the minimum amount of power within the audio subsystem at all times. It
|
||||
is independent of other kernel PM and as such, can easily co-exist with the
|
||||
other PM systems.
|
||||
|
||||
DAPM is also completely transparent to all user space applications as all power
|
||||
switching is done within the ASoC core. No code changes or recompiling are
|
||||
required for user space applications. DAPM makes power switching descisions based
|
||||
upon any audio stream (capture/playback) activity and audio mixer settings
|
||||
within the device.
|
||||
|
||||
DAPM spans the whole machine. It covers power control within the entire audio
|
||||
subsystem, this includes internal codec power blocks and machine level power
|
||||
systems.
|
||||
|
||||
There are 4 power domains within DAPM
|
||||
|
||||
1. Codec domain - VREF, VMID (core codec and audio power)
|
||||
Usually controlled at codec probe/remove and suspend/resume, although
|
||||
can be set at stream time if power is not needed for sidetone, etc.
|
||||
|
||||
2. Platform/Machine domain - physically connected inputs and outputs
|
||||
Is platform/machine and user action specific, is configured by the
|
||||
machine driver and responds to asynchronous events e.g when HP
|
||||
are inserted
|
||||
|
||||
3. Path domain - audio susbsystem signal paths
|
||||
Automatically set when mixer and mux settings are changed by the user.
|
||||
e.g. alsamixer, amixer.
|
||||
|
||||
4. Stream domain - DAC's and ADC's.
|
||||
Enabled and disabled when stream playback/capture is started and
|
||||
stopped respectively. e.g. aplay, arecord.
|
||||
|
||||
All DAPM power switching descisons are made automatically by consulting an audio
|
||||
routing map of the whole machine. This map is specific to each machine and
|
||||
consists of the interconnections between every audio component (including
|
||||
internal codec components). All audio components that effect power are called
|
||||
widgets hereafter.
|
||||
|
||||
|
||||
2. DAPM Widgets
|
||||
===============
|
||||
|
||||
Audio DAPM widgets fall into a number of types:-
|
||||
|
||||
o Mixer - Mixes several analog signals into a single analog signal.
|
||||
o Mux - An analog switch that outputs only 1 of it's inputs.
|
||||
o PGA - A programmable gain amplifier or attenuation widget.
|
||||
o ADC - Analog to Digital Converter
|
||||
o DAC - Digital to Analog Converter
|
||||
o Switch - An analog switch
|
||||
o Input - A codec input pin
|
||||
o Output - A codec output pin
|
||||
o Headphone - Headphone (and optional Jack)
|
||||
o Mic - Mic (and optional Jack)
|
||||
o Line - Line Input/Output (and optional Jack)
|
||||
o Speaker - Speaker
|
||||
o Pre - Special PRE widget (exec before all others)
|
||||
o Post - Special POST widget (exec after all others)
|
||||
|
||||
(Widgets are defined in include/sound/soc-dapm.h)
|
||||
|
||||
Widgets are usually added in the codec driver and the machine driver. There are
|
||||
convience macros defined in soc-dapm.h that can be used to quickly build a
|
||||
list of widgets of the codecs and machines DAPM widgets.
|
||||
|
||||
Most widgets have a name, register, shift and invert. Some widgets have extra
|
||||
parameters for stream name and kcontrols.
|
||||
|
||||
|
||||
2.1 Stream Domain Widgets
|
||||
-------------------------
|
||||
|
||||
Stream Widgets relate to the stream power domain and only consist of ADC's
|
||||
(analog to digital converters) and DAC's (digital to analog converters).
|
||||
|
||||
Stream widgets have the following format:-
|
||||
|
||||
SND_SOC_DAPM_DAC(name, stream name, reg, shift, invert),
|
||||
|
||||
NOTE: the stream name must match the corresponding stream name in your codecs
|
||||
snd_soc_codec_dai.
|
||||
|
||||
e.g. stream widgets for HiFi playback and capture
|
||||
|
||||
SND_SOC_DAPM_DAC("HiFi DAC", "HiFi Playback", REG, 3, 1),
|
||||
SND_SOC_DAPM_ADC("HiFi ADC", "HiFi Capture", REG, 2, 1),
|
||||
|
||||
|
||||
2.2 Path Domain Widgets
|
||||
-----------------------
|
||||
|
||||
Path domain widgets have a ability to control or effect the audio signal or
|
||||
audio paths within the audio subsystem. They have the following form:-
|
||||
|
||||
SND_SOC_DAPM_PGA(name, reg, shift, invert, controls, num_controls)
|
||||
|
||||
Any widget kcontrols can be set using the controls and num_controls members.
|
||||
|
||||
e.g. Mixer widget (the kcontrols are declared first)
|
||||
|
||||
/* Output Mixer */
|
||||
static const snd_kcontrol_new_t wm8731_output_mixer_controls[] = {
|
||||
SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0),
|
||||
SOC_DAPM_SINGLE("Mic Sidetone Switch", WM8731_APANA, 5, 1, 0),
|
||||
SOC_DAPM_SINGLE("HiFi Playback Switch", WM8731_APANA, 4, 1, 0),
|
||||
};
|
||||
|
||||
SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, wm8731_output_mixer_controls,
|
||||
ARRAY_SIZE(wm8731_output_mixer_controls)),
|
||||
|
||||
|
||||
2.3 Platform/Machine domain Widgets
|
||||
-----------------------------------
|
||||
|
||||
Machine widgets are different from codec widgets in that they don't have a
|
||||
codec register bit associated with them. A machine widget is assigned to each
|
||||
machine audio component (non codec) that can be independently powered. e.g.
|
||||
|
||||
o Speaker Amp
|
||||
o Microphone Bias
|
||||
o Jack connectors
|
||||
|
||||
A machine widget can have an optional call back.
|
||||
|
||||
e.g. Jack connector widget for an external Mic that enables Mic Bias
|
||||
when the Mic is inserted:-
|
||||
|
||||
static int spitz_mic_bias(struct snd_soc_dapm_widget* w, int event)
|
||||
{
|
||||
if(SND_SOC_DAPM_EVENT_ON(event))
|
||||
set_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_MIC_BIAS);
|
||||
else
|
||||
reset_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_MIC_BIAS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SND_SOC_DAPM_MIC("Mic Jack", spitz_mic_bias),
|
||||
|
||||
|
||||
2.4 Codec Domain
|
||||
----------------
|
||||
|
||||
The Codec power domain has no widgets and is handled by the codecs DAPM event
|
||||
handler. This handler is called when the codec powerstate is changed wrt to any
|
||||
stream event or by kernel PM events.
|
||||
|
||||
|
||||
2.5 Virtual Widgets
|
||||
-------------------
|
||||
|
||||
Sometimes widgets exist in the codec or machine audio map that don't have any
|
||||
corresponding register bit for power control. In this case it's necessary to
|
||||
create a virtual widget - a widget with no control bits e.g.
|
||||
|
||||
SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_DAPM_NOPM, 0, 0, NULL, 0),
|
||||
|
||||
This can be used to merge to signal paths together in software.
|
||||
|
||||
After all the widgets have been defined, they can then be added to the DAPM
|
||||
subsystem individually with a call to snd_soc_dapm_new_control().
|
||||
|
||||
|
||||
3. Codec Widget Interconnections
|
||||
================================
|
||||
|
||||
Widgets are connected to each other within the codec and machine by audio
|
||||
paths (called interconnections). Each interconnection must be defined in order
|
||||
to create a map of all audio paths between widgets.
|
||||
This is easiest with a diagram of the codec (and schematic of the machine audio
|
||||
system), as it requires joining widgets together via their audio signal paths.
|
||||
|
||||
i.e. from the WM8731 codec's output mixer (wm8731.c)
|
||||
|
||||
The WM8731 output mixer has 3 inputs (sources)
|
||||
|
||||
1. Line Bypass Input
|
||||
2. DAC (HiFi playback)
|
||||
3. Mic Sidetone Input
|
||||
|
||||
Each input in this example has a kcontrol associated with it (defined in example
|
||||
above) and is connected to the output mixer via it's kcontrol name. We can now
|
||||
connect the destination widget (wrt audio signal) with it's source widgets.
|
||||
|
||||
/* output mixer */
|
||||
{"Output Mixer", "Line Bypass Switch", "Line Input"},
|
||||
{"Output Mixer", "HiFi Playback Switch", "DAC"},
|
||||
{"Output Mixer", "Mic Sidetone Switch", "Mic Bias"},
|
||||
|
||||
So we have :-
|
||||
|
||||
Destination Widget <=== Path Name <=== Source Widget
|
||||
|
||||
Or:-
|
||||
|
||||
Sink, Path, Source
|
||||
|
||||
Or :-
|
||||
|
||||
"Output Mixer" is connected to the "DAC" via the "HiFi Playback Switch".
|
||||
|
||||
When there is no path name connecting widgets (e.g. a direct connection) we
|
||||
pass NULL for the path name.
|
||||
|
||||
Interconnections are created with a call to:-
|
||||
|
||||
snd_soc_dapm_connect_input(codec, sink, path, source);
|
||||
|
||||
Finally, snd_soc_dapm_new_widgets(codec) must be called after all widgets and
|
||||
interconnections have been registered with the core. This causes the core to
|
||||
scan the codec and machine so that the internal DAPM state matches the
|
||||
physical state of the machine.
|
||||
|
||||
|
||||
3.1 Machine Widget Interconnections
|
||||
-----------------------------------
|
||||
Machine widget interconnections are created in the same way as codec ones and
|
||||
directly connect the codec pins to machine level widgets.
|
||||
|
||||
e.g. connects the speaker out codec pins to the internal speaker.
|
||||
|
||||
/* ext speaker connected to codec pins LOUT2, ROUT2 */
|
||||
{"Ext Spk", NULL , "ROUT2"},
|
||||
{"Ext Spk", NULL , "LOUT2"},
|
||||
|
||||
This allows the DAPM to power on and off pins that are connected (and in use)
|
||||
and pins that are NC respectively.
|
||||
|
||||
|
||||
4 Endpoint Widgets
|
||||
===================
|
||||
An endpoint is a start or end point (widget) of an audio signal within the
|
||||
machine and includes the codec. e.g.
|
||||
|
||||
o Headphone Jack
|
||||
o Internal Speaker
|
||||
o Internal Mic
|
||||
o Mic Jack
|
||||
o Codec Pins
|
||||
|
||||
When a codec pin is NC it can be marked as not used with a call to
|
||||
|
||||
snd_soc_dapm_set_endpoint(codec, "Widget Name", 0);
|
||||
|
||||
The last argument is 0 for inactive and 1 for active. This way the pin and its
|
||||
input widget will never be powered up and consume power.
|
||||
|
||||
This also applies to machine widgets. e.g. if a headphone is connected to a
|
||||
jack then the jack can be marked active. If the headphone is removed, then
|
||||
the headphone jack can be marked inactive.
|
||||
|
||||
|
||||
5 DAPM Widget Events
|
||||
====================
|
||||
|
||||
Some widgets can register their interest with the DAPM core in PM events.
|
||||
e.g. A Speaker with an amplifier registers a widget so the amplifier can be
|
||||
powered only when the spk is in use.
|
||||
|
||||
/* turn speaker amplifier on/off depending on use */
|
||||
static int corgi_amp_event(struct snd_soc_dapm_widget *w, int event)
|
||||
{
|
||||
if (SND_SOC_DAPM_EVENT_ON(event))
|
||||
set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON);
|
||||
else
|
||||
reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* corgi machine dapm widgets */
|
||||
static const struct snd_soc_dapm_widget wm8731_dapm_widgets =
|
||||
SND_SOC_DAPM_SPK("Ext Spk", corgi_amp_event);
|
||||
|
||||
Please see soc-dapm.h for all other widgets that support events.
|
||||
|
||||
|
||||
5.1 Event types
|
||||
---------------
|
||||
|
||||
The following event types are supported by event widgets.
|
||||
|
||||
/* dapm event types */
|
||||
#define SND_SOC_DAPM_PRE_PMU 0x1 /* before widget power up */
|
||||
#define SND_SOC_DAPM_POST_PMU 0x2 /* after widget power up */
|
||||
#define SND_SOC_DAPM_PRE_PMD 0x4 /* before widget power down */
|
||||
#define SND_SOC_DAPM_POST_PMD 0x8 /* after widget power down */
|
||||
#define SND_SOC_DAPM_PRE_REG 0x10 /* before audio path setup */
|
||||
#define SND_SOC_DAPM_POST_REG 0x20 /* after audio path setup */
|
||||
@@ -0,0 +1,113 @@
|
||||
ASoC Machine Driver
|
||||
===================
|
||||
|
||||
The ASoC machine (or board) driver is the code that glues together the platform
|
||||
and codec drivers.
|
||||
|
||||
The machine driver can contain codec and platform specific code. It registers
|
||||
the audio subsystem with the kernel as a platform device and is represented by
|
||||
the following struct:-
|
||||
|
||||
/* SoC machine */
|
||||
struct snd_soc_machine {
|
||||
char *name;
|
||||
|
||||
int (*probe)(struct platform_device *pdev);
|
||||
int (*remove)(struct platform_device *pdev);
|
||||
|
||||
/* the pre and post PM functions are used to do any PM work before and
|
||||
* after the codec and DAI's do any PM work. */
|
||||
int (*suspend_pre)(struct platform_device *pdev, pm_message_t state);
|
||||
int (*suspend_post)(struct platform_device *pdev, pm_message_t state);
|
||||
int (*resume_pre)(struct platform_device *pdev);
|
||||
int (*resume_post)(struct platform_device *pdev);
|
||||
|
||||
/* machine stream operations */
|
||||
struct snd_soc_ops *ops;
|
||||
|
||||
/* CPU <--> Codec DAI links */
|
||||
struct snd_soc_dai_link *dai_link;
|
||||
int num_links;
|
||||
};
|
||||
|
||||
probe()/remove()
|
||||
----------------
|
||||
probe/remove are optional. Do any machine specific probe here.
|
||||
|
||||
|
||||
suspend()/resume()
|
||||
------------------
|
||||
The machine driver has pre and post versions of suspend and resume to take care
|
||||
of any machine audio tasks that have to be done before or after the codec, DAI's
|
||||
and DMA is suspended and resumed. Optional.
|
||||
|
||||
|
||||
Machine operations
|
||||
------------------
|
||||
The machine specific audio operations can be set here. Again this is optional.
|
||||
|
||||
|
||||
Machine DAI Configuration
|
||||
-------------------------
|
||||
The machine DAI configuration glues all the codec and CPU DAI's together. It can
|
||||
also be used to set up the DAI system clock and for any machine related DAI
|
||||
initialisation e.g. the machine audio map can be connected to the codec audio
|
||||
map, unconnnected codec pins can be set as such. Please see corgi.c, spitz.c
|
||||
for examples.
|
||||
|
||||
struct snd_soc_dai_link is used to set up each DAI in your machine. e.g.
|
||||
|
||||
/* corgi digital audio interface glue - connects codec <--> CPU */
|
||||
static struct snd_soc_dai_link corgi_dai = {
|
||||
.name = "WM8731",
|
||||
.stream_name = "WM8731",
|
||||
.cpu_dai = &pxa_i2s_dai,
|
||||
.codec_dai = &wm8731_dai,
|
||||
.init = corgi_wm8731_init,
|
||||
.ops = &corgi_ops,
|
||||
};
|
||||
|
||||
struct snd_soc_machine then sets up the machine with it's DAI's. e.g.
|
||||
|
||||
/* corgi audio machine driver */
|
||||
static struct snd_soc_machine snd_soc_machine_corgi = {
|
||||
.name = "Corgi",
|
||||
.dai_link = &corgi_dai,
|
||||
.num_links = 1,
|
||||
};
|
||||
|
||||
|
||||
Machine Audio Subsystem
|
||||
-----------------------
|
||||
|
||||
The machine soc device glues the platform, machine and codec driver together.
|
||||
Private data can also be set here. e.g.
|
||||
|
||||
/* corgi audio private data */
|
||||
static struct wm8731_setup_data corgi_wm8731_setup = {
|
||||
.i2c_address = 0x1b,
|
||||
};
|
||||
|
||||
/* corgi audio subsystem */
|
||||
static struct snd_soc_device corgi_snd_devdata = {
|
||||
.machine = &snd_soc_machine_corgi,
|
||||
.platform = &pxa2xx_soc_platform,
|
||||
.codec_dev = &soc_codec_dev_wm8731,
|
||||
.codec_data = &corgi_wm8731_setup,
|
||||
};
|
||||
|
||||
|
||||
Machine Power Map
|
||||
-----------------
|
||||
|
||||
The machine driver can optionally extend the codec power map and to become an
|
||||
audio power map of the audio subsystem. This allows for automatic power up/down
|
||||
of speaker/HP amplifiers, etc. Codec pins can be connected to the machines jack
|
||||
sockets in the machine init function. See soc/pxa/spitz.c and dapm.txt for
|
||||
details.
|
||||
|
||||
|
||||
Machine Controls
|
||||
----------------
|
||||
|
||||
Machine specific audio mixer controls can be added in the dai init function.
|
||||
@@ -0,0 +1,83 @@
|
||||
ALSA SoC Layer
|
||||
==============
|
||||
|
||||
The overall project goal of the ALSA System on Chip (ASoC) layer is to provide
|
||||
better ALSA support for embedded system on chip procesors (e.g. pxa2xx, au1x00,
|
||||
iMX, etc) and portable audio codecs. Currently there is some support in the
|
||||
kernel for SoC audio, however it has some limitations:-
|
||||
|
||||
* Currently, codec drivers are often tightly coupled to the underlying SoC
|
||||
cpu. This is not ideal and leads to code duplication i.e. Linux now has 4
|
||||
different wm8731 drivers for 4 different SoC platforms.
|
||||
|
||||
* There is no standard method to signal user initiated audio events.
|
||||
e.g. Headphone/Mic insertion, Headphone/Mic detection after an insertion
|
||||
event. These are quite common events on portable devices and ofter require
|
||||
machine specific code to re route audio, enable amps etc after such an event.
|
||||
|
||||
* Current drivers tend to power up the entire codec when playing
|
||||
(or recording) audio. This is fine for a PC, but tends to waste a lot of
|
||||
power on portable devices. There is also no support for saving power via
|
||||
changing codec oversampling rates, bias currents, etc.
|
||||
|
||||
|
||||
ASoC Design
|
||||
===========
|
||||
|
||||
The ASoC layer is designed to address these issues and provide the following
|
||||
features :-
|
||||
|
||||
* Codec independence. Allows reuse of codec drivers on other platforms
|
||||
and machines.
|
||||
|
||||
* Easy I2S/PCM audio interface setup between codec and SoC. Each SoC interface
|
||||
and codec registers it's audio interface capabilities with the core and are
|
||||
subsequently matched and configured when the application hw params are known.
|
||||
|
||||
* Dynamic Audio Power Management (DAPM). DAPM automatically sets the codec to
|
||||
it's minimum power state at all times. This includes powering up/down
|
||||
internal power blocks depending on the internal codec audio routing and any
|
||||
active streams.
|
||||
|
||||
* Pop and click reduction. Pops and clicks can be reduced by powering the
|
||||
codec up/down in the correct sequence (including using digital mute). ASoC
|
||||
signals the codec when to change power states.
|
||||
|
||||
* Machine specific controls: Allow machines to add controls to the sound card
|
||||
e.g. volume control for speaker amp.
|
||||
|
||||
To achieve all this, ASoC basically splits an embedded audio system into 3
|
||||
components :-
|
||||
|
||||
* Codec driver: The codec driver is platform independent and contains audio
|
||||
controls, audio interface capabilities, codec dapm definition and codec IO
|
||||
functions.
|
||||
|
||||
* Platform driver: The platform driver contains the audio dma engine and audio
|
||||
interface drivers (e.g. I2S, AC97, PCM) for that platform.
|
||||
|
||||
* Machine driver: The machine driver handles any machine specific controls and
|
||||
audio events. i.e. turing on an amp at start of playback.
|
||||
|
||||
|
||||
Documentation
|
||||
=============
|
||||
|
||||
The documentation is spilt into the following sections:-
|
||||
|
||||
overview.txt: This file.
|
||||
|
||||
codec.txt: Codec driver internals.
|
||||
|
||||
DAI.txt: Description of Digital Audio Interface standards and how to configure
|
||||
a DAI within your codec and CPU DAI drivers.
|
||||
|
||||
dapm.txt: Dynamic Audio Power Management
|
||||
|
||||
platform.txt: Platform audio DMA and DAI.
|
||||
|
||||
machine.txt: Machine driver internals.
|
||||
|
||||
pop_clicks.txt: How to minimise audio artifacts.
|
||||
|
||||
clocking.txt: ASoC clocking for best power performance.
|
||||
@@ -0,0 +1,58 @@
|
||||
ASoC Platform Driver
|
||||
====================
|
||||
|
||||
An ASoC platform driver can be divided into audio DMA and SoC DAI configuration
|
||||
and control. The platform drivers only target the SoC CPU and must have no board
|
||||
specific code.
|
||||
|
||||
Audio DMA
|
||||
=========
|
||||
|
||||
The platform DMA driver optionally supports the following alsa operations:-
|
||||
|
||||
/* SoC audio ops */
|
||||
struct snd_soc_ops {
|
||||
int (*startup)(struct snd_pcm_substream *);
|
||||
void (*shutdown)(struct snd_pcm_substream *);
|
||||
int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *);
|
||||
int (*hw_free)(struct snd_pcm_substream *);
|
||||
int (*prepare)(struct snd_pcm_substream *);
|
||||
int (*trigger)(struct snd_pcm_substream *, int);
|
||||
};
|
||||
|
||||
The platform driver exports it's DMA functionailty via struct snd_soc_platform:-
|
||||
|
||||
struct snd_soc_platform {
|
||||
char *name;
|
||||
|
||||
int (*probe)(struct platform_device *pdev);
|
||||
int (*remove)(struct platform_device *pdev);
|
||||
int (*suspend)(struct platform_device *pdev, struct snd_soc_cpu_dai *cpu_dai);
|
||||
int (*resume)(struct platform_device *pdev, struct snd_soc_cpu_dai *cpu_dai);
|
||||
|
||||
/* pcm creation and destruction */
|
||||
int (*pcm_new)(struct snd_card *, struct snd_soc_codec_dai *, struct snd_pcm *);
|
||||
void (*pcm_free)(struct snd_pcm *);
|
||||
|
||||
/* platform stream ops */
|
||||
struct snd_pcm_ops *pcm_ops;
|
||||
};
|
||||
|
||||
Please refer to the alsa driver documentation for details of audio DMA.
|
||||
http://www.alsa-project.org/~iwai/writing-an-alsa-driver/c436.htm
|
||||
|
||||
An example DMA driver is soc/pxa/pxa2xx-pcm.c
|
||||
|
||||
|
||||
SoC DAI Drivers
|
||||
===============
|
||||
|
||||
Each SoC DAI driver must provide the following features:-
|
||||
|
||||
1) Digital audio interface (DAI) description
|
||||
2) Digital audio interface configuration
|
||||
3) PCM's description
|
||||
4) Sysclk configuration
|
||||
5) Suspend and resume (optional)
|
||||
|
||||
Please see codec.txt for a description of items 1 - 4.
|
||||
@@ -0,0 +1,52 @@
|
||||
Audio Pops and Clicks
|
||||
=====================
|
||||
|
||||
Pops and clicks are unwanted audio artifacts caused by the powering up and down
|
||||
of components within the audio subsystem. This is noticable on PC's when an
|
||||
audio module is either loaded or unloaded (at module load time the sound card is
|
||||
powered up and causes a popping noise on the speakers).
|
||||
|
||||
Pops and clicks can be more frequent on portable systems with DAPM. This is
|
||||
because the components within the subsystem are being dynamically powered
|
||||
depending on the audio usage and this can subsequently cause a small pop or
|
||||
click every time a component power state is changed.
|
||||
|
||||
|
||||
Minimising Playback Pops and Clicks
|
||||
===================================
|
||||
|
||||
Playback pops in portable audio subsystems cannot be completely eliminated atm,
|
||||
however future audio codec hardware will have better pop and click supression.
|
||||
Pops can be reduced within playback by powering the audio components in a
|
||||
specific order. This order is different for startup and shutdown and follows
|
||||
some basic rules:-
|
||||
|
||||
Startup Order :- DAC --> Mixers --> Output PGA --> Digital Unmute
|
||||
|
||||
Shutdown Order :- Digital Mute --> Output PGA --> Mixers --> DAC
|
||||
|
||||
This assumes that the codec PCM output path from the DAC is via a mixer and then
|
||||
a PGA (programmable gain amplifier) before being output to the speakers.
|
||||
|
||||
|
||||
Minimising Capture Pops and Clicks
|
||||
==================================
|
||||
|
||||
Capture artifacts are somewhat easier to get rid as we can delay activating the
|
||||
ADC until all the pops have occured. This follows similar power rules to
|
||||
playback in that components are powered in a sequence depending upon stream
|
||||
startup or shutdown.
|
||||
|
||||
Startup Order - Input PGA --> Mixers --> ADC
|
||||
|
||||
Shutdown Order - ADC --> Mixers --> Input PGA
|
||||
|
||||
|
||||
Zipper Noise
|
||||
============
|
||||
An unwanted zipper noise can occur within the audio playback or capture stream
|
||||
when a volume control is changed near its maximum gain value. The zipper noise
|
||||
is heard when the gain increase or decrease changes the mean audio signal
|
||||
amplitude too quickly. It can be minimised by enabling the zero cross setting
|
||||
for each volume control. The ZC forces the gain change to occur when the signal
|
||||
crosses the zero amplitude line.
|
||||
@@ -3037,6 +3037,12 @@ M: perex@suse.cz
|
||||
L: alsa-devel@alsa-project.org
|
||||
S: Maintained
|
||||
|
||||
SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT
|
||||
P: Liam Girdwood
|
||||
M: liam.girdwood@wolfsonmicro.com
|
||||
L: alsa-devel@alsa-project.org
|
||||
S: Supported
|
||||
|
||||
SPI SUBSYSTEM
|
||||
P: David Brownell
|
||||
M: dbrownell@users.sourceforge.net
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
|
||||
|
||||
struct ucb1400 {
|
||||
ac97_t *ac97;
|
||||
struct snd_ac97 *ac97;
|
||||
struct input_dev *ts_idev;
|
||||
|
||||
int irq;
|
||||
|
||||
@@ -115,6 +115,8 @@
|
||||
#define I2C_DRIVERID_KS0127 86 /* Samsung ks0127 video decoder */
|
||||
#define I2C_DRIVERID_TLV320AIC23B 87 /* TI TLV320AIC23B audio codec */
|
||||
#define I2C_DRIVERID_ISL1208 88 /* Intersil ISL1208 RTC */
|
||||
#define I2C_DRIVERID_WM8731 89 /* Wolfson WM8731 audio codec */
|
||||
#define I2C_DRIVERID_WM8750 90 /* Wolfson WM8750 audio codec */
|
||||
|
||||
#define I2C_DRIVERID_I2CDEV 900
|
||||
#define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */
|
||||
|
||||
@@ -375,6 +375,7 @@
|
||||
#define AC97_SCAP_DETECT_BY_VENDOR (1<<8) /* use vendor registers for read tests */
|
||||
#define AC97_SCAP_NO_SPDIF (1<<9) /* don't build SPDIF controls */
|
||||
#define AC97_SCAP_EAPD_LED (1<<10) /* EAPD as mute LED */
|
||||
#define AC97_SCAP_POWER_SAVE (1<<11) /* capable for aggresive power-saving */
|
||||
|
||||
/* ac97->flags */
|
||||
#define AC97_HAS_PC_BEEP (1<<0) /* force PC Speaker usage */
|
||||
@@ -425,6 +426,7 @@ struct snd_ac97_build_ops {
|
||||
|
||||
struct snd_ac97_bus_ops {
|
||||
void (*reset) (struct snd_ac97 *ac97);
|
||||
void (*warm_reset)(struct snd_ac97 *ac97);
|
||||
void (*write) (struct snd_ac97 *ac97, unsigned short reg, unsigned short val);
|
||||
unsigned short (*read) (struct snd_ac97 *ac97, unsigned short reg);
|
||||
void (*wait) (struct snd_ac97 *ac97);
|
||||
@@ -501,6 +503,7 @@ struct snd_ac97 {
|
||||
unsigned short id[3]; // codec IDs (lower 16-bit word)
|
||||
unsigned short pcmreg[3]; // PCM registers
|
||||
unsigned short codec_cfg[3]; // CODEC_CFG bits
|
||||
unsigned char swap_mic_linein; // AD1986/AD1986A only
|
||||
} ad18xx;
|
||||
unsigned int dev_flags; /* device specific */
|
||||
} spec;
|
||||
@@ -510,7 +513,6 @@ struct snd_ac97 {
|
||||
|
||||
#ifdef CONFIG_SND_AC97_POWER_SAVE
|
||||
unsigned int power_up; /* power states */
|
||||
struct workqueue_struct *power_workq;
|
||||
struct delayed_work power_work;
|
||||
#endif
|
||||
struct device dev;
|
||||
|
||||
@@ -185,7 +185,7 @@ struct ad1848_mix_elem {
|
||||
int index;
|
||||
int type;
|
||||
unsigned long private_value;
|
||||
unsigned int *tlv;
|
||||
const unsigned int *tlv;
|
||||
};
|
||||
|
||||
#define AD1848_SINGLE(xname, xindex, reg, shift, mask, invert) \
|
||||
|
||||
@@ -181,7 +181,6 @@ struct ak4114 {
|
||||
unsigned long ccrc_errors;
|
||||
unsigned char rcs0;
|
||||
unsigned char rcs1;
|
||||
struct workqueue_struct *workqueue;
|
||||
struct delayed_work work;
|
||||
void *change_callback_private;
|
||||
void (*change_callback)(struct ak4114 *ak4114, unsigned char c0, unsigned char c1);
|
||||
@@ -189,7 +188,7 @@ struct ak4114 {
|
||||
|
||||
int snd_ak4114_create(struct snd_card *card,
|
||||
ak4114_read_t *read, ak4114_write_t *write,
|
||||
unsigned char pgm[7], unsigned char txcsb[5],
|
||||
const unsigned char pgm[7], const unsigned char txcsb[5],
|
||||
void *private_data, struct ak4114 **r_ak4114);
|
||||
void snd_ak4114_reg_write(struct ak4114 *ak4114, unsigned char reg, unsigned char mask, unsigned char val);
|
||||
void snd_ak4114_reinit(struct ak4114 *ak4114);
|
||||
|
||||
@@ -178,7 +178,7 @@ struct ak4117 {
|
||||
};
|
||||
|
||||
int snd_ak4117_create(struct snd_card *card, ak4117_read_t *read, ak4117_write_t *write,
|
||||
unsigned char pgm[5], void *private_data, struct ak4117 **r_ak4117);
|
||||
const unsigned char pgm[5], void *private_data, struct ak4117 **r_ak4117);
|
||||
void snd_ak4117_reg_write(struct ak4117 *ak4117, unsigned char reg, unsigned char mask, unsigned char val);
|
||||
void snd_ak4117_reinit(struct ak4117 *ak4117);
|
||||
int snd_ak4117_build(struct ak4117 *ak4117, struct snd_pcm_substream *capture_substream);
|
||||
|
||||
@@ -50,6 +50,8 @@ struct snd_akm4xxx_adc_channel {
|
||||
char *name; /* capture gain volume label */
|
||||
char *switch_name; /* capture switch */
|
||||
unsigned int num_channels;
|
||||
char *selector_name; /* capture source select label */
|
||||
const char **input_names; /* capture source names (NULL terminated) */
|
||||
};
|
||||
|
||||
struct snd_akm4xxx {
|
||||
@@ -69,8 +71,8 @@ struct snd_akm4xxx {
|
||||
} type;
|
||||
|
||||
/* (array) information of combined codecs */
|
||||
struct snd_akm4xxx_dac_channel *dac_info;
|
||||
struct snd_akm4xxx_adc_channel *adc_info;
|
||||
const struct snd_akm4xxx_dac_channel *dac_info;
|
||||
const struct snd_akm4xxx_adc_channel *adc_info;
|
||||
|
||||
struct snd_ak4xxx_ops ops;
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user