Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/mfd/davinci_voicecodec.c
15109 views
1
/*
2
* DaVinci Voice Codec Core Interface for TI platforms
3
*
4
* Copyright (C) 2010 Texas Instruments, Inc
5
*
6
* Author: Miguel Aguilar <[email protected]>
7
*
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
12
*
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
17
*
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
*/
22
23
#include <linux/init.h>
24
#include <linux/module.h>
25
#include <linux/device.h>
26
#include <linux/slab.h>
27
#include <linux/delay.h>
28
#include <linux/io.h>
29
#include <linux/clk.h>
30
31
#include <sound/pcm.h>
32
33
#include <linux/mfd/davinci_voicecodec.h>
34
35
u32 davinci_vc_read(struct davinci_vc *davinci_vc, int reg)
36
{
37
return __raw_readl(davinci_vc->base + reg);
38
}
39
40
void davinci_vc_write(struct davinci_vc *davinci_vc,
41
int reg, u32 val)
42
{
43
__raw_writel(val, davinci_vc->base + reg);
44
}
45
46
static int __init davinci_vc_probe(struct platform_device *pdev)
47
{
48
struct davinci_vc *davinci_vc;
49
struct resource *res, *mem;
50
struct mfd_cell *cell = NULL;
51
int ret;
52
53
davinci_vc = kzalloc(sizeof(struct davinci_vc), GFP_KERNEL);
54
if (!davinci_vc) {
55
dev_dbg(&pdev->dev,
56
"could not allocate memory for private data\n");
57
return -ENOMEM;
58
}
59
60
davinci_vc->clk = clk_get(&pdev->dev, NULL);
61
if (IS_ERR(davinci_vc->clk)) {
62
dev_dbg(&pdev->dev,
63
"could not get the clock for voice codec\n");
64
ret = -ENODEV;
65
goto fail1;
66
}
67
clk_enable(davinci_vc->clk);
68
69
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
70
if (!res) {
71
dev_err(&pdev->dev, "no mem resource\n");
72
ret = -ENODEV;
73
goto fail2;
74
}
75
76
davinci_vc->pbase = res->start;
77
davinci_vc->base_size = resource_size(res);
78
79
mem = request_mem_region(davinci_vc->pbase, davinci_vc->base_size,
80
pdev->name);
81
if (!mem) {
82
dev_err(&pdev->dev, "VCIF region already claimed\n");
83
ret = -EBUSY;
84
goto fail2;
85
}
86
87
davinci_vc->base = ioremap(davinci_vc->pbase, davinci_vc->base_size);
88
if (!davinci_vc->base) {
89
dev_err(&pdev->dev, "can't ioremap mem resource.\n");
90
ret = -ENOMEM;
91
goto fail3;
92
}
93
94
res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
95
if (!res) {
96
dev_err(&pdev->dev, "no DMA resource\n");
97
ret = -ENXIO;
98
goto fail4;
99
}
100
101
davinci_vc->davinci_vcif.dma_tx_channel = res->start;
102
davinci_vc->davinci_vcif.dma_tx_addr =
103
(dma_addr_t)(io_v2p(davinci_vc->base) + DAVINCI_VC_WFIFO);
104
105
res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
106
if (!res) {
107
dev_err(&pdev->dev, "no DMA resource\n");
108
ret = -ENXIO;
109
goto fail4;
110
}
111
112
davinci_vc->davinci_vcif.dma_rx_channel = res->start;
113
davinci_vc->davinci_vcif.dma_rx_addr =
114
(dma_addr_t)(io_v2p(davinci_vc->base) + DAVINCI_VC_RFIFO);
115
116
davinci_vc->dev = &pdev->dev;
117
davinci_vc->pdev = pdev;
118
119
/* Voice codec interface client */
120
cell = &davinci_vc->cells[DAVINCI_VC_VCIF_CELL];
121
cell->name = "davinci-vcif";
122
cell->platform_data = davinci_vc;
123
cell->pdata_size = sizeof(*davinci_vc);
124
125
/* Voice codec CQ93VC client */
126
cell = &davinci_vc->cells[DAVINCI_VC_CQ93VC_CELL];
127
cell->name = "cq93vc-codec";
128
cell->platform_data = davinci_vc;
129
cell->pdata_size = sizeof(*davinci_vc);
130
131
ret = mfd_add_devices(&pdev->dev, pdev->id, davinci_vc->cells,
132
DAVINCI_VC_CELLS, NULL, 0);
133
if (ret != 0) {
134
dev_err(&pdev->dev, "fail to register client devices\n");
135
goto fail4;
136
}
137
138
return 0;
139
140
fail4:
141
iounmap(davinci_vc->base);
142
fail3:
143
release_mem_region(davinci_vc->pbase, davinci_vc->base_size);
144
fail2:
145
clk_disable(davinci_vc->clk);
146
clk_put(davinci_vc->clk);
147
davinci_vc->clk = NULL;
148
fail1:
149
kfree(davinci_vc);
150
151
return ret;
152
}
153
154
static int __devexit davinci_vc_remove(struct platform_device *pdev)
155
{
156
struct davinci_vc *davinci_vc = platform_get_drvdata(pdev);
157
158
mfd_remove_devices(&pdev->dev);
159
160
iounmap(davinci_vc->base);
161
release_mem_region(davinci_vc->pbase, davinci_vc->base_size);
162
163
clk_disable(davinci_vc->clk);
164
clk_put(davinci_vc->clk);
165
davinci_vc->clk = NULL;
166
167
kfree(davinci_vc);
168
169
return 0;
170
}
171
172
static struct platform_driver davinci_vc_driver = {
173
.driver = {
174
.name = "davinci_voicecodec",
175
.owner = THIS_MODULE,
176
},
177
.remove = __devexit_p(davinci_vc_remove),
178
};
179
180
static int __init davinci_vc_init(void)
181
{
182
return platform_driver_probe(&davinci_vc_driver, davinci_vc_probe);
183
}
184
module_init(davinci_vc_init);
185
186
static void __exit davinci_vc_exit(void)
187
{
188
platform_driver_unregister(&davinci_vc_driver);
189
}
190
module_exit(davinci_vc_exit);
191
192
MODULE_AUTHOR("Miguel Aguilar");
193
MODULE_DESCRIPTION("Texas Instruments DaVinci Voice Codec Core Interface");
194
MODULE_LICENSE("GPL");
195
196