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