ubuntu 在 R40e 上 還有 Debian 在 Sempron 2600 上

2014年3月4日 星期二

sound soc codec driver reading notes..

http://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/tree/Documentation/sound/alsa/soc/DAI.txt?h=linux-3.0.y

DAI : Digital Audio Interface
I2S
===

 I2S is a common 4 wire DAI used in HiFi, STB and portable devices. The Tx and
Rx lines are used for audio transmission, 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 LRCLKs, this allows for simultaneous 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 BCLKs before LRC
                     transition.


http://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/tree/Documentation/sound/alsa/soc/machine.txt?h=linux-3.0.y

就是 board 的 driver, 聯繫 chip 的 i2s 和 外接的 codec.

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_name = "pxa-is2-dai",
 .codec_dai_name = "wm8731-hifi",
 .platform_name = "pxa-pcm-audio",
 .codec_name = "wm8713-codec.0-001a",
 .init = corgi_wm8731_init,
 .ops = &corgi_ops,
};

struct snd_soc_card then sets up the machine with its DAIs. e.g.

/* corgi audio machine driver */
static struct snd_soc_card snd_soc_corgi = {
 .name = "Corgi",
 .dai_link = &corgi_dai,
 .num_links = 1,
};

有關 I2S master/slave 的定義/操作..
http://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/tree/include/sound/soc-dai.h?h=linux-3.0.y#n66

/*
 * DAI hardware clock masters.
 *
 * This is wrt the codec, the inverse is true for the interface
 * i.e. if the codec is clk and FRM master then the interface is
 * clk and frame slave.
 */
#define SND_SOC_DAIFMT_CBM_CFM  (0 << 12) /* codec clk & FRM master */
#define SND_SOC_DAIFMT_CBS_CFM  (1 << 12) /* codec clk slave & FRM master */
#define SND_SOC_DAIFMT_CBM_CFS  (2 << 12) /* codec clk master & frame slave */
#define SND_SOC_DAIFMT_CBS_CFS  (3 << 12) /* codec clk & FRM slave */

有兩路
  • AIF1 : stereo
  • AIF2 : voice

可以使用各自的 clock source.

clock source 的選擇有:
  • MCLK : 就是 I2S 的 MCLK
  • PLL : 振盪器輸入,經由內部 PLL 倍頻
這個動作是由 set_dai_sysclk( ) 完成的。

這個也屬於alsa arch 標準 module interface 之一:
snd_soc_dai_ops 中的 set_sysclk:

struct snd_soc_dai_ops {
        /*
         * DAI clocking configuration, all optional.
         * Called by soc_card drivers, normally in their hw_params.
         */
        int (*set_sysclk)(struct snd_soc_dai *dai, int clk_id, unsigned int freq, int dir);
        int (*set_pll)(struct snd_soc_dai *dai, int pll_id, int source, unsigned int freq_in, unsigned int freq_out);
        int (*set_clkdiv)(struct snd_soc_dai *dai, int div_id, int div);

        /*
         * DAI format configuration
         * Called by soc_card drivers, normally in their hw_params.
         */
        int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt);
        int (*set_tdm_slot)(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width);
        int (*set_channel_map)(struct snd_soc_dai *dai, unsigned int tx_num, unsigned int *tx_slot, unsigned int rx_num, unsigned int *rx_slot);
        int (*set_tristate)(struct snd_soc_dai *dai, int tristate);

        /*
         * DAI digital mute - optional.
         * Called by soc-core to minimise any pops.
         */
        int (*digital_mute)(struct snd_soc_dai *dai, int mute);

        /*
         * ALSA PCM audio operations - all optional.
         * Called by soc-core during audio PCM operations.
         */
        int (*startup)(struct snd_pcm_substream *, struct snd_soc_dai *);
        void (*shutdown)(struct snd_pcm_substream *, struct snd_soc_dai *);
        int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *, struct snd_soc_dai *);
        int (*hw_free)(struct snd_pcm_substream *, struct snd_soc_dai *);
        int (*prepare)(struct snd_pcm_substream *, struct snd_soc_dai *);
        int (*trigger)(struct snd_pcm_substream *, int, struct snd_soc_dai *);
        /*
         * For hardware based FIFO caused delay reporting.
         * Optional.
         */
        snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *, struct snd_soc_dai *);
};
structure 間的關係
snd_soc_card
   |
   + dai_link --- snd_soc_dai_link
                     |
                     + ops ---------------- snd_soc_ops
                     |                         |
                     |                         + hw_params
                     + stream name
                     |
                     + cpu dai name
                     |
                     + codec dai name
                     |
                     + codec name
                     |
                     + platform name

沒有留言:

標籤

網誌存檔