sti-sas.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629
  1. /*
  2. * Copyright (C) STMicroelectronics SA 2015
  3. * Authors: Arnaud Pouliquen <arnaud.pouliquen@st.com>
  4. * for STMicroelectronics.
  5. * License terms: GNU General Public License (GPL), version 2
  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. /* chipID supported */
  15. #define CHIPID_STIH416 0
  16. #define CHIPID_STIH407 1
  17. /* DAC definitions */
  18. /* stih416 DAC registers */
  19. /* sysconf 2517: Audio-DAC-Control */
  20. #define STIH416_AUDIO_DAC_CTRL 0x00000814
  21. /* sysconf 2519: Audio-Gue-Control */
  22. #define STIH416_AUDIO_GLUE_CTRL 0x0000081C
  23. #define STIH416_DAC_NOT_STANDBY 0x3
  24. #define STIH416_DAC_SOFTMUTE 0x4
  25. #define STIH416_DAC_ANA_NOT_PWR 0x5
  26. #define STIH416_DAC_NOT_PNDBG 0x6
  27. #define STIH416_DAC_NOT_STANDBY_MASK BIT(STIH416_DAC_NOT_STANDBY)
  28. #define STIH416_DAC_SOFTMUTE_MASK BIT(STIH416_DAC_SOFTMUTE)
  29. #define STIH416_DAC_ANA_NOT_PWR_MASK BIT(STIH416_DAC_ANA_NOT_PWR)
  30. #define STIH416_DAC_NOT_PNDBG_MASK BIT(STIH416_DAC_NOT_PNDBG)
  31. /* stih407 DAC registers */
  32. /* sysconf 5041: Audio-Gue-Control */
  33. #define STIH407_AUDIO_GLUE_CTRL 0x000000A4
  34. /* sysconf 5042: Audio-DAC-Control */
  35. #define STIH407_AUDIO_DAC_CTRL 0x000000A8
  36. /* DAC definitions */
  37. #define STIH407_DAC_SOFTMUTE 0x0
  38. #define STIH407_DAC_STANDBY_ANA 0x1
  39. #define STIH407_DAC_STANDBY 0x2
  40. #define STIH407_DAC_SOFTMUTE_MASK BIT(STIH407_DAC_SOFTMUTE)
  41. #define STIH407_DAC_STANDBY_ANA_MASK BIT(STIH407_DAC_STANDBY_ANA)
  42. #define STIH407_DAC_STANDBY_MASK BIT(STIH407_DAC_STANDBY)
  43. /* SPDIF definitions */
  44. #define SPDIF_BIPHASE_ENABLE 0x6
  45. #define SPDIF_BIPHASE_IDLE 0x7
  46. #define SPDIF_BIPHASE_ENABLE_MASK BIT(SPDIF_BIPHASE_ENABLE)
  47. #define SPDIF_BIPHASE_IDLE_MASK BIT(SPDIF_BIPHASE_IDLE)
  48. enum {
  49. STI_SAS_DAI_SPDIF_OUT,
  50. STI_SAS_DAI_ANALOG_OUT,
  51. };
  52. static const struct reg_default stih416_sas_reg_defaults[] = {
  53. { STIH407_AUDIO_GLUE_CTRL, 0x00000040 },
  54. { STIH407_AUDIO_DAC_CTRL, 0x000000000 },
  55. };
  56. static const struct reg_default stih407_sas_reg_defaults[] = {
  57. { STIH416_AUDIO_DAC_CTRL, 0x000000000 },
  58. { STIH416_AUDIO_GLUE_CTRL, 0x00000040 },
  59. };
  60. struct sti_dac_audio {
  61. struct regmap *regmap;
  62. struct regmap *virt_regmap;
  63. struct regmap_field **field;
  64. struct reset_control *rst;
  65. int mclk;
  66. };
  67. struct sti_spdif_audio {
  68. struct regmap *regmap;
  69. struct regmap_field **field;
  70. int mclk;
  71. };
  72. /* device data structure */
  73. struct sti_sas_dev_data {
  74. const int chipid; /* IC version */
  75. const struct regmap_config *regmap;
  76. const struct snd_soc_dai_ops *dac_ops; /* DAC function callbacks */
  77. const struct snd_soc_dapm_widget *dapm_widgets; /* dapms declaration */
  78. const int num_dapm_widgets; /* dapms declaration */
  79. const struct snd_soc_dapm_route *dapm_routes; /* route declaration */
  80. const int num_dapm_routes; /* route declaration */
  81. };
  82. /* driver data structure */
  83. struct sti_sas_data {
  84. struct device *dev;
  85. const struct sti_sas_dev_data *dev_data;
  86. struct sti_dac_audio dac;
  87. struct sti_spdif_audio spdif;
  88. };
  89. /* Read a register from the sysconf reg bank */
  90. static int sti_sas_read_reg(void *context, unsigned int reg,
  91. unsigned int *value)
  92. {
  93. struct sti_sas_data *drvdata = context;
  94. int status;
  95. u32 val;
  96. status = regmap_read(drvdata->dac.regmap, reg, &val);
  97. *value = (unsigned int)val;
  98. return status;
  99. }
  100. /* Read a register from the sysconf reg bank */
  101. static int sti_sas_write_reg(void *context, unsigned int reg,
  102. unsigned int value)
  103. {
  104. struct sti_sas_data *drvdata = context;
  105. int status;
  106. status = regmap_write(drvdata->dac.regmap, reg, value);
  107. return status;
  108. }
  109. static int sti_sas_init_sas_registers(struct snd_soc_codec *codec,
  110. struct sti_sas_data *data)
  111. {
  112. int ret;
  113. /*
  114. * DAC and SPDIF are activated by default
  115. * put them in IDLE to save power
  116. */
  117. /* Initialise bi-phase formatter to disabled */
  118. ret = snd_soc_update_bits(codec, STIH407_AUDIO_GLUE_CTRL,
  119. SPDIF_BIPHASE_ENABLE_MASK, 0);
  120. if (!ret)
  121. /* Initialise bi-phase formatter idle value to 0 */
  122. ret = snd_soc_update_bits(codec, STIH407_AUDIO_GLUE_CTRL,
  123. SPDIF_BIPHASE_IDLE_MASK, 0);
  124. if (ret < 0) {
  125. dev_err(codec->dev, "Failed to update SPDIF registers");
  126. return ret;
  127. }
  128. /* Init DAC configuration */
  129. switch (data->dev_data->chipid) {
  130. case CHIPID_STIH407:
  131. /* init configuration */
  132. ret = snd_soc_update_bits(codec, STIH407_AUDIO_DAC_CTRL,
  133. STIH407_DAC_STANDBY_MASK,
  134. STIH407_DAC_STANDBY_MASK);
  135. if (!ret)
  136. ret = snd_soc_update_bits(codec, STIH407_AUDIO_DAC_CTRL,
  137. STIH407_DAC_STANDBY_ANA_MASK,
  138. STIH407_DAC_STANDBY_ANA_MASK);
  139. if (!ret)
  140. ret = snd_soc_update_bits(codec, STIH407_AUDIO_DAC_CTRL,
  141. STIH407_DAC_SOFTMUTE_MASK,
  142. STIH407_DAC_SOFTMUTE_MASK);
  143. break;
  144. case CHIPID_STIH416:
  145. ret = snd_soc_update_bits(codec, STIH416_AUDIO_DAC_CTRL,
  146. STIH416_DAC_NOT_STANDBY_MASK, 0);
  147. if (!ret)
  148. ret = snd_soc_update_bits(codec,
  149. STIH416_AUDIO_DAC_CTRL,
  150. STIH416_DAC_ANA_NOT_PWR, 0);
  151. if (!ret)
  152. ret = snd_soc_update_bits(codec,
  153. STIH416_AUDIO_DAC_CTRL,
  154. STIH416_DAC_NOT_PNDBG_MASK,
  155. 0);
  156. if (!ret)
  157. ret = snd_soc_update_bits(codec,
  158. STIH416_AUDIO_DAC_CTRL,
  159. STIH416_DAC_SOFTMUTE_MASK,
  160. STIH416_DAC_SOFTMUTE_MASK);
  161. break;
  162. default:
  163. return -EINVAL;
  164. }
  165. if (ret < 0) {
  166. dev_err(codec->dev, "Failed to update DAC registers");
  167. return ret;
  168. }
  169. return ret;
  170. }
  171. /*
  172. * DAC
  173. */
  174. static int sti_sas_dac_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
  175. {
  176. /* Sanity check only */
  177. if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
  178. dev_err(dai->codec->dev,
  179. "%s: ERROR: Unsupporter master mask 0x%x\n",
  180. __func__, fmt & SND_SOC_DAIFMT_MASTER_MASK);
  181. return -EINVAL;
  182. }
  183. return 0;
  184. }
  185. static int stih416_dac_probe(struct snd_soc_dai *dai)
  186. {
  187. struct snd_soc_codec *codec = dai->codec;
  188. struct sti_sas_data *drvdata = dev_get_drvdata(codec->dev);
  189. struct sti_dac_audio *dac = &drvdata->dac;
  190. /* Get reset control */
  191. dac->rst = devm_reset_control_get(codec->dev, "dac_rst");
  192. if (IS_ERR(dac->rst)) {
  193. dev_err(dai->codec->dev,
  194. "%s: ERROR: DAC reset control not defined !\n",
  195. __func__);
  196. dac->rst = NULL;
  197. return -EFAULT;
  198. }
  199. /* Put the DAC into reset */
  200. reset_control_assert(dac->rst);
  201. return 0;
  202. }
  203. static const struct snd_soc_dapm_widget stih416_sas_dapm_widgets[] = {
  204. SND_SOC_DAPM_PGA("DAC bandgap", STIH416_AUDIO_DAC_CTRL,
  205. STIH416_DAC_NOT_PNDBG_MASK, 0, NULL, 0),
  206. SND_SOC_DAPM_OUT_DRV("DAC standby ana", STIH416_AUDIO_DAC_CTRL,
  207. STIH416_DAC_ANA_NOT_PWR, 0, NULL, 0),
  208. SND_SOC_DAPM_DAC("DAC standby", "dac_p", STIH416_AUDIO_DAC_CTRL,
  209. STIH416_DAC_NOT_STANDBY, 0),
  210. SND_SOC_DAPM_OUTPUT("DAC Output"),
  211. };
  212. static const struct snd_soc_dapm_widget stih407_sas_dapm_widgets[] = {
  213. SND_SOC_DAPM_OUT_DRV("DAC standby ana", STIH407_AUDIO_DAC_CTRL,
  214. STIH407_DAC_STANDBY_ANA, 1, NULL, 0),
  215. SND_SOC_DAPM_DAC("DAC standby", "dac_p", STIH407_AUDIO_DAC_CTRL,
  216. STIH407_DAC_STANDBY, 1),
  217. SND_SOC_DAPM_OUTPUT("DAC Output"),
  218. };
  219. static const struct snd_soc_dapm_route stih416_sas_route[] = {
  220. {"DAC Output", NULL, "DAC bandgap"},
  221. {"DAC Output", NULL, "DAC standby ana"},
  222. {"DAC standby ana", NULL, "DAC standby"},
  223. };
  224. static const struct snd_soc_dapm_route stih407_sas_route[] = {
  225. {"DAC Output", NULL, "DAC standby ana"},
  226. {"DAC standby ana", NULL, "DAC standby"},
  227. };
  228. static int stih416_sas_dac_mute(struct snd_soc_dai *dai, int mute, int stream)
  229. {
  230. struct snd_soc_codec *codec = dai->codec;
  231. if (mute) {
  232. return snd_soc_update_bits(codec, STIH416_AUDIO_DAC_CTRL,
  233. STIH416_DAC_SOFTMUTE_MASK,
  234. STIH416_DAC_SOFTMUTE_MASK);
  235. } else {
  236. return snd_soc_update_bits(codec, STIH416_AUDIO_DAC_CTRL,
  237. STIH416_DAC_SOFTMUTE_MASK, 0);
  238. }
  239. }
  240. static int stih407_sas_dac_mute(struct snd_soc_dai *dai, int mute, int stream)
  241. {
  242. struct snd_soc_codec *codec = dai->codec;
  243. if (mute) {
  244. return snd_soc_update_bits(codec, STIH407_AUDIO_DAC_CTRL,
  245. STIH407_DAC_SOFTMUTE_MASK,
  246. STIH407_DAC_SOFTMUTE_MASK);
  247. } else {
  248. return snd_soc_update_bits(codec, STIH407_AUDIO_DAC_CTRL,
  249. STIH407_DAC_SOFTMUTE_MASK,
  250. 0);
  251. }
  252. }
  253. /*
  254. * SPDIF
  255. */
  256. static int sti_sas_spdif_set_fmt(struct snd_soc_dai *dai,
  257. unsigned int fmt)
  258. {
  259. if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
  260. dev_err(dai->codec->dev,
  261. "%s: ERROR: Unsupporter master mask 0x%x\n",
  262. __func__, fmt & SND_SOC_DAIFMT_MASTER_MASK);
  263. return -EINVAL;
  264. }
  265. return 0;
  266. }
  267. /*
  268. * sti_sas_spdif_trigger:
  269. * Trigger function is used to ensure that BiPhase Formater is disabled
  270. * before CPU dai is stopped.
  271. * This is mandatory to avoid that BPF is stalled
  272. */
  273. static int sti_sas_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
  274. struct snd_soc_dai *dai)
  275. {
  276. struct snd_soc_codec *codec = dai->codec;
  277. switch (cmd) {
  278. case SNDRV_PCM_TRIGGER_START:
  279. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  280. return snd_soc_update_bits(codec, STIH407_AUDIO_GLUE_CTRL,
  281. SPDIF_BIPHASE_ENABLE_MASK,
  282. SPDIF_BIPHASE_ENABLE_MASK);
  283. case SNDRV_PCM_TRIGGER_RESUME:
  284. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  285. case SNDRV_PCM_TRIGGER_STOP:
  286. case SNDRV_PCM_TRIGGER_SUSPEND:
  287. return snd_soc_update_bits(codec, STIH407_AUDIO_GLUE_CTRL,
  288. SPDIF_BIPHASE_ENABLE_MASK,
  289. 0);
  290. default:
  291. return -EINVAL;
  292. }
  293. }
  294. static bool sti_sas_volatile_register(struct device *dev, unsigned int reg)
  295. {
  296. if (reg == STIH407_AUDIO_GLUE_CTRL)
  297. return true;
  298. return false;
  299. }
  300. /*
  301. * CODEC DAIS
  302. */
  303. /*
  304. * sti_sas_set_sysclk:
  305. * get MCLK input frequency to check that MCLK-FS ratio is coherent
  306. */
  307. static int sti_sas_set_sysclk(struct snd_soc_dai *dai, int clk_id,
  308. unsigned int freq, int dir)
  309. {
  310. struct snd_soc_codec *codec = dai->codec;
  311. struct sti_sas_data *drvdata = dev_get_drvdata(codec->dev);
  312. if (dir == SND_SOC_CLOCK_OUT)
  313. return 0;
  314. if (clk_id != 0)
  315. return -EINVAL;
  316. switch (dai->id) {
  317. case STI_SAS_DAI_SPDIF_OUT:
  318. drvdata->spdif.mclk = freq;
  319. break;
  320. case STI_SAS_DAI_ANALOG_OUT:
  321. drvdata->dac.mclk = freq;
  322. break;
  323. }
  324. return 0;
  325. }
  326. static int sti_sas_prepare(struct snd_pcm_substream *substream,
  327. struct snd_soc_dai *dai)
  328. {
  329. struct snd_soc_codec *codec = dai->codec;
  330. struct sti_sas_data *drvdata = dev_get_drvdata(codec->dev);
  331. struct snd_pcm_runtime *runtime = substream->runtime;
  332. switch (dai->id) {
  333. case STI_SAS_DAI_SPDIF_OUT:
  334. if ((drvdata->spdif.mclk / runtime->rate) != 128) {
  335. dev_err(codec->dev, "unexpected mclk-fs ratio");
  336. return -EINVAL;
  337. }
  338. break;
  339. case STI_SAS_DAI_ANALOG_OUT:
  340. if ((drvdata->dac.mclk / runtime->rate) != 256) {
  341. dev_err(codec->dev, "unexpected mclk-fs ratio");
  342. return -EINVAL;
  343. }
  344. break;
  345. }
  346. return 0;
  347. }
  348. static const struct snd_soc_dai_ops stih416_dac_ops = {
  349. .set_fmt = sti_sas_dac_set_fmt,
  350. .mute_stream = stih416_sas_dac_mute,
  351. .prepare = sti_sas_prepare,
  352. .set_sysclk = sti_sas_set_sysclk,
  353. };
  354. static const struct snd_soc_dai_ops stih407_dac_ops = {
  355. .set_fmt = sti_sas_dac_set_fmt,
  356. .mute_stream = stih407_sas_dac_mute,
  357. .prepare = sti_sas_prepare,
  358. .set_sysclk = sti_sas_set_sysclk,
  359. };
  360. static const struct regmap_config stih407_sas_regmap = {
  361. .reg_bits = 32,
  362. .val_bits = 32,
  363. .fast_io = true,
  364. .max_register = STIH407_AUDIO_DAC_CTRL,
  365. .reg_defaults = stih407_sas_reg_defaults,
  366. .num_reg_defaults = ARRAY_SIZE(stih407_sas_reg_defaults),
  367. .volatile_reg = sti_sas_volatile_register,
  368. .cache_type = REGCACHE_RBTREE,
  369. .reg_read = sti_sas_read_reg,
  370. .reg_write = sti_sas_write_reg,
  371. };
  372. static const struct regmap_config stih416_sas_regmap = {
  373. .reg_bits = 32,
  374. .val_bits = 32,
  375. .max_register = STIH416_AUDIO_DAC_CTRL,
  376. .reg_defaults = stih416_sas_reg_defaults,
  377. .num_reg_defaults = ARRAY_SIZE(stih416_sas_reg_defaults),
  378. .volatile_reg = sti_sas_volatile_register,
  379. .cache_type = REGCACHE_RBTREE,
  380. .reg_read = sti_sas_read_reg,
  381. .reg_write = sti_sas_write_reg,
  382. };
  383. static const struct sti_sas_dev_data stih416_data = {
  384. .chipid = CHIPID_STIH416,
  385. .regmap = &stih416_sas_regmap,
  386. .dac_ops = &stih416_dac_ops,
  387. .dapm_widgets = stih416_sas_dapm_widgets,
  388. .num_dapm_widgets = ARRAY_SIZE(stih416_sas_dapm_widgets),
  389. .dapm_routes = stih416_sas_route,
  390. .num_dapm_routes = ARRAY_SIZE(stih416_sas_route),
  391. };
  392. static const struct sti_sas_dev_data stih407_data = {
  393. .chipid = CHIPID_STIH407,
  394. .regmap = &stih407_sas_regmap,
  395. .dac_ops = &stih407_dac_ops,
  396. .dapm_widgets = stih407_sas_dapm_widgets,
  397. .num_dapm_widgets = ARRAY_SIZE(stih407_sas_dapm_widgets),
  398. .dapm_routes = stih407_sas_route,
  399. .num_dapm_routes = ARRAY_SIZE(stih407_sas_route),
  400. };
  401. static struct snd_soc_dai_driver sti_sas_dai[] = {
  402. {
  403. .name = "sas-dai-spdif-out",
  404. .id = STI_SAS_DAI_SPDIF_OUT,
  405. .playback = {
  406. .stream_name = "spdif_p",
  407. .channels_min = 2,
  408. .channels_max = 2,
  409. .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
  410. SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 |
  411. SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
  412. SNDRV_PCM_RATE_192000,
  413. .formats = SNDRV_PCM_FMTBIT_S16_LE |
  414. SNDRV_PCM_FMTBIT_S32_LE,
  415. },
  416. .ops = (struct snd_soc_dai_ops[]) {
  417. {
  418. .set_fmt = sti_sas_spdif_set_fmt,
  419. .trigger = sti_sas_spdif_trigger,
  420. .set_sysclk = sti_sas_set_sysclk,
  421. .prepare = sti_sas_prepare,
  422. }
  423. },
  424. },
  425. {
  426. .name = "sas-dai-dac",
  427. .id = STI_SAS_DAI_ANALOG_OUT,
  428. .playback = {
  429. .stream_name = "dac_p",
  430. .channels_min = 2,
  431. .channels_max = 2,
  432. .rates = SNDRV_PCM_RATE_8000_48000,
  433. .formats = SNDRV_PCM_FMTBIT_S16_LE |
  434. SNDRV_PCM_FMTBIT_S32_LE,
  435. },
  436. },
  437. };
  438. #ifdef CONFIG_PM_SLEEP
  439. static int sti_sas_resume(struct snd_soc_codec *codec)
  440. {
  441. struct sti_sas_data *drvdata = dev_get_drvdata(codec->dev);
  442. return sti_sas_init_sas_registers(codec, drvdata);
  443. }
  444. #else
  445. #define sti_sas_resume NULL
  446. #endif
  447. static int sti_sas_codec_probe(struct snd_soc_codec *codec)
  448. {
  449. struct sti_sas_data *drvdata = dev_get_drvdata(codec->dev);
  450. int ret;
  451. ret = sti_sas_init_sas_registers(codec, drvdata);
  452. return ret;
  453. }
  454. static struct snd_soc_codec_driver sti_sas_driver = {
  455. .probe = sti_sas_codec_probe,
  456. .resume = sti_sas_resume,
  457. };
  458. static const struct of_device_id sti_sas_dev_match[] = {
  459. {
  460. .compatible = "st,stih416-sas-codec",
  461. .data = &stih416_data,
  462. },
  463. {
  464. .compatible = "st,stih407-sas-codec",
  465. .data = &stih407_data,
  466. },
  467. {},
  468. };
  469. static int sti_sas_driver_probe(struct platform_device *pdev)
  470. {
  471. struct device_node *pnode = pdev->dev.of_node;
  472. struct sti_sas_data *drvdata;
  473. const struct of_device_id *of_id;
  474. /* Allocate device structure */
  475. drvdata = devm_kzalloc(&pdev->dev, sizeof(struct sti_sas_data),
  476. GFP_KERNEL);
  477. if (!drvdata)
  478. return -ENOMEM;
  479. /* Populate data structure depending on compatibility */
  480. of_id = of_match_node(sti_sas_dev_match, pnode);
  481. if (!of_id->data) {
  482. dev_err(&pdev->dev, "data associated to device is missing");
  483. return -EINVAL;
  484. }
  485. drvdata->dev_data = (struct sti_sas_dev_data *)of_id->data;
  486. /* Initialise device structure */
  487. drvdata->dev = &pdev->dev;
  488. /* Request the DAC & SPDIF registers memory region */
  489. drvdata->dac.virt_regmap = devm_regmap_init(&pdev->dev, NULL, drvdata,
  490. drvdata->dev_data->regmap);
  491. if (IS_ERR(drvdata->dac.virt_regmap)) {
  492. dev_err(&pdev->dev, "audio registers not enabled\n");
  493. return PTR_ERR(drvdata->dac.virt_regmap);
  494. }
  495. /* Request the syscon region */
  496. drvdata->dac.regmap =
  497. syscon_regmap_lookup_by_phandle(pnode, "st,syscfg");
  498. if (IS_ERR(drvdata->dac.regmap)) {
  499. dev_err(&pdev->dev, "syscon registers not available\n");
  500. return PTR_ERR(drvdata->dac.regmap);
  501. }
  502. drvdata->spdif.regmap = drvdata->dac.regmap;
  503. /* Set DAC dai probe */
  504. if (drvdata->dev_data->chipid == CHIPID_STIH416)
  505. sti_sas_dai[STI_SAS_DAI_ANALOG_OUT].probe = stih416_dac_probe;
  506. sti_sas_dai[STI_SAS_DAI_ANALOG_OUT].ops = drvdata->dev_data->dac_ops;
  507. /* Set dapms*/
  508. sti_sas_driver.component_driver.dapm_widgets = drvdata->dev_data->dapm_widgets;
  509. sti_sas_driver.component_driver.num_dapm_widgets = drvdata->dev_data->num_dapm_widgets;
  510. sti_sas_driver.component_driver.dapm_routes = drvdata->dev_data->dapm_routes;
  511. sti_sas_driver.component_driver.num_dapm_routes = drvdata->dev_data->num_dapm_routes;
  512. /* Store context */
  513. dev_set_drvdata(&pdev->dev, drvdata);
  514. return snd_soc_register_codec(&pdev->dev, &sti_sas_driver,
  515. sti_sas_dai,
  516. ARRAY_SIZE(sti_sas_dai));
  517. }
  518. static int sti_sas_driver_remove(struct platform_device *pdev)
  519. {
  520. snd_soc_unregister_codec(&pdev->dev);
  521. return 0;
  522. }
  523. static struct platform_driver sti_sas_platform_driver = {
  524. .driver = {
  525. .name = "sti-sas-codec",
  526. .of_match_table = sti_sas_dev_match,
  527. },
  528. .probe = sti_sas_driver_probe,
  529. .remove = sti_sas_driver_remove,
  530. };
  531. module_platform_driver(sti_sas_platform_driver);
  532. MODULE_DESCRIPTION("audio codec for STMicroelectronics sti platforms");
  533. MODULE_AUTHOR("Arnaud.pouliquen@st.com");
  534. MODULE_LICENSE("GPL v2");