| Liam Girdwood | eb1a6af | 2006-10-06 18:34:51 +0200 | [diff] [blame] | 1 | ASoC Codec Driver | 
 | 2 | ================= | 
 | 3 |  | 
 | 4 | The codec driver is generic and hardware independent code that configures the | 
 | 5 | codec to provide audio capture and playback. It should contain no code that is | 
 | 6 | specific to the target platform or machine. All platform and machine specific | 
 | 7 | code should be added to the platform and machine drivers respectively. | 
 | 8 |  | 
| Liam Girdwood | 10b9852 | 2007-02-08 17:06:09 +0100 | [diff] [blame] | 9 | Each codec driver *must* provide the following features:- | 
| Liam Girdwood | eb1a6af | 2006-10-06 18:34:51 +0200 | [diff] [blame] | 10 |  | 
| Liam Girdwood | 10b9852 | 2007-02-08 17:06:09 +0100 | [diff] [blame] | 11 |  1) Codec DAI and PCM configuration | 
| Mark Brown | 7c4dbbd | 2008-01-23 08:41:46 +0100 | [diff] [blame] | 12 |  2) Codec control IO - using I2C, 3 Wire(SPI) or both APIs | 
| Liam Girdwood | 10b9852 | 2007-02-08 17:06:09 +0100 | [diff] [blame] | 13 |  3) Mixers and audio controls | 
 | 14 |  4) Codec audio operations | 
| Liam Girdwood | eb1a6af | 2006-10-06 18:34:51 +0200 | [diff] [blame] | 15 |  | 
 | 16 | Optionally, codec drivers can also provide:- | 
 | 17 |  | 
| Liam Girdwood | 10b9852 | 2007-02-08 17:06:09 +0100 | [diff] [blame] | 18 |  5) DAPM description. | 
 | 19 |  6) DAPM event handler. | 
 | 20 |  7) DAC Digital mute control. | 
| Liam Girdwood | eb1a6af | 2006-10-06 18:34:51 +0200 | [diff] [blame] | 21 |  | 
| Mark Brown | 7c4dbbd | 2008-01-23 08:41:46 +0100 | [diff] [blame] | 22 | Its probably best to use this guide in conjunction with the existing codec | 
| Liam Girdwood | eb1a6af | 2006-10-06 18:34:51 +0200 | [diff] [blame] | 23 | driver code in sound/soc/codecs/ | 
 | 24 |  | 
 | 25 | ASoC Codec driver breakdown | 
 | 26 | =========================== | 
 | 27 |  | 
| Liam Girdwood | 10b9852 | 2007-02-08 17:06:09 +0100 | [diff] [blame] | 28 | 1 - Codec DAI and PCM configuration | 
 | 29 | ----------------------------------- | 
| Seungwhan Youn | 379c4bf | 2011-01-13 11:08:21 +0900 | [diff] [blame] | 30 | Each codec driver must have a struct snd_soc_dai_driver to define its DAI and | 
| Mark Brown | 7c4dbbd | 2008-01-23 08:41:46 +0100 | [diff] [blame] | 31 | PCM capabilities and operations. This struct is exported so that it can be | 
| Liam Girdwood | 10b9852 | 2007-02-08 17:06:09 +0100 | [diff] [blame] | 32 | registered with the core by your machine driver. | 
| Liam Girdwood | eb1a6af | 2006-10-06 18:34:51 +0200 | [diff] [blame] | 33 |  | 
 | 34 | e.g. | 
 | 35 |  | 
