These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / 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.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
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");