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