| Seungwhan Youn | 379c4bf | 2011-01-13 11:08:21 +0900 | [diff] [blame] | 36 | static struct snd_soc_dai_ops wm8731_dai_ops = { | 
 | 37 | 	.prepare	= wm8731_pcm_prepare, | 
 | 38 | 	.hw_params	= wm8731_hw_params, | 
 | 39 | 	.shutdown	= wm8731_shutdown, | 
 | 40 | 	.digital_mute	= wm8731_mute, | 
 | 41 | 	.set_sysclk	= wm8731_set_dai_sysclk, | 
 | 42 | 	.set_fmt	= wm8731_set_dai_fmt, | 
 | 43 | }; | 
 | 44 |  | 
 | 45 | struct snd_soc_dai_driver wm8731_dai = { | 
 | 46 | 	.name = "wm8731-hifi", | 
| Liam Girdwood | eb1a6af | 2006-10-06 18:34:51 +0200 | [diff] [blame] | 47 | 	.playback = { | 
 | 48 | 		.stream_name = "Playback", | 
 | 49 | 		.channels_min = 1, | 
 | 50 | 		.channels_max = 2, | 
| Liam Girdwood | 10b9852 | 2007-02-08 17:06:09 +0100 | [diff] [blame] | 51 | 		.rates = WM8731_RATES, | 
 | 52 | 		.formats = WM8731_FORMATS,}, | 
| Liam Girdwood | eb1a6af | 2006-10-06 18:34:51 +0200 | [diff] [blame] | 53 | 	.capture = { | 
 | 54 | 		.stream_name = "Capture", | 
 | 55 | 		.channels_min = 1, | 
 | 56 | 		.channels_max = 2, | 
| Liam Girdwood | 10b9852 | 2007-02-08 17:06:09 +0100 | [diff] [blame] | 57 | 		.rates = WM8731_RATES, | 
 | 58 | 		.formats = WM8731_FORMATS,}, | 
| Seungwhan Youn | 379c4bf | 2011-01-13 11:08:21 +0900 | [diff] [blame] | 59 | 	.ops = &wm8731_dai_ops, | 
 | 60 | 	.symmetric_rates = 1, | 
| Liam Girdwood | eb1a6af | 2006-10-06 18:34:51 +0200 | [diff] [blame] | 61 | }; | 
 | 62 |  | 
 | 63 |  | 
| Liam Girdwood | 10b9852 | 2007-02-08 17:06:09 +0100 | [diff] [blame] | 64 | 2 - Codec control IO | 
| Liam Girdwood | eb1a6af | 2006-10-06 18:34:51 +0200 | [diff] [blame] | 65 | -------------------- | 
| Mark Brown | 7c4dbbd | 2008-01-23 08:41:46 +0100 | [diff] [blame] | 66 | The codec can usually be controlled via an I2C or SPI style interface | 
 | 67 | (AC97 combines control with data in the DAI). The codec drivers provide | 
 | 68 | functions to read and write the codec registers along with supplying a | 
 | 69 | register cache:- | 
| Liam Girdwood | eb1a6af | 2006-10-06 18:34:51 +0200 | [diff] [blame] | 70 |  | 
 | 71 | 	/* IO control data and register cache */ | 
| Mark Brown | 7c4dbbd | 2008-01-23 08:41:46 +0100 | [diff] [blame] | 72 | 	void *control_data; /* codec control (i2c/3wire) data */ | 
 | 73 | 	void *reg_cache; | 
| Liam Girdwood | eb1a6af | 2006-10-06 18:34:51 +0200 | [diff] [blame] | 74 |  | 
| Mark Brown | 7c4dbbd | 2008-01-23 08:41:46 +0100 | [diff] [blame] | 75 | Codec read/write should do any data formatting and call the hardware | 
 | 76 | read write below to perform the IO. These functions are called by the | 
 | 77 | core and ALSA when performing DAPM or changing the mixer:- | 
| Liam Girdwood | eb1a6af | 2006-10-06 18:34:51 +0200 | [diff] [blame] | 78 |  | 
 | 79 |     unsigned int (*read)(struct snd_soc_codec *, unsigned int); | 
 | 80 |     int (*write)(struct snd_soc_codec *, unsigned int, unsigned int); | 
 | 81 |  | 
 | 82 | Codec hardware IO functions - usually points to either the I2C, SPI or AC97 | 
 | 83 | read/write:- | 
 | 84 |  | 
 | 85 | 	hw_write_t hw_write; | 
 | 86 | 	hw_read_t hw_read; | 
 | 87 |  | 
 | 88 |  | 
