cs4265.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  1. /*
  2. * cs4265.c -- CS4265 ALSA SoC audio driver
  3. *
  4. * Copyright 2014 Cirrus Logic, Inc.
  5. *
  6. * Author: Paul Handrigan <paul.handrigan@cirrus.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License version 2 as
  10. * published by the Free Software Foundation.
  11. *
  12. */
  13. #include <linux/module.h>
  14. #include <linux/moduleparam.h>
  15. #include <linux/kernel.h>
  16. #include <linux/gpio/consumer.h>
  17. #include <linux/init.h>
  18. #include <linux/delay.h>
  19. #include <linux/i2c.h>
  20. #include <linux/input.h>
  21. #include <linux/regmap.h>
  22. #include <linux/slab.h>
  23. #include <linux/platform_device.h>
  24. #include <sound/core.h>
  25. #include <sound/pcm.h>
  26. #include <sound/pcm_params.h>
  27. #include <sound/soc.h>
  28. #include <sound/soc-dapm.h>
  29. #include <sound/initval.h>
  30. #include <sound/tlv.h>
  31. #include "cs4265.h"
  32. struct cs4265_private {
  33. struct device *dev;
  34. struct regmap *regmap;
  35. struct gpio_desc *reset_gpio;
  36. u8 format;
  37. u32 sysclk;
  38. };
  39. static const struct reg_default cs4265_reg_defaults[] = {
  40. { CS4265_PWRCTL, 0x0F },
  41. { CS4265_DAC_CTL, 0x08 },
  42. { CS4265_ADC_CTL, 0x00 },
  43. { CS4265_MCLK_FREQ, 0x00 },
  44. { CS4265_SIG_SEL, 0x40 },
  45. { CS4265_CHB_PGA_CTL, 0x00 },
  46. { CS4265_CHA_PGA_CTL, 0x00 },
  47. { CS4265_ADC_CTL2, 0x19 },
  48. { CS4265_DAC_CHA_VOL, 0x00 },
  49. { CS4265_DAC_CHB_VOL, 0x00 },
  50. { CS4265_DAC_CTL2, 0xC0 },
  51. { CS4265_SPDIF_CTL1, 0x00 },
  52. { CS4265_SPDIF_CTL2, 0x00 },
  53. { CS4265_INT_MASK, 0x00 },
  54. { CS4265_STATUS_MODE_MSB, 0x00 },
  55. { CS4265_STATUS_MODE_LSB, 0x00 },
  56. };
  57. static bool cs4265_readable_register(struct device *dev, unsigned int reg)
  58. {
  59. switch (reg) {
  60. case CS4265_PWRCTL:
  61. case CS4265_DAC_CTL:
  62. case CS4265_ADC_CTL:
  63. case CS4265_MCLK_FREQ:
  64. case CS4265_SIG_SEL:
  65. case CS4265_CHB_PGA_CTL:
  66. case CS4265_CHA_PGA_CTL:
  67. case CS4265_ADC_CTL2:
  68. case CS4265_DAC_CHA_VOL:
  69. case CS4265_DAC_CHB_VOL:
  70. case CS4265_DAC_CTL2:
  71. case CS4265_SPDIF_CTL1:
  72. case CS4265_SPDIF_CTL2:
  73. case CS4265_INT_MASK:
  74. case CS4265_STATUS_MODE_MSB:
  75. case CS4265_STATUS_MODE_LSB:
  76. case CS4265_CHIP_ID:
  77. return true;
  78. default:
  79. return false;
  80. }
  81. }
  82. static bool cs4265_volatile_register(struct device *dev, unsigned int reg)
  83. {
  84. switch (reg) {
  85. case CS4265_INT_STATUS:
  86. return true;
  87. default:
  88. return false;
  89. }
  90. }
  91. static DECLARE_TLV_DB_SCALE(pga_tlv, -1200, 50, 0);
  92. static DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 0);
  93. static const char * const digital_input_mux_text[] = {
  94. "SDIN1", "SDIN2"
  95. };
  96. static SOC_ENUM_SINGLE_DECL(digital_input_mux_enum, CS4265_SIG_SEL, 7,
  97. digital_input_mux_text);
  98. static const struct snd_kcontrol_new digital_input_mux =
  99. SOC_DAPM_ENUM("Digital Input Mux", digital_input_mux_enum);
  100. static const char * const mic_linein_text[] = {
  101. "MIC", "LINEIN"
  102. };
  103. static SOC_ENUM_SINGLE_DECL(mic_linein_enum, CS4265_ADC_CTL2, 0,
  104. mic_linein_text);
  105. static const char * const cam_mode_text[] = {
  106. "One Byte", "Two Byte"
  107. };
  108. static SOC_ENUM_SINGLE_DECL(cam_mode_enum, CS4265_SPDIF_CTL1, 5,
  109. cam_mode_text);
  110. static const char * const cam_mono_stereo_text[] = {
  111. "Stereo", "Mono"
  112. };
  113. static SOC_ENUM_SINGLE_DECL(spdif_mono_stereo_enum, CS4265_SPDIF_CTL2, 2,
  114. cam_mono_stereo_text);
  115. static const char * const mono_select_text[] = {
  116. "Channel A", "Channel B"
  117. };
  118. static SOC_ENUM_SINGLE_DECL(spdif_mono_select_enum, CS4265_SPDIF_CTL2, 0,
  119. mono_select_text);
  120. static const struct snd_kcontrol_new mic_linein_mux =
  121. SOC_DAPM_ENUM("ADC Input Capture Mux", mic_linein_enum);
  122. static const struct snd_kcontrol_new loopback_ctl =
  123. SOC_DAPM_SINGLE("Switch", CS4265_SIG_SEL, 1, 1, 0);
  124. static const struct snd_kcontrol_new spdif_switch =
  125. SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 0, 0);
  126. static const struct snd_kcontrol_new dac_switch =
  127. SOC_DAPM_SINGLE("Switch", CS4265_PWRCTL, 1, 1, 0);
  128. static const struct snd_kcontrol_new cs4265_snd_controls[] = {
  129. SOC_DOUBLE_R_SX_TLV("PGA Volume", CS4265_CHA_PGA_CTL,
  130. CS4265_CHB_PGA_CTL, 0, 0x28, 0x30, pga_tlv),
  131. SOC_DOUBLE_R_TLV("DAC Volume", CS4265_DAC_CHA_VOL,
  132. CS4265_DAC_CHB_VOL, 0, 0xFF, 1, dac_tlv),
  133. SOC_SINGLE("De-emp 44.1kHz Switch", CS4265_DAC_CTL, 1,
  134. 1, 0),
  135. SOC_SINGLE("DAC INV Switch", CS4265_DAC_CTL2, 5,
  136. 1, 0),
  137. SOC_SINGLE("DAC Zero Cross Switch", CS4265_DAC_CTL2, 6,
  138. 1, 0),
  139. SOC_SINGLE("DAC Soft Ramp Switch", CS4265_DAC_CTL2, 7,
  140. 1, 0),
  141. SOC_SINGLE("ADC HPF Switch", CS4265_ADC_CTL, 1,
  142. 1, 0),
  143. SOC_SINGLE("ADC Zero Cross Switch", CS4265_ADC_CTL2, 3,
  144. 1, 1),
  145. SOC_SINGLE("ADC Soft Ramp Switch", CS4265_ADC_CTL2, 7,
  146. 1, 0),
  147. SOC_SINGLE("E to F Buffer Disable Switch", CS4265_SPDIF_CTL1,
  148. 6, 1, 0),
  149. SOC_ENUM("C Data Access", cam_mode_enum),
  150. SOC_SINGLE("Validity Bit Control Switch", CS4265_SPDIF_CTL2,
  151. 3, 1, 0),
  152. SOC_ENUM("SPDIF Mono/Stereo", spdif_mono_stereo_enum),
  153. SOC_SINGLE("MMTLR Data Switch", 0,
  154. 1, 1, 0),
  155. SOC_ENUM("Mono Channel Select", spdif_mono_select_enum),
  156. SND_SOC_BYTES("C Data Buffer", CS4265_C_DATA_BUFF, 24),
  157. };
  158. static const struct snd_soc_dapm_widget cs4265_dapm_widgets[] = {
  159. SND_SOC_DAPM_INPUT("LINEINL"),
  160. SND_SOC_DAPM_INPUT("LINEINR"),
  161. SND_SOC_DAPM_INPUT("MICL"),
  162. SND_SOC_DAPM_INPUT("MICR"),
  163. SND_SOC_DAPM_AIF_OUT("DOUT", NULL, 0,
  164. SND_SOC_NOPM, 0, 0),
  165. SND_SOC_DAPM_AIF_OUT("SPDIFOUT", NULL, 0,
  166. SND_SOC_NOPM, 0, 0),
  167. SND_SOC_DAPM_MUX("ADC Mux", SND_SOC_NOPM, 0, 0, &mic_linein_mux),
  168. SND_SOC_DAPM_ADC("ADC", NULL, CS4265_PWRCTL, 2, 1),
  169. SND_SOC_DAPM_PGA("Pre-amp MIC", CS4265_PWRCTL, 3,
  170. 1, NULL, 0),
  171. SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM,
  172. 0, 0, &digital_input_mux),
  173. SND_SOC_DAPM_MIXER("SDIN1 Input Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
  174. SND_SOC_DAPM_MIXER("SDIN2 Input Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
  175. SND_SOC_DAPM_MIXER("SPDIF Transmitter", SND_SOC_NOPM, 0, 0, NULL, 0),
  176. SND_SOC_DAPM_SWITCH("Loopback", SND_SOC_NOPM, 0, 0,
  177. &loopback_ctl),
  178. SND_SOC_DAPM_SWITCH("SPDIF", SND_SOC_NOPM, 0, 0,
  179. &spdif_switch),
  180. SND_SOC_DAPM_SWITCH("DAC", CS4265_PWRCTL, 1, 1,
  181. &dac_switch),
  182. SND_SOC_DAPM_AIF_IN("DIN1", NULL, 0,
  183. SND_SOC_NOPM, 0, 0),
  184. SND_SOC_DAPM_AIF_IN("DIN2", NULL, 0,
  185. SND_SOC_NOPM, 0, 0),
  186. SND_SOC_DAPM_AIF_IN("TXIN", NULL, 0,
  187. CS4265_SPDIF_CTL2, 5, 1),
  188. SND_SOC_DAPM_OUTPUT("LINEOUTL"),
  189. SND_SOC_DAPM_OUTPUT("LINEOUTR"),
  190. };
  191. static const struct snd_soc_dapm_route cs4265_audio_map[] = {
  192. {"DIN1", NULL, "DAI1 Playback"},
  193. {"DIN2", NULL, "DAI2 Playback"},
  194. {"SDIN1 Input Mixer", NULL, "DIN1"},
  195. {"SDIN2 Input Mixer", NULL, "DIN2"},
  196. {"Input Mux", "SDIN1", "SDIN1 Input Mixer"},
  197. {"Input Mux", "SDIN2", "SDIN2 Input Mixer"},
  198. {"DAC", "Switch", "Input Mux"},
  199. {"SPDIF", "Switch", "Input Mux"},
  200. {"LINEOUTL", NULL, "DAC"},
  201. {"LINEOUTR", NULL, "DAC"},
  202. {"SPDIFOUT", NULL, "SPDIF"},
  203. {"ADC Mux", "LINEIN", "LINEINL"},
  204. {"ADC Mux", "LINEIN", "LINEINR"},
  205. {"ADC Mux", "MIC", "MICL"},
  206. {"ADC Mux", "MIC", "MICR"},
  207. {"ADC", NULL, "ADC Mux"},
  208. {"DOUT", NULL, "ADC"},
  209. {"DAI1 Capture", NULL, "DOUT"},
  210. {"DAI2 Capture", NULL, "DOUT"},
  211. /* Loopback */
  212. {"Loopback", "Switch", "ADC"},
  213. {"DAC", NULL, "Loopback"},
  214. };
  215. struct cs4265_clk_para {
  216. u32 mclk;
  217. u32 rate;
  218. u8 fm_mode; /* values 1, 2, or 4 */
  219. u8 mclkdiv;
  220. };
  221. static const struct cs4265_clk_para clk_map_table[] = {
  222. /*32k*/
  223. {8192000, 32000, 0, 0},
  224. {12288000, 32000, 0, 1},
  225. {16384000, 32000, 0, 2},
  226. {24576000, 32000, 0, 3},
  227. {32768000, 32000, 0, 4},
  228. /*44.1k*/
  229. {11289600, 44100, 0, 0},
  230. {16934400, 44100, 0, 1},
  231. {22579200, 44100, 0, 2},
  232. {33868000, 44100, 0, 3},
  233. {45158400, 44100, 0, 4},
  234. /*48k*/
  235. {12288000, 48000, 0, 0},
  236. {18432000, 48000, 0, 1},
  237. {24576000, 48000, 0, 2},
  238. {36864000, 48000, 0, 3},
  239. {49152000, 48000, 0, 4},
  240. /*64k*/
  241. {8192000, 64000, 1, 0},
  242. {12288000, 64000, 1, 1},
  243. {16934400, 64000, 1, 2},
  244. {24576000, 64000, 1, 3},
  245. {32768000, 64000, 1, 4},
  246. /* 88.2k */
  247. {11289600, 88200, 1, 0},
  248. {16934400, 88200, 1, 1},
  249. {22579200, 88200, 1, 2},
  250. {33868000, 88200, 1, 3},
  251. {45158400, 88200, 1, 4},
  252. /* 96k */
  253. {12288000, 96000, 1, 0},
  254. {18432000, 96000, 1, 1},
  255. {24576000, 96000, 1, 2},
  256. {36864000, 96000, 1, 3},
  257. {49152000, 96000, 1, 4},
  258. /* 128k */
  259. {8192000, 128000, 2, 0},
  260. {12288000, 128000, 2, 1},
  261. {16934400, 128000, 2, 2},
  262. {24576000, 128000, 2, 3},
  263. {32768000, 128000, 2, 4},
  264. /* 176.4k */
  265. {11289600, 176400, 2, 0},
  266. {16934400, 176400, 2, 1},
  267. {22579200, 176400, 2, 2},
  268. {33868000, 176400, 2, 3},
  269. {49152000, 176400, 2, 4},
  270. /* 192k */
  271. {12288000, 192000, 2, 0},
  272. {18432000, 192000, 2, 1},
  273. {24576000, 192000, 2, 2},
  274. {36864000, 192000, 2, 3},
  275. {49152000, 192000, 2, 4},
  276. };
  277. static int cs4265_get_clk_index(int mclk, int rate)
  278. {
  279. int i;
  280. for (i = 0; i < ARRAY_SIZE(clk_map_table); i++) {
  281. if (clk_map_table[i].rate == rate &&
  282. clk_map_table[i].mclk == mclk)
  283. return i;
  284. }
  285. return -EINVAL;
  286. }
  287. static int cs4265_set_sysclk(struct snd_soc_dai *codec_dai, int clk_id,
  288. unsigned int freq, int dir)
  289. {
  290. struct snd_soc_codec *codec = codec_dai->codec;
  291. struct cs4265_private *cs4265 = snd_soc_codec_get_drvdata(codec);
  292. int i;
  293. if (clk_id != 0) {
  294. dev_err(codec->dev, "Invalid clk_id %d\n", clk_id);
  295. return -EINVAL;
  296. }
  297. for (i = 0; i < ARRAY_SIZE(clk_map_table); i++) {
  298. if (clk_map_table[i].mclk == freq) {
  299. cs4265->sysclk = freq;
  300. return 0;
  301. }
  302. }
  303. cs4265->sysclk = 0;
  304. dev_err(codec->dev, "Invalid freq parameter %d\n", freq);
  305. return -EINVAL;
  306. }
  307. static int cs4265_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
  308. {
  309. struct snd_soc_codec *codec = codec_dai->codec;
  310. struct cs4265_private *cs4265 = snd_soc_codec_get_drvdata(codec);
  311. u8 iface = 0;
  312. switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
  313. case SND_SOC_DAIFMT_CBM_CFM:
  314. snd_soc_update_bits(codec, CS4265_ADC_CTL,
  315. CS4265_ADC_MASTER,
  316. CS4265_ADC_MASTER);
  317. break;
  318. case SND_SOC_DAIFMT_CBS_CFS:
  319. snd_soc_update_bits(codec, CS4265_ADC_CTL,
  320. CS4265_ADC_MASTER,
  321. 0);
  322. break;
  323. default:
  324. return -EINVAL;
  325. }
  326. /* interface format */
  327. switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  328. case SND_SOC_DAIFMT_I2S:
  329. iface |= SND_SOC_DAIFMT_I2S;
  330. break;
  331. case SND_SOC_DAIFMT_RIGHT_J:
  332. iface |= SND_SOC_DAIFMT_RIGHT_J;
  333. break;
  334. case SND_SOC_DAIFMT_LEFT_J:
  335. iface |= SND_SOC_DAIFMT_LEFT_J;
  336. break;
  337. default:
  338. return -EINVAL;
  339. }
  340. cs4265->format = iface;
  341. return 0;
  342. }
  343. static int cs4265_digital_mute(struct snd_soc_dai *dai, int mute)
  344. {
  345. struct snd_soc_codec *codec = dai->codec;
  346. if (mute) {
  347. snd_soc_update_bits(codec, CS4265_DAC_CTL,
  348. CS4265_DAC_CTL_MUTE,
  349. CS4265_DAC_CTL_MUTE);
  350. snd_soc_update_bits(codec, CS4265_SPDIF_CTL2,
  351. CS4265_SPDIF_CTL2_MUTE,
  352. CS4265_SPDIF_CTL2_MUTE);
  353. } else {
  354. snd_soc_update_bits(codec, CS4265_DAC_CTL,
  355. CS4265_DAC_CTL_MUTE,
  356. 0);
  357. snd_soc_update_bits(codec, CS4265_SPDIF_CTL2,
  358. CS4265_SPDIF_CTL2_MUTE,
  359. 0);
  360. }
  361. return 0;
  362. }
  363. static int cs4265_pcm_hw_params(struct snd_pcm_substream *substream,
  364. struct snd_pcm_hw_params *params,
  365. struct snd_soc_dai *dai)
  366. {
  367. struct snd_soc_codec *codec = dai->codec;
  368. struct cs4265_private *cs4265 = snd_soc_codec_get_drvdata(codec);
  369. int index;
  370. if (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
  371. ((cs4265->format & SND_SOC_DAIFMT_FORMAT_MASK)
  372. == SND_SOC_DAIFMT_RIGHT_J))
  373. return -EINVAL;
  374. index = cs4265_get_clk_index(cs4265->sysclk, params_rate(params));
  375. if (index >= 0) {
  376. snd_soc_update_bits(codec, CS4265_ADC_CTL,
  377. CS4265_ADC_FM, clk_map_table[index].fm_mode << 6);
  378. snd_soc_update_bits(codec, CS4265_MCLK_FREQ,
  379. CS4265_MCLK_FREQ_MASK,
  380. clk_map_table[index].mclkdiv << 4);
  381. } else {
  382. dev_err(codec->dev, "can't get correct mclk\n");
  383. return -EINVAL;
  384. }
  385. switch (cs4265->format & SND_SOC_DAIFMT_FORMAT_MASK) {
  386. case SND_SOC_DAIFMT_I2S:
  387. snd_soc_update_bits(codec, CS4265_DAC_CTL,
  388. CS4265_DAC_CTL_DIF, (1 << 4));
  389. snd_soc_update_bits(codec, CS4265_ADC_CTL,
  390. CS4265_ADC_DIF, (1 << 4));
  391. snd_soc_update_bits(codec, CS4265_SPDIF_CTL2,
  392. CS4265_SPDIF_CTL2_DIF, (1 << 6));
  393. break;
  394. case SND_SOC_DAIFMT_RIGHT_J:
  395. if (params_width(params) == 16) {
  396. snd_soc_update_bits(codec, CS4265_DAC_CTL,
  397. CS4265_DAC_CTL_DIF, (1 << 5));
  398. snd_soc_update_bits(codec, CS4265_SPDIF_CTL2,
  399. CS4265_SPDIF_CTL2_DIF, (1 << 7));
  400. } else {
  401. snd_soc_update_bits(codec, CS4265_DAC_CTL,
  402. CS4265_DAC_CTL_DIF, (3 << 5));
  403. snd_soc_update_bits(codec, CS4265_SPDIF_CTL2,
  404. CS4265_SPDIF_CTL2_DIF, (1 << 7));
  405. }
  406. break;
  407. case SND_SOC_DAIFMT_LEFT_J:
  408. snd_soc_update_bits(codec, CS4265_DAC_CTL,
  409. CS4265_DAC_CTL_DIF, 0);
  410. snd_soc_update_bits(codec, CS4265_ADC_CTL,
  411. CS4265_ADC_DIF, 0);
  412. snd_soc_update_bits(codec, CS4265_SPDIF_CTL2,
  413. CS4265_SPDIF_CTL2_DIF, (1 << 6));
  414. break;
  415. default:
  416. return -EINVAL;
  417. }
  418. return 0;
  419. }
  420. static int cs4265_set_bias_level(struct snd_soc_codec *codec,
  421. enum snd_soc_bias_level level)
  422. {
  423. switch (level) {
  424. case SND_SOC_BIAS_ON:
  425. break;
  426. case SND_SOC_BIAS_PREPARE:
  427. snd_soc_update_bits(codec, CS4265_PWRCTL,
  428. CS4265_PWRCTL_PDN, 0);
  429. break;
  430. case SND_SOC_BIAS_STANDBY:
  431. snd_soc_update_bits(codec, CS4265_PWRCTL,
  432. CS4265_PWRCTL_PDN,
  433. CS4265_PWRCTL_PDN);
  434. break;
  435. case SND_SOC_BIAS_OFF:
  436. snd_soc_update_bits(codec, CS4265_PWRCTL,
  437. CS4265_PWRCTL_PDN,
  438. CS4265_PWRCTL_PDN);
  439. break;
  440. }
  441. codec->dapm.bias_level = level;
  442. return 0;
  443. }
  444. #define CS4265_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
  445. SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \
  446. SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \
  447. SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
  448. #define CS4265_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | \
  449. SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U24_LE)
  450. static const struct snd_soc_dai_ops cs4265_ops = {
  451. .hw_params = cs4265_pcm_hw_params,
  452. .digital_mute = cs4265_digital_mute,
  453. .set_fmt = cs4265_set_fmt,
  454. .set_sysclk = cs4265_set_sysclk,
  455. };
  456. static struct snd_soc_dai_driver cs4265_dai[] = {
  457. {
  458. .name = "cs4265-dai1",
  459. .playback = {
  460. .stream_name = "DAI1 Playback",
  461. .channels_min = 1,
  462. .channels_max = 2,
  463. .rates = CS4265_RATES,
  464. .formats = CS4265_FORMATS,
  465. },
  466. .capture = {
  467. .stream_name = "DAI1 Capture",
  468. .channels_min = 1,
  469. .channels_max = 2,
  470. .rates = CS4265_RATES,
  471. .formats = CS4265_FORMATS,
  472. },
  473. .ops = &cs4265_ops,
  474. },
  475. {
  476. .name = "cs4265-dai2",
  477. .playback = {
  478. .stream_name = "DAI2 Playback",
  479. .channels_min = 1,
  480. .channels_max = 2,
  481. .rates = CS4265_RATES,
  482. .formats = CS4265_FORMATS,
  483. },
  484. .capture = {
  485. .stream_name = "DAI2 Capture",
  486. .channels_min = 1,
  487. .channels_max = 2,
  488. .rates = CS4265_RATES,
  489. .formats = CS4265_FORMATS,
  490. },
  491. .ops = &cs4265_ops,
  492. },
  493. };
  494. static const struct snd_soc_codec_driver soc_codec_cs4265 = {
  495. .set_bias_level = cs4265_set_bias_level,
  496. .dapm_widgets = cs4265_dapm_widgets,
  497. .num_dapm_widgets = ARRAY_SIZE(cs4265_dapm_widgets),
  498. .dapm_routes = cs4265_audio_map,
  499. .num_dapm_routes = ARRAY_SIZE(cs4265_audio_map),
  500. .controls = cs4265_snd_controls,
  501. .num_controls = ARRAY_SIZE(cs4265_snd_controls),
  502. };
  503. static const struct regmap_config cs4265_regmap = {
  504. .reg_bits = 8,
  505. .val_bits = 8,
  506. .max_register = CS4265_MAX_REGISTER,
  507. .reg_defaults = cs4265_reg_defaults,
  508. .num_reg_defaults = ARRAY_SIZE(cs4265_reg_defaults),
  509. .readable_reg = cs4265_readable_register,
  510. .volatile_reg = cs4265_volatile_register,
  511. .cache_type = REGCACHE_RBTREE,
  512. };
  513. static int cs4265_i2c_probe(struct i2c_client *i2c_client,
  514. const struct i2c_device_id *id)
  515. {
  516. struct cs4265_private *cs4265;
  517. int ret = 0;
  518. unsigned int devid = 0;
  519. unsigned int reg;
  520. cs4265 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4265_private),
  521. GFP_KERNEL);
  522. if (cs4265 == NULL)
  523. return -ENOMEM;
  524. cs4265->dev = &i2c_client->dev;
  525. cs4265->regmap = devm_regmap_init_i2c(i2c_client, &cs4265_regmap);
  526. if (IS_ERR(cs4265->regmap)) {
  527. ret = PTR_ERR(cs4265->regmap);
  528. dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
  529. return ret;
  530. }
  531. cs4265->reset_gpio = devm_gpiod_get(&i2c_client->dev,
  532. "reset-gpios");
  533. if (IS_ERR(cs4265->reset_gpio)) {
  534. ret = PTR_ERR(cs4265->reset_gpio);
  535. if (ret != -ENOENT && ret != -ENOSYS)
  536. return ret;
  537. cs4265->reset_gpio = NULL;
  538. } else {
  539. ret = gpiod_direction_output(cs4265->reset_gpio, 0);
  540. if (ret)
  541. return ret;
  542. mdelay(1);
  543. gpiod_set_value_cansleep(cs4265->reset_gpio, 1);
  544. }
  545. i2c_set_clientdata(i2c_client, cs4265);
  546. ret = regmap_read(cs4265->regmap, CS4265_CHIP_ID, &reg);
  547. devid = reg & CS4265_CHIP_ID_MASK;
  548. if (devid != CS4265_CHIP_ID_VAL) {
  549. ret = -ENODEV;
  550. dev_err(&i2c_client->dev,
  551. "CS4265 Device ID (%X). Expected %X\n",
  552. devid, CS4265_CHIP_ID);
  553. return ret;
  554. }
  555. dev_info(&i2c_client->dev,
  556. "CS4265 Version %x\n",
  557. reg & CS4265_REV_ID_MASK);
  558. regmap_write(cs4265->regmap, CS4265_PWRCTL, 0x0F);
  559. ret = snd_soc_register_codec(&i2c_client->dev,
  560. &soc_codec_cs4265, cs4265_dai,
  561. ARRAY_SIZE(cs4265_dai));
  562. return ret;
  563. }
  564. static int cs4265_i2c_remove(struct i2c_client *client)
  565. {
  566. snd_soc_unregister_codec(&client->dev);
  567. return 0;
  568. }
  569. static const struct of_device_id cs4265_of_match[] = {
  570. { .compatible = "cirrus,cs4265", },
  571. { }
  572. };
  573. MODULE_DEVICE_TABLE(of, cs4265_of_match);
  574. static const struct i2c_device_id cs4265_id[] = {
  575. { "cs4265", 0 },
  576. { }
  577. };
  578. MODULE_DEVICE_TABLE(i2c, cs4265_id);
  579. static struct i2c_driver cs4265_i2c_driver = {
  580. .driver = {
  581. .name = "cs4265",
  582. .owner = THIS_MODULE,
  583. .of_match_table = cs4265_of_match,
  584. },
  585. .id_table = cs4265_id,
  586. .probe = cs4265_i2c_probe,
  587. .remove = cs4265_i2c_remove,
  588. };
  589. module_i2c_driver(cs4265_i2c_driver);
  590. MODULE_DESCRIPTION("ASoC CS4265 driver");
  591. MODULE_AUTHOR("Paul Handrigan, Cirrus Logic Inc, <paul.handrigan@cirrus.com>");
  592. MODULE_LICENSE("GPL");