ml26124.c 18 KB

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