| Liam Girdwood | 10b9852 | 2007-02-08 17:06:09 +0100 | [diff] [blame] | 89 | 3 - Mixers and audio controls | 
| Liam Girdwood | eb1a6af | 2006-10-06 18:34:51 +0200 | [diff] [blame] | 90 | ----------------------------- | 
 | 91 | All the codec mixers and audio controls can be defined using the convenience | 
 | 92 | macros defined in soc.h. | 
 | 93 |  | 
 | 94 |     #define SOC_SINGLE(xname, reg, shift, mask, invert) | 
 | 95 |  | 
 | 96 | Defines a single control as follows:- | 
 | 97 |  | 
 | 98 |   xname = Control name e.g. "Playback Volume" | 
 | 99 |   reg = codec register | 
 | 100 |   shift = control bit(s) offset in register | 
 | 101 |   mask = control bit size(s) e.g. mask of 7 = 3 bits | 
 | 102 |   invert = the control is inverted | 
 | 103 |  | 
 | 104 | Other macros include:- | 
 | 105 |  | 
 | 106 |     #define SOC_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) | 
 | 107 |  | 
 | 108 | A stereo control | 
 | 109 |  | 
 | 110 |     #define SOC_DOUBLE_R(xname, reg_left, reg_right, shift, mask, invert) | 
 | 111 |  | 
 | 112 | A stereo control spanning 2 registers | 
 | 113 |  | 
 | 114 |     #define SOC_ENUM_SINGLE(xreg, xshift, xmask, xtexts) | 
 | 115 |  | 
 | 116 | Defines an single enumerated control as follows:- | 
 | 117 |  | 
 | 118 |    xreg = register | 
 | 119 |    xshift = control bit(s) offset in register | 
 | 120 |    xmask = control bit(s) size | 
 | 121 |    xtexts = pointer to array of strings that describe each setting | 
 | 122 |  | 
 | 123 |    #define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts) | 
 | 124 |  | 
 | 125 | Defines a stereo enumerated control | 
 | 126 |  | 
 | 127 |  | 
| Liam Girdwood | 10b9852 | 2007-02-08 17:06:09 +0100 | [diff] [blame] | 128 | 4 - Codec Audio Operations | 
| Liam Girdwood | eb1a6af | 2006-10-06 18:34:51 +0200 | [diff] [blame] | 129 | -------------------------- | 
| Mark Brown | 7c4dbbd | 2008-01-23 08:41:46 +0100 | [diff] [blame] | 130 | The codec driver also supports the following ALSA operations:- | 
| Liam Girdwood | eb1a6af | 2006-10-06 18:34:51 +0200 | [diff] [blame] | 131 |  | 
 | 132 | /* SoC audio ops */ | 
 | 133 | struct snd_soc_ops { | 
| Takashi Iwai | 5b78efd | 2006-11-24 16:12:50 +0100 | [diff] [blame] | 134 | 	int (*startup)(struct snd_pcm_substream *); | 
 | 135 | 	void (*shutdown)(struct snd_pcm_substream *); | 
 | 136 | 	int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *); | 
 | 137 | 	int (*hw_free)(struct snd_pcm_substream *); | 
 | 138 | 	int (*prepare)(struct snd_pcm_substream *); | 
| Liam Girdwood | eb1a6af | 2006-10-06 18:34:51 +0200 | [diff] [blame] | 139 | }; | 
 | 140 |  | 
| Mark Brown | 7c4dbbd | 2008-01-23 08:41:46 +0100 | [diff] [blame] | 141 | Please refer to the ALSA driver PCM documentation for details. | 
| Justin P. Mattock | 0ea6e61 | 2010-07-23 20:51:24 -0700 | [diff] [blame] | 142 | http://www.alsa-project.org/~iwai/writing-an-alsa-driver/ | 
| Liam Girdwood | eb1a6af | 2006-10-06 18:34:51 +0200 | [diff] [blame] | 143 |  | 
 | 144 |  | 
| Liam Girdwood | 10b9852 | 2007-02-08 17:06:09 +0100 | [diff] [blame] | 145 | 5 - DAPM description. | 
| Liam Girdwood | eb1a6af | 2006-10-06 18:34:51 +0200 | [diff] [blame] | 146 | --------------------- | 
| Mark Brown | 7c4dbbd | 2008-01-23 08:41:46 +0100 | [diff] [blame] | 147 | The Dynamic Audio Power Management description describes the codec power | 
 | 148 | components and their relationships and registers to the ASoC core. | 
 | 149 | Please read dapm.txt for details of building the description. | 
