ml26124.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. /*
  2. * Copyright (C) 2011 LAPIS Semiconductor Co., Ltd.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; version 2 of the License.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program; if not, write to the Free Software
  15. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  16. */
  17. #include <linux/module.h>
  18. #include <linux/moduleparam.h>
  19. #include <linux/init.h>
  20. #include <linux/delay.h>
  21. #include <linux/pm.h>
  22. #include <linux/i2c.h>
  23. #include <linux/slab.h>
  24. #include <linux/platform_device.h>
  25. #include <linux/regmap.h>
  26. #include <sound/core.h>
  27. #include <sound/pcm.h>
  28. #include <sound/pcm_params.h>
  29. #include <sound/soc.h>
  30. #include <sound/tlv.h>
  31. #include "ml26124.h"
  32. #define DVOL_CTL_DVMUTE_ON BIT(4) /* Digital volume MUTE On */
  33. #define DVOL_CTL_DVMUTE_OFF 0 /* Digital volume MUTE Off */
  34. #define ML26124_SAI_NO_DELAY BIT(1)
  35. #define ML26124_SAI_FRAME_SYNC (BIT(5) | BIT(0)) /* For mono (Telecodec) */
  36. #define ML26134_CACHESIZE 212
  37. #define ML26124_VMID BIT(1)
  38. #define ML26124_RATES (SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_32000 |\
  39. SNDRV_PCM_RATE_48000)
  40. #define ML26124_FORMATS (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |\
  41. SNDRV_PCM_FMTBIT_S32_LE)
  42. #define ML26124_NUM_REGISTER ML26134_CACHESIZE
  43. struct ml26124_priv {
  44. u32 mclk;
  45. u32 rate;
  46. struct regmap *regmap;
  47. int clk_in;
  48. struct snd_pcm_substream *substream;
  49. };
  50. struct clk_coeff {
  51. u32 mclk;
  52. u32 rate;
  53. u8 pllnl;
  54. u8 pllnh;
  55. u8 pllml;
  56. u8 pllmh;
  57. u8 plldiv;
  58. };
  59. /* ML26124 configuration */
  60. static const DECLARE_TLV_DB_SCALE(digital_tlv, -7150, 50, 0);
  61. static const DECLARE_TLV_DB_SCALE(alclvl, -2250, 150, 0);
  62. static const DECLARE_TLV_DB_SCALE(mingain, -1200, 600, 0);
  63. static const DECLARE_TLV_DB_SCALE(maxgain, -675, 600, 0);
  64. static const DECLARE_TLV_DB_SCALE(boost_vol, -1200, 75, 0);
  65. static const DECLARE_TLV_DB_SCALE(ngth, -7650, 150, 0);
  66. static const char * const ml26124_companding[] = {"16bit PCM", "u-law",
  67. "A-law"};
  68. static SOC_ENUM_SINGLE_DECL(ml26124_adc_companding_enum,
  69. ML26124_SAI_TRANS_CTL, 6, ml26124_companding);
  70. static SOC_ENUM_SINGLE_DECL(ml26124_dac_companding_enum,
  71. ML26124_SAI_RCV_CTL, 6, ml26124_companding);
  72. static const struct snd_kcontrol_new ml26124_snd_controls[] = {
  73. SOC_SINGLE_TLV("Capture Digital Volume", ML26124_RECORD_DIG_VOL, 0,
  74. 0xff, 1, digital_tlv),
  75. SOC_SINGLE_TLV("Playback Digital Volume", ML26124_PLBAK_DIG_VOL, 0,
  76. 0xff, 1, digital_tlv),
  77. SOC_SINGLE_TLV("Digital Boost Volume", ML26124_DIGI_BOOST_VOL, 0,
  78. 0x3f, 0, boost_vol),
  79. SOC_SINGLE_TLV("EQ Band0 Volume", ML26124_EQ_GAIN_BRAND0, 0,
  80. 0xff, 1, digital_tlv),
  81. SOC_SINGLE_TLV("EQ Band1 Volume", ML26124_EQ_GAIN_BRAND1, 0,
  82. 0xff, 1, digital_tlv),
  83. SOC_SINGLE_TLV("EQ Band2 Volume", ML26124_EQ_GAIN_BRAND2, 0,
  84. 0xff, 1, digital_tlv),
  85. SOC_SINGLE_TLV("EQ Band3 Volume", ML26124_EQ_GAIN_BRAND3, 0,
  86. 0xff, 1, digital_tlv),
  87. SOC_SINGLE_TLV("EQ Band4 Volume", ML26124_EQ_GAIN_BRAND4, 0,
  88. 0xff, 1, digital_tlv),
  89. SOC_SINGLE_TLV("ALC Target Level", ML26124_ALC_TARGET_LEV, 0,
  90. 0xf, 1, alclvl),
  91. SOC_SINGLE_TLV("ALC Min Input Volume", ML26124_ALC_MAXMIN_GAIN, 0,
  92. 7, 0, mingain),
  93. SOC_SINGLE_TLV("ALC Max Input Volume", ML26124_ALC_MAXMIN_GAIN, 4,
  94. 7, 1, maxgain),
  95. SOC_SINGLE_TLV("Playback Limiter Min Input Volume",
  96. ML26124_PL_MAXMIN_GAIN, 0, 7, 0, mingain),
  97. SOC_SINGLE_TLV("Playback Limiter Max Input Volume",
  98. ML26124_PL_MAXMIN_GAIN, 4, 7, 1, maxgain),
  99. SOC_SINGLE_TLV("Playback Boost Volume", ML26124_PLYBAK_BOST_VOL, 0,
  100. 0x3f, 0, boost_vol),
  101. SOC_SINGLE("DC High Pass Filter Switch", ML26124_FILTER_EN, 0, 1, 0),
  102. SOC_SINGLE("Noise High Pass Filter Switch", ML26124_FILTER_EN, 1, 1, 0),
  103. SOC_SINGLE("ZC Switch", ML26124_PW_ZCCMP_PW_MNG, 1,
  104. 1, 0),
  105. SOC_SINGLE("EQ Band0 Switch", ML26124_FILTER_EN, 2, 1, 0),
  106. SOC_SINGLE("EQ Band1 Switch", ML26124_FILTER_EN, 3, 1, 0),
  107. SOC_SINGLE("EQ Band2 Switch", ML26124_FILTER_EN, 4, 1, 0),
  108. SOC_SINGLE("EQ Band3 Switch", ML26124_FILTER_EN, 5, 1, 0),
  109. SOC_SINGLE("EQ Band4 Switch", ML26124_FILTER_EN, 6, 1, 0),
  110. SOC_SINGLE("Play Limiter", ML26124_DVOL_CTL, 0, 1, 0),
  111. SOC_SINGLE("Capture Limiter", ML26124_DVOL_CTL, 1, 1, 0),
  112. SOC_SINGLE("Digital Volume Fade Switch", ML26124_DVOL_CTL, 3, 1, 0),
  113. SOC_SINGLE("Digital Switch", ML26124_DVOL_CTL, 4, 1, 0),
  114. SOC_ENUM("DAC Companding", ml26124_dac_companding_enum),
  115. SOC_ENUM("ADC Companding", ml26124_adc_companding_enum),
  116. };
  117. static const struct snd_kcontrol_new ml26124_output_mixer_controls[] = {
  118. SOC_DAPM_SINGLE("DAC Switch", ML26124_SPK_AMP_OUT, 1, 1, 0),
  119. SOC_DAPM_SINGLE("Line in loopback Switch", ML26124_SPK_AMP_OUT, 3, 1,
  120. 0),
  121. SOC_DAPM_SINGLE("PGA Switch", ML26124_SPK_AMP_OUT, 5, 1, 0),
  122. };
  123. /* Input mux */
  124. static const char * const ml26124_input_select[] = {"Analog MIC SingleEnded in",
  125. "Digital MIC in", "Analog MIC Differential in"};
  126. static SOC_ENUM_SINGLE_DECL(ml26124_insel_enum,
  127. ML26124_MIC_IF_CTL, 0, ml26124_input_select);
  128. static const struct snd_kcontrol_new ml26124_input_mux_controls =
  129. SOC_DAPM_ENUM("Input Select", ml26124_insel_enum);
  130. static const struct snd_kcontrol_new ml26124_line_control =
  131. SOC_DAPM_SINGLE("Switch", ML26124_PW_LOUT_PW_MNG, 1, 1, 0);
  132. static const struct snd_soc_dapm_widget ml26124_dapm_widgets[] = {
  133. SND_SOC_DAPM_SUPPLY("MCLKEN", ML26124_CLK_EN, 0, 0, NULL, 0),
  134. SND_SOC_DAPM_SUPPLY("PLLEN", ML26124_CLK_EN, 1, 0, NULL, 0),
  135. SND_SOC_DAPM_SUPPLY("PLLOE", ML26124_CLK_EN, 2, 0, NULL, 0),
  136. SND_SOC_DAPM_SUPPLY("MICBIAS", ML26124_PW_REF_PW_MNG, 2, 0, NULL, 0),
  137. SND_SOC_DAPM_MIXER("Output Mixer", SND_SOC_NOPM, 0, 0,
  138. &ml26124_output_mixer_controls[0],
  139. ARRAY_SIZE(ml26124_output_mixer_controls)),
  140. SND_SOC_DAPM_DAC("DAC", "Playback", ML26124_PW_DAC_PW_MNG, 1, 0),
  141. SND_SOC_DAPM_ADC("ADC", "Capture", ML26124_PW_IN_PW_MNG, 1, 0),
  142. SND_SOC_DAPM_PGA("PGA", ML26124_PW_IN_PW_MNG, 3, 0, NULL, 0),
  143. SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0,
  144. &ml26124_input_mux_controls),
  145. SND_SOC_DAPM_SWITCH("Line Out Enable", SND_SOC_NOPM, 0, 0,
  146. &ml26124_line_control),
  147. SND_SOC_DAPM_INPUT("MDIN"),
  148. SND_SOC_DAPM_INPUT("MIN"),
  149. SND_SOC_DAPM_INPUT("LIN"),
  150. SND_SOC_DAPM_OUTPUT("SPOUT"),
  151. SND_SOC_DAPM_OUTPUT("LOUT"),
  152. };
  153. static const struct snd_soc_dapm_route ml26124_intercon[] = {
  154. /* Supply */
  155. {"DAC", NULL, "MCLKEN"},
  156. {"ADC", NULL, "MCLKEN"},
  157. {"DAC", NULL, "PLLEN"},
  158. {"ADC", NULL, "PLLEN"},
  159. {"DAC", NULL, "PLLOE"},
  160. {"ADC", NULL, "PLLOE"},
  161. /* output mixer */
  162. {"Output Mixer", "DAC Switch", "DAC"},
  163. {"Output Mixer", "Line in loopback Switch", "LIN"},
  164. /* outputs */
  165. {"LOUT", NULL, "Output Mixer"},
  166. {"SPOUT", NULL, "Output Mixer"},
  167. {"Line Out Enable", NULL, "LOUT"},
  168. /* input */
  169. {"ADC", NULL, "Input Mux"},
  170. {"Input Mux", "Analog MIC SingleEnded in", "PGA"},
  171. {"Input Mux", "Analog MIC Differential in", "PGA"},
  172. {"PGA", NULL, "MIN"},
  173. };
  174. /* PLLOutputFreq(Hz) = InputMclkFreq(Hz) * PLLM / (PLLN * PLLDIV) */
  175. static const struct clk_coeff coeff_div[] = {
  176. {12288000, 16000, 0xc, 0x0, 0x20, 0x0, 0x4},
  177. {12288000, 32000, 0xc, 0x0, 0x20, 0x0, 0x4},
  178. {12288000, 48000, 0xc, 0x0, 0x30, 0x0, 0x4},
  179. };
  180. static const struct reg_default ml26124_reg[] = {
  181. /* CLOCK control Register */
  182. {0x00, 0x00 }, /* Sampling Rate */
  183. {0x02, 0x00}, /* PLL NL */
  184. {0x04, 0x00}, /* PLLNH */
  185. {0x06, 0x00}, /* PLLML */
  186. {0x08, 0x00}, /* MLLMH */
  187. {0x0a, 0x00}, /* PLLDIV */
  188. {0x0c, 0x00}, /* Clock Enable */
  189. {0x0e, 0x00}, /* CLK Input/Output Control */
  190. /* System Control Register */
  191. {0x10, 0x00}, /* Software RESET */
  192. {0x12, 0x00}, /* Record/Playback Run */
  193. {0x14, 0x00}, /* Mic Input/Output control */
  194. /* Power Management Register */
  195. {0x20, 0x00}, /* Reference Power Management */
  196. {0x22, 0x00}, /* Input Power Management */
  197. {0x24, 0x00}, /* DAC Power Management */
  198. {0x26, 0x00}, /* SP-AMP Power Management */
  199. {0x28, 0x00}, /* LINEOUT Power Management */
  200. {0x2a, 0x00}, /* VIDEO Power Management */
  201. {0x2e, 0x00}, /* AC-CMP Power Management */
  202. /* Analog reference Control Register */
  203. {0x30, 0x04}, /* MICBIAS Voltage Control */
  204. /* Input/Output Amplifier Control Register */
  205. {0x32, 0x10}, /* MIC Input Volume */
  206. {0x38, 0x00}, /* Mic Boost Volume */
  207. {0x3a, 0x33}, /* Speaker AMP Volume */
  208. {0x48, 0x00}, /* AMP Volume Control Function Enable */
  209. {0x4a, 0x00}, /* Amplifier Volume Fader Control */
  210. /* Analog Path Control Register */
  211. {0x54, 0x00}, /* Speaker AMP Output Control */
  212. {0x5a, 0x00}, /* Mic IF Control */
  213. {0xe8, 0x01}, /* Mic Select Control */
  214. /* Audio Interface Control Register */
  215. {0x60, 0x00}, /* SAI-Trans Control */
  216. {0x62, 0x00}, /* SAI-Receive Control */
  217. {0x64, 0x00}, /* SAI Mode select */
  218. /* DSP Control Register */
  219. {0x66, 0x01}, /* Filter Func Enable */
  220. {0x68, 0x00}, /* Volume Control Func Enable */
  221. {0x6A, 0x00}, /* Mixer & Volume Control*/
  222. {0x6C, 0xff}, /* Record Digital Volume */
  223. {0x70, 0xff}, /* Playback Digital Volume */
  224. {0x72, 0x10}, /* Digital Boost Volume */
  225. {0x74, 0xe7}, /* EQ gain Band0 */
  226. {0x76, 0xe7}, /* EQ gain Band1 */
  227. {0x78, 0xe7}, /* EQ gain Band2 */
  228. {0x7A, 0xe7}, /* EQ gain Band3 */
  229. {0x7C, 0xe7}, /* EQ gain Band4 */
  230. {0x7E, 0x00}, /* HPF2 CutOff*/
  231. {0x80, 0x00}, /* EQ Band0 Coef0L */
  232. {0x82, 0x00}, /* EQ Band0 Coef0H */
  233. {0x84, 0x00}, /* EQ Band0 Coef0L */
  234. {0x86, 0x00}, /* EQ Band0 Coef0H */
  235. {0x88, 0x00}, /* EQ Band1 Coef0L */
  236. {0x8A, 0x00}, /* EQ Band1 Coef0H */
  237. {0x8C, 0x00}, /* EQ Band1 Coef0L */
  238. {0x8E, 0x00}, /* EQ Band1 Coef0H */
  239. {0x90, 0x00}, /* EQ Band2 Coef0L */
  240. {0x92, 0x00}, /* EQ Band2 Coef0H */
  241. {0x94, 0x00}, /* EQ Band2 Coef0L */
  242. {0x96, 0x00}, /* EQ Band2 Coef0H */
  243. {0x98, 0x00}, /* EQ Band3 Coef0L */
  244. {0x9A, 0x00}, /* EQ Band3 Coef0H */
  245. {0x9C, 0x00}, /* EQ Band3 Coef0L */
  246. {0x9E, 0x00}, /* EQ Band3 Coef0H */
  247. {0xA0, 0x00}, /* EQ Band4 Coef0L */
  248. {0xA2, 0x00}, /* EQ Band4 Coef0H */
  249. {0xA4, 0x00}, /* EQ Band4 Coef0L */
  250. {0xA6, 0x00}, /* EQ Band4 Coef0H */
  251. /* ALC Control Register */
  252. {0xb0, 0x00}, /* ALC Mode */
  253. {0xb2, 0x02}, /* ALC Attack Time */
  254. {0xb4, 0x03}, /* ALC Decay Time */
  255. {0xb6, 0x00}, /* ALC Hold Time */
  256. {0xb8, 0x0b}, /* ALC Target Level */
  257. {0xba, 0x70}, /* ALC Max/Min Gain */
  258. {0xbc, 0x00}, /* Noise Gate Threshold */
  259. {0xbe, 0x00}, /* ALC ZeroCross TimeOut */
  260. /* Playback Limiter Control Register */
  261. {0xc0, 0x04}, /* PL Attack Time */
  262. {0xc2, 0x05}, /* PL Decay Time */
  263. {0xc4, 0x0d}, /* PL Target Level */
  264. {0xc6, 0x70}, /* PL Max/Min Gain */
  265. {0xc8, 0x10}, /* Playback Boost Volume */
  266. {0xca, 0x00}, /* PL ZeroCross TimeOut */
  267. /* Video Amplifier Control Register */
  268. {0xd0, 0x01}, /* VIDEO AMP Gain Control */
  269. {0xd2, 0x01}, /* VIDEO AMP Setup 1 */
  270. {0xd4, 0x01}, /* VIDEO AMP Control2 */
  271. };
  272. /* Get sampling rate value of sampling rate setting register (0x0) */
  273. static inline int get_srate(int rate)
  274. {
  275. int srate;
  276. switch (rate) {
  277. case 16000:
  278. srate = 3;
  279. break;
  280. case 32000:
  281. srate = 6;
  282. break;
  283. case 48000:
  284. srate = 8;
  285. break;
  286. default:
  287. return -EINVAL;
  288. }
  289. return srate;
  290. }
  291. static inline int get_coeff(int mclk, int rate)
  292. {
  293. int i;
  294. for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
  295. if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
  296. return i;
  297. }
  298. return -EINVAL;
  299. }
  300. static int ml26124_hw_params(struct snd_pcm_substream *substream,
  301. struct snd_pcm_hw_params *hw_params,
  302. struct snd_soc_dai *dai)
  303. {
  304. struct snd_soc_codec *codec = dai->codec;
  305. struct ml26124_priv *priv = snd_soc_codec_get_drvdata(codec);
  306. int i = get_coeff(priv->mclk, params_rate(hw_params));
  307. int srate;
  308. if (i < 0)
  309. return i;
  310. priv->substream = substream;
  311. priv->rate = params_rate(hw_params);
  312. if (priv->clk_in) {
  313. switch (priv->mclk / params_rate(hw_params)) {
  314. case 256:
  315. snd_soc_update_bits(codec, ML26124_CLK_CTL,
  316. BIT(0) | BIT(1), 1);
  317. break;
  318. case 512:
  319. snd_soc_update_bits(codec, ML26124_CLK_CTL,
  320. BIT(0) | BIT(1), 2);
  321. break;
  322. case 1024:
  323. snd_soc_update_bits(codec, ML26124_CLK_CTL,
  324. BIT(0) | BIT(1), 3);
  325. break;
  326. default:
  327. dev_err(codec->dev, "Unsupported MCLKI\n");
  328. break;
  329. }
  330. } else {
  331. snd_soc_update_bits(codec, ML26124_CLK_CTL,
  332. BIT(0) | BIT(1), 0);
  333. }
  334. srate = get_srate(params_rate(hw_params));
  335. if (srate < 0)
  336. return srate;
  337. snd_soc_update_bits(codec, ML26124_SMPLING_RATE, 0xf, srate);
  338. snd_soc_update_bits(codec, ML26124_PLLNL, 0xff, coeff_div[i].pllnl);
  339. snd_soc_update_bits(codec, ML26124_PLLNH, 0x1, coeff_div[i].pllnh);
  340. snd_soc_update_bits(codec, ML26124_PLLML, 0xff, coeff_div[i].pllml);
  341. snd_soc_update_bits(codec, ML26124_PLLMH, 0x3f, coeff_div[i].pllmh);
  342. snd_soc_update_bits(codec, ML26124_PLLDIV, 0x1f, coeff_div[i].plldiv);
  343. return 0;
  344. }
  345. static int ml26124_mute(struct snd_soc_dai *dai, int mute)
  346. {
  347. struct snd_soc_codec *codec = dai->codec;
  348. struct ml26124_priv *priv = snd_soc_codec_get_drvdata(codec);
  349. switch (priv->substream->stream) {
  350. case SNDRV_PCM_STREAM_CAPTURE:
  351. snd_soc_update_bits(codec, ML26124_REC_PLYBAK_RUN, BIT(0), 1);
  352. break;
  353. case SNDRV_PCM_STREAM_PLAYBACK:
  354. snd_soc_update_bits(codec, ML26124_REC_PLYBAK_RUN, BIT(1), 2);
  355. break;
  356. }
  357. if (mute)
  358. snd_soc_update_bits(codec, ML26124_DVOL_CTL, BIT(4),
  359. DVOL_CTL_DVMUTE_ON);
  360. else
  361. snd_soc_update_bits(codec, ML26124_DVOL_CTL, BIT(4),
  362. DVOL_CTL_DVMUTE_OFF);
  363. return 0;
  364. }
  365. static int ml26124_set_dai_fmt(struct snd_soc_dai *codec_dai,
  366. unsigned int fmt)
  367. {
  368. unsigned char mode;
  369. struct snd_soc_codec *codec = codec_dai->codec;
  370. /* set master/slave audio interface */
  371. switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
  372. case SND_SOC_DAIFMT_CBM_CFM:
  373. mode = 1;
  374. break;
  375. case SND_SOC_DAIFMT_CBS_CFS:
  376. mode = 0;
  377. break;
  378. default:
  379. return -EINVAL;
  380. }
  381. snd_soc_update_bits(codec, ML26124_SAI_MODE_SEL, BIT(0), mode);
  382. /* interface format */
  383. switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  384. case SND_SOC_DAIFMT_I2S:
  385. break;
  386. default:
  387. return -EINVAL;
  388. }
  389. /* clock inversion */
  390. switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
  391. case SND_SOC_DAIFMT_NB_NF:
  392. break;
  393. default:
  394. return -EINVAL;
  395. }
  396. return 0;
  397. }
  398. static int ml26124_set_dai_sysclk(struct snd_soc_dai *codec_dai,
  399. int clk_id, unsigned int freq, int dir)
  400. {
  401. struct snd_soc_codec *codec = codec_dai->codec;
  402. struct ml26124_priv *priv = snd_soc_codec_get_drvdata(codec);
  403. switch (clk_id) {
  404. case ML26124_USE_PLLOUT:
  405. priv->clk_in = ML26124_USE_PLLOUT;
  406. break;
  407. case ML26124_USE_MCLKI:
  408. priv->clk_in = ML26124_USE_MCLKI;
  409. break;
  410. default:
  411. return -EINVAL;
  412. }
  413. priv->mclk = freq;
  414. return 0;
  415. }
  416. static int ml26124_set_bias_level(struct snd_soc_codec *codec,
  417. enum snd_soc_bias_level level)
  418. {
  419. struct ml26124_priv *priv = snd_soc_codec_get_drvdata(codec);
  420. switch (level) {
  421. case SND_SOC_BIAS_ON:
  422. snd_soc_update_bits(codec, ML26124_PW_SPAMP_PW_MNG,
  423. ML26124_R26_MASK, ML26124_BLT_PREAMP_ON);
  424. msleep(100);
  425. snd_soc_update_bits(codec, ML26124_PW_SPAMP_PW_MNG,
  426. ML26124_R26_MASK,
  427. ML26124_MICBEN_ON | ML26124_BLT_ALL_ON);
  428. break;
  429. case SND_SOC_BIAS_PREPARE:
  430. break;
  431. case SND_SOC_BIAS_STANDBY:
  432. /* VMID ON */
  433. if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
  434. snd_soc_update_bits(codec, ML26124_PW_REF_PW_MNG,
  435. ML26124_VMID, ML26124_VMID);
  436. msleep(500);
  437. regcache_sync(priv->regmap);
  438. }
  439. break;
  440. case SND_SOC_BIAS_OFF:
  441. /* VMID OFF */
  442. snd_soc_update_bits(codec, ML26124_PW_REF_PW_MNG,
  443. ML26124_VMID, 0);
  444. break;
  445. }
  446. return 0;
  447. }
  448. static const struct snd_soc_dai_ops ml26124_dai_ops = {
  449. .hw_params = ml26124_hw_params,
  450. .digital_mute = ml26124_mute,
  451. .set_fmt = ml26124_set_dai_fmt,
  452. .set_sysclk = ml26124_set_dai_sysclk,
  453. };
  454. static struct snd_soc_dai_driver ml26124_dai = {
  455. .name = "ml26124-hifi",
  456. .playback = {
  457. .stream_name = "Playback",
  458. .channels_min = 1,
  459. .channels_max = 2,
  460. .rates = ML26124_RATES,
  461. .formats = ML26124_FORMATS,},
  462. .capture = {
  463. .stream_name = "Capture",
  464. .channels_min = 1,
  465. .channels_max = 2,
  466. .rates = ML26124_RATES,
  467. .formats = ML26124_FORMATS,},
  468. .ops = &ml26124_dai_ops,
  469. .symmetric_rates = 1,
  470. };
  471. static int ml26124_probe(struct snd_soc_codec *codec)
  472. {
  473. /* Software Reset */
  474. snd_soc_update_bits(codec, ML26124_SW_RST, 0x01, 1);
  475. snd_soc_update_bits(codec, ML26124_SW_RST, 0x01, 0);
  476. return 0;
  477. }
  478. static struct snd_soc_codec_driver soc_codec_dev_ml26124 = {
  479. .probe = ml26124_probe,
  480. .set_bias_level = ml26124_set_bias_level,
  481. .suspend_bias_off = true,
  482. .component_driver = {
  483. .controls = ml26124_snd_controls,
  484. .num_controls = ARRAY_SIZE(ml26124_snd_controls),
  485. .dapm_widgets = ml26124_dapm_widgets,
  486. .num_dapm_widgets = ARRAY_SIZE(ml26124_dapm_widgets),
  487. .dapm_routes = ml26124_intercon,
  488. .num_dapm_routes = ARRAY_SIZE(ml26124_intercon),
  489. },
  490. };
  491. static const struct regmap_config ml26124_i2c_regmap = {
  492. .val_bits = 8,
  493. .reg_bits = 8,
  494. .max_register = ML26124_NUM_REGISTER,
  495. .reg_defaults = ml26124_reg,
  496. .num_reg_defaults = ARRAY_SIZE(ml26124_reg),
  497. .cache_type = REGCACHE_RBTREE,
  498. .write_flag_mask = 0x01,
  499. };
  500. static int ml26124_i2c_probe(struct i2c_client *i2c,
  501. const struct i2c_device_id *id)
  502. {
  503. struct ml26124_priv *priv;
  504. int ret;
  505. priv = devm_kzalloc(&i2c->dev, sizeof(*priv), GFP_KERNEL);
  506. if (!priv)
  507. return -ENOMEM;
  508. i2c_set_clientdata(i2c, priv);
  509. priv->regmap = devm_regmap_init_i2c(i2c, &ml26124_i2c_regmap);
  510. if (IS_ERR(priv->regmap)) {
  511. ret = PTR_ERR(priv->regmap);
  512. dev_err(&i2c->dev, "regmap_init_i2c() failed: %d\n", ret);
  513. return ret;
  514. }
  515. return snd_soc_register_codec(&i2c->dev,
  516. &soc_codec_dev_ml26124, &ml26124_dai, 1);
  517. }
  518. static int ml26124_i2c_remove(struct i2c_client *client)
  519. {
  520. snd_soc_unregister_codec(&client->dev);
  521. return 0;
  522. }
  523. static const struct i2c_device_id ml26124_i2c_id[] = {
  524. { "ml26124", 0 },
  525. { }
  526. };
  527. MODULE_DEVICE_TABLE(i2c, ml26124_i2c_id);
  528. static struct i2c_driver ml26124_i2c_driver = {
  529. .driver = {
  530. .name = "ml26124",
  531. },
  532. .probe = ml26124_i2c_probe,
  533. .remove = ml26124_i2c_remove,
  534. .id_table = ml26124_i2c_id,
  535. };
  536. module_i2c_driver(ml26124_i2c_driver);
  537. MODULE_AUTHOR("Tomoya MORINAGA <tomoya.rohm@gmail.com>");
  538. MODULE_DESCRIPTION("LAPIS Semiconductor ML26124 ALSA SoC codec driver");
  539. MODULE_LICENSE("GPL");