ml26124.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  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 const struct soc_enum ml26124_adc_companding_enum
  69. = SOC_ENUM_SINGLE(ML26124_SAI_TRANS_CTL, 6, 3, ml26124_companding);
  70. static const struct soc_enum ml26124_dac_companding_enum
  71. = SOC_ENUM_SINGLE(ML26124_SAI_RCV_CTL, 6, 3, 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 const struct soc_enum ml26124_insel_enum =
  127. SOC_ENUM_SINGLE(ML26124_MIC_IF_CTL, 0, 3, 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 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. priv->substream = substream;
  308. priv->rate = params_rate(hw_params);
  309. if (priv->clk_in) {
  310. switch (priv->mclk / params_rate(hw_params)) {
  311. case 256:
  312. snd_soc_update_bits(codec, ML26124_CLK_CTL,
  313. BIT(0) | BIT(1), 1);
  314. break;
  315. case 512:
  316. snd_soc_update_bits(codec, ML26124_CLK_CTL,
  317. BIT(0) | BIT(1), 2);
  318. break;
  319. case 1024:
  320. snd_soc_update_bits(codec, ML26124_CLK_CTL,
  321. BIT(0) | BIT(1), 3);
  322. break;
  323. default:
  324. dev_err(codec->dev, "Unsupported MCLKI\n");
  325. break;
  326. }
  327. } else {
  328. snd_soc_update_bits(codec, ML26124_CLK_CTL,
  329. BIT(0) | BIT(1), 0);
  330. }
  331. switch (params_rate(hw_params)) {
  332. case 16000:
  333. snd_soc_update_bits(codec, ML26124_SMPLING_RATE, 0xf,
  334. get_srate(params_rate(hw_params)));
  335. snd_soc_update_bits(codec, ML26124_PLLNL, 0xff,
  336. coeff_div[i].pllnl);
  337. snd_soc_update_bits(codec, ML26124_PLLNH, 0x1,
  338. coeff_div[i].pllnh);
  339. snd_soc_update_bits(codec, ML26124_PLLML, 0xff,
  340. coeff_div[i].pllml);
  341. snd_soc_update_bits(codec, ML26124_PLLMH, 0x3f,
  342. coeff_div[i].pllmh);
  343. snd_soc_update_bits(codec, ML26124_PLLDIV, 0x1f,
  344. coeff_div[i].plldiv);
  345. break;
  346. case 32000:
  347. snd_soc_update_bits(codec, ML26124_SMPLING_RATE, 0xf,
  348. get_srate(params_rate(hw_params)));
  349. snd_soc_update_bits(codec, ML26124_PLLNL, 0xff,
  350. coeff_div[i].pllnl);
  351. snd_soc_update_bits(codec, ML26124_PLLNH, 0x1,
  352. coeff_div[i].pllnh);
  353. snd_soc_update_bits(codec, ML26124_PLLML, 0xff,
  354. coeff_div[i].pllml);
  355. snd_soc_update_bits(codec, ML26124_PLLMH, 0x3f,
  356. coeff_div[i].pllmh);
  357. snd_soc_update_bits(codec, ML26124_PLLDIV, 0x1f,
  358. coeff_div[i].plldiv);
  359. break;
  360. case 48000:
  361. snd_soc_update_bits(codec, ML26124_SMPLING_RATE, 0xf,
  362. get_srate(params_rate(hw_params)));
  363. snd_soc_update_bits(codec, ML26124_PLLNL, 0xff,
  364. coeff_div[i].pllnl);
  365. snd_soc_update_bits(codec, ML26124_PLLNH, 0x1,
  366. coeff_div[i].pllnh);
  367. snd_soc_update_bits(codec, ML26124_PLLML, 0xff,
  368. coeff_div[i].pllml);
  369. snd_soc_update_bits(codec, ML26124_PLLMH, 0x3f,
  370. coeff_div[i].pllmh);
  371. snd_soc_update_bits(codec, ML26124_PLLDIV, 0x1f,
  372. coeff_div[i].plldiv);
  373. break;
  374. default:
  375. pr_err("%s:this rate is no support for ml26124\n", __func__);
  376. return -EINVAL;
  377. }
  378. return 0;
  379. }
  380. static int ml26124_mute(struct snd_soc_dai *dai, int mute)
  381. {
  382. struct snd_soc_codec *codec = dai->codec;
  383. struct ml26124_priv *priv = snd_soc_codec_get_drvdata(codec);
  384. switch (priv->substream->stream) {
  385. case SNDRV_PCM_STREAM_CAPTURE:
  386. snd_soc_update_bits(codec, ML26124_REC_PLYBAK_RUN, BIT(0), 1);
  387. break;
  388. case SNDRV_PCM_STREAM_PLAYBACK:
  389. snd_soc_update_bits(codec, ML26124_REC_PLYBAK_RUN, BIT(1), 2);
  390. break;
  391. }
  392. if (mute)
  393. snd_soc_update_bits(codec, ML26124_DVOL_CTL, BIT(4),
  394. DVOL_CTL_DVMUTE_ON);
  395. else
  396. snd_soc_update_bits(codec, ML26124_DVOL_CTL, BIT(4),
  397. DVOL_CTL_DVMUTE_OFF);
  398. return 0;
  399. }
  400. static int ml26124_set_dai_fmt(struct snd_soc_dai *codec_dai,
  401. unsigned int fmt)
  402. {
  403. unsigned char mode;
  404. struct snd_soc_codec *codec = codec_dai->codec;
  405. /* set master/slave audio interface */
  406. switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
  407. case SND_SOC_DAIFMT_CBM_CFM:
  408. mode = 1;
  409. break;
  410. case SND_SOC_DAIFMT_CBS_CFS:
  411. mode = 0;
  412. break;
  413. default:
  414. return -EINVAL;
  415. }
  416. snd_soc_update_bits(codec, ML26124_SAI_MODE_SEL, BIT(0), mode);
  417. /* interface format */
  418. switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  419. case SND_SOC_DAIFMT_I2S:
  420. break;
  421. default:
  422. return -EINVAL;
  423. }
  424. /* clock inversion */
  425. switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
  426. case SND_SOC_DAIFMT_NB_NF:
  427. break;
  428. default:
  429. return -EINVAL;
  430. }
  431. return 0;
  432. }
  433. static int ml26124_set_dai_sysclk(struct snd_soc_dai *codec_dai,
  434. int clk_id, unsigned int freq, int dir)
  435. {
  436. struct snd_soc_codec *codec = codec_dai->codec;
  437. struct ml26124_priv *priv = snd_soc_codec_get_drvdata(codec);
  438. switch (clk_id) {
  439. case ML26124_USE_PLLOUT:
  440. priv->clk_in = ML26124_USE_PLLOUT;
  441. break;
  442. case ML26124_USE_MCLKI:
  443. priv->clk_in = ML26124_USE_MCLKI;
  444. break;
  445. default:
  446. return -EINVAL;
  447. }
  448. priv->mclk = freq;
  449. return 0;
  450. }
  451. static int ml26124_set_bias_level(struct snd_soc_codec *codec,
  452. enum snd_soc_bias_level level)
  453. {
  454. struct ml26124_priv *priv = snd_soc_codec_get_drvdata(codec);
  455. switch (level) {
  456. case SND_SOC_BIAS_ON:
  457. snd_soc_update_bits(codec, ML26124_PW_SPAMP_PW_MNG,
  458. ML26124_R26_MASK, ML26124_BLT_PREAMP_ON);
  459. msleep(100);
  460. snd_soc_update_bits(codec, ML26124_PW_SPAMP_PW_MNG,
  461. ML26124_R26_MASK,
  462. ML26124_MICBEN_ON | ML26124_BLT_ALL_ON);
  463. break;
  464. case SND_SOC_BIAS_PREPARE:
  465. break;
  466. case SND_SOC_BIAS_STANDBY:
  467. /* VMID ON */
  468. if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
  469. snd_soc_update_bits(codec, ML26124_PW_REF_PW_MNG,
  470. ML26124_VMID, ML26124_VMID);
  471. msleep(500);
  472. regcache_sync(priv->regmap);
  473. }
  474. break;
  475. case SND_SOC_BIAS_OFF:
  476. /* VMID OFF */
  477. snd_soc_update_bits(codec, ML26124_PW_REF_PW_MNG,
  478. ML26124_VMID, 0);
  479. break;
  480. }
  481. codec->dapm.bias_level = level;
  482. return 0;
  483. }
  484. static const struct snd_soc_dai_ops ml26124_dai_ops = {
  485. .hw_params = ml26124_hw_params,
  486. .digital_mute = ml26124_mute,
  487. .set_fmt = ml26124_set_dai_fmt,
  488. .set_sysclk = ml26124_set_dai_sysclk,
  489. };
  490. static struct snd_soc_dai_driver ml26124_dai = {
  491. .name = "ml26124-hifi",
  492. .playback = {
  493. .stream_name = "Playback",
  494. .channels_min = 1,
  495. .channels_max = 2,
  496. .rates = ML26124_RATES,
  497. .formats = ML26124_FORMATS,},
  498. .capture = {
  499. .stream_name = "Capture",
  500. .channels_min = 1,
  501. .channels_max = 2,
  502. .rates = ML26124_RATES,
  503. .formats = ML26124_FORMATS,},
  504. .ops = &ml26124_dai_ops,
  505. .symmetric_rates = 1,
  506. };
  507. #ifdef CONFIG_PM
  508. static int ml26124_suspend(struct snd_soc_codec *codec)
  509. {
  510. ml26124_set_bias_level(codec, SND_SOC_BIAS_OFF);
  511. return 0;
  512. }
  513. static int ml26124_resume(struct snd_soc_codec *codec)
  514. {
  515. ml26124_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
  516. return 0;
  517. }
  518. #else
  519. #define ml26124_suspend NULL
  520. #define ml26124_resume NULL
  521. #endif
  522. static int ml26124_probe(struct snd_soc_codec *codec)
  523. {
  524. int ret;
  525. struct ml26124_priv *priv = snd_soc_codec_get_drvdata(codec);
  526. codec->control_data = priv->regmap;
  527. ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
  528. if (ret < 0) {
  529. dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
  530. return ret;
  531. }
  532. /* Software Reset */
  533. snd_soc_update_bits(codec, ML26124_SW_RST, 0x01, 1);
  534. snd_soc_update_bits(codec, ML26124_SW_RST, 0x01, 0);
  535. ml26124_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
  536. return 0;
  537. }
  538. static struct snd_soc_codec_driver soc_codec_dev_ml26124 = {
  539. .probe = ml26124_probe,
  540. .suspend = ml26124_suspend,
  541. .resume = ml26124_resume,
  542. .set_bias_level = ml26124_set_bias_level,
  543. .dapm_widgets = ml26124_dapm_widgets,
  544. .num_dapm_widgets = ARRAY_SIZE(ml26124_dapm_widgets),
  545. .dapm_routes = ml26124_intercon,
  546. .num_dapm_routes = ARRAY_SIZE(ml26124_intercon),
  547. .controls = ml26124_snd_controls,
  548. .num_controls = ARRAY_SIZE(ml26124_snd_controls),
  549. };
  550. static const struct regmap_config ml26124_i2c_regmap = {
  551. .val_bits = 8,
  552. .reg_bits = 8,
  553. .max_register = ML26124_NUM_REGISTER,
  554. .reg_defaults = ml26124_reg,
  555. .num_reg_defaults = ARRAY_SIZE(ml26124_reg),
  556. .cache_type = REGCACHE_RBTREE,
  557. .write_flag_mask = 0x01,
  558. };
  559. static int ml26124_i2c_probe(struct i2c_client *i2c,
  560. const struct i2c_device_id *id)
  561. {
  562. struct ml26124_priv *priv;
  563. int ret;
  564. priv = devm_kzalloc(&i2c->dev, sizeof(*priv), GFP_KERNEL);
  565. if (!priv)
  566. return -ENOMEM;
  567. i2c_set_clientdata(i2c, priv);
  568. priv->regmap = devm_regmap_init_i2c(i2c, &ml26124_i2c_regmap);
  569. if (IS_ERR(priv->regmap)) {
  570. ret = PTR_ERR(priv->regmap);
  571. dev_err(&i2c->dev, "regmap_init_i2c() failed: %d\n", ret);
  572. return ret;
  573. }
  574. return snd_soc_register_codec(&i2c->dev,
  575. &soc_codec_dev_ml26124, &ml26124_dai, 1);
  576. }
  577. static int ml26124_i2c_remove(struct i2c_client *client)
  578. {
  579. snd_soc_unregister_codec(&client->dev);
  580. return 0;
  581. }
  582. static const struct i2c_device_id ml26124_i2c_id[] = {
  583. { "ml26124", 0 },
  584. { }
  585. };
  586. MODULE_DEVICE_TABLE(i2c, ml26124_i2c_id);
  587. static struct i2c_driver ml26124_i2c_driver = {
  588. .driver = {
  589. .name = "ml26124",
  590. .owner = THIS_MODULE,
  591. },
  592. .probe = ml26124_i2c_probe,
  593. .remove = ml26124_i2c_remove,
  594. .id_table = ml26124_i2c_id,
  595. };
  596. module_i2c_driver(ml26124_i2c_driver);
  597. MODULE_AUTHOR("Tomoya MORINAGA <tomoya.rohm@gmail.com>");
  598. MODULE_DESCRIPTION("LAPIS Semiconductor ML26124 ALSA SoC codec driver");
  599. MODULE_LICENSE("GPL");