Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/sound/soc/tegra/trimslice.c
10817 views
1
/*
2
* trimslice.c - TrimSlice machine ASoC driver
3
*
4
* Copyright (C) 2011 - CompuLab, Ltd.
5
* Author: Mike Rapoport <[email protected]>
6
*
7
* Based on code copyright/by:
8
* Author: Stephen Warren <[email protected]>
9
* Copyright (C) 2010-2011 - NVIDIA, Inc.
10
*
11
* This program is free software; you can redistribute it and/or
12
* modify it under the terms of the GNU General Public License
13
* version 2 as published by the Free Software Foundation.
14
*
15
* This program is distributed in the hope that it will be useful, but
16
* WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18
* General Public License for more details.
19
*
20
* You should have received a copy of the GNU General Public License
21
* along with this program; if not, write to the Free Software
22
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23
* 02110-1301 USA
24
*
25
*/
26
27
#include <asm/mach-types.h>
28
29
#include <linux/module.h>
30
#include <linux/platform_device.h>
31
#include <linux/slab.h>
32
33
#include <sound/core.h>
34
#include <sound/jack.h>
35
#include <sound/pcm.h>
36
#include <sound/pcm_params.h>
37
#include <sound/soc.h>
38
39
#include "../codecs/tlv320aic23.h"
40
41
#include "tegra_das.h"
42
#include "tegra_i2s.h"
43
#include "tegra_pcm.h"
44
#include "tegra_asoc_utils.h"
45
46
#define DRV_NAME "tegra-snd-trimslice"
47
48
struct tegra_trimslice {
49
struct tegra_asoc_utils_data util_data;
50
};
51
52
static int trimslice_asoc_hw_params(struct snd_pcm_substream *substream,
53
struct snd_pcm_hw_params *params)
54
{
55
struct snd_soc_pcm_runtime *rtd = substream->private_data;
56
struct snd_soc_dai *codec_dai = rtd->codec_dai;
57
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
58
struct snd_soc_codec *codec = rtd->codec;
59
struct snd_soc_card *card = codec->card;
60
struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card);
61
int srate, mclk;
62
int err;
63
64
srate = params_rate(params);
65
mclk = 128 * srate;
66
67
err = tegra_asoc_utils_set_rate(&trimslice->util_data, srate, mclk);
68
if (err < 0) {
69
dev_err(card->dev, "Can't configure clocks\n");
70
return err;
71
}
72
73
err = snd_soc_dai_set_fmt(codec_dai,
74
SND_SOC_DAIFMT_I2S |
75
SND_SOC_DAIFMT_NB_NF |
76
SND_SOC_DAIFMT_CBS_CFS);
77
if (err < 0) {
78
dev_err(card->dev, "codec_dai fmt not set\n");
79
return err;
80
}
81
82
err = snd_soc_dai_set_fmt(cpu_dai,
83
SND_SOC_DAIFMT_I2S |
84
SND_SOC_DAIFMT_NB_NF |
85
SND_SOC_DAIFMT_CBS_CFS);
86
if (err < 0) {
87
dev_err(card->dev, "cpu_dai fmt not set\n");
88
return err;
89
}
90
91
err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
92
SND_SOC_CLOCK_IN);
93
if (err < 0) {
94
dev_err(card->dev, "codec_dai clock not set\n");
95
return err;
96
}
97
98
return 0;
99
}
100
101
static struct snd_soc_ops trimslice_asoc_ops = {
102
.hw_params = trimslice_asoc_hw_params,
103
};
104
105
static const struct snd_soc_dapm_widget trimslice_dapm_widgets[] = {
106
SND_SOC_DAPM_HP("Line Out", NULL),
107
SND_SOC_DAPM_LINE("Line In", NULL),
108
};
109
110
static const struct snd_soc_dapm_route trimslice_audio_map[] = {
111
{"Line Out", NULL, "LOUT"},
112
{"Line Out", NULL, "ROUT"},
113
114
{"LLINEIN", NULL, "Line In"},
115
{"RLINEIN", NULL, "Line In"},
116
};
117
118
static int trimslice_asoc_init(struct snd_soc_pcm_runtime *rtd)
119
{
120
struct snd_soc_codec *codec = rtd->codec;
121
struct snd_soc_dapm_context *dapm = &codec->dapm;
122
123
snd_soc_dapm_nc_pin(dapm, "LHPOUT");
124
snd_soc_dapm_nc_pin(dapm, "RHPOUT");
125
snd_soc_dapm_nc_pin(dapm, "MICIN");
126
127
snd_soc_dapm_sync(dapm);
128
129
return 0;
130
}
131
132
static struct snd_soc_dai_link trimslice_tlv320aic23_dai = {
133
.name = "TLV320AIC23",
134
.stream_name = "AIC23",
135
.codec_name = "tlv320aic23-codec.2-001a",
136
.platform_name = "tegra-pcm-audio",
137
.cpu_dai_name = "tegra-i2s.0",
138
.codec_dai_name = "tlv320aic23-hifi",
139
.init = trimslice_asoc_init,
140
.ops = &trimslice_asoc_ops,
141
};
142
143
static struct snd_soc_card snd_soc_trimslice = {
144
.name = "tegra-trimslice",
145
.dai_link = &trimslice_tlv320aic23_dai,
146
.num_links = 1,
147
148
.dapm_widgets = trimslice_dapm_widgets,
149
.num_dapm_widgets = ARRAY_SIZE(trimslice_dapm_widgets),
150
.dapm_routes = trimslice_audio_map,
151
.num_dapm_routes = ARRAY_SIZE(trimslice_audio_map),
152
};
153
154
static __devinit int tegra_snd_trimslice_probe(struct platform_device *pdev)
155
{
156
struct snd_soc_card *card = &snd_soc_trimslice;
157
struct tegra_trimslice *trimslice;
158
int ret;
159
160
trimslice = kzalloc(sizeof(struct tegra_trimslice), GFP_KERNEL);
161
if (!trimslice) {
162
dev_err(&pdev->dev, "Can't allocate tegra_trimslice\n");
163
return -ENOMEM;
164
}
165
166
ret = tegra_asoc_utils_init(&trimslice->util_data, &pdev->dev);
167
if (ret)
168
goto err_free_trimslice;
169
170
card->dev = &pdev->dev;
171
platform_set_drvdata(pdev, card);
172
snd_soc_card_set_drvdata(card, trimslice);
173
174
ret = snd_soc_register_card(card);
175
if (ret) {
176
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
177
ret);
178
goto err_fini_utils;
179
}
180
181
return 0;
182
183
err_fini_utils:
184
tegra_asoc_utils_fini(&trimslice->util_data);
185
err_free_trimslice:
186
kfree(trimslice);
187
return ret;
188
}
189
190
static int __devexit tegra_snd_trimslice_remove(struct platform_device *pdev)
191
{
192
struct snd_soc_card *card = platform_get_drvdata(pdev);
193
struct tegra_trimslice *trimslice = snd_soc_card_get_drvdata(card);
194
195
snd_soc_unregister_card(card);
196
197
tegra_asoc_utils_fini(&trimslice->util_data);
198
199
kfree(trimslice);
200
201
return 0;
202
}
203
204
static struct platform_driver tegra_snd_trimslice_driver = {
205
.driver = {
206
.name = DRV_NAME,
207
.owner = THIS_MODULE,
208
},
209
.probe = tegra_snd_trimslice_probe,
210
.remove = __devexit_p(tegra_snd_trimslice_remove),
211
};
212
213
static int __init snd_tegra_trimslice_init(void)
214
{
215
return platform_driver_register(&tegra_snd_trimslice_driver);
216
}
217
module_init(snd_tegra_trimslice_init);
218
219
static void __exit snd_tegra_trimslice_exit(void)
220
{
221
platform_driver_unregister(&tegra_snd_trimslice_driver);
222
}
223
module_exit(snd_tegra_trimslice_exit);
224
225
MODULE_AUTHOR("Mike Rapoport <[email protected]>");
226
MODULE_DESCRIPTION("Trimslice machine ASoC driver");
227
MODULE_LICENSE("GPL");
228
MODULE_ALIAS("platform:" DRV_NAME);
229
230