18c2ecf20Sopenharmony_ci======================= 28c2ecf20Sopenharmony_ciASoC Codec Class Driver 38c2ecf20Sopenharmony_ci======================= 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ciThe codec class driver is generic and hardware independent code that configures 68c2ecf20Sopenharmony_cithe codec, FM, MODEM, BT or external DSP to provide audio capture and playback. 78c2ecf20Sopenharmony_ciIt should contain no code that is specific to the target platform or machine. 88c2ecf20Sopenharmony_ciAll platform and machine specific code should be added to the platform and 98c2ecf20Sopenharmony_cimachine drivers respectively. 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ciEach codec class driver *must* provide the following features:- 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci1. Codec DAI and PCM configuration 148c2ecf20Sopenharmony_ci2. Codec control IO - using RegMap API 158c2ecf20Sopenharmony_ci3. Mixers and audio controls 168c2ecf20Sopenharmony_ci4. Codec audio operations 178c2ecf20Sopenharmony_ci5. DAPM description. 188c2ecf20Sopenharmony_ci6. DAPM event handler. 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ciOptionally, codec drivers can also provide:- 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci7. DAC Digital mute control. 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ciIts probably best to use this guide in conjunction with the existing codec 258c2ecf20Sopenharmony_cidriver code in sound/soc/codecs/ 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ciASoC Codec driver breakdown 288c2ecf20Sopenharmony_ci=========================== 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ciCodec DAI and PCM configuration 318c2ecf20Sopenharmony_ci------------------------------- 328c2ecf20Sopenharmony_ciEach codec driver must have a struct snd_soc_dai_driver to define its DAI and 338c2ecf20Sopenharmony_ciPCM capabilities and operations. This struct is exported so that it can be 348c2ecf20Sopenharmony_ciregistered with the core by your machine driver. 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cie.g. 378c2ecf20Sopenharmony_ci:: 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci static struct snd_soc_dai_ops wm8731_dai_ops = { 408c2ecf20Sopenharmony_ci .prepare = wm8731_pcm_prepare, 418c2ecf20Sopenharmony_ci .hw_params = wm8731_hw_params, 428c2ecf20Sopenharmony_ci .shutdown = wm8731_shutdown, 438c2ecf20Sopenharmony_ci .digital_mute = wm8731_mute, 448c2ecf20Sopenharmony_ci .set_sysclk = wm8731_set_dai_sysclk, 458c2ecf20Sopenharmony_ci .set_fmt = wm8731_set_dai_fmt, 468c2ecf20Sopenharmony_ci }; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci struct snd_soc_dai_driver wm8731_dai = { 498c2ecf20Sopenharmony_ci .name = "wm8731-hifi", 508c2ecf20Sopenharmony_ci .playback = { 518c2ecf20Sopenharmony_ci .stream_name = "Playback", 528c2ecf20Sopenharmony_ci .channels_min = 1, 538c2ecf20Sopenharmony_ci .channels_max = 2, 548c2ecf20Sopenharmony_ci .rates = WM8731_RATES, 558c2ecf20Sopenharmony_ci .formats = WM8731_FORMATS,}, 568c2ecf20Sopenharmony_ci .capture = { 578c2ecf20Sopenharmony_ci .stream_name = "Capture", 588c2ecf20Sopenharmony_ci .channels_min = 1, 598c2ecf20Sopenharmony_ci .channels_max = 2, 608c2ecf20Sopenharmony_ci .rates = WM8731_RATES, 618c2ecf20Sopenharmony_ci .formats = WM8731_FORMATS,}, 628c2ecf20Sopenharmony_ci .ops = &wm8731_dai_ops, 638c2ecf20Sopenharmony_ci .symmetric_rates = 1, 648c2ecf20Sopenharmony_ci }; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ciCodec control IO 688c2ecf20Sopenharmony_ci---------------- 698c2ecf20Sopenharmony_ciThe codec can usually be controlled via an I2C or SPI style interface 708c2ecf20Sopenharmony_ci(AC97 combines control with data in the DAI). The codec driver should use the 718c2ecf20Sopenharmony_ciRegmap API for all codec IO. Please see include/linux/regmap.h and existing 728c2ecf20Sopenharmony_cicodec drivers for example regmap usage. 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ciMixers and audio controls 768c2ecf20Sopenharmony_ci------------------------- 778c2ecf20Sopenharmony_ciAll the codec mixers and audio controls can be defined using the convenience 788c2ecf20Sopenharmony_cimacros defined in soc.h. 798c2ecf20Sopenharmony_ci:: 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci #define SOC_SINGLE(xname, reg, shift, mask, invert) 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ciDefines a single control as follows:- 848c2ecf20Sopenharmony_ci:: 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci xname = Control name e.g. "Playback Volume" 878c2ecf20Sopenharmony_ci reg = codec register 888c2ecf20Sopenharmony_ci shift = control bit(s) offset in register 898c2ecf20Sopenharmony_ci mask = control bit size(s) e.g. mask of 7 = 3 bits 908c2ecf20Sopenharmony_ci invert = the control is inverted 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ciOther macros include:- 938c2ecf20Sopenharmony_ci:: 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci #define SOC_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ciA stereo control 988c2ecf20Sopenharmony_ci:: 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci #define SOC_DOUBLE_R(xname, reg_left, reg_right, shift, mask, invert) 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ciA stereo control spanning 2 registers 1038c2ecf20Sopenharmony_ci:: 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci #define SOC_ENUM_SINGLE(xreg, xshift, xmask, xtexts) 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ciDefines an single enumerated control as follows:- 1088c2ecf20Sopenharmony_ci:: 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci xreg = register 1118c2ecf20Sopenharmony_ci xshift = control bit(s) offset in register 1128c2ecf20Sopenharmony_ci xmask = control bit(s) size 1138c2ecf20Sopenharmony_ci xtexts = pointer to array of strings that describe each setting 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci #define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts) 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ciDefines a stereo enumerated control 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ciCodec Audio Operations 1218c2ecf20Sopenharmony_ci---------------------- 1228c2ecf20Sopenharmony_ciThe codec driver also supports the following ALSA PCM operations:- 1238c2ecf20Sopenharmony_ci:: 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci /* SoC audio ops */ 1268c2ecf20Sopenharmony_ci struct snd_soc_ops { 1278c2ecf20Sopenharmony_ci int (*startup)(struct snd_pcm_substream *); 1288c2ecf20Sopenharmony_ci void (*shutdown)(struct snd_pcm_substream *); 1298c2ecf20Sopenharmony_ci int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *); 1308c2ecf20Sopenharmony_ci int (*hw_free)(struct snd_pcm_substream *); 1318c2ecf20Sopenharmony_ci int (*prepare)(struct snd_pcm_substream *); 1328c2ecf20Sopenharmony_ci }; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ciPlease refer to the ALSA driver PCM documentation for details. 1358c2ecf20Sopenharmony_cihttp://www.alsa-project.org/~iwai/writing-an-alsa-driver/ 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ciDAPM description 1398c2ecf20Sopenharmony_ci---------------- 1408c2ecf20Sopenharmony_ciThe Dynamic Audio Power Management description describes the codec power 1418c2ecf20Sopenharmony_cicomponents and their relationships and registers to the ASoC core. 1428c2ecf20Sopenharmony_ciPlease read dapm.rst for details of building the description. 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ciPlease also see the examples in other codec drivers. 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ciDAPM event handler 1488c2ecf20Sopenharmony_ci------------------ 1498c2ecf20Sopenharmony_ciThis function is a callback that handles codec domain PM calls and system 1508c2ecf20Sopenharmony_cidomain PM calls (e.g. suspend and resume). It is used to put the codec 1518c2ecf20Sopenharmony_cito sleep when not in use. 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ciPower states:- 1548c2ecf20Sopenharmony_ci:: 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci SNDRV_CTL_POWER_D0: /* full On */ 1578c2ecf20Sopenharmony_ci /* vref/mid, clk and osc on, active */ 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci SNDRV_CTL_POWER_D1: /* partial On */ 1608c2ecf20Sopenharmony_ci SNDRV_CTL_POWER_D2: /* partial On */ 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci SNDRV_CTL_POWER_D3hot: /* Off, with power */ 1638c2ecf20Sopenharmony_ci /* everything off except vref/vmid, inactive */ 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci SNDRV_CTL_POWER_D3cold: /* Everything Off, without power */ 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ciCodec DAC digital mute control 1698c2ecf20Sopenharmony_ci------------------------------ 1708c2ecf20Sopenharmony_ciMost codecs have a digital mute before the DACs that can be used to 1718c2ecf20Sopenharmony_ciminimise any system noise. The mute stops any digital data from 1728c2ecf20Sopenharmony_cientering the DAC. 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ciA callback can be created that is called by the core for each codec DAI 1758c2ecf20Sopenharmony_ciwhen the mute is applied or freed. 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_cii.e. 1788c2ecf20Sopenharmony_ci:: 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci static int wm8974_mute(struct snd_soc_dai *dai, int mute) 1818c2ecf20Sopenharmony_ci { 1828c2ecf20Sopenharmony_ci struct snd_soc_component *component = dai->component; 1838c2ecf20Sopenharmony_ci u16 mute_reg = snd_soc_component_read32(component, WM8974_DAC) & 0xffbf; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci if (mute) 1868c2ecf20Sopenharmony_ci snd_soc_component_write(component, WM8974_DAC, mute_reg | 0x40); 1878c2ecf20Sopenharmony_ci else 1888c2ecf20Sopenharmony_ci snd_soc_component_write(component, WM8974_DAC, mute_reg); 1898c2ecf20Sopenharmony_ci return 0; 1908c2ecf20Sopenharmony_ci } 191