[Alsa Document]2, codec.txt

[Alsa Document]1, overall.txt的描述中我们了解到Alsa分为三部分,分别是:
<1> codec driver
<2> platform driver
<3> Machine driver

本篇来介绍codec driver
基于4.9.123版本内核 Documentation/sound/alsa/soc/codec.txt

ASoC Codec Class Driver
=======================

The codec class driver is generic and hardware independent code that configures
the codec, FM, MODEM, BT or external DSP 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.
编解码器类驱动程序是通用的,与硬件无关的代码,用于配置编解码器,FM,MODEM,BT或外部
DSP,以提供音频捕获和回放。 它不应包含特定于目标平台或计算机的代码。应将所有平台和机器
特定代码分别添加到平台和机器驱动程序中。

Each codec class driver *must* provide the following features:-
每个编解码器类驱动程序*必须*提供以下功能:

 1) Codec DAI and PCM configuration					Codec DAI和PCM的配置
 2) Codec control IO - using RegMap API				Codec 控制IO - 用寄存器Map的API	
 3) Mixers and audio controls						调音器和音频控制(基于图形界面)
 4) Codec audio operations							编解码器音频操作
 5) DAPM description.								DAPM描述
 6) DAPM event handler.								DAPM 事件句柄

Optionally, codec drivers can also provide:-
可选地,codec驱动也可以提偶刚下列功能:

 7) DAC Digital mute control.						DAC 数字静音控制

Its probably best to use this guide in conjunction with the existing codec
driver code in sound/soc/codecs/
最好将本指南与 sound/soc/codecs/ 中的现有编解码器驱动程序代码结合使用

ASoC Codec driver breakdown
===========================

1 - Codec DAI and PCM configuration
-----------------------------------
Each codec driver must have a struct snd_soc_dai_driver 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.
每个编解码器驱动程序必须具有struct snd_soc_dai_driver来定义其DAI和PCM功能和操作。 
导出此结构,以便机器驱动程序可以将其注册到核心。

e.g.

static struct snd_soc_dai_ops wm8731_dai_ops = {
  .prepare  = wm8731_pcm_prepare,
  .hw_params  = wm8731_hw_params,
  .shutdown = wm8731_shutdown,
  .digital_mute = wm8731_mute,
  .set_sysclk = wm8731_set_dai_sysclk,
  .set_fmt  = wm8731_set_dai_fmt,
};

struct snd_soc_dai_driver wm8731_dai = {
  .name = "wm8731-hifi",
  .playback = {
    .stream_name = "Playback",
    .channels_min = 1,
    .channels_max = 2,
    .rates = WM8731_RATES,
    .formats = WM8731_FORMATS,},
  .capture = {
    .stream_name = "Capture",
    .channels_min = 1,
    .channels_max = 2,
    .rates = WM8731_RATES,
    .formats = WM8731_FORMATS,
  },
  .ops = &wm8731_dai_ops,
  .symmetric_rates = 1,
};


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 driver should use the
Regmap API for all codec IO. Please see include/linux/regmap.h and existing
codec drivers for example regmap usage.
编解码器通常可以通过I2C或SPI样式接口进行控制(AC97将控制与DAI中的数据相结合)。 
编解码器驱动程序应该将Regmap API用于所有编解码器IO。 
请参阅include/linux/regmap.h和现有的编解码器驱动程序,例如regmap用法。

3 - Mixers and audio controls
-----------------------------
All the codec mixers and audio controls can be defined using the convenience
macros defined in soc.h.
所有编解码器混音器和音频控件都可以使用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:-
其它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
一个跨越2个寄存器的立体声控制

    #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 PCM operations:-
codec驱动也支持以下ALSA PCM操作: 

/* 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.
更多细节请参考ALSA 驱动的PCM文档。
http://www.alsa-project.org/~iwai/writing-an-alsa-driver/

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.txt for details of building the description.
动态音频电源管理简介描述了编解码器电源组件及其与ASoC内核的关系和寄存器。 
有关构建描述的详细信息,请阅读dapm.txt。

Please also see the examples in other codec drivers.
请参考其他codec驱动中的例子。

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.
此函数是处理编解码器域PM调用和系统域PM调用(例如,挂起和恢复)的回调。 
它用于在不使用时将编解码器置于休眠状态。

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.
大多数编解码器在DAC之前都具有数字静音,可用于最小化任何系统噪声。 
静音可以阻止任何数字数据进入DAC。

当静音开启或关闭时,可以为每个codec的DAI创建一个由核心调用的回调。

i.e.

static int wm8974_mute(struct snd_soc_dai *dai, int mute)
{
  struct snd_soc_codec *codec = dai->codec;
  u16 mute_reg = snd_soc_read(codec, WM8974_DAC) & 0xffbf;

  if (mute)
    snd_soc_write(codec, WM8974_DAC, mute_reg | 0x40);
  else
    snd_soc_write(codec, WM8974_DAC, mute_reg);
  return 0;
}

猜你喜欢

转载自blog.csdn.net/wangyijieonline/article/details/88114457