cs42l51.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763
  1. /*
  2. * cs42l51.c
  3. *
  4. * ASoC Driver for Cirrus Logic CS42L51 codecs
  5. *
  6. * Copyright (c) 2010 Arnaud Patard <apatard@mandriva.com>
  7. *
  8. * Based on cs4270.c - Copyright (c) Freescale Semiconductor
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License version 2 as
  12. * published by the Free Software Foundation.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * For now:
  20. * - Only I2C is support. Not SPI
  21. * - master mode *NOT* supported
  22. */
  23. #include <linux/module.h>
  24. #include <linux/platform_device.h>
  25. #include <linux/slab.h>
  26. #include <sound/core.h>
  27. #include <sound/soc.h>
  28. #include <sound/soc-dapm.h>
  29. #include <sound/tlv.h>
  30. #include <sound/initval.h>
  31. #include <sound/pcm_params.h>
  32. #include <sound/pcm.h>
  33. #include <linux/i2c.h>
  34. #include "cs42l51.h"
  35. enum master_slave_mode {
  36. MODE_SLAVE,
  37. MODE_SLAVE_AUTO,
  38. MODE_MASTER,
  39. };
  40. struct cs42l51_private {
  41. unsigned int mclk;
  42. unsigned int audio_mode; /* The mode (I2S or left-justified) */
  43. enum master_slave_mode func;
  44. struct snd_soc_codec codec;
  45. u8 reg_cache[CS42L51_NUMREGS];
  46. };
  47. static struct snd_soc_codec *cs42l51_codec;
  48. #define CS42L51_FORMATS ( \
  49. SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \
  50. SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \
  51. SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \
  52. SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE)
  53. static int cs42l51_fill_cache(struct snd_soc_codec *codec)
  54. {
  55. u8 *cache = codec->reg_cache + 1;
  56. struct i2c_client *i2c_client = codec->control_data;
  57. s32 length;
  58. length = i2c_smbus_read_i2c_block_data(i2c_client,
  59. CS42L51_FIRSTREG | 0x80, CS42L51_NUMREGS, cache);
  60. if (length != CS42L51_NUMREGS) {
  61. dev_err(&i2c_client->dev,
  62. "I2C read failure, addr=0x%x (ret=%d vs %d)\n",
  63. i2c_client->addr, length, CS42L51_NUMREGS);
  64. return -EIO;
  65. }
  66. return 0;
  67. }
  68. static int cs42l51_i2c_probe(struct i2c_client *i2c_client,
  69. const struct i2c_device_id *id)
  70. {
  71. struct snd_soc_codec *codec;
  72. struct cs42l51_private *cs42l51;
  73. int ret = 0;
  74. int reg;
  75. if (cs42l51_codec)
  76. return -EBUSY;
  77. /* Verify that we have a CS42L51 */
  78. ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID);
  79. if (ret < 0) {
  80. dev_err(&i2c_client->dev, "failed to read I2C\n");
  81. goto error;
  82. }
  83. if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) &&
  84. (ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) {
  85. dev_err(&i2c_client->dev, "Invalid chip id\n");
  86. ret = -ENODEV;
  87. goto error;
  88. }
  89. dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n",
  90. ret & 7);
  91. cs42l51 = kzalloc(sizeof(struct cs42l51_private), GFP_KERNEL);
  92. if (!cs42l51) {
  93. dev_err(&i2c_client->dev, "could not allocate codec\n");
  94. return -ENOMEM;
  95. }
  96. codec = &cs42l51->codec;
  97. mutex_init(&codec->mutex);
  98. INIT_LIST_HEAD(&codec->dapm_widgets);
  99. INIT_LIST_HEAD(&codec->dapm_paths);
  100. codec->dev = &i2c_client->dev;
  101. codec->name = "CS42L51";
  102. codec->owner = THIS_MODULE;
  103. codec->dai = &cs42l51_dai;
  104. codec->num_dai = 1;
  105. snd_soc_codec_set_drvdata(codec, cs42l51);
  106. codec->control_data = i2c_client;
  107. codec->reg_cache = cs42l51->reg_cache;
  108. codec->reg_cache_size = CS42L51_NUMREGS;
  109. i2c_set_clientdata(i2c_client, codec);
  110. ret = cs42l51_fill_cache(codec);
  111. if (ret < 0) {
  112. dev_err(&i2c_client->dev, "failed to fill register cache\n");
  113. goto error_alloc;
  114. }
  115. ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
  116. if (ret < 0) {
  117. dev_err(&i2c_client->dev, "Failed to set cache I/O: %d\n", ret);
  118. goto error_alloc;
  119. }
  120. /*
  121. * DAC configuration
  122. * - Use signal processor
  123. * - auto mute
  124. * - vol changes immediate
  125. * - no de-emphasize
  126. */
  127. reg = CS42L51_DAC_CTL_DATA_SEL(1)
  128. | CS42L51_DAC_CTL_AMUTE | CS42L51_DAC_CTL_DACSZ(0);
  129. ret = snd_soc_write(codec, CS42L51_DAC_CTL, reg);
  130. if (ret < 0)
  131. goto error_alloc;
  132. cs42l51_dai.dev = codec->dev;
  133. cs42l51_codec = codec;
  134. ret = snd_soc_register_codec(codec);
  135. if (ret != 0) {
  136. dev_err(codec->dev, "Failed to register codec: %d\n", ret);
  137. goto error_alloc;
  138. }
  139. ret = snd_soc_register_dai(&cs42l51_dai);
  140. if (ret < 0) {
  141. dev_err(&i2c_client->dev, "failed to register DAIe\n");
  142. goto error_reg;
  143. }
  144. return 0;
  145. error_reg:
  146. snd_soc_unregister_codec(codec);
  147. error_alloc:
  148. kfree(cs42l51);
  149. error:
  150. return ret;
  151. }
  152. static int cs42l51_i2c_remove(struct i2c_client *client)
  153. {
  154. struct cs42l51_private *cs42l51 = i2c_get_clientdata(client);
  155. snd_soc_unregister_dai(&cs42l51_dai);
  156. snd_soc_unregister_codec(cs42l51_codec);
  157. cs42l51_codec = NULL;
  158. kfree(cs42l51);
  159. return 0;
  160. }
  161. static const struct i2c_device_id cs42l51_id[] = {
  162. {"cs42l51", 0},
  163. {}
  164. };
  165. MODULE_DEVICE_TABLE(i2c, cs42l51_id);
  166. static struct i2c_driver cs42l51_i2c_driver = {
  167. .driver = {
  168. .name = "CS42L51 I2C",
  169. .owner = THIS_MODULE,
  170. },
  171. .id_table = cs42l51_id,
  172. .probe = cs42l51_i2c_probe,
  173. .remove = cs42l51_i2c_remove,
  174. };
  175. static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol,
  176. struct snd_ctl_elem_value *ucontrol)
  177. {
  178. struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
  179. unsigned long value = snd_soc_read(codec, CS42L51_PCM_MIXER)&3;
  180. switch (value) {
  181. default:
  182. case 0:
  183. ucontrol->value.integer.value[0] = 0;
  184. break;
  185. /* same value : (L+R)/2 and (R+L)/2 */
  186. case 1:
  187. case 2:
  188. ucontrol->value.integer.value[0] = 1;
  189. break;
  190. case 3:
  191. ucontrol->value.integer.value[0] = 2;
  192. break;
  193. }
  194. return 0;
  195. }
  196. #define CHAN_MIX_NORMAL 0x00
  197. #define CHAN_MIX_BOTH 0x55
  198. #define CHAN_MIX_SWAP 0xFF
  199. static int cs42l51_set_chan_mix(struct snd_kcontrol *kcontrol,
  200. struct snd_ctl_elem_value *ucontrol)
  201. {
  202. struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
  203. unsigned char val;
  204. switch (ucontrol->value.integer.value[0]) {
  205. default:
  206. case 0:
  207. val = CHAN_MIX_NORMAL;
  208. break;
  209. case 1:
  210. val = CHAN_MIX_BOTH;
  211. break;
  212. case 2:
  213. val = CHAN_MIX_SWAP;
  214. break;
  215. }
  216. snd_soc_write(codec, CS42L51_PCM_MIXER, val);
  217. return 1;
  218. }
  219. static const DECLARE_TLV_DB_SCALE(adc_pcm_tlv, -5150, 50, 0);
  220. static const DECLARE_TLV_DB_SCALE(tone_tlv, -1050, 150, 0);
  221. /* This is a lie. after -102 db, it stays at -102 */
  222. /* maybe a range would be better */
  223. static const DECLARE_TLV_DB_SCALE(aout_tlv, -11550, 50, 0);
  224. static const DECLARE_TLV_DB_SCALE(boost_tlv, 1600, 1600, 0);
  225. static const char *chan_mix[] = {
  226. "L R",
  227. "L+R",
  228. "R L",
  229. };
  230. static const struct soc_enum cs42l51_chan_mix =
  231. SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(chan_mix), chan_mix);
  232. static const struct snd_kcontrol_new cs42l51_snd_controls[] = {
  233. SOC_DOUBLE_R_SX_TLV("PCM Playback Volume",
  234. CS42L51_PCMA_VOL, CS42L51_PCMB_VOL,
  235. 7, 0xffffff99, 0x18, adc_pcm_tlv),
  236. SOC_DOUBLE_R("PCM Playback Switch",
  237. CS42L51_PCMA_VOL, CS42L51_PCMB_VOL, 7, 1, 1),
  238. SOC_DOUBLE_R_SX_TLV("Analog Playback Volume",
  239. CS42L51_AOUTA_VOL, CS42L51_AOUTB_VOL,
  240. 8, 0xffffff19, 0x18, aout_tlv),
  241. SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume",
  242. CS42L51_ADCA_VOL, CS42L51_ADCB_VOL,
  243. 7, 0xffffff99, 0x18, adc_pcm_tlv),
  244. SOC_DOUBLE_R("ADC Mixer Switch",
  245. CS42L51_ADCA_VOL, CS42L51_ADCB_VOL, 7, 1, 1),
  246. SOC_SINGLE("Playback Deemphasis Switch", CS42L51_DAC_CTL, 3, 1, 0),
  247. SOC_SINGLE("Auto-Mute Switch", CS42L51_DAC_CTL, 2, 1, 0),
  248. SOC_SINGLE("Soft Ramp Switch", CS42L51_DAC_CTL, 1, 1, 0),
  249. SOC_SINGLE("Zero Cross Switch", CS42L51_DAC_CTL, 0, 0, 0),
  250. SOC_DOUBLE_TLV("Mic Boost Volume",
  251. CS42L51_MIC_CTL, 0, 1, 1, 0, boost_tlv),
  252. SOC_SINGLE_TLV("Bass Volume", CS42L51_TONE_CTL, 0, 0xf, 1, tone_tlv),
  253. SOC_SINGLE_TLV("Treble Volume", CS42L51_TONE_CTL, 4, 0xf, 1, tone_tlv),
  254. SOC_ENUM_EXT("PCM channel mixer",
  255. cs42l51_chan_mix,
  256. cs42l51_get_chan_mix, cs42l51_set_chan_mix),
  257. };
  258. /*
  259. * to power down, one must:
  260. * 1.) Enable the PDN bit
  261. * 2.) enable power-down for the select channels
  262. * 3.) disable the PDN bit.
  263. */
  264. static int cs42l51_pdn_event(struct snd_soc_dapm_widget *w,
  265. struct snd_kcontrol *kcontrol, int event)
  266. {
  267. unsigned long value;
  268. value = snd_soc_read(w->codec, CS42L51_POWER_CTL1);
  269. value &= ~CS42L51_POWER_CTL1_PDN;
  270. switch (event) {
  271. case SND_SOC_DAPM_PRE_PMD:
  272. value |= CS42L51_POWER_CTL1_PDN;
  273. break;
  274. default:
  275. case SND_SOC_DAPM_POST_PMD:
  276. break;
  277. }
  278. snd_soc_update_bits(w->codec, CS42L51_POWER_CTL1,
  279. CS42L51_POWER_CTL1_PDN, value);
  280. return 0;
  281. }
  282. static const char *cs42l51_dac_names[] = {"Direct PCM",
  283. "DSP PCM", "ADC"};
  284. static const struct soc_enum cs42l51_dac_mux_enum =
  285. SOC_ENUM_SINGLE(CS42L51_DAC_CTL, 6, 3, cs42l51_dac_names);
  286. static const struct snd_kcontrol_new cs42l51_dac_mux_controls =
  287. SOC_DAPM_ENUM("Route", cs42l51_dac_mux_enum);
  288. static const char *cs42l51_adcl_names[] = {"AIN1 Left", "AIN2 Left",
  289. "MIC Left", "MIC+preamp Left"};
  290. static const struct soc_enum cs42l51_adcl_mux_enum =
  291. SOC_ENUM_SINGLE(CS42L51_ADC_INPUT, 4, 4, cs42l51_adcl_names);
  292. static const struct snd_kcontrol_new cs42l51_adcl_mux_controls =
  293. SOC_DAPM_ENUM("Route", cs42l51_adcl_mux_enum);
  294. static const char *cs42l51_adcr_names[] = {"AIN1 Right", "AIN2 Right",
  295. "MIC Right", "MIC+preamp Right"};
  296. static const struct soc_enum cs42l51_adcr_mux_enum =
  297. SOC_ENUM_SINGLE(CS42L51_ADC_INPUT, 6, 4, cs42l51_adcr_names);
  298. static const struct snd_kcontrol_new cs42l51_adcr_mux_controls =
  299. SOC_DAPM_ENUM("Route", cs42l51_adcr_mux_enum);
  300. static const struct snd_soc_dapm_widget cs42l51_dapm_widgets[] = {
  301. SND_SOC_DAPM_MICBIAS("Mic Bias", CS42L51_MIC_POWER_CTL, 1, 1),
  302. SND_SOC_DAPM_PGA_E("Left PGA", CS42L51_POWER_CTL1, 3, 1, NULL, 0,
  303. cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
  304. SND_SOC_DAPM_PGA_E("Right PGA", CS42L51_POWER_CTL1, 4, 1, NULL, 0,
  305. cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
  306. SND_SOC_DAPM_ADC_E("Left ADC", "Left HiFi Capture",
  307. CS42L51_POWER_CTL1, 1, 1,
  308. cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
  309. SND_SOC_DAPM_ADC_E("Right ADC", "Right HiFi Capture",
  310. CS42L51_POWER_CTL1, 2, 1,
  311. cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
  312. SND_SOC_DAPM_DAC_E("Left DAC", "Left HiFi Playback",
  313. CS42L51_POWER_CTL1, 5, 1,
  314. cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
  315. SND_SOC_DAPM_DAC_E("Right DAC", "Right HiFi Playback",
  316. CS42L51_POWER_CTL1, 6, 1,
  317. cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
  318. /* analog/mic */
  319. SND_SOC_DAPM_INPUT("AIN1L"),
  320. SND_SOC_DAPM_INPUT("AIN1R"),
  321. SND_SOC_DAPM_INPUT("AIN2L"),
  322. SND_SOC_DAPM_INPUT("AIN2R"),
  323. SND_SOC_DAPM_INPUT("MICL"),
  324. SND_SOC_DAPM_INPUT("MICR"),
  325. SND_SOC_DAPM_MIXER("Mic Preamp Left",
  326. CS42L51_MIC_POWER_CTL, 2, 1, NULL, 0),
  327. SND_SOC_DAPM_MIXER("Mic Preamp Right",
  328. CS42L51_MIC_POWER_CTL, 3, 1, NULL, 0),
  329. /* HP */
  330. SND_SOC_DAPM_OUTPUT("HPL"),
  331. SND_SOC_DAPM_OUTPUT("HPR"),
  332. /* mux */
  333. SND_SOC_DAPM_MUX("DAC Mux", SND_SOC_NOPM, 0, 0,
  334. &cs42l51_dac_mux_controls),
  335. SND_SOC_DAPM_MUX("PGA-ADC Mux Left", SND_SOC_NOPM, 0, 0,
  336. &cs42l51_adcl_mux_controls),
  337. SND_SOC_DAPM_MUX("PGA-ADC Mux Right", SND_SOC_NOPM, 0, 0,
  338. &cs42l51_adcr_mux_controls),
  339. };
  340. static const struct snd_soc_dapm_route cs42l51_routes[] = {
  341. {"HPL", NULL, "Left DAC"},
  342. {"HPR", NULL, "Right DAC"},
  343. {"Left ADC", NULL, "Left PGA"},
  344. {"Right ADC", NULL, "Right PGA"},
  345. {"Mic Preamp Left", NULL, "MICL"},
  346. {"Mic Preamp Right", NULL, "MICR"},
  347. {"PGA-ADC Mux Left", "AIN1 Left", "AIN1L" },
  348. {"PGA-ADC Mux Left", "AIN2 Left", "AIN2L" },
  349. {"PGA-ADC Mux Left", "MIC Left", "MICL" },
  350. {"PGA-ADC Mux Left", "MIC+preamp Left", "Mic Preamp Left" },
  351. {"PGA-ADC Mux Right", "AIN1 Right", "AIN1R" },
  352. {"PGA-ADC Mux Right", "AIN2 Right", "AIN2R" },
  353. {"PGA-ADC Mux Right", "MIC Right", "MICR" },
  354. {"PGA-ADC Mux Right", "MIC+preamp Right", "Mic Preamp Right" },
  355. {"Left PGA", NULL, "PGA-ADC Mux Left"},
  356. {"Right PGA", NULL, "PGA-ADC Mux Right"},
  357. };
  358. static int cs42l51_set_dai_fmt(struct snd_soc_dai *codec_dai,
  359. unsigned int format)
  360. {
  361. struct snd_soc_codec *codec = codec_dai->codec;
  362. struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
  363. int ret = 0;
  364. switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
  365. case SND_SOC_DAIFMT_I2S:
  366. case SND_SOC_DAIFMT_LEFT_J:
  367. case SND_SOC_DAIFMT_RIGHT_J:
  368. cs42l51->audio_mode = format & SND_SOC_DAIFMT_FORMAT_MASK;
  369. break;
  370. default:
  371. dev_err(codec->dev, "invalid DAI format\n");
  372. ret = -EINVAL;
  373. }
  374. switch (format & SND_SOC_DAIFMT_MASTER_MASK) {
  375. case SND_SOC_DAIFMT_CBM_CFM:
  376. cs42l51->func = MODE_MASTER;
  377. break;
  378. case SND_SOC_DAIFMT_CBS_CFS:
  379. cs42l51->func = MODE_SLAVE_AUTO;
  380. break;
  381. default:
  382. ret = -EINVAL;
  383. break;
  384. }
  385. return ret;
  386. }
  387. struct cs42l51_ratios {
  388. unsigned int ratio;
  389. unsigned char speed_mode;
  390. unsigned char mclk;
  391. };
  392. static struct cs42l51_ratios slave_ratios[] = {
  393. { 512, CS42L51_QSM_MODE, 0 }, { 768, CS42L51_QSM_MODE, 0 },
  394. { 1024, CS42L51_QSM_MODE, 0 }, { 1536, CS42L51_QSM_MODE, 0 },
  395. { 2048, CS42L51_QSM_MODE, 0 }, { 3072, CS42L51_QSM_MODE, 0 },
  396. { 256, CS42L51_HSM_MODE, 0 }, { 384, CS42L51_HSM_MODE, 0 },
  397. { 512, CS42L51_HSM_MODE, 0 }, { 768, CS42L51_HSM_MODE, 0 },
  398. { 1024, CS42L51_HSM_MODE, 0 }, { 1536, CS42L51_HSM_MODE, 0 },
  399. { 128, CS42L51_SSM_MODE, 0 }, { 192, CS42L51_SSM_MODE, 0 },
  400. { 256, CS42L51_SSM_MODE, 0 }, { 384, CS42L51_SSM_MODE, 0 },
  401. { 512, CS42L51_SSM_MODE, 0 }, { 768, CS42L51_SSM_MODE, 0 },
  402. { 128, CS42L51_DSM_MODE, 0 }, { 192, CS42L51_DSM_MODE, 0 },
  403. { 256, CS42L51_DSM_MODE, 0 }, { 384, CS42L51_DSM_MODE, 0 },
  404. };
  405. static struct cs42l51_ratios slave_auto_ratios[] = {
  406. { 1024, CS42L51_QSM_MODE, 0 }, { 1536, CS42L51_QSM_MODE, 0 },
  407. { 2048, CS42L51_QSM_MODE, 1 }, { 3072, CS42L51_QSM_MODE, 1 },
  408. { 512, CS42L51_HSM_MODE, 0 }, { 768, CS42L51_HSM_MODE, 0 },
  409. { 1024, CS42L51_HSM_MODE, 1 }, { 1536, CS42L51_HSM_MODE, 1 },
  410. { 256, CS42L51_SSM_MODE, 0 }, { 384, CS42L51_SSM_MODE, 0 },
  411. { 512, CS42L51_SSM_MODE, 1 }, { 768, CS42L51_SSM_MODE, 1 },
  412. { 128, CS42L51_DSM_MODE, 0 }, { 192, CS42L51_DSM_MODE, 0 },
  413. { 256, CS42L51_DSM_MODE, 1 }, { 384, CS42L51_DSM_MODE, 1 },
  414. };
  415. static int cs42l51_set_dai_sysclk(struct snd_soc_dai *codec_dai,
  416. int clk_id, unsigned int freq, int dir)
  417. {
  418. struct snd_soc_codec *codec = codec_dai->codec;
  419. struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
  420. struct cs42l51_ratios *ratios = NULL;
  421. int nr_ratios = 0;
  422. unsigned int rates = 0;
  423. unsigned int rate_min = -1;
  424. unsigned int rate_max = 0;
  425. int i;
  426. cs42l51->mclk = freq;
  427. switch (cs42l51->func) {
  428. case MODE_MASTER:
  429. return -EINVAL;
  430. case MODE_SLAVE:
  431. ratios = slave_ratios;
  432. nr_ratios = ARRAY_SIZE(slave_ratios);
  433. break;
  434. case MODE_SLAVE_AUTO:
  435. ratios = slave_auto_ratios;
  436. nr_ratios = ARRAY_SIZE(slave_auto_ratios);
  437. break;
  438. }
  439. for (i = 0; i < nr_ratios; i++) {
  440. unsigned int rate = freq / ratios[i].ratio;
  441. rates |= snd_pcm_rate_to_rate_bit(rate);
  442. if (rate < rate_min)
  443. rate_min = rate;
  444. if (rate > rate_max)
  445. rate_max = rate;
  446. }
  447. rates &= ~SNDRV_PCM_RATE_KNOT;
  448. if (!rates) {
  449. dev_err(codec->dev, "could not find a valid sample rate\n");
  450. return -EINVAL;
  451. }
  452. codec_dai->playback.rates = rates;
  453. codec_dai->playback.rate_min = rate_min;
  454. codec_dai->playback.rate_max = rate_max;
  455. codec_dai->capture.rates = rates;
  456. codec_dai->capture.rate_min = rate_min;
  457. codec_dai->capture.rate_max = rate_max;
  458. return 0;
  459. }
  460. static int cs42l51_hw_params(struct snd_pcm_substream *substream,
  461. struct snd_pcm_hw_params *params,
  462. struct snd_soc_dai *dai)
  463. {
  464. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  465. struct snd_soc_device *socdev = rtd->socdev;
  466. struct snd_soc_codec *codec = socdev->card->codec;
  467. struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
  468. int ret;
  469. unsigned int i;
  470. unsigned int rate;
  471. unsigned int ratio;
  472. struct cs42l51_ratios *ratios = NULL;
  473. int nr_ratios = 0;
  474. int intf_ctl, power_ctl, fmt;
  475. switch (cs42l51->func) {
  476. case MODE_MASTER:
  477. return -EINVAL;
  478. case MODE_SLAVE:
  479. ratios = slave_ratios;
  480. nr_ratios = ARRAY_SIZE(slave_ratios);
  481. break;
  482. case MODE_SLAVE_AUTO:
  483. ratios = slave_auto_ratios;
  484. nr_ratios = ARRAY_SIZE(slave_auto_ratios);
  485. break;
  486. }
  487. /* Figure out which MCLK/LRCK ratio to use */
  488. rate = params_rate(params); /* Sampling rate, in Hz */
  489. ratio = cs42l51->mclk / rate; /* MCLK/LRCK ratio */
  490. for (i = 0; i < nr_ratios; i++) {
  491. if (ratios[i].ratio == ratio)
  492. break;
  493. }
  494. if (i == nr_ratios) {
  495. /* We did not find a matching ratio */
  496. dev_err(codec->dev, "could not find matching ratio\n");
  497. return -EINVAL;
  498. }
  499. intf_ctl = snd_soc_read(codec, CS42L51_INTF_CTL);
  500. power_ctl = snd_soc_read(codec, CS42L51_MIC_POWER_CTL);
  501. intf_ctl &= ~(CS42L51_INTF_CTL_MASTER | CS42L51_INTF_CTL_ADC_I2S
  502. | CS42L51_INTF_CTL_DAC_FORMAT(7));
  503. power_ctl &= ~(CS42L51_MIC_POWER_CTL_SPEED(3)
  504. | CS42L51_MIC_POWER_CTL_MCLK_DIV2);
  505. switch (cs42l51->func) {
  506. case MODE_MASTER:
  507. intf_ctl |= CS42L51_INTF_CTL_MASTER;
  508. power_ctl |= CS42L51_MIC_POWER_CTL_SPEED(ratios[i].speed_mode);
  509. break;
  510. case MODE_SLAVE:
  511. power_ctl |= CS42L51_MIC_POWER_CTL_SPEED(ratios[i].speed_mode);
  512. break;
  513. case MODE_SLAVE_AUTO:
  514. power_ctl |= CS42L51_MIC_POWER_CTL_AUTO;
  515. break;
  516. }
  517. switch (cs42l51->audio_mode) {
  518. case SND_SOC_DAIFMT_I2S:
  519. intf_ctl |= CS42L51_INTF_CTL_ADC_I2S;
  520. intf_ctl |= CS42L51_INTF_CTL_DAC_FORMAT(CS42L51_DAC_DIF_I2S);
  521. break;
  522. case SND_SOC_DAIFMT_LEFT_J:
  523. intf_ctl |= CS42L51_INTF_CTL_DAC_FORMAT(CS42L51_DAC_DIF_LJ24);
  524. break;
  525. case SND_SOC_DAIFMT_RIGHT_J:
  526. switch (params_format(params)) {
  527. case SNDRV_PCM_FORMAT_S16_LE:
  528. case SNDRV_PCM_FORMAT_S16_BE:
  529. fmt = CS42L51_DAC_DIF_RJ16;
  530. break;
  531. case SNDRV_PCM_FORMAT_S18_3LE:
  532. case SNDRV_PCM_FORMAT_S18_3BE:
  533. fmt = CS42L51_DAC_DIF_RJ18;
  534. break;
  535. case SNDRV_PCM_FORMAT_S20_3LE:
  536. case SNDRV_PCM_FORMAT_S20_3BE:
  537. fmt = CS42L51_DAC_DIF_RJ20;
  538. break;
  539. case SNDRV_PCM_FORMAT_S24_LE:
  540. case SNDRV_PCM_FORMAT_S24_BE:
  541. fmt = CS42L51_DAC_DIF_RJ24;
  542. break;
  543. default:
  544. dev_err(codec->dev, "unknown format\n");
  545. return -EINVAL;
  546. }
  547. intf_ctl |= CS42L51_INTF_CTL_DAC_FORMAT(fmt);
  548. break;
  549. default:
  550. dev_err(codec->dev, "unknown format\n");
  551. return -EINVAL;
  552. }
  553. if (ratios[i].mclk)
  554. power_ctl |= CS42L51_MIC_POWER_CTL_MCLK_DIV2;
  555. ret = snd_soc_write(codec, CS42L51_INTF_CTL, intf_ctl);
  556. if (ret < 0)
  557. return ret;
  558. ret = snd_soc_write(codec, CS42L51_MIC_POWER_CTL, power_ctl);
  559. if (ret < 0)
  560. return ret;
  561. return 0;
  562. }
  563. static int cs42l51_dai_mute(struct snd_soc_dai *dai, int mute)
  564. {
  565. struct snd_soc_codec *codec = dai->codec;
  566. int reg;
  567. int mask = CS42L51_DAC_OUT_CTL_DACA_MUTE|CS42L51_DAC_OUT_CTL_DACB_MUTE;
  568. reg = snd_soc_read(codec, CS42L51_DAC_OUT_CTL);
  569. if (mute)
  570. reg |= mask;
  571. else
  572. reg &= ~mask;
  573. return snd_soc_write(codec, CS42L51_DAC_OUT_CTL, reg);
  574. }
  575. static struct snd_soc_dai_ops cs42l51_dai_ops = {
  576. .hw_params = cs42l51_hw_params,
  577. .set_sysclk = cs42l51_set_dai_sysclk,
  578. .set_fmt = cs42l51_set_dai_fmt,
  579. .digital_mute = cs42l51_dai_mute,
  580. };
  581. struct snd_soc_dai cs42l51_dai = {
  582. .name = "CS42L51 HiFi",
  583. .playback = {
  584. .stream_name = "Playback",
  585. .channels_min = 1,
  586. .channels_max = 2,
  587. .rates = SNDRV_PCM_RATE_8000_96000,
  588. .formats = CS42L51_FORMATS,
  589. },
  590. .capture = {
  591. .stream_name = "Capture",
  592. .channels_min = 1,
  593. .channels_max = 2,
  594. .rates = SNDRV_PCM_RATE_8000_96000,
  595. .formats = CS42L51_FORMATS,
  596. },
  597. .ops = &cs42l51_dai_ops,
  598. };
  599. EXPORT_SYMBOL_GPL(cs42l51_dai);
  600. static int cs42l51_probe(struct platform_device *pdev)
  601. {
  602. struct snd_soc_device *socdev = platform_get_drvdata(pdev);
  603. struct snd_soc_codec *codec;
  604. int ret = 0;
  605. if (!cs42l51_codec) {
  606. dev_err(&pdev->dev, "CS42L51 codec not yet registered\n");
  607. return -EINVAL;
  608. }
  609. socdev->card->codec = cs42l51_codec;
  610. codec = socdev->card->codec;
  611. /* Register PCMs */
  612. ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
  613. if (ret < 0) {
  614. dev_err(&pdev->dev, "failed to create PCMs\n");
  615. return ret;
  616. }
  617. snd_soc_add_controls(codec, cs42l51_snd_controls,
  618. ARRAY_SIZE(cs42l51_snd_controls));
  619. snd_soc_dapm_new_controls(codec, cs42l51_dapm_widgets,
  620. ARRAY_SIZE(cs42l51_dapm_widgets));
  621. snd_soc_dapm_add_routes(codec, cs42l51_routes,
  622. ARRAY_SIZE(cs42l51_routes));
  623. return 0;
  624. }
  625. static int cs42l51_remove(struct platform_device *pdev)
  626. {
  627. struct snd_soc_device *socdev = platform_get_drvdata(pdev);
  628. snd_soc_free_pcms(socdev);
  629. snd_soc_dapm_free(socdev);
  630. return 0;
  631. }
  632. struct snd_soc_codec_device soc_codec_device_cs42l51 = {
  633. .probe = cs42l51_probe,
  634. .remove = cs42l51_remove
  635. };
  636. EXPORT_SYMBOL_GPL(soc_codec_device_cs42l51);
  637. static int __init cs42l51_init(void)
  638. {
  639. int ret;
  640. ret = i2c_add_driver(&cs42l51_i2c_driver);
  641. if (ret != 0) {
  642. printk(KERN_ERR "%s: can't add i2c driver\n", __func__);
  643. return ret;
  644. }
  645. return 0;
  646. }
  647. module_init(cs42l51_init);
  648. static void __exit cs42l51_exit(void)
  649. {
  650. i2c_del_driver(&cs42l51_i2c_driver);
  651. }
  652. module_exit(cs42l51_exit);
  653. MODULE_AUTHOR("Arnaud Patard <apatard@mandriva.com>");
  654. MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver");
  655. MODULE_LICENSE("GPL");