Merge current mainline tree into linux-omap tree
[pandora-kernel.git] / drivers / spi / tsc2101.c
1 /*
2  * linux/drivers/spi/tsc2101.c
3  *
4  * TSC2101 codec interface driver for the OMAP platform
5  *
6  * Copyright (C) 2004 Texas Instruments, Inc.
7  *
8  * This package is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  *
12  * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
13  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
14  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15  *
16  * History:
17  *
18  * 2004/11/07   Nishanth Menon - Modified for common hooks for Audio and Touchscreen
19  */
20
21 #include <linux/kernel.h>
22 #include <linux/clk.h>
23 #include <linux/device.h>
24 #include <linux/spi/spi.h>
25 #include <linux/spi/tsc2101.h>
26
27 struct tsc2101_device {
28         struct mutex            mutex;
29         int                     mclk_enabled;
30         struct clock            *mclk_ck;
31         struct spi_message      message;
32         struct spi_transfer     transfer[2];
33         u16                     command;
34         void                    (*enable_mclk)(struct spi_device *spi);
35         void                    (*disable_mclk)(struct spi_device *spi);
36 };
37
38 int tsc2101_enable_mclk(struct spi_device *spi)
39 {
40         struct tsc2101_device *tsc2101;
41
42         tsc2101 = spi_get_drvdata(spi);
43
44         mutex_lock(&tsc2101->mutex);
45
46         if (spi->dev.power.power_state.event != PM_EVENT_ON) {
47                 mutex_unlock(&tsc2101->mutex);
48                 return -ENODEV;
49         }
50
51         if (tsc2101->mclk_enabled++ == 0) {
52                 if (tsc2101->enable_mclk != NULL)
53                         tsc2101->enable_mclk(spi);
54         }
55
56         mutex_unlock(&tsc2101->mutex);
57         return 0;
58 }
59 EXPORT_SYMBOL(tsc2101_enable_mclk);
60
61 void tsc2101_disable_mclk(struct spi_device *spi)
62 {
63         struct tsc2101_device *tsc2101;
64
65         tsc2101 = spi_get_drvdata(spi);
66
67         mutex_lock(&tsc2101->mutex);
68
69         if (--tsc2101->mclk_enabled == 0) {
70                 if (tsc2101->disable_mclk != NULL &&
71                     spi->dev.power.power_state.event == PM_EVENT_ON)
72                         tsc2101->disable_mclk(spi);
73         }
74
75         mutex_lock(&tsc2101->mutex);
76 }
77 EXPORT_SYMBOL(tsc2101_disable_mclk);
78
79 int tsc2101_write_sync(struct spi_device *spi, int page, u8 address, u16 data)
80 {
81         struct tsc2101_device *tsc2101;
82         struct spi_message *m;
83         struct spi_transfer *t;
84         int ret;
85
86         tsc2101 = spi_get_drvdata(spi);
87
88         mutex_lock(&tsc2101->mutex);
89         if (spi->dev.power.power_state.event != PM_EVENT_ON) {
90                 mutex_unlock(&tsc2101->mutex);
91                 return -ENODEV;
92         }
93
94         m = &tsc2101->message;
95         spi_message_init(m);
96         t = &tsc2101->transfer[0];
97         memset(t, 0, sizeof(tsc2101->transfer));
98
99         /* Address */
100         tsc2101->command = (page << 11) | (address << 5);
101         t->tx_buf = &tsc2101->command;
102         t->len = 2;
103         spi_message_add_tail(t, m);
104
105         /* Data */
106         t++;
107         t->tx_buf = &data;
108         t->len = 2;
109         spi_message_add_tail(t, m);
110
111         ret = spi_sync(spi, m);
112         if (!ret)
113                 ret = tsc2101->message.status;
114         mutex_unlock(&tsc2101->mutex);
115
116         return ret;
117 }
118 EXPORT_SYMBOL(tsc2101_write_sync);
119
120 int tsc2101_reads_sync(struct spi_device *spi,
121                        int page, u8 startaddress, u16 *data, int numregs)
122 {
123         struct tsc2101_device *tsc2101;
124         struct spi_message *m;
125         struct spi_transfer *t;
126         int ret;
127
128         tsc2101 = spi_get_drvdata(spi);
129
130         mutex_lock(&tsc2101->mutex);
131         if (spi->dev.power.power_state.event != PM_EVENT_ON) {
132                 mutex_unlock(&tsc2101->mutex);
133                 return -ENODEV;
134         }
135
136         m = &tsc2101->message;
137         spi_message_init(m);
138         t = &tsc2101->transfer[0];
139         memset(t, 0, sizeof(tsc2101->transfer));
140
141         /* Address */
142         tsc2101->command = 0x8000 | (page << 11) | (startaddress << 5);
143         t->tx_buf = &tsc2101->command;
144         t->len = 2;
145         spi_message_add_tail(t, m);
146
147         /* Data */
148         t++;
149         t->rx_buf = data;
150         t->len = numregs << 1;
151         spi_message_add_tail(t, m);
152
153         ret = spi_sync(spi, m);
154         if (!ret)
155                 ret = tsc2101->message.status;
156
157         mutex_unlock(&tsc2101->mutex);
158
159         return ret;
160 }
161 EXPORT_SYMBOL(tsc2101_reads_sync);
162
163 int tsc2101_read_sync(struct spi_device *spi, int page, u8 address)
164 {
165         int err;
166         u16 val;
167
168         err = tsc2101_reads_sync(spi, page, address, &val, 1);
169         if (err)
170                 return err;
171         return val;
172 }
173 EXPORT_SYMBOL(tsc2101_read_sync);
174
175 static int tsc2101_suspend(struct spi_device *spi, pm_message_t state)
176 {
177         struct tsc2101_device *tsc2101;
178
179         tsc2101 = spi_get_drvdata(spi);
180
181         if (tsc2101 == NULL)
182                 return 0;
183
184         mutex_lock(&tsc2101->mutex);
185
186         spi->dev.power.power_state = state;
187         if (tsc2101->mclk_enabled && tsc2101->disable_mclk != NULL)
188                 tsc2101->disable_mclk(spi);
189
190         mutex_unlock(&tsc2101->mutex);
191
192         return 0;
193 }
194
195 static int tsc2101_resume(struct spi_device *spi)
196 {
197         struct tsc2101_device *tsc2101;
198
199         tsc2101 = spi_get_drvdata(spi);
200
201         if (tsc2101 == NULL)
202                 return 0;
203
204         mutex_lock(&tsc2101->mutex);
205
206         spi->dev.power.power_state = PMSG_ON;
207         if (tsc2101->mclk_enabled && tsc2101->enable_mclk != NULL)
208                 tsc2101->enable_mclk(spi);
209
210         mutex_unlock(&tsc2101->mutex);
211
212         return 0;
213 }
214
215 static int tsc2101_probe(struct spi_device *spi)
216 {
217         struct tsc2101_platform_data *pdata;
218         struct tsc2101_device *tsc2101;
219         u16 w;
220         int r;
221
222         pdata = spi->dev.platform_data;
223         if (pdata == NULL) {
224                 dev_err(&spi->dev, "no platform data\n");
225                 return -ENODEV;
226         }
227
228         tsc2101 = kzalloc(sizeof(*tsc2101), GFP_KERNEL);
229         if (tsc2101 == NULL) {
230                 dev_err(&spi->dev, "out of mem\n");
231                 return -ENOMEM;
232         }
233
234         spi_set_drvdata(spi, tsc2101);
235         tsc2101->enable_mclk = pdata->enable_mclk;
236         tsc2101->disable_mclk = pdata->disable_mclk;
237
238         mutex_init(&tsc2101->mutex);
239
240         spi->mode = SPI_MODE_1;
241         spi->bits_per_word = 16;
242         if ((r = spi_setup(spi)) < 0) {
243                 dev_err(&spi->dev, "SPI setup failed\n");
244                 goto err;
245         }
246
247         w = tsc2101_read_sync(spi, 1, 0);
248         if (!(w & (1 << 14))) {
249                 dev_err(&spi->dev, "invalid ADC register value %04x\n", w);
250                 goto err;
251         }
252
253         if (pdata->init != NULL) {
254                 if ((r = pdata->init(spi)) < 0) {
255                         dev_err(&spi->dev, "platform init failed\n");
256                         goto err;
257                 }
258         }
259
260         dev_info(&spi->dev, "initialized\n");
261
262         return 0;
263 err:
264         kfree(tsc2101);
265         return r;
266 }
267
268 static int tsc2101_remove(struct spi_device *spi)
269 {
270         struct tsc2101_platform_data *pdata;
271         struct tsc2101_device *tsc2101;
272
273         pdata = spi->dev.platform_data;
274         tsc2101 = spi_get_drvdata(spi);
275
276         /* We assume that this can't race with the rest of the driver. */
277         if (tsc2101->mclk_enabled && tsc2101->disable_mclk != NULL)
278                 tsc2101->disable_mclk(spi);
279
280         if (pdata->cleanup != NULL)
281                 pdata->cleanup(spi);
282
283         spi_set_drvdata(spi, NULL);
284         kfree(tsc2101);
285
286         return 0;
287 }
288
289 static struct spi_driver tsc2101_driver = {
290         .probe          = tsc2101_probe,
291         .remove         = tsc2101_remove,
292         .suspend        = tsc2101_suspend,
293         .resume         = tsc2101_resume,
294         .driver         = {
295                 .name   = "tsc2101",
296                 .owner  = THIS_MODULE,
297         },
298 };
299
300 static int tsc2101_init(void)
301 {
302         return spi_register_driver(&tsc2101_driver);
303 }
304
305 static void tsc2101_exit(void)
306 {
307         spi_unregister_driver(&tsc2101_driver);
308 }
309
310 module_init(tsc2101_init);
311 module_exit(tsc2101_exit);
312
313 MODULE_AUTHOR("Texas Instruments");
314 MODULE_DESCRIPTION
315     ("Glue audio driver for the TI OMAP1610/OMAP1710 TSC2101 codec.");
316 MODULE_LICENSE("GPL");