Merge remote-tracking branch 'xen-tip/linux-next'
[deliverable/linux.git] / sound / soc / codecs / sti-sas.c
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 */
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 */
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
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 */
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
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
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
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 */
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 */
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
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 */
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
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
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
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
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
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
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");
This page took 0.061092 seconds and 5 git commands to generate.