• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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 
61 enum {
62 	STI_SAS_DAI_SPDIF_OUT,
63 	STI_SAS_DAI_ANALOG_OUT,
64 };
65 
66 static const struct reg_default stih416_sas_reg_defaults[] = {
67 	{ STIH407_AUDIO_GLUE_CTRL, 0x00000040 },
68 	{ STIH407_AUDIO_DAC_CTRL, 0x000000000 },
69 };
70 
71 static const struct reg_default stih407_sas_reg_defaults[] = {
72 	{ STIH416_AUDIO_DAC_CTRL, 0x000000000 },
73 	{ STIH416_AUDIO_GLUE_CTRL, 0x00000040 },
74 };
75 
76 struct 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 
84 struct sti_spdif_audio {
85 	struct regmap *regmap;
86 	struct regmap_field  **field;
87 	int mclk;
88 };
89 
90 /* device data structure */
91 struct 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 */
102 struct 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 */
sti_sas_read_reg(void * context,unsigned int reg,unsigned int * value)110 static 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 */
sti_sas_write_reg(void * context,unsigned int reg,unsigned int value)124 static 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 
sti_sas_init_sas_registers(struct snd_soc_codec * codec,struct sti_sas_data * data)135 static 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  */
sti_sas_dac_set_fmt(struct snd_soc_dai * dai,unsigned int fmt)207 static 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 
stih416_dac_probe(struct snd_soc_dai * dai)220 static 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,
230 			"%s: ERROR: DAC reset control not defined !\n",
231 			__func__);
232 		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 
241 static const struct snd_soc_dapm_widget stih416_sas_dapm_widgets[] = {
242 	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 
251 static const struct snd_soc_dapm_widget stih407_sas_dapm_widgets[] = {
252 	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 
259 static const struct snd_soc_dapm_route stih416_sas_route[] = {
260 	{"DAC Output", NULL, "DAC bandgap"},
261 	{"DAC Output", NULL, "DAC standby ana"},
262 	{"DAC standby ana", NULL, "DAC standby"},
263 };
264 
265 static const struct snd_soc_dapm_route stih407_sas_route[] = {
266 	{"DAC Output", NULL, "DAC standby ana"},
267 	{"DAC standby ana", NULL, "DAC standby"},
268 };
269 
stih416_sas_dac_mute(struct snd_soc_dai * dai,int mute,int stream)270 static 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 
stih407_sas_dac_mute(struct snd_soc_dai * dai,int mute,int stream)284 static 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  */
sti_sas_spdif_set_fmt(struct snd_soc_dai * dai,unsigned int fmt)302 static 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  */
sti_sas_spdif_trigger(struct snd_pcm_substream * substream,int cmd,struct snd_soc_dai * dai)321 static 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 
sti_sas_volatile_register(struct device * dev,unsigned int reg)344 static 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  */
sti_sas_set_sysclk(struct snd_soc_dai * dai,int clk_id,unsigned int freq,int dir)360 static 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 
sti_sas_prepare(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)385 static 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 
410 static const struct snd_soc_dai_ops stih416_dac_ops = {
411 	.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 
417 static const struct snd_soc_dai_ops stih407_dac_ops = {
418 	.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 
424 static const struct regmap_config stih407_sas_regmap = {
425 	.reg_bits = 32,
426 	.val_bits = 32,
427 	.fast_io = true,
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 
437 static const struct regmap_config stih416_sas_regmap = {
438 	.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 
450 static const struct sti_sas_dev_data stih416_data = {
451 	.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 
460 static const struct sti_sas_dev_data stih407_data = {
461 	.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 
470 static 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
sti_sas_resume(struct snd_soc_codec * codec)509 static 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 
sti_sas_codec_probe(struct snd_soc_codec * codec)519 static 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 
529 static struct snd_soc_codec_driver sti_sas_driver = {
530 	.probe = sti_sas_codec_probe,
531 	.resume = sti_sas_resume,
532 };
533 
534 static 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 
sti_sas_driver_probe(struct platform_device * pdev)546 static 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;
550 	const struct of_device_id *of_id;
551 
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 */
559 	of_id = of_match_node(sti_sas_dev_match, pnode);
560 	if (!of_id->data) {
561 		dev_err(&pdev->dev, "data associated to device is missing");
562 		return -EINVAL;
563 	}
564 
565 	drvdata->dev_data = (struct sti_sas_dev_data *)of_id->data;
566 
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);
573 	if (IS_ERR(drvdata->dac.virt_regmap)) {
574 		dev_err(&pdev->dev, "audio registers not enabled\n");
575 		return PTR_ERR(drvdata->dac.virt_regmap);
576 	}
577 
578 	/* Request the syscon region */
579 	drvdata->dac.regmap =
580 		syscon_regmap_lookup_by_phandle(pnode, "st,syscfg");
581 	if (IS_ERR(drvdata->dac.regmap)) {
582 		dev_err(&pdev->dev, "syscon registers not available\n");
583 		return PTR_ERR(drvdata->dac.regmap);
584 	}
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.component_driver.dapm_widgets = drvdata->dev_data->dapm_widgets;
595 	sti_sas_driver.component_driver.num_dapm_widgets = drvdata->dev_data->num_dapm_widgets;
596 
597 	sti_sas_driver.component_driver.dapm_routes = drvdata->dev_data->dapm_routes;
598 	sti_sas_driver.component_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 
sti_sas_driver_remove(struct platform_device * pdev)608 static int sti_sas_driver_remove(struct platform_device *pdev)
609 {
610 	snd_soc_unregister_codec(&pdev->dev);
611 
612 	return 0;
613 }
614 
615 static struct platform_driver sti_sas_platform_driver = {
616 	.driver = {
617 		.name = "sti-sas-codec",
618 		.of_match_table = sti_sas_dev_match,
619 	},
620 	.probe = sti_sas_driver_probe,
621 	.remove = sti_sas_driver_remove,
622 };
623 
624 module_platform_driver(sti_sas_platform_driver);
625 
626 MODULE_DESCRIPTION("audio codec for STMicroelectronics sti platforms");
627 MODULE_AUTHOR("Arnaud.pouliquen@st.com");
628 MODULE_LICENSE("GPL v2");
629