pcm512x.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  1. /*
  2. * Driver for the PCM512x CODECs
  3. *
  4. * Author: Mark Brown <broonie@linaro.org>
  5. * Copyright 2014 Linaro Ltd
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * version 2 as published by the Free Software Foundation.
  10. *
  11. * This program is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. */
  16. #include <linux/init.h>
  17. #include <linux/module.h>
  18. #include <linux/clk.h>
  19. #include <linux/pm_runtime.h>
  20. #include <linux/regmap.h>
  21. #include <linux/regulator/consumer.h>
  22. #include <sound/soc.h>
  23. #include <sound/soc-dapm.h>
  24. #include <sound/tlv.h>
  25. #include "pcm512x.h"
  26. #define PCM512x_NUM_SUPPLIES 3
  27. static const char * const pcm512x_supply_names[PCM512x_NUM_SUPPLIES] = {
  28. "AVDD",
  29. "DVDD",
  30. "CPVDD",
  31. };
  32. struct pcm512x_priv {
  33. struct regmap *regmap;
  34. struct clk *sclk;
  35. struct regulator_bulk_data supplies[PCM512x_NUM_SUPPLIES];
  36. struct notifier_block supply_nb[PCM512x_NUM_SUPPLIES];
  37. };
  38. /*
  39. * We can't use the same notifier block for more than one supply and
  40. * there's no way I can see to get from a callback to the caller
  41. * except container_of().
  42. */
  43. #define PCM512x_REGULATOR_EVENT(n) \
  44. static int pcm512x_regulator_event_##n(struct notifier_block *nb, \
  45. unsigned long event, void *data) \
  46. { \
  47. struct pcm512x_priv *pcm512x = container_of(nb, struct pcm512x_priv, \
  48. supply_nb[n]); \
  49. if (event & REGULATOR_EVENT_DISABLE) { \
  50. regcache_mark_dirty(pcm512x->regmap); \
  51. regcache_cache_only(pcm512x->regmap, true); \
  52. } \
  53. return 0; \
  54. }
  55. PCM512x_REGULATOR_EVENT(0)
  56. PCM512x_REGULATOR_EVENT(1)
  57. PCM512x_REGULATOR_EVENT(2)
  58. static const struct reg_default pcm512x_reg_defaults[] = {
  59. { PCM512x_RESET, 0x00 },
  60. { PCM512x_POWER, 0x00 },
  61. { PCM512x_MUTE, 0x00 },
  62. { PCM512x_DSP, 0x00 },
  63. { PCM512x_PLL_REF, 0x00 },
  64. { PCM512x_DAC_ROUTING, 0x11 },
  65. { PCM512x_DSP_PROGRAM, 0x01 },
  66. { PCM512x_CLKDET, 0x00 },
  67. { PCM512x_AUTO_MUTE, 0x00 },
  68. { PCM512x_ERROR_DETECT, 0x00 },
  69. { PCM512x_DIGITAL_VOLUME_1, 0x00 },
  70. { PCM512x_DIGITAL_VOLUME_2, 0x30 },
  71. { PCM512x_DIGITAL_VOLUME_3, 0x30 },
  72. { PCM512x_DIGITAL_MUTE_1, 0x22 },
  73. { PCM512x_DIGITAL_MUTE_2, 0x00 },
  74. { PCM512x_DIGITAL_MUTE_3, 0x07 },
  75. { PCM512x_OUTPUT_AMPLITUDE, 0x00 },
  76. { PCM512x_ANALOG_GAIN_CTRL, 0x00 },
  77. { PCM512x_UNDERVOLTAGE_PROT, 0x00 },
  78. { PCM512x_ANALOG_MUTE_CTRL, 0x00 },
  79. { PCM512x_ANALOG_GAIN_BOOST, 0x00 },
  80. { PCM512x_VCOM_CTRL_1, 0x00 },
  81. { PCM512x_VCOM_CTRL_2, 0x01 },
  82. };
  83. static bool pcm512x_readable(struct device *dev, unsigned int reg)
  84. {
  85. switch (reg) {
  86. case PCM512x_RESET:
  87. case PCM512x_POWER:
  88. case PCM512x_MUTE:
  89. case PCM512x_PLL_EN:
  90. case PCM512x_SPI_MISO_FUNCTION:
  91. case PCM512x_DSP:
  92. case PCM512x_GPIO_EN:
  93. case PCM512x_BCLK_LRCLK_CFG:
  94. case PCM512x_DSP_GPIO_INPUT:
  95. case PCM512x_MASTER_MODE:
  96. case PCM512x_PLL_REF:
  97. case PCM512x_PLL_COEFF_0:
  98. case PCM512x_PLL_COEFF_1:
  99. case PCM512x_PLL_COEFF_2:
  100. case PCM512x_PLL_COEFF_3:
  101. case PCM512x_PLL_COEFF_4:
  102. case PCM512x_DSP_CLKDIV:
  103. case PCM512x_DAC_CLKDIV:
  104. case PCM512x_NCP_CLKDIV:
  105. case PCM512x_OSR_CLKDIV:
  106. case PCM512x_MASTER_CLKDIV_1:
  107. case PCM512x_MASTER_CLKDIV_2:
  108. case PCM512x_FS_SPEED_MODE:
  109. case PCM512x_IDAC_1:
  110. case PCM512x_IDAC_2:
  111. case PCM512x_ERROR_DETECT:
  112. case PCM512x_I2S_1:
  113. case PCM512x_I2S_2:
  114. case PCM512x_DAC_ROUTING:
  115. case PCM512x_DSP_PROGRAM:
  116. case PCM512x_CLKDET:
  117. case PCM512x_AUTO_MUTE:
  118. case PCM512x_DIGITAL_VOLUME_1:
  119. case PCM512x_DIGITAL_VOLUME_2:
  120. case PCM512x_DIGITAL_VOLUME_3:
  121. case PCM512x_DIGITAL_MUTE_1:
  122. case PCM512x_DIGITAL_MUTE_2:
  123. case PCM512x_DIGITAL_MUTE_3:
  124. case PCM512x_GPIO_OUTPUT_1:
  125. case PCM512x_GPIO_OUTPUT_2:
  126. case PCM512x_GPIO_OUTPUT_3:
  127. case PCM512x_GPIO_OUTPUT_4:
  128. case PCM512x_GPIO_OUTPUT_5:
  129. case PCM512x_GPIO_OUTPUT_6:
  130. case PCM512x_GPIO_CONTROL_1:
  131. case PCM512x_GPIO_CONTROL_2:
  132. case PCM512x_OVERFLOW:
  133. case PCM512x_RATE_DET_1:
  134. case PCM512x_RATE_DET_2:
  135. case PCM512x_RATE_DET_3:
  136. case PCM512x_RATE_DET_4:
  137. case PCM512x_ANALOG_MUTE_DET:
  138. case PCM512x_GPIN:
  139. case PCM512x_DIGITAL_MUTE_DET:
  140. case PCM512x_OUTPUT_AMPLITUDE:
  141. case PCM512x_ANALOG_GAIN_CTRL:
  142. case PCM512x_UNDERVOLTAGE_PROT:
  143. case PCM512x_ANALOG_MUTE_CTRL:
  144. case PCM512x_ANALOG_GAIN_BOOST:
  145. case PCM512x_VCOM_CTRL_1:
  146. case PCM512x_VCOM_CTRL_2:
  147. case PCM512x_CRAM_CTRL:
  148. return true;
  149. default:
  150. /* There are 256 raw register addresses */
  151. return reg < 0xff;
  152. }
  153. }
  154. static bool pcm512x_volatile(struct device *dev, unsigned int reg)
  155. {
  156. switch (reg) {
  157. case PCM512x_PLL_EN:
  158. case PCM512x_OVERFLOW:
  159. case PCM512x_RATE_DET_1:
  160. case PCM512x_RATE_DET_2:
  161. case PCM512x_RATE_DET_3:
  162. case PCM512x_RATE_DET_4:
  163. case PCM512x_ANALOG_MUTE_DET:
  164. case PCM512x_GPIN:
  165. case PCM512x_DIGITAL_MUTE_DET:
  166. case PCM512x_CRAM_CTRL:
  167. return true;
  168. default:
  169. /* There are 256 raw register addresses */
  170. return reg < 0xff;
  171. }
  172. }
  173. static const DECLARE_TLV_DB_SCALE(digital_tlv, -10350, 50, 1);
  174. static const DECLARE_TLV_DB_SCALE(analog_tlv, -600, 600, 0);
  175. static const DECLARE_TLV_DB_SCALE(boost_tlv, 0, 80, 0);
  176. static const char * const pcm512x_dsp_program_texts[] = {
  177. "FIR interpolation with de-emphasis",
  178. "Low latency IIR with de-emphasis",
  179. "High attenuation with de-emphasis",
  180. "Fixed process flow",
  181. "Ringing-less low latency FIR",
  182. };
  183. static const unsigned int pcm512x_dsp_program_values[] = {
  184. 1,
  185. 2,
  186. 3,
  187. 5,
  188. 7,
  189. };
  190. static SOC_VALUE_ENUM_SINGLE_DECL(pcm512x_dsp_program,
  191. PCM512x_DSP_PROGRAM, 0, 0x1f,
  192. pcm512x_dsp_program_texts,
  193. pcm512x_dsp_program_values);
  194. static const char * const pcm512x_clk_missing_text[] = {
  195. "1s", "2s", "3s", "4s", "5s", "6s", "7s", "8s"
  196. };
  197. static const struct soc_enum pcm512x_clk_missing =
  198. SOC_ENUM_SINGLE(PCM512x_CLKDET, 0, 8, pcm512x_clk_missing_text);
  199. static const char * const pcm512x_autom_text[] = {
  200. "21ms", "106ms", "213ms", "533ms", "1.07s", "2.13s", "5.33s", "10.66s"
  201. };
  202. static const struct soc_enum pcm512x_autom_l =
  203. SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATML_SHIFT, 8,
  204. pcm512x_autom_text);
  205. static const struct soc_enum pcm512x_autom_r =
  206. SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATMR_SHIFT, 8,
  207. pcm512x_autom_text);
  208. static const char * const pcm512x_ramp_rate_text[] = {
  209. "1 sample/update", "2 samples/update", "4 samples/update",
  210. "Immediate"
  211. };
  212. static const struct soc_enum pcm512x_vndf =
  213. SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDF_SHIFT, 4,
  214. pcm512x_ramp_rate_text);
  215. static const struct soc_enum pcm512x_vnuf =
  216. SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUF_SHIFT, 4,
  217. pcm512x_ramp_rate_text);
  218. static const struct soc_enum pcm512x_vedf =
  219. SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDF_SHIFT, 4,
  220. pcm512x_ramp_rate_text);
  221. static const char * const pcm512x_ramp_step_text[] = {
  222. "4dB/step", "2dB/step", "1dB/step", "0.5dB/step"
  223. };
  224. static const struct soc_enum pcm512x_vnds =
  225. SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDS_SHIFT, 4,
  226. pcm512x_ramp_step_text);
  227. static const struct soc_enum pcm512x_vnus =
  228. SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUS_SHIFT, 4,
  229. pcm512x_ramp_step_text);
  230. static const struct soc_enum pcm512x_veds =
  231. SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDS_SHIFT, 4,
  232. pcm512x_ramp_step_text);
  233. static const struct snd_kcontrol_new pcm512x_controls[] = {
  234. SOC_DOUBLE_R_TLV("Digital Playback Volume", PCM512x_DIGITAL_VOLUME_2,
  235. PCM512x_DIGITAL_VOLUME_3, 0, 255, 1, digital_tlv),
  236. SOC_DOUBLE_TLV("Analogue Playback Volume", PCM512x_ANALOG_GAIN_CTRL,
  237. PCM512x_LAGN_SHIFT, PCM512x_RAGN_SHIFT, 1, 1, analog_tlv),
  238. SOC_DOUBLE_TLV("Analogue Playback Boost Volume", PCM512x_ANALOG_GAIN_BOOST,
  239. PCM512x_AGBL_SHIFT, PCM512x_AGBR_SHIFT, 1, 0, boost_tlv),
  240. SOC_DOUBLE("Digital Playback Switch", PCM512x_MUTE, PCM512x_RQML_SHIFT,
  241. PCM512x_RQMR_SHIFT, 1, 1),
  242. SOC_SINGLE("Deemphasis Switch", PCM512x_DSP, PCM512x_DEMP_SHIFT, 1, 1),
  243. SOC_ENUM("DSP Program", pcm512x_dsp_program),
  244. SOC_ENUM("Clock Missing Period", pcm512x_clk_missing),
  245. SOC_ENUM("Auto Mute Time Left", pcm512x_autom_l),
  246. SOC_ENUM("Auto Mute Time Right", pcm512x_autom_r),
  247. SOC_SINGLE("Auto Mute Mono Switch", PCM512x_DIGITAL_MUTE_3,
  248. PCM512x_ACTL_SHIFT, 1, 0),
  249. SOC_DOUBLE("Auto Mute Switch", PCM512x_DIGITAL_MUTE_3, PCM512x_AMLE_SHIFT,
  250. PCM512x_AMLR_SHIFT, 1, 0),
  251. SOC_ENUM("Volume Ramp Down Rate", pcm512x_vndf),
  252. SOC_ENUM("Volume Ramp Down Step", pcm512x_vnds),
  253. SOC_ENUM("Volume Ramp Up Rate", pcm512x_vnuf),
  254. SOC_ENUM("Volume Ramp Up Step", pcm512x_vnus),
  255. SOC_ENUM("Volume Ramp Down Emergency Rate", pcm512x_vedf),
  256. SOC_ENUM("Volume Ramp Down Emergency Step", pcm512x_veds),
  257. };
  258. static const struct snd_soc_dapm_widget pcm512x_dapm_widgets[] = {
  259. SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0),
  260. SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0),
  261. SND_SOC_DAPM_OUTPUT("OUTL"),
  262. SND_SOC_DAPM_OUTPUT("OUTR"),
  263. };
  264. static const struct snd_soc_dapm_route pcm512x_dapm_routes[] = {
  265. { "DACL", NULL, "Playback" },
  266. { "DACR", NULL, "Playback" },
  267. { "OUTL", NULL, "DACL" },
  268. { "OUTR", NULL, "DACR" },
  269. };
  270. static int pcm512x_set_bias_level(struct snd_soc_codec *codec,
  271. enum snd_soc_bias_level level)
  272. {
  273. struct pcm512x_priv *pcm512x = dev_get_drvdata(codec->dev);
  274. int ret;
  275. switch (level) {
  276. case SND_SOC_BIAS_ON:
  277. case SND_SOC_BIAS_PREPARE:
  278. break;
  279. case SND_SOC_BIAS_STANDBY:
  280. ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
  281. PCM512x_RQST, 0);
  282. if (ret != 0) {
  283. dev_err(codec->dev, "Failed to remove standby: %d\n",
  284. ret);
  285. return ret;
  286. }
  287. break;
  288. case SND_SOC_BIAS_OFF:
  289. ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
  290. PCM512x_RQST, PCM512x_RQST);
  291. if (ret != 0) {
  292. dev_err(codec->dev, "Failed to request standby: %d\n",
  293. ret);
  294. return ret;
  295. }
  296. break;
  297. }
  298. codec->dapm.bias_level = level;
  299. return 0;
  300. }
  301. static struct snd_soc_dai_driver pcm512x_dai = {
  302. .name = "pcm512x-hifi",
  303. .playback = {
  304. .stream_name = "Playback",
  305. .channels_min = 2,
  306. .channels_max = 2,
  307. .rates = SNDRV_PCM_RATE_8000_192000,
  308. .formats = SNDRV_PCM_FMTBIT_S16_LE |
  309. SNDRV_PCM_FMTBIT_S24_LE |
  310. SNDRV_PCM_FMTBIT_S32_LE
  311. },
  312. };
  313. static struct snd_soc_codec_driver pcm512x_codec_driver = {
  314. .set_bias_level = pcm512x_set_bias_level,
  315. .idle_bias_off = true,
  316. .controls = pcm512x_controls,
  317. .num_controls = ARRAY_SIZE(pcm512x_controls),
  318. .dapm_widgets = pcm512x_dapm_widgets,
  319. .num_dapm_widgets = ARRAY_SIZE(pcm512x_dapm_widgets),
  320. .dapm_routes = pcm512x_dapm_routes,
  321. .num_dapm_routes = ARRAY_SIZE(pcm512x_dapm_routes),
  322. };
  323. static const struct regmap_range_cfg pcm512x_range = {
  324. .name = "Pages", .range_min = PCM512x_VIRT_BASE,
  325. .range_max = PCM512x_MAX_REGISTER,
  326. .selector_reg = PCM512x_PAGE,
  327. .selector_mask = 0xff,
  328. .window_start = 0, .window_len = 0x100,
  329. };
  330. const struct regmap_config pcm512x_regmap = {
  331. .reg_bits = 8,
  332. .val_bits = 8,
  333. .readable_reg = pcm512x_readable,
  334. .volatile_reg = pcm512x_volatile,
  335. .ranges = &pcm512x_range,
  336. .num_ranges = 1,
  337. .max_register = PCM512x_MAX_REGISTER,
  338. .reg_defaults = pcm512x_reg_defaults,
  339. .num_reg_defaults = ARRAY_SIZE(pcm512x_reg_defaults),
  340. .cache_type = REGCACHE_RBTREE,
  341. };
  342. EXPORT_SYMBOL_GPL(pcm512x_regmap);
  343. int pcm512x_probe(struct device *dev, struct regmap *regmap)
  344. {
  345. struct pcm512x_priv *pcm512x;
  346. int i, ret;
  347. pcm512x = devm_kzalloc(dev, sizeof(struct pcm512x_priv), GFP_KERNEL);
  348. if (!pcm512x)
  349. return -ENOMEM;
  350. dev_set_drvdata(dev, pcm512x);
  351. pcm512x->regmap = regmap;
  352. for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++)
  353. pcm512x->supplies[i].supply = pcm512x_supply_names[i];
  354. ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(pcm512x->supplies),
  355. pcm512x->supplies);
  356. if (ret != 0) {
  357. dev_err(dev, "Failed to get supplies: %d\n", ret);
  358. return ret;
  359. }
  360. pcm512x->supply_nb[0].notifier_call = pcm512x_regulator_event_0;
  361. pcm512x->supply_nb[1].notifier_call = pcm512x_regulator_event_1;
  362. pcm512x->supply_nb[2].notifier_call = pcm512x_regulator_event_2;
  363. for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++) {
  364. ret = regulator_register_notifier(pcm512x->supplies[i].consumer,
  365. &pcm512x->supply_nb[i]);
  366. if (ret != 0) {
  367. dev_err(dev,
  368. "Failed to register regulator notifier: %d\n",
  369. ret);
  370. }
  371. }
  372. ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies),
  373. pcm512x->supplies);
  374. if (ret != 0) {
  375. dev_err(dev, "Failed to enable supplies: %d\n", ret);
  376. return ret;
  377. }
  378. /* Reset the device, verifying I/O in the process for I2C */
  379. ret = regmap_write(regmap, PCM512x_RESET,
  380. PCM512x_RSTM | PCM512x_RSTR);
  381. if (ret != 0) {
  382. dev_err(dev, "Failed to reset device: %d\n", ret);
  383. goto err;
  384. }
  385. ret = regmap_write(regmap, PCM512x_RESET, 0);
  386. if (ret != 0) {
  387. dev_err(dev, "Failed to reset device: %d\n", ret);
  388. goto err;
  389. }
  390. pcm512x->sclk = devm_clk_get(dev, NULL);
  391. if (IS_ERR(pcm512x->sclk)) {
  392. if (PTR_ERR(pcm512x->sclk) == -EPROBE_DEFER)
  393. return -EPROBE_DEFER;
  394. dev_info(dev, "No SCLK, using BCLK: %ld\n",
  395. PTR_ERR(pcm512x->sclk));
  396. /* Disable reporting of missing SCLK as an error */
  397. regmap_update_bits(regmap, PCM512x_ERROR_DETECT,
  398. PCM512x_IDCH, PCM512x_IDCH);
  399. /* Switch PLL input to BCLK */
  400. regmap_update_bits(regmap, PCM512x_PLL_REF,
  401. PCM512x_SREF, PCM512x_SREF);
  402. } else {
  403. ret = clk_prepare_enable(pcm512x->sclk);
  404. if (ret != 0) {
  405. dev_err(dev, "Failed to enable SCLK: %d\n", ret);
  406. return ret;
  407. }
  408. }
  409. /* Default to standby mode */
  410. ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
  411. PCM512x_RQST, PCM512x_RQST);
  412. if (ret != 0) {
  413. dev_err(dev, "Failed to request standby: %d\n",
  414. ret);
  415. goto err_clk;
  416. }
  417. pm_runtime_set_active(dev);
  418. pm_runtime_enable(dev);
  419. pm_runtime_idle(dev);
  420. ret = snd_soc_register_codec(dev, &pcm512x_codec_driver,
  421. &pcm512x_dai, 1);
  422. if (ret != 0) {
  423. dev_err(dev, "Failed to register CODEC: %d\n", ret);
  424. goto err_pm;
  425. }
  426. return 0;
  427. err_pm:
  428. pm_runtime_disable(dev);
  429. err_clk:
  430. if (!IS_ERR(pcm512x->sclk))
  431. clk_disable_unprepare(pcm512x->sclk);
  432. err:
  433. regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies),
  434. pcm512x->supplies);
  435. return ret;
  436. }
  437. EXPORT_SYMBOL_GPL(pcm512x_probe);
  438. void pcm512x_remove(struct device *dev)
  439. {
  440. struct pcm512x_priv *pcm512x = dev_get_drvdata(dev);
  441. snd_soc_unregister_codec(dev);
  442. pm_runtime_disable(dev);
  443. if (!IS_ERR(pcm512x->sclk))
  444. clk_disable_unprepare(pcm512x->sclk);
  445. regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies),
  446. pcm512x->supplies);
  447. }
  448. EXPORT_SYMBOL_GPL(pcm512x_remove);
  449. #ifdef CONFIG_PM_RUNTIME
  450. static int pcm512x_suspend(struct device *dev)
  451. {
  452. struct pcm512x_priv *pcm512x = dev_get_drvdata(dev);
  453. int ret;
  454. ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
  455. PCM512x_RQPD, PCM512x_RQPD);
  456. if (ret != 0) {
  457. dev_err(dev, "Failed to request power down: %d\n", ret);
  458. return ret;
  459. }
  460. ret = regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies),
  461. pcm512x->supplies);
  462. if (ret != 0) {
  463. dev_err(dev, "Failed to disable supplies: %d\n", ret);
  464. return ret;
  465. }
  466. if (!IS_ERR(pcm512x->sclk))
  467. clk_disable_unprepare(pcm512x->sclk);
  468. return 0;
  469. }
  470. static int pcm512x_resume(struct device *dev)
  471. {
  472. struct pcm512x_priv *pcm512x = dev_get_drvdata(dev);
  473. int ret;
  474. if (!IS_ERR(pcm512x->sclk)) {
  475. ret = clk_prepare_enable(pcm512x->sclk);
  476. if (ret != 0) {
  477. dev_err(dev, "Failed to enable SCLK: %d\n", ret);
  478. return ret;
  479. }
  480. }
  481. ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies),
  482. pcm512x->supplies);
  483. if (ret != 0) {
  484. dev_err(dev, "Failed to enable supplies: %d\n", ret);
  485. return ret;
  486. }
  487. regcache_cache_only(pcm512x->regmap, false);
  488. ret = regcache_sync(pcm512x->regmap);
  489. if (ret != 0) {
  490. dev_err(dev, "Failed to sync cache: %d\n", ret);
  491. return ret;
  492. }
  493. ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
  494. PCM512x_RQPD, 0);
  495. if (ret != 0) {
  496. dev_err(dev, "Failed to remove power down: %d\n", ret);
  497. return ret;
  498. }
  499. return 0;
  500. }
  501. #endif
  502. const struct dev_pm_ops pcm512x_pm_ops = {
  503. SET_RUNTIME_PM_OPS(pcm512x_suspend, pcm512x_resume, NULL)
  504. };
  505. EXPORT_SYMBOL_GPL(pcm512x_pm_ops);
  506. MODULE_DESCRIPTION("ASoC PCM512x codec driver");
  507. MODULE_AUTHOR("Mark Brown <broonie@linaro.org>");
  508. MODULE_LICENSE("GPL v2");