| Liam Girdwood | eb1a6af | 2006-10-06 18:34:51 +0200 | [diff] [blame] | 150 |  | 
 | 151 | Please also see the examples in other codec drivers. | 
 | 152 |  | 
 | 153 |  | 
| Liam Girdwood | 10b9852 | 2007-02-08 17:06:09 +0100 | [diff] [blame] | 154 | 6 - DAPM event handler | 
| Liam Girdwood | eb1a6af | 2006-10-06 18:34:51 +0200 | [diff] [blame] | 155 | ---------------------- | 
 | 156 | This function is a callback that handles codec domain PM calls and system | 
| Mark Brown | 7c4dbbd | 2008-01-23 08:41:46 +0100 | [diff] [blame] | 157 | domain PM calls (e.g. suspend and resume). It is used to put the codec | 
 | 158 | to sleep when not in use. | 
| Liam Girdwood | eb1a6af | 2006-10-06 18:34:51 +0200 | [diff] [blame] | 159 |  | 
 | 160 | Power states:- | 
 | 161 |  | 
 | 162 | 	SNDRV_CTL_POWER_D0: /* full On */ | 
 | 163 | 	/* vref/mid, clk and osc on, active */ | 
 | 164 |  | 
 | 165 | 	SNDRV_CTL_POWER_D1: /* partial On */ | 
 | 166 | 	SNDRV_CTL_POWER_D2: /* partial On */ | 
 | 167 |  | 
 | 168 | 	SNDRV_CTL_POWER_D3hot: /* Off, with power */ | 
 | 169 | 	/* everything off except vref/vmid, inactive */ | 
 | 170 |  | 
 | 171 | 	SNDRV_CTL_POWER_D3cold: /* Everything Off, without power */ | 
 | 172 |  | 
 | 173 |  | 
| Mark Brown | 7c4dbbd | 2008-01-23 08:41:46 +0100 | [diff] [blame] | 174 | 7 - Codec DAC digital mute control | 
 | 175 | ---------------------------------- | 
 | 176 | Most codecs have a digital mute before the DACs that can be used to | 
 | 177 | minimise any system noise.  The mute stops any digital data from | 
 | 178 | entering the DAC. | 
| Liam Girdwood | eb1a6af | 2006-10-06 18:34:51 +0200 | [diff] [blame] | 179 |  | 
| Mark Brown | 7c4dbbd | 2008-01-23 08:41:46 +0100 | [diff] [blame] | 180 | A callback can be created that is called by the core for each codec DAI | 
 | 181 | when the mute is applied or freed. | 
| Liam Girdwood | eb1a6af | 2006-10-06 18:34:51 +0200 | [diff] [blame] | 182 |  | 
 | 183 | i.e. | 
 | 184 |  | 
| Seungwhan Youn | 379c4bf | 2011-01-13 11:08:21 +0900 | [diff] [blame] | 185 | static int wm8974_mute(struct snd_soc_dai *dai, int mute) | 
| Liam Girdwood | eb1a6af | 2006-10-06 18:34:51 +0200 | [diff] [blame] | 186 | { | 
| Seungwhan Youn | 379c4bf | 2011-01-13 11:08:21 +0900 | [diff] [blame] | 187 | 	struct snd_soc_codec *codec = dai->codec; | 
 | 188 | 	u16 mute_reg = snd_soc_read(codec, WM8974_DAC) & 0xffbf; | 
 | 189 |  | 
 | 190 | 	if (mute) | 
 | 191 | 		snd_soc_write(codec, WM8974_DAC, mute_reg | 0x40); | 
| Liam Girdwood | eb1a6af | 2006-10-06 18:34:51 +0200 | [diff] [blame] | 192 | 	else | 
| Seungwhan Youn | 379c4bf | 2011-01-13 11:08:21 +0900 | [diff] [blame] | 193 | 		snd_soc_write(codec, WM8974_DAC, mute_reg); | 
| Liam Girdwood | eb1a6af | 2006-10-06 18:34:51 +0200 | [diff] [blame] | 194 | 	return 0; | 
 | 195 | } |