f2c8ca0b4df6417e8d06a27b8de13e61564156ed
[cascardo/linux.git] / drivers / staging / greybus / audio-dai.c
1 #include <linux/kernel.h>
2 #include <linux/device.h>
3 #include <linux/interrupt.h>
4 #include <linux/module.h>
5 #include <linux/platform_device.h>
6 #include <linux/workqueue.h>
7 #include <linux/i2c.h>
8 #include <sound/core.h>
9 #include <sound/pcm.h>
10 #include <sound/pcm_params.h>
11 #include <sound/soc.h>
12 #include <sound/dmaengine_pcm.h>
13 #include <sound/simple_card.h>
14 #include "greybus.h"
15 #include "gpbridge.h"
16 #include "audio.h"
17
18 /*
19  * This is the greybus cpu dai logic. It really doesn't do much
20  * other then provide the TRIGGER_START/STOP hooks that start
21  * and stop the timer sending audio data in the pcm logic.
22  */
23
24
25 static int gb_dai_trigger(struct snd_pcm_substream *substream, int cmd,
26                                 struct snd_soc_dai *dai)
27 {
28         struct snd_soc_pcm_runtime *rtd = substream->private_data;
29         struct gb_snd *snd_dev;
30
31
32         snd_dev = snd_soc_dai_get_drvdata(rtd->cpu_dai);
33
34         switch (cmd) {
35         case SNDRV_PCM_TRIGGER_START:
36                 gb_pcm_hrtimer_start(snd_dev);
37                 break;
38         case SNDRV_PCM_TRIGGER_STOP:
39                 gb_pcm_hrtimer_stop(snd_dev);
40                 break;
41         default:
42                 return -EINVAL;
43         }
44         return 0;
45 }
46
47 /*
48  * XXX This is annoying, if we don't have a set_fmt function
49  * the subsystem returns -ENOTSUPP, which causes applications
50  * to fail, so add a dummy function here.
51  */
52 static int gb_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
53 {
54         return 0;
55 }
56
57 static const struct snd_soc_dai_ops gb_dai_ops = {
58         .trigger        = gb_dai_trigger,
59         .set_fmt        = gb_dai_set_fmt,
60 };
61
62 struct snd_soc_dai_driver gb_cpu_dai = {
63         .name                   = "gb-cpu-dai",
64         .playback = {
65                 .rates          = GB_RATES,
66                 .formats        = GB_FMTS,
67                 .channels_min   = 1,
68                 .channels_max   = 2,
69         },
70         .ops = &gb_dai_ops,
71 };
72
73 static const struct snd_soc_component_driver gb_soc_component = {
74         .name           = "gb-component",
75 };
76
77 static int gb_plat_probe(struct platform_device *pdev)
78 {
79         struct gb_snd *snd_dev;
80         int ret;
81
82         snd_dev = (struct gb_snd *)pdev->dev.platform_data;
83         dev_set_drvdata(&pdev->dev, snd_dev);
84
85         ret = snd_soc_register_component(&pdev->dev, &gb_soc_component,
86                                                         &gb_cpu_dai, 1);
87         return ret;
88 }
89
90 static int gb_plat_remove(struct platform_device *pdev)
91 {
92         snd_soc_unregister_component(&pdev->dev);
93         snd_soc_unregister_platform(&pdev->dev);
94         return 0;
95 }
96
97 struct platform_driver gb_audio_plat_driver = {
98         .driver         = {
99                 .name   = "gb-dai-audio",
100         },
101         .probe          = gb_plat_probe,
102         .remove         = gb_plat_remove,
103 };