162306a36Sopenharmony_ci=======================
262306a36Sopenharmony_ciASoC Codec Class Driver
362306a36Sopenharmony_ci=======================
462306a36Sopenharmony_ci
562306a36Sopenharmony_ciThe codec class driver is generic and hardware independent code that configures
662306a36Sopenharmony_cithe codec, FM, MODEM, BT or external DSP to provide audio capture and playback.
762306a36Sopenharmony_ciIt should contain no code that is specific to the target platform or machine.
862306a36Sopenharmony_ciAll platform and machine specific code should be added to the platform and
962306a36Sopenharmony_cimachine drivers respectively.
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ciEach codec class driver *must* provide the following features:-
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci1. Codec DAI and PCM configuration
1462306a36Sopenharmony_ci2. Codec control IO - using RegMap API
1562306a36Sopenharmony_ci3. Mixers and audio controls
1662306a36Sopenharmony_ci4. Codec audio operations
1762306a36Sopenharmony_ci5. DAPM description.
1862306a36Sopenharmony_ci6. DAPM event handler.
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ciOptionally, codec drivers can also provide:-
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci7. DAC Digital mute control.
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ciIts probably best to use this guide in conjunction with the existing codec
2562306a36Sopenharmony_cidriver code in sound/soc/codecs/
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ciASoC Codec driver breakdown
2862306a36Sopenharmony_ci===========================
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ciCodec DAI and PCM configuration
3162306a36Sopenharmony_ci-------------------------------
3262306a36Sopenharmony_ciEach codec driver must have a struct snd_soc_dai_driver to define its DAI and
3362306a36Sopenharmony_ciPCM capabilities and operations. This struct is exported so that it can be
3462306a36Sopenharmony_ciregistered with the core by your machine driver.
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_cie.g.
3762306a36Sopenharmony_ci::
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci  static struct snd_soc_dai_ops wm8731_dai_ops = {
4062306a36Sopenharmony_ci	.prepare	= wm8731_pcm_prepare,
4162306a36Sopenharmony_ci	.hw_params	= wm8731_hw_params,
4262306a36Sopenharmony_ci	.shutdown	= wm8731_shutdown,
4362306a36Sopenharmony_ci	.mute_stream	= wm8731_mute,
4462306a36Sopenharmony_ci	.set_sysclk	= wm8731_set_dai_sysclk,
4562306a36Sopenharmony_ci	.set_fmt	= wm8731_set_dai_fmt,
4662306a36Sopenharmony_ci  };
4762306a36Sopenharmony_ci  
4862306a36Sopenharmony_ci  struct snd_soc_dai_driver wm8731_dai = {
4962306a36Sopenharmony_ci	.name = "wm8731-hifi",
5062306a36Sopenharmony_ci	.playback = {
5162306a36Sopenharmony_ci		.stream_name = "Playback",
5262306a36Sopenharmony_ci		.channels_min = 1,
5362306a36Sopenharmony_ci		.channels_max = 2,
5462306a36Sopenharmony_ci		.rates = WM8731_RATES,
5562306a36Sopenharmony_ci		.formats = WM8731_FORMATS,},
5662306a36Sopenharmony_ci	.capture = {
5762306a36Sopenharmony_ci		.stream_name = "Capture",
5862306a36Sopenharmony_ci		.channels_min = 1,
5962306a36Sopenharmony_ci		.channels_max = 2,
6062306a36Sopenharmony_ci		.rates = WM8731_RATES,
6162306a36Sopenharmony_ci		.formats = WM8731_FORMATS,},
6262306a36Sopenharmony_ci	.ops = &wm8731_dai_ops,
6362306a36Sopenharmony_ci	.symmetric_rate = 1,
6462306a36Sopenharmony_ci  };
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ciCodec control IO
6862306a36Sopenharmony_ci----------------
6962306a36Sopenharmony_ciThe codec can usually be controlled via an I2C or SPI style interface
7062306a36Sopenharmony_ci(AC97 combines control with data in the DAI). The codec driver should use the
7162306a36Sopenharmony_ciRegmap API for all codec IO. Please see include/linux/regmap.h and existing
7262306a36Sopenharmony_cicodec drivers for example regmap usage.
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ciMixers and audio controls
7662306a36Sopenharmony_ci-------------------------
7762306a36Sopenharmony_ciAll the codec mixers and audio controls can be defined using the convenience
7862306a36Sopenharmony_cimacros defined in soc.h.
7962306a36Sopenharmony_ci::
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci    #define SOC_SINGLE(xname, reg, shift, mask, invert)
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ciDefines a single control as follows:-
8462306a36Sopenharmony_ci::
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci  xname = Control name e.g. "Playback Volume"
8762306a36Sopenharmony_ci  reg = codec register
8862306a36Sopenharmony_ci  shift = control bit(s) offset in register
8962306a36Sopenharmony_ci  mask = control bit size(s) e.g. mask of 7 = 3 bits
9062306a36Sopenharmony_ci  invert = the control is inverted
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ciOther macros include:-
9362306a36Sopenharmony_ci::
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci    #define SOC_DOUBLE(xname, reg, shift_left, shift_right, mask, invert)
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ciA stereo control
9862306a36Sopenharmony_ci::
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci    #define SOC_DOUBLE_R(xname, reg_left, reg_right, shift, mask, invert)
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ciA stereo control spanning 2 registers
10362306a36Sopenharmony_ci::
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci    #define SOC_ENUM_SINGLE(xreg, xshift, xmask, xtexts)
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ciDefines an single enumerated control as follows:-
10862306a36Sopenharmony_ci::
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci   xreg = register
11162306a36Sopenharmony_ci   xshift = control bit(s) offset in register
11262306a36Sopenharmony_ci   xmask = control bit(s) size
11362306a36Sopenharmony_ci   xtexts = pointer to array of strings that describe each setting
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci   #define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts)
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ciDefines a stereo enumerated control
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ciCodec Audio Operations
12162306a36Sopenharmony_ci----------------------
12262306a36Sopenharmony_ciThe codec driver also supports the following ALSA PCM operations:-
12362306a36Sopenharmony_ci::
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci  /* SoC audio ops */
12662306a36Sopenharmony_ci  struct snd_soc_ops {
12762306a36Sopenharmony_ci	int (*startup)(struct snd_pcm_substream *);
12862306a36Sopenharmony_ci	void (*shutdown)(struct snd_pcm_substream *);
12962306a36Sopenharmony_ci	int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *);
13062306a36Sopenharmony_ci	int (*hw_free)(struct snd_pcm_substream *);
13162306a36Sopenharmony_ci	int (*prepare)(struct snd_pcm_substream *);
13262306a36Sopenharmony_ci  };
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ciPlease refer to the ALSA driver PCM documentation for details.
13562306a36Sopenharmony_cihttps://www.kernel.org/doc/html/latest/sound/kernel-api/writing-an-alsa-driver.html
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ciDAPM description
13962306a36Sopenharmony_ci----------------
14062306a36Sopenharmony_ciThe Dynamic Audio Power Management description describes the codec power
14162306a36Sopenharmony_cicomponents and their relationships and registers to the ASoC core.
14262306a36Sopenharmony_ciPlease read dapm.rst for details of building the description.
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ciPlease also see the examples in other codec drivers.
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ciDAPM event handler
14862306a36Sopenharmony_ci------------------
14962306a36Sopenharmony_ciThis function is a callback that handles codec domain PM calls and system
15062306a36Sopenharmony_cidomain PM calls (e.g. suspend and resume). It is used to put the codec
15162306a36Sopenharmony_cito sleep when not in use.
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ciPower states:-
15462306a36Sopenharmony_ci::
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci	SNDRV_CTL_POWER_D0: /* full On */
15762306a36Sopenharmony_ci	/* vref/mid, clk and osc on, active */
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	SNDRV_CTL_POWER_D1: /* partial On */
16062306a36Sopenharmony_ci	SNDRV_CTL_POWER_D2: /* partial On */
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	SNDRV_CTL_POWER_D3hot: /* Off, with power */
16362306a36Sopenharmony_ci	/* everything off except vref/vmid, inactive */
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	SNDRV_CTL_POWER_D3cold: /* Everything Off, without power */
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ciCodec DAC digital mute control
16962306a36Sopenharmony_ci------------------------------
17062306a36Sopenharmony_ciMost codecs have a digital mute before the DACs that can be used to
17162306a36Sopenharmony_ciminimise any system noise.  The mute stops any digital data from
17262306a36Sopenharmony_cientering the DAC.
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ciA callback can be created that is called by the core for each codec DAI
17562306a36Sopenharmony_ciwhen the mute is applied or freed.
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_cii.e.
17862306a36Sopenharmony_ci::
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci  static int wm8974_mute(struct snd_soc_dai *dai, int mute, int direction)
18162306a36Sopenharmony_ci  {
18262306a36Sopenharmony_ci	struct snd_soc_component *component = dai->component;
18362306a36Sopenharmony_ci	u16 mute_reg = snd_soc_component_read(component, WM8974_DAC) & 0xffbf;
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	if (mute)
18662306a36Sopenharmony_ci		snd_soc_component_write(component, WM8974_DAC, mute_reg | 0x40);
18762306a36Sopenharmony_ci	else
18862306a36Sopenharmony_ci		snd_soc_component_write(component, WM8974_DAC, mute_reg);
18962306a36Sopenharmony_ci	return 0;
19062306a36Sopenharmony_ci  }
191