Alsa SoC Audio(part 1)

 

1.Overview
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 processors (e.g. pxa2xx, au1x00, iMX, etc) and portable audio codecs. Prior to the ASoC subsystem there was some support in the kernel for SoC audio, however it had some limitations:-

   * Codec drivers were often tightly coupled to the underlying SoC
     CPU. This is not ideal and leads to code duplication - for example,
     Linux had different wm8731 drivers for 4 different SoC platforms.

   * There was 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 often require
     machine specific code to re-route audio, enable amps, etc., after such an
     event.

   * Drivers tended 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 was 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
     hardware parameters are known.

   * Dynamic Audio Power Management (DAPM). DAPM automatically sets the codec to
     its 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 amplifier).

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 (e.g. turning on an amp at start of playback).


2.Codec
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 APIs
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.

Its probably best to use this guide in conjunction 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 its DAI and PCM capabilities 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 usually be controlled via an I2C or SPI style interface (AC97 combines control with data in the DAI). The codec drivers 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 power components and their relationships and registers to the ASoC core.
Please read dapm part.
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 is 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 DACs 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;
}


3 DAI
ASoC currently supports the three main Digital Audio Interfaces (DAI) found on SoC controllers and portable audio CODECs today, namely AC97, I2S and PCM.                       
Please see http://hi.baidu.com/zhlg_hzh/blog/item/6f6651c8144e5e107e3e6f19.html
                          
                          
4 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 DAIs 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, DAIs
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 DAIs 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, unconnected 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 DAIs. 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.
                                                                                 
                                                                                 
5 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 its DMA functionality 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.

你可能感兴趣的:(struct,documentation,interface,audio,Codec,playback)