sti-sas.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) STMicroelectronics SA 2015
  4. * Authors: Arnaud Pouliquen <arnaud.pouliquen@st.com>
  5. * for STMicroelectronics.
  6. */
  7. #include <linux/io.h>
  8. #include <linux/module.h>
  9. #include <linux/regmap.h>
  10. #include <linux/reset.h>
  11. #include <linux/mfd/syscon.h>
  12. #include <sound/soc.h>
  13. #include <sound/soc-dapm.h>
  14. /* DAC definitions */
  15. /* stih407 DAC registers */
  16. /* sysconf 5041: Audio-Gue-Control */
  17. #define STIH407_AUDIO_GLUE_CTRL 0x000000A4
  18. /* sysconf 5042: Audio-DAC-Control */
  19. #define STIH407_AUDIO_DAC_CTRL 0x000000A8
  20. /* DAC definitions */
  21. #define STIH407_DAC_SOFTMUTE 0x0
  22. #define STIH407_DAC_STANDBY_ANA 0x1
  23. #define STIH407_DAC_STANDBY 0x2
  24. #define STIH407_DAC_SOFTMUTE_MASK BIT(STIH407_DAC_SOFTMUTE)
  25. #define STIH407_DAC_STANDBY_ANA_MASK BIT(STIH407_DAC_STANDBY_ANA)
  26. #define STIH407_DAC_STANDBY_MASK BIT(STIH407_DAC_STANDBY)
  27. /* SPDIF definitions */
  28. #define SPDIF_BIPHASE_ENABLE 0x6
  29. #define SPDIF_BIPHASE_IDLE 0x7
  30. #define SPDIF_BIPHASE_ENABLE_MASK BIT(SPDIF_BIPHASE_ENABLE)
  31. #define SPDIF_BIPHASE_IDLE_MASK BIT(SPDIF_BIPHASE_IDLE)
  32. enum {
  33. STI_SAS_DAI_SPDIF_OUT,
  34. STI_SAS_DAI_ANALOG_OUT,
  35. };
  36. static const struct reg_default stih407_sas_reg_defaults[] = {
  37. { STIH407_AUDIO_DAC_CTRL, 0x000000000 },
  38. { STIH407_AUDIO_GLUE_CTRL, 0x00000040 },
  39. };
  40. struct sti_dac_audio {
  41. struct regmap *regmap;
  42. struct regmap *virt_regmap;
  43. struct regmap_field **field;
  44. struct reset_control *rst;
  45. int mclk;
  46. };
  47. struct sti_spdif_audio {
  48. struct regmap *regmap;
  49. struct regmap_field **field;
  50. int mclk;
  51. };
  52. /* device data structure */
  53. struct sti_sas_dev_data {
  54. const struct regmap_config *regmap;
  55. const struct snd_soc_dai_ops *dac_ops; /* DAC function callbacks */
  56. const struct snd_soc_dapm_widget *dapm_widgets; /* dapms declaration */
  57. const int num_dapm_widgets; /* dapms declaration */
  58. const struct snd_soc_dapm_route *dapm_routes; /* route declaration */
  59. const int num_dapm_routes; /* route declaration */
  60. };
  61. /* driver data structure */
  62. struct sti_sas_data {
  63. struct device *dev;
  64. const struct sti_sas_dev_data *dev_data;
  65. struct sti_dac_audio dac;
  66. struct sti_spdif_audio spdif;
  67. };
  68. /* Read a register from the sysconf reg bank */
  69. static int sti_sas_read_reg(void *context, unsigned int reg,
  70. unsigned int *value)
  71. {
  72. struct sti_sas_data *drvdata = context;
  73. int status;
  74. u32 val;
  75. status = regmap_read(drvdata->dac.regmap, reg, &val);
  76. *value = (unsigned int)val;
  77. return status;
  78. }
  79. /* Read a register from the sysconf reg bank */
  80. static int sti_sas_write_reg(void *context, unsigned int reg,
  81. unsigned int value)
  82. {
  83. struct sti_sas_data *drvdata = context;
  84. int status;
  85. status = regmap_write(drvdata->dac.regmap, reg, value);
  86. return status;
  87. }
  88. static int sti_sas_init_sas_registers(struct snd_soc_component *component,
  89. struct sti_sas_data *data)
  90. {
  91. int ret;
  92. /*
  93. * DAC and SPDIF are activated by default
  94. * put them in IDLE to save power
  95. */
  96. /* Initialise bi-phase formatter to disabled */
  97. ret = snd_soc_component_update_bits(component, STIH407_AUDIO_GLUE_CTRL,
  98. SPDIF_BIPHASE_ENABLE_MASK, 0);
  99. if (!ret)
  100. /* Initialise bi-phase formatter idle value to 0 */
  101. ret = snd_soc_component_update_bits(component, STIH407_AUDIO_GLUE_CTRL,
  102. SPDIF_BIPHASE_IDLE_MASK, 0);
  103. if (ret < 0) {
  104. dev_err(component->dev, "Failed to update SPDIF registers\n");
  105. return ret;
  106. }
  107. /* Init DAC configuration */
  108. /* init configuration */
  109. ret = snd_soc_component_update_bits(component, STIH407_AUDIO_DAC_CTRL,
  110. STIH407_DAC_STANDBY_MASK,
  111. STIH407_DAC_STANDBY_MASK);
  112. if (!ret)
  113. ret = snd_soc_component_update_bits(component, STIH407_AUDIO_DAC_CTRL,
  114. STIH407_DAC_STANDBY_ANA_MASK,
  115. STIH407_DAC_STANDBY_ANA_MASK);
  116. if (!ret)
  117. ret = snd_soc_component_update_bits(component, STIH407_AUDIO_DAC_CTRL,
  118. STIH407_DAC_SOFTMUTE_MASK,
  119. STIH407_DAC_SOFTMUTE_MASK);
  120. if (ret < 0) {
  121. dev_err(component->dev, "Failed to update DAC registers\n");
  122. return ret;
  123. }
  124. return ret;
  125. }
  126. /*
  127. * DAC
  128. */
  129. static int sti_sas_dac_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
  130. {
  131. /* Sanity check only */
  132. if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
  133. dev_err(dai->component->dev,
  134. "%s: ERROR: Unsupporter master mask 0x%x\n",
  135. __func__, fmt & SND_SOC_DAIFMT_MASTER_MASK);
  136. return -EINVAL;
  137. }
  138. return 0;
  139. }
  140. static const struct snd_soc_dapm_widget stih407_sas_dapm_widgets[] = {
  141. SND_SOC_DAPM_OUT_DRV("DAC standby ana", STIH407_AUDIO_DAC_CTRL,
  142. STIH407_DAC_STANDBY_ANA, 1, NULL, 0),
  143. SND_SOC_DAPM_DAC("DAC standby", "dac_p", STIH407_AUDIO_DAC_CTRL,
  144. STIH407_DAC_STANDBY, 1),
  145. SND_SOC_DAPM_OUTPUT("DAC Output"),
  146. };
  147. static const struct snd_soc_dapm_route stih407_sas_route[] = {
  148. {"DAC Output", NULL, "DAC standby ana"},
  149. {"DAC standby ana", NULL, "DAC standby"},
  150. };
  151. static int stih407_sas_dac_mute(struct snd_soc_dai *dai, int mute, int stream)
  152. {
  153. struct snd_soc_component *component = dai->component;
  154. if (mute) {
  155. return snd_soc_component_update_bits(component, STIH407_AUDIO_DAC_CTRL,
  156. STIH407_DAC_SOFTMUTE_MASK,
  157. STIH407_DAC_SOFTMUTE_MASK);
  158. } else {
  159. return snd_soc_component_update_bits(component, STIH407_AUDIO_DAC_CTRL,
  160. STIH407_DAC_SOFTMUTE_MASK,
  161. 0);
  162. }
  163. }
  164. /*
  165. * SPDIF
  166. */
  167. static int sti_sas_spdif_set_fmt(struct snd_soc_dai *dai,
  168. unsigned int fmt)
  169. {
  170. if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
  171. dev_err(dai->component->dev,
  172. "%s: ERROR: Unsupporter master mask 0x%x\n",
  173. __func__, fmt & SND_SOC_DAIFMT_MASTER_MASK);
  174. return -EINVAL;
  175. }
  176. return 0;
  177. }
  178. /*
  179. * sti_sas_spdif_trigger:
  180. * Trigger function is used to ensure that BiPhase Formater is disabled
  181. * before CPU dai is stopped.
  182. * This is mandatory to avoid that BPF is stalled
  183. */
  184. static int sti_sas_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
  185. struct snd_soc_dai *dai)
  186. {
  187. struct snd_soc_component *component = dai->component;
  188. switch (cmd) {
  189. case SNDRV_PCM_TRIGGER_START:
  190. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  191. return snd_soc_component_update_bits(component, STIH407_AUDIO_GLUE_CTRL,
  192. SPDIF_BIPHASE_ENABLE_MASK,
  193. SPDIF_BIPHASE_ENABLE_MASK);
  194. case SNDRV_PCM_TRIGGER_RESUME:
  195. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  196. case SNDRV_PCM_TRIGGER_STOP:
  197. case SNDRV_PCM_TRIGGER_SUSPEND:
  198. return snd_soc_component_update_bits(component, STIH407_AUDIO_GLUE_CTRL,
  199. SPDIF_BIPHASE_ENABLE_MASK,
  200. 0);
  201. default:
  202. return -EINVAL;
  203. }
  204. }
  205. static bool sti_sas_volatile_register(struct device *dev, unsigned int reg)
  206. {
  207. if (reg == STIH407_AUDIO_GLUE_CTRL)
  208. return true;
  209. return false;
  210. }
  211. /*
  212. * CODEC DAIS
  213. */
  214. /*
  215. * sti_sas_set_sysclk:
  216. * get MCLK input frequency to check that MCLK-FS ratio is coherent
  217. */
  218. static int sti_sas_set_sysclk(struct snd_soc_dai *dai, int clk_id,
  219. unsigned int freq, int dir)
  220. {
  221. struct snd_soc_component *component = dai->component;
  222. struct sti_sas_data *drvdata = dev_get_drvdata(component->dev);
  223. if (dir == SND_SOC_CLOCK_OUT)
  224. return 0;
  225. if (clk_id != 0)
  226. return -EINVAL;
  227. switch (dai->id) {
  228. case STI_SAS_DAI_SPDIF_OUT:
  229. drvdata->spdif.mclk = freq;
  230. break;
  231. case STI_SAS_DAI_ANALOG_OUT:
  232. drvdata->dac.mclk = freq;
  233. break;
  234. }
  235. return 0;
  236. }
  237. static int sti_sas_prepare(struct snd_pcm_substream *substream,
  238. struct snd_soc_dai *dai)
  239. {
  240. struct snd_soc_component *component = dai->component;
  241. struct sti_sas_data *drvdata = dev_get_drvdata(component->dev);
  242. struct snd_pcm_runtime *runtime = substream->runtime;
  243. switch (dai->id) {
  244. case STI_SAS_DAI_SPDIF_OUT:
  245. if ((drvdata->spdif.mclk / runtime->rate) != 128) {
  246. dev_err(component->dev, "unexpected mclk-fs ratio\n");
  247. return -EINVAL;
  248. }
  249. break;
  250. case STI_SAS_DAI_ANALOG_OUT:
  251. if ((drvdata->dac.mclk / runtime->rate) != 256) {
  252. dev_err(component->dev, "unexpected mclk-fs ratio\n");
  253. return -EINVAL;
  254. }
  255. break;
  256. }
  257. return 0;
  258. }
  259. static const struct snd_soc_dai_ops stih407_dac_ops = {
  260. .set_fmt = sti_sas_dac_set_fmt,
  261. .mute_stream = stih407_sas_dac_mute,
  262. .prepare = sti_sas_prepare,
  263. .set_sysclk = sti_sas_set_sysclk,
  264. };
  265. static const struct regmap_config stih407_sas_regmap = {
  266. .reg_bits = 32,
  267. .val_bits = 32,
  268. .fast_io = true,
  269. .max_register = STIH407_AUDIO_DAC_CTRL,
  270. .reg_defaults = stih407_sas_reg_defaults,
  271. .num_reg_defaults = ARRAY_SIZE(stih407_sas_reg_defaults),
  272. .volatile_reg = sti_sas_volatile_register,
  273. .cache_type = REGCACHE_RBTREE,
  274. .reg_read = sti_sas_read_reg,
  275. .reg_write = sti_sas_write_reg,
  276. };
  277. static const struct sti_sas_dev_data stih407_data = {
  278. .regmap = &stih407_sas_regmap,
  279. .dac_ops = &stih407_dac_ops,
  280. .dapm_widgets = stih407_sas_dapm_widgets,
  281. .num_dapm_widgets = ARRAY_SIZE(stih407_sas_dapm_widgets),
  282. .dapm_routes = stih407_sas_route,
  283. .num_dapm_routes = ARRAY_SIZE(stih407_sas_route),
  284. };
  285. static struct snd_soc_dai_driver sti_sas_dai[] = {
  286. {
  287. .name = "sas-dai-spdif-out",
  288. .id = STI_SAS_DAI_SPDIF_OUT,
  289. .playback = {
  290. .stream_name = "spdif_p",
  291. .channels_min = 2,
  292. .channels_max = 2,
  293. .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
  294. SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 |
  295. SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
  296. SNDRV_PCM_RATE_192000,
  297. .formats = SNDRV_PCM_FMTBIT_S16_LE |
  298. SNDRV_PCM_FMTBIT_S32_LE,
  299. },
  300. .ops = (struct snd_soc_dai_ops[]) {
  301. {
  302. .set_fmt = sti_sas_spdif_set_fmt,
  303. .trigger = sti_sas_spdif_trigger,
  304. .set_sysclk = sti_sas_set_sysclk,
  305. .prepare = sti_sas_prepare,
  306. }
  307. },
  308. },
  309. {
  310. .name = "sas-dai-dac",
  311. .id = STI_SAS_DAI_ANALOG_OUT,
  312. .playback = {
  313. .stream_name = "dac_p",
  314. .channels_min = 2,
  315. .channels_max = 2,
  316. .rates = SNDRV_PCM_RATE_8000_48000,
  317. .formats = SNDRV_PCM_FMTBIT_S16_LE |
  318. SNDRV_PCM_FMTBIT_S32_LE,
  319. },
  320. },
  321. };
  322. #ifdef CONFIG_PM_SLEEP
  323. static int sti_sas_resume(struct snd_soc_component *component)
  324. {
  325. struct sti_sas_data *drvdata = dev_get_drvdata(component->dev);
  326. return sti_sas_init_sas_registers(component, drvdata);
  327. }
  328. #else
  329. #define sti_sas_resume NULL
  330. #endif
  331. static int sti_sas_component_probe(struct snd_soc_component *component)
  332. {
  333. struct sti_sas_data *drvdata = dev_get_drvdata(component->dev);
  334. int ret;
  335. ret = sti_sas_init_sas_registers(component, drvdata);
  336. return ret;
  337. }
  338. static struct snd_soc_component_driver sti_sas_driver = {
  339. .probe = sti_sas_component_probe,
  340. .resume = sti_sas_resume,
  341. .idle_bias_on = 1,
  342. .use_pmdown_time = 1,
  343. .endianness = 1,
  344. .non_legacy_dai_naming = 1,
  345. };
  346. static const struct of_device_id sti_sas_dev_match[] = {
  347. {
  348. .compatible = "st,stih407-sas-codec",
  349. .data = &stih407_data,
  350. },
  351. {},
  352. };
  353. MODULE_DEVICE_TABLE(of, sti_sas_dev_match);
  354. static int sti_sas_driver_probe(struct platform_device *pdev)
  355. {
  356. struct device_node *pnode = pdev->dev.of_node;
  357. struct sti_sas_data *drvdata;
  358. const struct of_device_id *of_id;
  359. /* Allocate device structure */
  360. drvdata = devm_kzalloc(&pdev->dev, sizeof(struct sti_sas_data),
  361. GFP_KERNEL);
  362. if (!drvdata)
  363. return -ENOMEM;
  364. /* Populate data structure depending on compatibility */
  365. of_id = of_match_node(sti_sas_dev_match, pnode);
  366. if (!of_id->data) {
  367. dev_err(&pdev->dev, "data associated to device is missing\n");
  368. return -EINVAL;
  369. }
  370. drvdata->dev_data = (struct sti_sas_dev_data *)of_id->data;
  371. /* Initialise device structure */
  372. drvdata->dev = &pdev->dev;
  373. /* Request the DAC & SPDIF registers memory region */
  374. drvdata->dac.virt_regmap = devm_regmap_init(&pdev->dev, NULL, drvdata,
  375. drvdata->dev_data->regmap);
  376. if (IS_ERR(drvdata->dac.virt_regmap)) {
  377. dev_err(&pdev->dev, "audio registers not enabled\n");
  378. return PTR_ERR(drvdata->dac.virt_regmap);
  379. }
  380. /* Request the syscon region */
  381. drvdata->dac.regmap =
  382. syscon_regmap_lookup_by_phandle(pnode, "st,syscfg");
  383. if (IS_ERR(drvdata->dac.regmap)) {
  384. dev_err(&pdev->dev, "syscon registers not available\n");
  385. return PTR_ERR(drvdata->dac.regmap);
  386. }
  387. drvdata->spdif.regmap = drvdata->dac.regmap;
  388. sti_sas_dai[STI_SAS_DAI_ANALOG_OUT].ops = drvdata->dev_data->dac_ops;
  389. /* Set dapms*/
  390. sti_sas_driver.dapm_widgets = drvdata->dev_data->dapm_widgets;
  391. sti_sas_driver.num_dapm_widgets = drvdata->dev_data->num_dapm_widgets;
  392. sti_sas_driver.dapm_routes = drvdata->dev_data->dapm_routes;
  393. sti_sas_driver.num_dapm_routes = drvdata->dev_data->num_dapm_routes;
  394. /* Store context */
  395. dev_set_drvdata(&pdev->dev, drvdata);
  396. return devm_snd_soc_register_component(&pdev->dev, &sti_sas_driver,
  397. sti_sas_dai,
  398. ARRAY_SIZE(sti_sas_dai));
  399. }
  400. static struct platform_driver sti_sas_platform_driver = {
  401. .driver = {
  402. .name = "sti-sas-codec",
  403. .of_match_table = sti_sas_dev_match,
  404. },
  405. .probe = sti_sas_driver_probe,
  406. };
  407. module_platform_driver(sti_sas_platform_driver);
  408. MODULE_DESCRIPTION("audio codec for STMicroelectronics sti platforms");
  409. MODULE_AUTHOR("Arnaud.pouliquen@st.com");
  410. MODULE_LICENSE("GPL v2");