wm9713.c 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * wm9713.c -- ALSA Soc WM9713 codec support
  4. *
  5. * Copyright 2006-10 Wolfson Microelectronics PLC.
  6. * Author: Liam Girdwood <lrg@slimlogic.co.uk>
  7. *
  8. * Features:-
  9. *
  10. * o Support for AC97 Codec, Voice DAC and Aux DAC
  11. * o Support for DAPM
  12. */
  13. #include <linux/init.h>
  14. #include <linux/slab.h>
  15. #include <linux/mfd/wm97xx.h>
  16. #include <linux/module.h>
  17. #include <linux/device.h>
  18. #include <linux/regmap.h>
  19. #include <sound/core.h>
  20. #include <sound/pcm.h>
  21. #include <sound/ac97_codec.h>
  22. #include <sound/ac97/codec.h>
  23. #include <sound/ac97/compat.h>
  24. #include <sound/initval.h>
  25. #include <sound/pcm_params.h>
  26. #include <sound/tlv.h>
  27. #include <sound/soc.h>
  28. #include "wm9713.h"
  29. #define WM9713_VENDOR_ID 0x574d4c13
  30. #define WM9713_VENDOR_ID_MASK 0xffffffff
  31. struct wm9713_priv {
  32. struct snd_ac97 *ac97;
  33. u32 pll_in; /* PLL input frequency */
  34. unsigned int hp_mixer[2];
  35. struct mutex lock;
  36. struct wm97xx_platform_data *mfd_pdata;
  37. };
  38. #define HPL_MIXER 0
  39. #define HPR_MIXER 1
  40. static const char *wm9713_mic_mixer[] = {"Stereo", "Mic 1", "Mic 2", "Mute"};
  41. static const char *wm9713_rec_mux[] = {"Stereo", "Left", "Right", "Mute"};
  42. static const char *wm9713_rec_src[] =
  43. {"Mic 1", "Mic 2", "Line", "Mono In", "Headphone", "Speaker",
  44. "Mono Out", "Zh"};
  45. static const char *wm9713_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"};
  46. static const char *wm9713_alc_select[] = {"None", "Left", "Right", "Stereo"};
  47. static const char *wm9713_mono_pga[] = {"Vmid", "Zh", "Mono", "Inv"};
  48. static const char *wm9713_spk_pga[] =
  49. {"Vmid", "Zh", "Headphone", "Speaker", "Inv", "Headphone Vmid",
  50. "Speaker Vmid", "Inv Vmid"};
  51. static const char *wm9713_hp_pga[] = {"Vmid", "Zh", "Headphone",
  52. "Headphone Vmid"};
  53. static const char *wm9713_out3_pga[] = {"Vmid", "Zh", "Inv 1", "Inv 1 Vmid"};
  54. static const char *wm9713_out4_pga[] = {"Vmid", "Zh", "Inv 2", "Inv 2 Vmid"};
  55. static const char *wm9713_dac_inv[] =
  56. {"Off", "Mono", "Speaker", "Left Headphone", "Right Headphone",
  57. "Headphone Mono", "NC", "Vmid"};
  58. static const char *wm9713_bass[] = {"Linear Control", "Adaptive Boost"};
  59. static const char *wm9713_ng_type[] = {"Constant Gain", "Mute"};
  60. static const char *wm9713_mic_select[] = {"Mic 1", "Mic 2 A", "Mic 2 B"};
  61. static const char *wm9713_micb_select[] = {"MPB", "MPA"};
  62. static const struct soc_enum wm9713_enum[] = {
  63. SOC_ENUM_SINGLE(AC97_LINE, 3, 4, wm9713_mic_mixer), /* record mic mixer 0 */
  64. SOC_ENUM_SINGLE(AC97_VIDEO, 14, 4, wm9713_rec_mux), /* record mux hp 1 */
  65. SOC_ENUM_SINGLE(AC97_VIDEO, 9, 4, wm9713_rec_mux), /* record mux mono 2 */
  66. SOC_ENUM_SINGLE(AC97_VIDEO, 3, 8, wm9713_rec_src), /* record mux left 3 */
  67. SOC_ENUM_SINGLE(AC97_VIDEO, 0, 8, wm9713_rec_src), /* record mux right 4*/
  68. SOC_ENUM_DOUBLE(AC97_CD, 14, 6, 2, wm9713_rec_gain), /* record step size 5 */
  69. SOC_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9713_alc_select), /* alc source select 6*/
  70. SOC_ENUM_SINGLE(AC97_REC_GAIN, 14, 4, wm9713_mono_pga), /* mono input select 7 */
  71. SOC_ENUM_SINGLE(AC97_REC_GAIN, 11, 8, wm9713_spk_pga), /* speaker left input select 8 */
  72. SOC_ENUM_SINGLE(AC97_REC_GAIN, 8, 8, wm9713_spk_pga), /* speaker right input select 9 */
  73. SOC_ENUM_SINGLE(AC97_REC_GAIN, 6, 3, wm9713_hp_pga), /* headphone left input 10 */
  74. SOC_ENUM_SINGLE(AC97_REC_GAIN, 4, 3, wm9713_hp_pga), /* headphone right input 11 */
  75. SOC_ENUM_SINGLE(AC97_REC_GAIN, 2, 4, wm9713_out3_pga), /* out 3 source 12 */
  76. SOC_ENUM_SINGLE(AC97_REC_GAIN, 0, 4, wm9713_out4_pga), /* out 4 source 13 */
  77. SOC_ENUM_SINGLE(AC97_REC_GAIN_MIC, 13, 8, wm9713_dac_inv), /* dac invert 1 14 */
  78. SOC_ENUM_SINGLE(AC97_REC_GAIN_MIC, 10, 8, wm9713_dac_inv), /* dac invert 2 15 */
  79. SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, wm9713_bass), /* bass control 16 */
  80. SOC_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9713_ng_type), /* noise gate type 17 */
  81. SOC_ENUM_SINGLE(AC97_3D_CONTROL, 12, 3, wm9713_mic_select), /* mic selection 18 */
  82. SOC_ENUM_SINGLE_VIRT(2, wm9713_micb_select), /* mic selection 19 */
  83. };
  84. static const DECLARE_TLV_DB_SCALE(out_tlv, -4650, 150, 0);
  85. static const DECLARE_TLV_DB_SCALE(main_tlv, -3450, 150, 0);
  86. static const DECLARE_TLV_DB_SCALE(misc_tlv, -1500, 300, 0);
  87. static const DECLARE_TLV_DB_RANGE(mic_tlv,
  88. 0, 2, TLV_DB_SCALE_ITEM(1200, 600, 0),
  89. 3, 3, TLV_DB_SCALE_ITEM(3000, 0, 0)
  90. );
  91. static const struct snd_kcontrol_new wm9713_snd_ac97_controls[] = {
  92. SOC_DOUBLE_TLV("Speaker Playback Volume", AC97_MASTER, 8, 0, 31, 1, out_tlv),
  93. SOC_DOUBLE("Speaker Playback Switch", AC97_MASTER, 15, 7, 1, 1),
  94. SOC_DOUBLE_TLV("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1,
  95. out_tlv),
  96. SOC_DOUBLE("Headphone Playback Switch", AC97_HEADPHONE, 15, 7, 1, 1),
  97. SOC_DOUBLE_TLV("Line In Volume", AC97_PC_BEEP, 8, 0, 31, 1, main_tlv),
  98. SOC_DOUBLE_TLV("PCM Playback Volume", AC97_PHONE, 8, 0, 31, 1, main_tlv),
  99. SOC_SINGLE_TLV("Mic 1 Volume", AC97_MIC, 8, 31, 1, main_tlv),
  100. SOC_SINGLE_TLV("Mic 2 Volume", AC97_MIC, 0, 31, 1, main_tlv),
  101. SOC_SINGLE_TLV("Mic 1 Preamp Volume", AC97_3D_CONTROL, 10, 3, 0, mic_tlv),
  102. SOC_SINGLE_TLV("Mic 2 Preamp Volume", AC97_3D_CONTROL, 12, 3, 0, mic_tlv),
  103. SOC_SINGLE("Mic Boost (+20dB) Switch", AC97_LINE, 5, 1, 0),
  104. SOC_SINGLE("Mic Headphone Mixer Volume", AC97_LINE, 0, 7, 1),
  105. SOC_SINGLE("Capture Switch", AC97_CD, 15, 1, 1),
  106. SOC_ENUM("Capture Volume Steps", wm9713_enum[5]),
  107. SOC_DOUBLE("Capture Volume", AC97_CD, 8, 0, 31, 0),
  108. SOC_SINGLE("Capture ZC Switch", AC97_CD, 7, 1, 0),
  109. SOC_SINGLE_TLV("Capture to Headphone Volume", AC97_VIDEO, 11, 7, 1, misc_tlv),
  110. SOC_SINGLE("Capture to Mono Boost (+20dB) Switch", AC97_VIDEO, 8, 1, 0),
  111. SOC_SINGLE("Capture ADC Boost (+20dB) Switch", AC97_VIDEO, 6, 1, 0),
  112. SOC_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0),
  113. SOC_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0),
  114. SOC_SINGLE("ALC Decay Time", AC97_CODEC_CLASS_REV, 4, 15, 0),
  115. SOC_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0),
  116. SOC_ENUM("ALC Function", wm9713_enum[6]),
  117. SOC_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 0),
  118. SOC_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 0),
  119. SOC_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 1, 0),
  120. SOC_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 1, 0),
  121. SOC_ENUM("ALC NG Type", wm9713_enum[17]),
  122. SOC_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 0),
  123. SOC_DOUBLE("Speaker Playback ZC Switch", AC97_MASTER, 14, 6, 1, 0),
  124. SOC_DOUBLE("Headphone Playback ZC Switch", AC97_HEADPHONE, 14, 6, 1, 0),
  125. SOC_SINGLE("Out4 Playback Switch", AC97_MASTER_MONO, 15, 1, 1),
  126. SOC_SINGLE("Out4 Playback ZC Switch", AC97_MASTER_MONO, 14, 1, 0),
  127. SOC_SINGLE_TLV("Out4 Playback Volume", AC97_MASTER_MONO, 8, 31, 1, out_tlv),
  128. SOC_SINGLE("Out3 Playback Switch", AC97_MASTER_MONO, 7, 1, 1),
  129. SOC_SINGLE("Out3 Playback ZC Switch", AC97_MASTER_MONO, 6, 1, 0),
  130. SOC_SINGLE_TLV("Out3 Playback Volume", AC97_MASTER_MONO, 0, 31, 1, out_tlv),
  131. SOC_SINGLE_TLV("Mono Capture Volume", AC97_MASTER_TONE, 8, 31, 1, main_tlv),
  132. SOC_SINGLE("Mono Playback Switch", AC97_MASTER_TONE, 7, 1, 1),
  133. SOC_SINGLE("Mono Playback ZC Switch", AC97_MASTER_TONE, 6, 1, 0),
  134. SOC_SINGLE_TLV("Mono Playback Volume", AC97_MASTER_TONE, 0, 31, 1, out_tlv),
  135. SOC_SINGLE_TLV("Headphone Mixer Beep Playback Volume", AC97_AUX, 12, 7, 1,
  136. misc_tlv),
  137. SOC_SINGLE_TLV("Speaker Mixer Beep Playback Volume", AC97_AUX, 8, 7, 1,
  138. misc_tlv),
  139. SOC_SINGLE_TLV("Mono Mixer Beep Playback Volume", AC97_AUX, 4, 7, 1, misc_tlv),
  140. SOC_SINGLE_TLV("Voice Playback Headphone Volume", AC97_PCM, 12, 7, 1,
  141. misc_tlv),
  142. SOC_SINGLE("Voice Playback Master Volume", AC97_PCM, 8, 7, 1),
  143. SOC_SINGLE("Voice Playback Mono Volume", AC97_PCM, 4, 7, 1),
  144. SOC_SINGLE_TLV("Headphone Mixer Aux Playback Volume", AC97_REC_SEL, 12, 7, 1,
  145. misc_tlv),
  146. SOC_SINGLE_TLV("Speaker Mixer Voice Playback Volume", AC97_PCM, 8, 7, 1,
  147. misc_tlv),
  148. SOC_SINGLE_TLV("Speaker Mixer Aux Playback Volume", AC97_REC_SEL, 8, 7, 1,
  149. misc_tlv),
  150. SOC_SINGLE_TLV("Mono Mixer Voice Playback Volume", AC97_PCM, 4, 7, 1,
  151. misc_tlv),
  152. SOC_SINGLE_TLV("Mono Mixer Aux Playback Volume", AC97_REC_SEL, 4, 7, 1,
  153. misc_tlv),
  154. SOC_SINGLE("Aux Playback Headphone Volume", AC97_REC_SEL, 12, 7, 1),
  155. SOC_SINGLE("Aux Playback Master Volume", AC97_REC_SEL, 8, 7, 1),
  156. SOC_ENUM("Bass Control", wm9713_enum[16]),
  157. SOC_SINGLE("Bass Cut-off Switch", AC97_GENERAL_PURPOSE, 12, 1, 1),
  158. SOC_SINGLE("Tone Cut-off Switch", AC97_GENERAL_PURPOSE, 4, 1, 1),
  159. SOC_SINGLE("Playback Attenuate (-6dB) Switch", AC97_GENERAL_PURPOSE, 6, 1, 0),
  160. SOC_SINGLE("Bass Volume", AC97_GENERAL_PURPOSE, 8, 15, 1),
  161. SOC_SINGLE("Tone Volume", AC97_GENERAL_PURPOSE, 0, 15, 1),
  162. SOC_SINGLE("3D Upper Cut-off Switch", AC97_REC_GAIN_MIC, 5, 1, 0),
  163. SOC_SINGLE("3D Lower Cut-off Switch", AC97_REC_GAIN_MIC, 4, 1, 0),
  164. SOC_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1),
  165. };
  166. static int wm9713_voice_shutdown(struct snd_soc_dapm_widget *w,
  167. struct snd_kcontrol *kcontrol, int event)
  168. {
  169. struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
  170. if (WARN_ON(event != SND_SOC_DAPM_PRE_PMD))
  171. return -EINVAL;
  172. /* Gracefully shut down the voice interface. */
  173. snd_soc_component_update_bits(component, AC97_HANDSET_RATE, 0x0f00, 0x0200);
  174. schedule_timeout_interruptible(msecs_to_jiffies(1));
  175. snd_soc_component_update_bits(component, AC97_HANDSET_RATE, 0x0f00, 0x0f00);
  176. snd_soc_component_update_bits(component, AC97_EXTENDED_MID, 0x1000, 0x1000);
  177. return 0;
  178. }
  179. static const unsigned int wm9713_mixer_mute_regs[] = {
  180. AC97_PC_BEEP,
  181. AC97_MASTER_TONE,
  182. AC97_PHONE,
  183. AC97_REC_SEL,
  184. AC97_PCM,
  185. AC97_AUX,
  186. };
  187. /* We have to create a fake left and right HP mixers because
  188. * the codec only has a single control that is shared by both channels.
  189. * This makes it impossible to determine the audio path using the current
  190. * register map, thus we add a new (virtual) register to help determine the
  191. * audio route within the device.
  192. */
  193. static int wm9713_hp_mixer_put(struct snd_kcontrol *kcontrol,
  194. struct snd_ctl_elem_value *ucontrol)
  195. {
  196. struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
  197. struct snd_soc_component *component = snd_soc_dapm_to_component(dapm);
  198. struct wm9713_priv *wm9713 = snd_soc_component_get_drvdata(component);
  199. unsigned int val = ucontrol->value.integer.value[0];
  200. struct soc_mixer_control *mc =
  201. (struct soc_mixer_control *)kcontrol->private_value;
  202. unsigned int mixer, mask, shift, old;
  203. struct snd_soc_dapm_update update = {};
  204. bool change;
  205. mixer = mc->shift >> 8;
  206. shift = mc->shift & 0xff;
  207. mask = (1 << shift);
  208. mutex_lock(&wm9713->lock);
  209. old = wm9713->hp_mixer[mixer];
  210. if (ucontrol->value.integer.value[0])
  211. wm9713->hp_mixer[mixer] |= mask;
  212. else
  213. wm9713->hp_mixer[mixer] &= ~mask;
  214. change = old != wm9713->hp_mixer[mixer];
  215. if (change) {
  216. update.kcontrol = kcontrol;
  217. update.reg = wm9713_mixer_mute_regs[shift];
  218. update.mask = 0x8000;
  219. if ((wm9713->hp_mixer[0] & mask) ||
  220. (wm9713->hp_mixer[1] & mask))
  221. update.val = 0x0;
  222. else
  223. update.val = 0x8000;
  224. snd_soc_dapm_mixer_update_power(dapm, kcontrol, val,
  225. &update);
  226. }
  227. mutex_unlock(&wm9713->lock);
  228. return change;
  229. }
  230. static int wm9713_hp_mixer_get(struct snd_kcontrol *kcontrol,
  231. struct snd_ctl_elem_value *ucontrol)
  232. {
  233. struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
  234. struct snd_soc_component *component = snd_soc_dapm_to_component(dapm);
  235. struct wm9713_priv *wm9713 = snd_soc_component_get_drvdata(component);
  236. struct soc_mixer_control *mc =
  237. (struct soc_mixer_control *)kcontrol->private_value;
  238. unsigned int mixer, shift;
  239. mixer = mc->shift >> 8;
  240. shift = mc->shift & 0xff;
  241. ucontrol->value.integer.value[0] =
  242. (wm9713->hp_mixer[mixer] >> shift) & 1;
  243. return 0;
  244. }
  245. #define WM9713_HP_MIXER_CTRL(xname, xmixer, xshift) { \
  246. .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
  247. .info = snd_soc_info_volsw, \
  248. .get = wm9713_hp_mixer_get, .put = wm9713_hp_mixer_put, \
  249. .private_value = SOC_DOUBLE_VALUE(SND_SOC_NOPM, \
  250. xshift, xmixer, 1, 0, 0) \
  251. }
  252. /* Left Headphone Mixers */
  253. static const struct snd_kcontrol_new wm9713_hpl_mixer_controls[] = {
  254. WM9713_HP_MIXER_CTRL("Beep Playback Switch", HPL_MIXER, 5),
  255. WM9713_HP_MIXER_CTRL("Voice Playback Switch", HPL_MIXER, 4),
  256. WM9713_HP_MIXER_CTRL("Aux Playback Switch", HPL_MIXER, 3),
  257. WM9713_HP_MIXER_CTRL("PCM Playback Switch", HPL_MIXER, 2),
  258. WM9713_HP_MIXER_CTRL("MonoIn Playback Switch", HPL_MIXER, 1),
  259. WM9713_HP_MIXER_CTRL("Bypass Playback Switch", HPL_MIXER, 0),
  260. };
  261. /* Right Headphone Mixers */
  262. static const struct snd_kcontrol_new wm9713_hpr_mixer_controls[] = {
  263. WM9713_HP_MIXER_CTRL("Beep Playback Switch", HPR_MIXER, 5),
  264. WM9713_HP_MIXER_CTRL("Voice Playback Switch", HPR_MIXER, 4),
  265. WM9713_HP_MIXER_CTRL("Aux Playback Switch", HPR_MIXER, 3),
  266. WM9713_HP_MIXER_CTRL("PCM Playback Switch", HPR_MIXER, 2),
  267. WM9713_HP_MIXER_CTRL("MonoIn Playback Switch", HPR_MIXER, 1),
  268. WM9713_HP_MIXER_CTRL("Bypass Playback Switch", HPR_MIXER, 0),
  269. };
  270. /* headphone capture mux */
  271. static const struct snd_kcontrol_new wm9713_hp_rec_mux_controls =
  272. SOC_DAPM_ENUM("Route", wm9713_enum[1]);
  273. /* headphone mic mux */
  274. static const struct snd_kcontrol_new wm9713_hp_mic_mux_controls =
  275. SOC_DAPM_ENUM("Route", wm9713_enum[0]);
  276. /* Speaker Mixer */
  277. static const struct snd_kcontrol_new wm9713_speaker_mixer_controls[] = {
  278. SOC_DAPM_SINGLE("Beep Playback Switch", AC97_AUX, 11, 1, 1),
  279. SOC_DAPM_SINGLE("Voice Playback Switch", AC97_PCM, 11, 1, 1),
  280. SOC_DAPM_SINGLE("Aux Playback Switch", AC97_REC_SEL, 11, 1, 1),
  281. SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PHONE, 14, 1, 1),
  282. SOC_DAPM_SINGLE("MonoIn Playback Switch", AC97_MASTER_TONE, 14, 1, 1),
  283. SOC_DAPM_SINGLE("Bypass Playback Switch", AC97_PC_BEEP, 14, 1, 1),
  284. };
  285. /* Mono Mixer */
  286. static const struct snd_kcontrol_new wm9713_mono_mixer_controls[] = {
  287. SOC_DAPM_SINGLE("Beep Playback Switch", AC97_AUX, 7, 1, 1),
  288. SOC_DAPM_SINGLE("Voice Playback Switch", AC97_PCM, 7, 1, 1),
  289. SOC_DAPM_SINGLE("Aux Playback Switch", AC97_REC_SEL, 7, 1, 1),
  290. SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PHONE, 13, 1, 1),
  291. SOC_DAPM_SINGLE("MonoIn Playback Switch", AC97_MASTER_TONE, 13, 1, 1),
  292. SOC_DAPM_SINGLE("Bypass Playback Switch", AC97_PC_BEEP, 13, 1, 1),
  293. SOC_DAPM_SINGLE("Mic 1 Sidetone Switch", AC97_LINE, 7, 1, 1),
  294. SOC_DAPM_SINGLE("Mic 2 Sidetone Switch", AC97_LINE, 6, 1, 1),
  295. };
  296. /* mono mic mux */
  297. static const struct snd_kcontrol_new wm9713_mono_mic_mux_controls =
  298. SOC_DAPM_ENUM("Route", wm9713_enum[2]);
  299. /* mono output mux */
  300. static const struct snd_kcontrol_new wm9713_mono_mux_controls =
  301. SOC_DAPM_ENUM("Route", wm9713_enum[7]);
  302. /* speaker left output mux */
  303. static const struct snd_kcontrol_new wm9713_hp_spkl_mux_controls =
  304. SOC_DAPM_ENUM("Route", wm9713_enum[8]);
  305. /* speaker right output mux */
  306. static const struct snd_kcontrol_new wm9713_hp_spkr_mux_controls =
  307. SOC_DAPM_ENUM("Route", wm9713_enum[9]);
  308. /* headphone left output mux */
  309. static const struct snd_kcontrol_new wm9713_hpl_out_mux_controls =
  310. SOC_DAPM_ENUM("Route", wm9713_enum[10]);
  311. /* headphone right output mux */
  312. static const struct snd_kcontrol_new wm9713_hpr_out_mux_controls =
  313. SOC_DAPM_ENUM("Route", wm9713_enum[11]);
  314. /* Out3 mux */
  315. static const struct snd_kcontrol_new wm9713_out3_mux_controls =
  316. SOC_DAPM_ENUM("Route", wm9713_enum[12]);
  317. /* Out4 mux */
  318. static const struct snd_kcontrol_new wm9713_out4_mux_controls =
  319. SOC_DAPM_ENUM("Route", wm9713_enum[13]);
  320. /* DAC inv mux 1 */
  321. static const struct snd_kcontrol_new wm9713_dac_inv1_mux_controls =
  322. SOC_DAPM_ENUM("Route", wm9713_enum[14]);
  323. /* DAC inv mux 2 */
  324. static const struct snd_kcontrol_new wm9713_dac_inv2_mux_controls =
  325. SOC_DAPM_ENUM("Route", wm9713_enum[15]);
  326. /* Capture source left */
  327. static const struct snd_kcontrol_new wm9713_rec_srcl_mux_controls =
  328. SOC_DAPM_ENUM("Route", wm9713_enum[3]);
  329. /* Capture source right */
  330. static const struct snd_kcontrol_new wm9713_rec_srcr_mux_controls =
  331. SOC_DAPM_ENUM("Route", wm9713_enum[4]);
  332. /* mic source */
  333. static const struct snd_kcontrol_new wm9713_mic_sel_mux_controls =
  334. SOC_DAPM_ENUM("Route", wm9713_enum[18]);
  335. /* mic source B virtual control */
  336. static const struct snd_kcontrol_new wm9713_micb_sel_mux_controls =
  337. SOC_DAPM_ENUM("Route", wm9713_enum[19]);
  338. static const struct snd_soc_dapm_widget wm9713_dapm_widgets[] = {
  339. SND_SOC_DAPM_MUX("Capture Headphone Mux", SND_SOC_NOPM, 0, 0,
  340. &wm9713_hp_rec_mux_controls),
  341. SND_SOC_DAPM_MUX("Sidetone Mux", SND_SOC_NOPM, 0, 0,
  342. &wm9713_hp_mic_mux_controls),
  343. SND_SOC_DAPM_MUX("Capture Mono Mux", SND_SOC_NOPM, 0, 0,
  344. &wm9713_mono_mic_mux_controls),
  345. SND_SOC_DAPM_MUX("Mono Out Mux", SND_SOC_NOPM, 0, 0,
  346. &wm9713_mono_mux_controls),
  347. SND_SOC_DAPM_MUX("Left Speaker Out Mux", SND_SOC_NOPM, 0, 0,
  348. &wm9713_hp_spkl_mux_controls),
  349. SND_SOC_DAPM_MUX("Right Speaker Out Mux", SND_SOC_NOPM, 0, 0,
  350. &wm9713_hp_spkr_mux_controls),
  351. SND_SOC_DAPM_MUX("Left Headphone Out Mux", SND_SOC_NOPM, 0, 0,
  352. &wm9713_hpl_out_mux_controls),
  353. SND_SOC_DAPM_MUX("Right Headphone Out Mux", SND_SOC_NOPM, 0, 0,
  354. &wm9713_hpr_out_mux_controls),
  355. SND_SOC_DAPM_MUX("Out 3 Mux", SND_SOC_NOPM, 0, 0,
  356. &wm9713_out3_mux_controls),
  357. SND_SOC_DAPM_MUX("Out 4 Mux", SND_SOC_NOPM, 0, 0,
  358. &wm9713_out4_mux_controls),
  359. SND_SOC_DAPM_MUX("DAC Inv Mux 1", SND_SOC_NOPM, 0, 0,
  360. &wm9713_dac_inv1_mux_controls),
  361. SND_SOC_DAPM_MUX("DAC Inv Mux 2", SND_SOC_NOPM, 0, 0,
  362. &wm9713_dac_inv2_mux_controls),
  363. SND_SOC_DAPM_MUX("Left Capture Source", SND_SOC_NOPM, 0, 0,
  364. &wm9713_rec_srcl_mux_controls),
  365. SND_SOC_DAPM_MUX("Right Capture Source", SND_SOC_NOPM, 0, 0,
  366. &wm9713_rec_srcr_mux_controls),
  367. SND_SOC_DAPM_MUX("Mic A Source", SND_SOC_NOPM, 0, 0,
  368. &wm9713_mic_sel_mux_controls),
  369. SND_SOC_DAPM_MUX("Mic B Source", SND_SOC_NOPM, 0, 0,
  370. &wm9713_micb_sel_mux_controls),
  371. SND_SOC_DAPM_MIXER("Left HP Mixer", AC97_EXTENDED_MID, 3, 1,
  372. &wm9713_hpl_mixer_controls[0], ARRAY_SIZE(wm9713_hpl_mixer_controls)),
  373. SND_SOC_DAPM_MIXER("Right HP Mixer", AC97_EXTENDED_MID, 2, 1,
  374. &wm9713_hpr_mixer_controls[0], ARRAY_SIZE(wm9713_hpr_mixer_controls)),
  375. SND_SOC_DAPM_MIXER("Mono Mixer", AC97_EXTENDED_MID, 0, 1,
  376. &wm9713_mono_mixer_controls[0], ARRAY_SIZE(wm9713_mono_mixer_controls)),
  377. SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_EXTENDED_MID, 1, 1,
  378. &wm9713_speaker_mixer_controls[0],
  379. ARRAY_SIZE(wm9713_speaker_mixer_controls)),
  380. SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback", AC97_EXTENDED_MID, 7, 1),
  381. SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback", AC97_EXTENDED_MID, 6, 1),
  382. SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
  383. SND_SOC_DAPM_MIXER("HP Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
  384. SND_SOC_DAPM_MIXER("Line Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
  385. SND_SOC_DAPM_MIXER("Capture Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
  386. SND_SOC_DAPM_DAC_E("Voice DAC", "Voice Playback", AC97_EXTENDED_MID, 12, 1,
  387. wm9713_voice_shutdown, SND_SOC_DAPM_PRE_PMD),
  388. SND_SOC_DAPM_DAC("Aux DAC", "Aux Playback", AC97_EXTENDED_MID, 11, 1),
  389. SND_SOC_DAPM_PGA("Left ADC", AC97_EXTENDED_MID, 5, 1, NULL, 0),
  390. SND_SOC_DAPM_PGA("Right ADC", AC97_EXTENDED_MID, 4, 1, NULL, 0),
  391. SND_SOC_DAPM_ADC("Left HiFi ADC", "Left HiFi Capture", SND_SOC_NOPM, 0, 0),
  392. SND_SOC_DAPM_ADC("Right HiFi ADC", "Right HiFi Capture", SND_SOC_NOPM, 0, 0),
  393. SND_SOC_DAPM_ADC("Left Voice ADC", "Left Voice Capture", SND_SOC_NOPM, 0, 0),
  394. SND_SOC_DAPM_ADC("Right Voice ADC", "Right Voice Capture", SND_SOC_NOPM, 0, 0),
  395. SND_SOC_DAPM_PGA("Left Headphone", AC97_EXTENDED_MSTATUS, 10, 1, NULL, 0),
  396. SND_SOC_DAPM_PGA("Right Headphone", AC97_EXTENDED_MSTATUS, 9, 1, NULL, 0),
  397. SND_SOC_DAPM_PGA("Left Speaker", AC97_EXTENDED_MSTATUS, 8, 1, NULL, 0),
  398. SND_SOC_DAPM_PGA("Right Speaker", AC97_EXTENDED_MSTATUS, 7, 1, NULL, 0),
  399. SND_SOC_DAPM_PGA("Out 3", AC97_EXTENDED_MSTATUS, 11, 1, NULL, 0),
  400. SND_SOC_DAPM_PGA("Out 4", AC97_EXTENDED_MSTATUS, 12, 1, NULL, 0),
  401. SND_SOC_DAPM_PGA("Mono Out", AC97_EXTENDED_MSTATUS, 13, 1, NULL, 0),
  402. SND_SOC_DAPM_PGA("Left Line In", AC97_EXTENDED_MSTATUS, 6, 1, NULL, 0),
  403. SND_SOC_DAPM_PGA("Right Line In", AC97_EXTENDED_MSTATUS, 5, 1, NULL, 0),
  404. SND_SOC_DAPM_PGA("Mono In", AC97_EXTENDED_MSTATUS, 4, 1, NULL, 0),
  405. SND_SOC_DAPM_PGA("Mic A PGA", AC97_EXTENDED_MSTATUS, 3, 1, NULL, 0),
  406. SND_SOC_DAPM_PGA("Mic B PGA", AC97_EXTENDED_MSTATUS, 2, 1, NULL, 0),
  407. SND_SOC_DAPM_PGA("Mic A Pre Amp", AC97_EXTENDED_MSTATUS, 1, 1, NULL, 0),
  408. SND_SOC_DAPM_PGA("Mic B Pre Amp", AC97_EXTENDED_MSTATUS, 0, 1, NULL, 0),
  409. SND_SOC_DAPM_MICBIAS("Mic Bias", AC97_EXTENDED_MSTATUS, 14, 1),
  410. SND_SOC_DAPM_OUTPUT("MONO"),
  411. SND_SOC_DAPM_OUTPUT("HPL"),
  412. SND_SOC_DAPM_OUTPUT("HPR"),
  413. SND_SOC_DAPM_OUTPUT("SPKL"),
  414. SND_SOC_DAPM_OUTPUT("SPKR"),
  415. SND_SOC_DAPM_OUTPUT("OUT3"),
  416. SND_SOC_DAPM_OUTPUT("OUT4"),
  417. SND_SOC_DAPM_INPUT("LINEL"),
  418. SND_SOC_DAPM_INPUT("LINER"),
  419. SND_SOC_DAPM_INPUT("MONOIN"),
  420. SND_SOC_DAPM_INPUT("PCBEEP"),
  421. SND_SOC_DAPM_INPUT("MIC1"),
  422. SND_SOC_DAPM_INPUT("MIC2A"),
  423. SND_SOC_DAPM_INPUT("MIC2B"),
  424. SND_SOC_DAPM_VMID("VMID"),
  425. };
  426. static const struct snd_soc_dapm_route wm9713_audio_map[] = {
  427. /* left HP mixer */
  428. {"Left HP Mixer", "Beep Playback Switch", "PCBEEP"},
  429. {"Left HP Mixer", "Voice Playback Switch", "Voice DAC"},
  430. {"Left HP Mixer", "Aux Playback Switch", "Aux DAC"},
  431. {"Left HP Mixer", "Bypass Playback Switch", "Left Line In"},
  432. {"Left HP Mixer", "PCM Playback Switch", "Left DAC"},
  433. {"Left HP Mixer", "MonoIn Playback Switch", "Mono In"},
  434. {"Left HP Mixer", NULL, "Capture Headphone Mux"},
  435. /* right HP mixer */
  436. {"Right HP Mixer", "Beep Playback Switch", "PCBEEP"},
  437. {"Right HP Mixer", "Voice Playback Switch", "Voice DAC"},
  438. {"Right HP Mixer", "Aux Playback Switch", "Aux DAC"},
  439. {"Right HP Mixer", "Bypass Playback Switch", "Right Line In"},
  440. {"Right HP Mixer", "PCM Playback Switch", "Right DAC"},
  441. {"Right HP Mixer", "MonoIn Playback Switch", "Mono In"},
  442. {"Right HP Mixer", NULL, "Capture Headphone Mux"},
  443. /* virtual mixer - mixes left & right channels for spk and mono */
  444. {"AC97 Mixer", NULL, "Left DAC"},
  445. {"AC97 Mixer", NULL, "Right DAC"},
  446. {"Line Mixer", NULL, "Right Line In"},
  447. {"Line Mixer", NULL, "Left Line In"},
  448. {"HP Mixer", NULL, "Left HP Mixer"},
  449. {"HP Mixer", NULL, "Right HP Mixer"},
  450. {"Capture Mixer", NULL, "Left Capture Source"},
  451. {"Capture Mixer", NULL, "Right Capture Source"},
  452. /* speaker mixer */
  453. {"Speaker Mixer", "Beep Playback Switch", "PCBEEP"},
  454. {"Speaker Mixer", "Voice Playback Switch", "Voice DAC"},
  455. {"Speaker Mixer", "Aux Playback Switch", "Aux DAC"},
  456. {"Speaker Mixer", "Bypass Playback Switch", "Line Mixer"},
  457. {"Speaker Mixer", "PCM Playback Switch", "AC97 Mixer"},
  458. {"Speaker Mixer", "MonoIn Playback Switch", "Mono In"},
  459. /* mono mixer */
  460. {"Mono Mixer", "Beep Playback Switch", "PCBEEP"},
  461. {"Mono Mixer", "Voice Playback Switch", "Voice DAC"},
  462. {"Mono Mixer", "Aux Playback Switch", "Aux DAC"},
  463. {"Mono Mixer", "Bypass Playback Switch", "Line Mixer"},
  464. {"Mono Mixer", "PCM Playback Switch", "AC97 Mixer"},
  465. {"Mono Mixer", "Mic 1 Sidetone Switch", "Mic A PGA"},
  466. {"Mono Mixer", "Mic 2 Sidetone Switch", "Mic B PGA"},
  467. {"Mono Mixer", NULL, "Capture Mono Mux"},
  468. /* DAC inv mux 1 */
  469. {"DAC Inv Mux 1", "Mono", "Mono Mixer"},
  470. {"DAC Inv Mux 1", "Speaker", "Speaker Mixer"},
  471. {"DAC Inv Mux 1", "Left Headphone", "Left HP Mixer"},
  472. {"DAC Inv Mux 1", "Right Headphone", "Right HP Mixer"},
  473. {"DAC Inv Mux 1", "Headphone Mono", "HP Mixer"},
  474. /* DAC inv mux 2 */
  475. {"DAC Inv Mux 2", "Mono", "Mono Mixer"},
  476. {"DAC Inv Mux 2", "Speaker", "Speaker Mixer"},
  477. {"DAC Inv Mux 2", "Left Headphone", "Left HP Mixer"},
  478. {"DAC Inv Mux 2", "Right Headphone", "Right HP Mixer"},
  479. {"DAC Inv Mux 2", "Headphone Mono", "HP Mixer"},
  480. /* headphone left mux */
  481. {"Left Headphone Out Mux", "Headphone", "Left HP Mixer"},
  482. /* headphone right mux */
  483. {"Right Headphone Out Mux", "Headphone", "Right HP Mixer"},
  484. /* speaker left mux */
  485. {"Left Speaker Out Mux", "Headphone", "Left HP Mixer"},
  486. {"Left Speaker Out Mux", "Speaker", "Speaker Mixer"},
  487. {"Left Speaker Out Mux", "Inv", "DAC Inv Mux 1"},
  488. /* speaker right mux */
  489. {"Right Speaker Out Mux", "Headphone", "Right HP Mixer"},
  490. {"Right Speaker Out Mux", "Speaker", "Speaker Mixer"},
  491. {"Right Speaker Out Mux", "Inv", "DAC Inv Mux 2"},
  492. /* mono mux */
  493. {"Mono Out Mux", "Mono", "Mono Mixer"},
  494. {"Mono Out Mux", "Inv", "DAC Inv Mux 1"},
  495. /* out 3 mux */
  496. {"Out 3 Mux", "Inv 1", "DAC Inv Mux 1"},
  497. /* out 4 mux */
  498. {"Out 4 Mux", "Inv 2", "DAC Inv Mux 2"},
  499. /* output pga */
  500. {"HPL", NULL, "Left Headphone"},
  501. {"Left Headphone", NULL, "Left Headphone Out Mux"},
  502. {"HPR", NULL, "Right Headphone"},
  503. {"Right Headphone", NULL, "Right Headphone Out Mux"},
  504. {"OUT3", NULL, "Out 3"},
  505. {"Out 3", NULL, "Out 3 Mux"},
  506. {"OUT4", NULL, "Out 4"},
  507. {"Out 4", NULL, "Out 4 Mux"},
  508. {"SPKL", NULL, "Left Speaker"},
  509. {"Left Speaker", NULL, "Left Speaker Out Mux"},
  510. {"SPKR", NULL, "Right Speaker"},
  511. {"Right Speaker", NULL, "Right Speaker Out Mux"},
  512. {"MONO", NULL, "Mono Out"},
  513. {"Mono Out", NULL, "Mono Out Mux"},
  514. /* input pga */
  515. {"Left Line In", NULL, "LINEL"},
  516. {"Right Line In", NULL, "LINER"},
  517. {"Mono In", NULL, "MONOIN"},
  518. {"Mic A PGA", NULL, "Mic A Pre Amp"},
  519. {"Mic B PGA", NULL, "Mic B Pre Amp"},
  520. /* left capture select */
  521. {"Left Capture Source", "Mic 1", "Mic A Pre Amp"},
  522. {"Left Capture Source", "Mic 2", "Mic B Pre Amp"},
  523. {"Left Capture Source", "Line", "LINEL"},
  524. {"Left Capture Source", "Mono In", "MONOIN"},
  525. {"Left Capture Source", "Headphone", "Left HP Mixer"},
  526. {"Left Capture Source", "Speaker", "Speaker Mixer"},
  527. {"Left Capture Source", "Mono Out", "Mono Mixer"},
  528. /* right capture select */
  529. {"Right Capture Source", "Mic 1", "Mic A Pre Amp"},
  530. {"Right Capture Source", "Mic 2", "Mic B Pre Amp"},
  531. {"Right Capture Source", "Line", "LINER"},
  532. {"Right Capture Source", "Mono In", "MONOIN"},
  533. {"Right Capture Source", "Headphone", "Right HP Mixer"},
  534. {"Right Capture Source", "Speaker", "Speaker Mixer"},
  535. {"Right Capture Source", "Mono Out", "Mono Mixer"},
  536. /* left ADC */
  537. {"Left ADC", NULL, "Left Capture Source"},
  538. {"Left Voice ADC", NULL, "Left ADC"},
  539. {"Left HiFi ADC", NULL, "Left ADC"},
  540. /* right ADC */
  541. {"Right ADC", NULL, "Right Capture Source"},
  542. {"Right Voice ADC", NULL, "Right ADC"},
  543. {"Right HiFi ADC", NULL, "Right ADC"},
  544. /* mic */
  545. {"Mic A Pre Amp", NULL, "Mic A Source"},
  546. {"Mic A Source", "Mic 1", "MIC1"},
  547. {"Mic A Source", "Mic 2 A", "MIC2A"},
  548. {"Mic A Source", "Mic 2 B", "Mic B Source"},
  549. {"Mic B Pre Amp", "MPB", "Mic B Source"},
  550. {"Mic B Source", NULL, "MIC2B"},
  551. /* headphone capture */
  552. {"Capture Headphone Mux", "Stereo", "Capture Mixer"},
  553. {"Capture Headphone Mux", "Left", "Left Capture Source"},
  554. {"Capture Headphone Mux", "Right", "Right Capture Source"},
  555. /* mono capture */
  556. {"Capture Mono Mux", "Stereo", "Capture Mixer"},
  557. {"Capture Mono Mux", "Left", "Left Capture Source"},
  558. {"Capture Mono Mux", "Right", "Right Capture Source"},
  559. };
  560. static bool wm9713_readable_reg(struct device *dev, unsigned int reg)
  561. {
  562. switch (reg) {
  563. case AC97_RESET ... AC97_PCM_SURR_DAC_RATE:
  564. case AC97_PCM_LR_ADC_RATE:
  565. case AC97_CENTER_LFE_MASTER:
  566. case AC97_SPDIF ... AC97_LINE1_LEVEL:
  567. case AC97_GPIO_CFG ... 0x5c:
  568. case AC97_CODEC_CLASS_REV ... AC97_PCI_SID:
  569. case 0x74 ... AC97_VENDOR_ID2:
  570. return true;
  571. default:
  572. return false;
  573. }
  574. }
  575. static bool wm9713_writeable_reg(struct device *dev, unsigned int reg)
  576. {
  577. switch (reg) {
  578. case AC97_VENDOR_ID1:
  579. case AC97_VENDOR_ID2:
  580. return false;
  581. default:
  582. return wm9713_readable_reg(dev, reg);
  583. }
  584. }
  585. static const struct reg_default wm9713_reg_defaults[] = {
  586. { 0x02, 0x8080 }, /* Speaker Output Volume */
  587. { 0x04, 0x8080 }, /* Headphone Output Volume */
  588. { 0x06, 0x8080 }, /* Out3/OUT4 Volume */
  589. { 0x08, 0xc880 }, /* Mono Volume */
  590. { 0x0a, 0xe808 }, /* LINEIN Volume */
  591. { 0x0c, 0xe808 }, /* DAC PGA Volume */
  592. { 0x0e, 0x0808 }, /* MIC PGA Volume */
  593. { 0x10, 0x00da }, /* MIC Routing Control */
  594. { 0x12, 0x8000 }, /* Record PGA Volume */
  595. { 0x14, 0xd600 }, /* Record Routing */
  596. { 0x16, 0xaaa0 }, /* PCBEEP Volume */
  597. { 0x18, 0xaaa0 }, /* VxDAC Volume */
  598. { 0x1a, 0xaaa0 }, /* AUXDAC Volume */
  599. { 0x1c, 0x0000 }, /* Output PGA Mux */
  600. { 0x1e, 0x0000 }, /* DAC 3D control */
  601. { 0x20, 0x0f0f }, /* DAC Tone Control*/
  602. { 0x22, 0x0040 }, /* MIC Input Select & Bias */
  603. { 0x24, 0x0000 }, /* Output Volume Mapping & Jack */
  604. { 0x26, 0x7f00 }, /* Powerdown Ctrl/Stat*/
  605. { 0x28, 0x0405 }, /* Extended Audio ID */
  606. { 0x2a, 0x0410 }, /* Extended Audio Start/Ctrl */
  607. { 0x2c, 0xbb80 }, /* Audio DACs Sample Rate */
  608. { 0x2e, 0xbb80 }, /* AUXDAC Sample Rate */
  609. { 0x32, 0xbb80 }, /* Audio ADCs Sample Rate */
  610. { 0x36, 0x4523 }, /* PCM codec control */
  611. { 0x3a, 0x2000 }, /* SPDIF control */
  612. { 0x3c, 0xfdff }, /* Powerdown 1 */
  613. { 0x3e, 0xffff }, /* Powerdown 2 */
  614. { 0x40, 0x0000 }, /* General Purpose */
  615. { 0x42, 0x0000 }, /* Fast Power-Up Control */
  616. { 0x44, 0x0080 }, /* MCLK/PLL Control */
  617. { 0x46, 0x0000 }, /* MCLK/PLL Control */
  618. { 0x4c, 0xfffe }, /* GPIO Pin Configuration */
  619. { 0x4e, 0xffff }, /* GPIO Pin Polarity / Type */
  620. { 0x50, 0x0000 }, /* GPIO Pin Sticky */
  621. { 0x52, 0x0000 }, /* GPIO Pin Wake-Up */
  622. /* GPIO Pin Status */
  623. { 0x56, 0xfffe }, /* GPIO Pin Sharing */
  624. { 0x58, 0x4000 }, /* GPIO PullUp/PullDown */
  625. { 0x5a, 0x0000 }, /* Additional Functions 1 */
  626. { 0x5c, 0x0000 }, /* Additional Functions 2 */
  627. { 0x60, 0xb032 }, /* ALC Control */
  628. { 0x62, 0x3e00 }, /* ALC / Noise Gate Control */
  629. { 0x64, 0x0000 }, /* AUXDAC input control */
  630. { 0x74, 0x0000 }, /* Digitiser Reg 1 */
  631. { 0x76, 0x0006 }, /* Digitiser Reg 2 */
  632. { 0x78, 0x0001 }, /* Digitiser Reg 3 */
  633. { 0x7a, 0x0000 }, /* Digitiser Read Back */
  634. };
  635. static const struct regmap_config wm9713_regmap_config = {
  636. .reg_bits = 16,
  637. .reg_stride = 2,
  638. .val_bits = 16,
  639. .max_register = 0x7e,
  640. .cache_type = REGCACHE_RBTREE,
  641. .reg_defaults = wm9713_reg_defaults,
  642. .num_reg_defaults = ARRAY_SIZE(wm9713_reg_defaults),
  643. .volatile_reg = regmap_ac97_default_volatile,
  644. .readable_reg = wm9713_readable_reg,
  645. .writeable_reg = wm9713_writeable_reg,
  646. };
  647. /* PLL divisors */
  648. struct _pll_div {
  649. u32 divsel:1;
  650. u32 divctl:1;
  651. u32 lf:1;
  652. u32 n:4;
  653. u32 k:24;
  654. };
  655. /* The size in bits of the PLL divide multiplied by 10
  656. * to allow rounding later */
  657. #define FIXED_PLL_SIZE ((1 << 22) * 10)
  658. static void pll_factors(struct snd_soc_component *component,
  659. struct _pll_div *pll_div, unsigned int source)
  660. {
  661. u64 Kpart;
  662. unsigned int K, Ndiv, Nmod, target;
  663. /* The PLL output is always 98.304MHz. */
  664. target = 98304000;
  665. /* If the input frequency is over 14.4MHz then scale it down. */
  666. if (source > 14400000) {
  667. source >>= 1;
  668. pll_div->divsel = 1;
  669. if (source > 14400000) {
  670. source >>= 1;
  671. pll_div->divctl = 1;
  672. } else
  673. pll_div->divctl = 0;
  674. } else {
  675. pll_div->divsel = 0;
  676. pll_div->divctl = 0;
  677. }
  678. /* Low frequency sources require an additional divide in the
  679. * loop.
  680. */
  681. if (source < 8192000) {
  682. pll_div->lf = 1;
  683. target >>= 2;
  684. } else
  685. pll_div->lf = 0;
  686. Ndiv = target / source;
  687. if ((Ndiv < 5) || (Ndiv > 12))
  688. dev_warn(component->dev,
  689. "WM9713 PLL N value %u out of recommended range!\n",
  690. Ndiv);
  691. pll_div->n = Ndiv;
  692. Nmod = target % source;
  693. Kpart = FIXED_PLL_SIZE * (long long)Nmod;
  694. do_div(Kpart, source);
  695. K = Kpart & 0xFFFFFFFF;
  696. /* Check if we need to round */
  697. if ((K % 10) >= 5)
  698. K += 5;
  699. /* Move down to proper range now rounding is done */
  700. K /= 10;
  701. pll_div->k = K;
  702. }
  703. /*
  704. * Please note that changing the PLL input frequency may require
  705. * resynchronisation with the AC97 controller.
  706. */
  707. static int wm9713_set_pll(struct snd_soc_component *component,
  708. int pll_id, unsigned int freq_in, unsigned int freq_out)
  709. {
  710. struct wm9713_priv *wm9713 = snd_soc_component_get_drvdata(component);
  711. u16 reg, reg2;
  712. struct _pll_div pll_div;
  713. /* turn PLL off ? */
  714. if (freq_in == 0) {
  715. /* disable PLL power and select ext source */
  716. snd_soc_component_update_bits(component, AC97_HANDSET_RATE, 0x0080, 0x0080);
  717. snd_soc_component_update_bits(component, AC97_EXTENDED_MID, 0x0200, 0x0200);
  718. wm9713->pll_in = 0;
  719. return 0;
  720. }
  721. pll_factors(component, &pll_div, freq_in);
  722. if (pll_div.k == 0) {
  723. reg = (pll_div.n << 12) | (pll_div.lf << 11) |
  724. (pll_div.divsel << 9) | (pll_div.divctl << 8);
  725. snd_soc_component_write(component, AC97_LINE1_LEVEL, reg);
  726. } else {
  727. /* write the fractional k to the reg 0x46 pages */
  728. reg2 = (pll_div.n << 12) | (pll_div.lf << 11) | (1 << 10) |
  729. (pll_div.divsel << 9) | (pll_div.divctl << 8);
  730. /* K [21:20] */
  731. reg = reg2 | (0x5 << 4) | (pll_div.k >> 20);
  732. snd_soc_component_write(component, AC97_LINE1_LEVEL, reg);
  733. /* K [19:16] */
  734. reg = reg2 | (0x4 << 4) | ((pll_div.k >> 16) & 0xf);
  735. snd_soc_component_write(component, AC97_LINE1_LEVEL, reg);
  736. /* K [15:12] */
  737. reg = reg2 | (0x3 << 4) | ((pll_div.k >> 12) & 0xf);
  738. snd_soc_component_write(component, AC97_LINE1_LEVEL, reg);
  739. /* K [11:8] */
  740. reg = reg2 | (0x2 << 4) | ((pll_div.k >> 8) & 0xf);
  741. snd_soc_component_write(component, AC97_LINE1_LEVEL, reg);
  742. /* K [7:4] */
  743. reg = reg2 | (0x1 << 4) | ((pll_div.k >> 4) & 0xf);
  744. snd_soc_component_write(component, AC97_LINE1_LEVEL, reg);
  745. reg = reg2 | (0x0 << 4) | (pll_div.k & 0xf); /* K [3:0] */
  746. snd_soc_component_write(component, AC97_LINE1_LEVEL, reg);
  747. }
  748. /* turn PLL on and select as source */
  749. snd_soc_component_update_bits(component, AC97_EXTENDED_MID, 0x0200, 0x0000);
  750. snd_soc_component_update_bits(component, AC97_HANDSET_RATE, 0x0080, 0x0000);
  751. wm9713->pll_in = freq_in;
  752. /* wait 10ms AC97 link frames for the link to stabilise */
  753. schedule_timeout_interruptible(msecs_to_jiffies(10));
  754. return 0;
  755. }
  756. static int wm9713_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
  757. int source, unsigned int freq_in, unsigned int freq_out)
  758. {
  759. struct snd_soc_component *component = codec_dai->component;
  760. return wm9713_set_pll(component, pll_id, freq_in, freq_out);
  761. }
  762. /*
  763. * Tristate the PCM DAI lines, tristate can be disabled by calling
  764. * wm9713_set_dai_fmt()
  765. */
  766. static int wm9713_set_dai_tristate(struct snd_soc_dai *codec_dai,
  767. int tristate)
  768. {
  769. struct snd_soc_component *component = codec_dai->component;
  770. if (tristate)
  771. snd_soc_component_update_bits(component, AC97_CENTER_LFE_MASTER,
  772. 0x6000, 0x0000);
  773. return 0;
  774. }
  775. /*
  776. * Configure WM9713 clock dividers.
  777. * Voice DAC needs 256 FS
  778. */
  779. static int wm9713_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
  780. int div_id, int div)
  781. {
  782. struct snd_soc_component *component = codec_dai->component;
  783. switch (div_id) {
  784. case WM9713_PCMCLK_DIV:
  785. snd_soc_component_update_bits(component, AC97_HANDSET_RATE, 0x0f00, div);
  786. break;
  787. case WM9713_CLKA_MULT:
  788. snd_soc_component_update_bits(component, AC97_HANDSET_RATE, 0x0002, div);
  789. break;
  790. case WM9713_CLKB_MULT:
  791. snd_soc_component_update_bits(component, AC97_HANDSET_RATE, 0x0004, div);
  792. break;
  793. case WM9713_HIFI_DIV:
  794. snd_soc_component_update_bits(component, AC97_HANDSET_RATE, 0x7000, div);
  795. break;
  796. case WM9713_PCMBCLK_DIV:
  797. snd_soc_component_update_bits(component, AC97_CENTER_LFE_MASTER, 0x0e00, div);
  798. break;
  799. case WM9713_PCMCLK_PLL_DIV:
  800. snd_soc_component_update_bits(component, AC97_LINE1_LEVEL,
  801. 0x007f, div | 0x60);
  802. break;
  803. case WM9713_HIFI_PLL_DIV:
  804. snd_soc_component_update_bits(component, AC97_LINE1_LEVEL,
  805. 0x007f, div | 0x70);
  806. break;
  807. default:
  808. return -EINVAL;
  809. }
  810. return 0;
  811. }
  812. static int wm9713_set_dai_fmt(struct snd_soc_dai *codec_dai,
  813. unsigned int fmt)
  814. {
  815. struct snd_soc_component *component = codec_dai->component;
  816. u16 gpio = snd_soc_component_read(component, AC97_GPIO_CFG) & 0xffc5;
  817. u16 reg = 0x8000;
  818. /* clock masters */
  819. switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
  820. case SND_SOC_DAIFMT_CBM_CFM:
  821. reg |= 0x4000;
  822. gpio |= 0x0010;
  823. break;
  824. case SND_SOC_DAIFMT_CBM_CFS:
  825. reg |= 0x6000;
  826. gpio |= 0x0018;
  827. break;
  828. case SND_SOC_DAIFMT_CBS_CFS:
  829. reg |= 0x2000;
  830. gpio |= 0x001a;
  831. break;
  832. case SND_SOC_DAIFMT_CBS_CFM:
  833. gpio |= 0x0012;
  834. break;
  835. }
  836. /* clock inversion */
  837. switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
  838. case SND_SOC_DAIFMT_IB_IF:
  839. reg |= 0x00c0;
  840. break;
  841. case SND_SOC_DAIFMT_IB_NF:
  842. reg |= 0x0080;
  843. break;
  844. case SND_SOC_DAIFMT_NB_IF:
  845. reg |= 0x0040;
  846. break;
  847. }
  848. /* DAI format */
  849. switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  850. case SND_SOC_DAIFMT_I2S:
  851. reg |= 0x0002;
  852. break;
  853. case SND_SOC_DAIFMT_RIGHT_J:
  854. break;
  855. case SND_SOC_DAIFMT_LEFT_J:
  856. reg |= 0x0001;
  857. break;
  858. case SND_SOC_DAIFMT_DSP_A:
  859. reg |= 0x0003;
  860. break;
  861. case SND_SOC_DAIFMT_DSP_B:
  862. reg |= 0x0043;
  863. break;
  864. }
  865. snd_soc_component_write(component, AC97_GPIO_CFG, gpio);
  866. snd_soc_component_write(component, AC97_CENTER_LFE_MASTER, reg);
  867. return 0;
  868. }
  869. static int wm9713_pcm_hw_params(struct snd_pcm_substream *substream,
  870. struct snd_pcm_hw_params *params,
  871. struct snd_soc_dai *dai)
  872. {
  873. struct snd_soc_component *component = dai->component;
  874. /* enable PCM interface in master mode */
  875. switch (params_width(params)) {
  876. case 16:
  877. break;
  878. case 20:
  879. snd_soc_component_update_bits(component, AC97_CENTER_LFE_MASTER,
  880. 0x000c, 0x0004);
  881. break;
  882. case 24:
  883. snd_soc_component_update_bits(component, AC97_CENTER_LFE_MASTER,
  884. 0x000c, 0x0008);
  885. break;
  886. case 32:
  887. snd_soc_component_update_bits(component, AC97_CENTER_LFE_MASTER,
  888. 0x000c, 0x000c);
  889. break;
  890. }
  891. return 0;
  892. }
  893. static int ac97_hifi_prepare(struct snd_pcm_substream *substream,
  894. struct snd_soc_dai *dai)
  895. {
  896. struct snd_soc_component *component = dai->component;
  897. struct snd_pcm_runtime *runtime = substream->runtime;
  898. int reg;
  899. snd_soc_component_update_bits(component, AC97_EXTENDED_STATUS, 0x0001, 0x0001);
  900. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  901. reg = AC97_PCM_FRONT_DAC_RATE;
  902. else
  903. reg = AC97_PCM_LR_ADC_RATE;
  904. return snd_soc_component_write(component, reg, runtime->rate);
  905. }
  906. static int ac97_aux_prepare(struct snd_pcm_substream *substream,
  907. struct snd_soc_dai *dai)
  908. {
  909. struct snd_soc_component *component = dai->component;
  910. struct snd_pcm_runtime *runtime = substream->runtime;
  911. snd_soc_component_update_bits(component, AC97_EXTENDED_STATUS, 0x0001, 0x0001);
  912. snd_soc_component_update_bits(component, AC97_PCI_SID, 0x8000, 0x8000);
  913. if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
  914. return -ENODEV;
  915. return snd_soc_component_write(component, AC97_PCM_SURR_DAC_RATE, runtime->rate);
  916. }
  917. #define WM9713_RATES (SNDRV_PCM_RATE_8000 | \
  918. SNDRV_PCM_RATE_11025 | \
  919. SNDRV_PCM_RATE_22050 | \
  920. SNDRV_PCM_RATE_44100 | \
  921. SNDRV_PCM_RATE_48000)
  922. #define WM9713_PCM_RATES (SNDRV_PCM_RATE_8000 | \
  923. SNDRV_PCM_RATE_11025 | \
  924. SNDRV_PCM_RATE_16000 | \
  925. SNDRV_PCM_RATE_22050 | \
  926. SNDRV_PCM_RATE_44100 | \
  927. SNDRV_PCM_RATE_48000)
  928. #define WM9713_PCM_FORMATS \
  929. (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
  930. SNDRV_PCM_FMTBIT_S24_LE)
  931. static const struct snd_soc_dai_ops wm9713_dai_ops_hifi = {
  932. .prepare = ac97_hifi_prepare,
  933. .set_clkdiv = wm9713_set_dai_clkdiv,
  934. .set_pll = wm9713_set_dai_pll,
  935. };
  936. static const struct snd_soc_dai_ops wm9713_dai_ops_aux = {
  937. .prepare = ac97_aux_prepare,
  938. .set_clkdiv = wm9713_set_dai_clkdiv,
  939. .set_pll = wm9713_set_dai_pll,
  940. };
  941. static const struct snd_soc_dai_ops wm9713_dai_ops_voice = {
  942. .hw_params = wm9713_pcm_hw_params,
  943. .set_clkdiv = wm9713_set_dai_clkdiv,
  944. .set_pll = wm9713_set_dai_pll,
  945. .set_fmt = wm9713_set_dai_fmt,
  946. .set_tristate = wm9713_set_dai_tristate,
  947. };
  948. static struct snd_soc_dai_driver wm9713_dai[] = {
  949. {
  950. .name = "wm9713-hifi",
  951. .playback = {
  952. .stream_name = "HiFi Playback",
  953. .channels_min = 1,
  954. .channels_max = 2,
  955. .rates = WM9713_RATES,
  956. .formats = SND_SOC_STD_AC97_FMTS,},
  957. .capture = {
  958. .stream_name = "HiFi Capture",
  959. .channels_min = 1,
  960. .channels_max = 2,
  961. .rates = WM9713_RATES,
  962. .formats = SND_SOC_STD_AC97_FMTS,},
  963. .ops = &wm9713_dai_ops_hifi,
  964. },
  965. {
  966. .name = "wm9713-aux",
  967. .playback = {
  968. .stream_name = "Aux Playback",
  969. .channels_min = 1,
  970. .channels_max = 1,
  971. .rates = WM9713_RATES,
  972. .formats = SND_SOC_STD_AC97_FMTS,},
  973. .ops = &wm9713_dai_ops_aux,
  974. },
  975. {
  976. .name = "wm9713-voice",
  977. .playback = {
  978. .stream_name = "Voice Playback",
  979. .channels_min = 1,
  980. .channels_max = 1,
  981. .rates = WM9713_PCM_RATES,
  982. .formats = WM9713_PCM_FORMATS,},
  983. .capture = {
  984. .stream_name = "Voice Capture",
  985. .channels_min = 1,
  986. .channels_max = 2,
  987. .rates = WM9713_PCM_RATES,
  988. .formats = WM9713_PCM_FORMATS,},
  989. .ops = &wm9713_dai_ops_voice,
  990. .symmetric_rates = 1,
  991. },
  992. };
  993. static int wm9713_set_bias_level(struct snd_soc_component *component,
  994. enum snd_soc_bias_level level)
  995. {
  996. switch (level) {
  997. case SND_SOC_BIAS_ON:
  998. /* enable thermal shutdown */
  999. snd_soc_component_update_bits(component, AC97_EXTENDED_MID, 0xe400, 0x0000);
  1000. break;
  1001. case SND_SOC_BIAS_PREPARE:
  1002. break;
  1003. case SND_SOC_BIAS_STANDBY:
  1004. /* enable master bias and vmid */
  1005. snd_soc_component_update_bits(component, AC97_EXTENDED_MID, 0xc400, 0x0000);
  1006. snd_soc_component_write(component, AC97_POWERDOWN, 0x0000);
  1007. break;
  1008. case SND_SOC_BIAS_OFF:
  1009. /* disable everything including AC link */
  1010. snd_soc_component_write(component, AC97_EXTENDED_MID, 0xffff);
  1011. snd_soc_component_write(component, AC97_EXTENDED_MSTATUS, 0xffff);
  1012. snd_soc_component_write(component, AC97_POWERDOWN, 0xffff);
  1013. break;
  1014. }
  1015. return 0;
  1016. }
  1017. static int wm9713_soc_suspend(struct snd_soc_component *component)
  1018. {
  1019. /* Disable everything except touchpanel - that will be handled
  1020. * by the touch driver and left disabled if touch is not in
  1021. * use. */
  1022. snd_soc_component_update_bits(component, AC97_EXTENDED_MID, 0x7fff,
  1023. 0x7fff);
  1024. snd_soc_component_write(component, AC97_EXTENDED_MSTATUS, 0xffff);
  1025. snd_soc_component_write(component, AC97_POWERDOWN, 0x6f00);
  1026. snd_soc_component_write(component, AC97_POWERDOWN, 0xffff);
  1027. return 0;
  1028. }
  1029. static int wm9713_soc_resume(struct snd_soc_component *component)
  1030. {
  1031. struct wm9713_priv *wm9713 = snd_soc_component_get_drvdata(component);
  1032. int ret;
  1033. ret = snd_ac97_reset(wm9713->ac97, true, WM9713_VENDOR_ID,
  1034. WM9713_VENDOR_ID_MASK);
  1035. if (ret < 0)
  1036. return ret;
  1037. snd_soc_component_force_bias_level(component, SND_SOC_BIAS_STANDBY);
  1038. /* do we need to re-start the PLL ? */
  1039. if (wm9713->pll_in)
  1040. wm9713_set_pll(component, 0, wm9713->pll_in, 0);
  1041. /* only synchronise the codec if warm reset failed */
  1042. if (ret == 0) {
  1043. regcache_mark_dirty(component->regmap);
  1044. snd_soc_component_cache_sync(component);
  1045. }
  1046. return ret;
  1047. }
  1048. static int wm9713_soc_probe(struct snd_soc_component *component)
  1049. {
  1050. struct wm9713_priv *wm9713 = snd_soc_component_get_drvdata(component);
  1051. struct regmap *regmap = NULL;
  1052. if (wm9713->mfd_pdata) {
  1053. wm9713->ac97 = wm9713->mfd_pdata->ac97;
  1054. regmap = wm9713->mfd_pdata->regmap;
  1055. } else if (IS_ENABLED(CONFIG_SND_SOC_AC97_BUS)) {
  1056. wm9713->ac97 = snd_soc_new_ac97_component(component, WM9713_VENDOR_ID,
  1057. WM9713_VENDOR_ID_MASK);
  1058. if (IS_ERR(wm9713->ac97))
  1059. return PTR_ERR(wm9713->ac97);
  1060. regmap = regmap_init_ac97(wm9713->ac97, &wm9713_regmap_config);
  1061. if (IS_ERR(regmap)) {
  1062. snd_soc_free_ac97_component(wm9713->ac97);
  1063. return PTR_ERR(regmap);
  1064. }
  1065. } else {
  1066. return -ENXIO;
  1067. }
  1068. snd_soc_component_init_regmap(component, regmap);
  1069. /* unmute the adc - move to kcontrol */
  1070. snd_soc_component_update_bits(component, AC97_CD, 0x7fff, 0x0000);
  1071. return 0;
  1072. }
  1073. static void wm9713_soc_remove(struct snd_soc_component *component)
  1074. {
  1075. struct wm9713_priv *wm9713 = snd_soc_component_get_drvdata(component);
  1076. if (IS_ENABLED(CONFIG_SND_SOC_AC97_BUS) && !wm9713->mfd_pdata) {
  1077. snd_soc_component_exit_regmap(component);
  1078. snd_soc_free_ac97_component(wm9713->ac97);
  1079. }
  1080. }
  1081. static const struct snd_soc_component_driver soc_component_dev_wm9713 = {
  1082. .probe = wm9713_soc_probe,
  1083. .remove = wm9713_soc_remove,
  1084. .suspend = wm9713_soc_suspend,
  1085. .resume = wm9713_soc_resume,
  1086. .set_bias_level = wm9713_set_bias_level,
  1087. .controls = wm9713_snd_ac97_controls,
  1088. .num_controls = ARRAY_SIZE(wm9713_snd_ac97_controls),
  1089. .dapm_widgets = wm9713_dapm_widgets,
  1090. .num_dapm_widgets = ARRAY_SIZE(wm9713_dapm_widgets),
  1091. .dapm_routes = wm9713_audio_map,
  1092. .num_dapm_routes = ARRAY_SIZE(wm9713_audio_map),
  1093. .idle_bias_on = 1,
  1094. .use_pmdown_time = 1,
  1095. .endianness = 1,
  1096. .non_legacy_dai_naming = 1,
  1097. };
  1098. static int wm9713_probe(struct platform_device *pdev)
  1099. {
  1100. struct wm9713_priv *wm9713;
  1101. wm9713 = devm_kzalloc(&pdev->dev, sizeof(*wm9713), GFP_KERNEL);
  1102. if (wm9713 == NULL)
  1103. return -ENOMEM;
  1104. mutex_init(&wm9713->lock);
  1105. wm9713->mfd_pdata = dev_get_platdata(&pdev->dev);
  1106. platform_set_drvdata(pdev, wm9713);
  1107. return devm_snd_soc_register_component(&pdev->dev,
  1108. &soc_component_dev_wm9713, wm9713_dai, ARRAY_SIZE(wm9713_dai));
  1109. }
  1110. static struct platform_driver wm9713_codec_driver = {
  1111. .driver = {
  1112. .name = "wm9713-codec",
  1113. },
  1114. .probe = wm9713_probe,
  1115. };
  1116. module_platform_driver(wm9713_codec_driver);
  1117. MODULE_DESCRIPTION("ASoC WM9713/WM9714 driver");
  1118. MODULE_AUTHOR("Liam Girdwood");
  1119. MODULE_LICENSE("GPL");