2 * linux/drivers/spi/tsc2101.c
4 * TSC2101 codec interface driver for the OMAP platform
6 * Copyright (C) 2004 Texas Instruments, Inc.
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.
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.
18 * 2004/11/07 Nishanth Menon - Modified for common hooks for Audio and Touchscreen
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>
27 struct tsc2101_device {
30 struct clock *mclk_ck;
31 struct spi_message message;
32 struct spi_transfer transfer[2];
34 void (*enable_mclk)(struct spi_device *spi);
35 void (*disable_mclk)(struct spi_device *spi);
38 int tsc2101_enable_mclk(struct spi_device *spi)
40 struct tsc2101_device *tsc2101;
42 tsc2101 = spi_get_drvdata(spi);
44 mutex_lock(&tsc2101->mutex);
46 if (spi->dev.power.power_state.event != PM_EVENT_ON) {
47 mutex_unlock(&tsc2101->mutex);
51 if (tsc2101->mclk_enabled++ == 0) {
52 if (tsc2101->enable_mclk != NULL)
53 tsc2101->enable_mclk(spi);
56 mutex_unlock(&tsc2101->mutex);
59 EXPORT_SYMBOL(tsc2101_enable_mclk);
61 void tsc2101_disable_mclk(struct spi_device *spi)
63 struct tsc2101_device *tsc2101;
65 tsc2101 = spi_get_drvdata(spi);
67 mutex_lock(&tsc2101->mutex);
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);
75 mutex_lock(&tsc2101->mutex);
77 EXPORT_SYMBOL(tsc2101_disable_mclk);
79 int tsc2101_write_sync(struct spi_device *spi, int page, u8 address, u16 data)
81 struct tsc2101_device *tsc2101;
82 struct spi_message *m;
83 struct spi_transfer *t;
86 tsc2101 = spi_get_drvdata(spi);
88 mutex_lock(&tsc2101->mutex);
89 if (spi->dev.power.power_state.event != PM_EVENT_ON) {
90 mutex_unlock(&tsc2101->mutex);
94 m = &tsc2101->message;
96 t = &tsc2101->transfer[0];
97 memset(t, 0, sizeof(tsc2101->transfer));
100 tsc2101->command = (page << 11) | (address << 5);
101 t->tx_buf = &tsc2101->command;
103 spi_message_add_tail(t, m);
109 spi_message_add_tail(t, m);
111 ret = spi_sync(spi, m);
113 ret = tsc2101->message.status;
114 mutex_unlock(&tsc2101->mutex);
118 EXPORT_SYMBOL(tsc2101_write_sync);
120 int tsc2101_reads_sync(struct spi_device *spi,
121 int page, u8 startaddress, u16 *data, int numregs)
123 struct tsc2101_device *tsc2101;
124 struct spi_message *m;
125 struct spi_transfer *t;
128 tsc2101 = spi_get_drvdata(spi);
130 mutex_lock(&tsc2101->mutex);
131 if (spi->dev.power.power_state.event != PM_EVENT_ON) {
132 mutex_unlock(&tsc2101->mutex);
136 m = &tsc2101->message;
138 t = &tsc2101->transfer[0];
139 memset(t, 0, sizeof(tsc2101->transfer));
142 tsc2101->command = 0x8000 | (page << 11) | (startaddress << 5);
143 t->tx_buf = &tsc2101->command;
145 spi_message_add_tail(t, m);
150 t->len = numregs << 1;
151 spi_message_add_tail(t, m);
153 ret = spi_sync(spi, m);
155 ret = tsc2101->message.status;
157 mutex_unlock(&tsc2101->mutex);
161 EXPORT_SYMBOL(tsc2101_reads_sync);
163 int tsc2101_read_sync(struct spi_device *spi, int page, u8 address)
168 err = tsc2101_reads_sync(spi, page, address, &val, 1);
173 EXPORT_SYMBOL(tsc2101_read_sync);
175 static int tsc2101_suspend(struct spi_device *spi, pm_message_t state)
177 struct tsc2101_device *tsc2101;
179 tsc2101 = spi_get_drvdata(spi);
184 mutex_lock(&tsc2101->mutex);
186 spi->dev.power.power_state = state;
187 if (tsc2101->mclk_enabled && tsc2101->disable_mclk != NULL)
188 tsc2101->disable_mclk(spi);
190 mutex_unlock(&tsc2101->mutex);
195 static int tsc2101_resume(struct spi_device *spi)
197 struct tsc2101_device *tsc2101;
199 tsc2101 = spi_get_drvdata(spi);
204 mutex_lock(&tsc2101->mutex);
206 spi->dev.power.power_state = PMSG_ON;
207 if (tsc2101->mclk_enabled && tsc2101->enable_mclk != NULL)
208 tsc2101->enable_mclk(spi);
210 mutex_unlock(&tsc2101->mutex);
215 static int tsc2101_probe(struct spi_device *spi)
217 struct tsc2101_platform_data *pdata;
218 struct tsc2101_device *tsc2101;
222 pdata = spi->dev.platform_data;
224 dev_err(&spi->dev, "no platform data\n");
228 tsc2101 = kzalloc(sizeof(*tsc2101), GFP_KERNEL);
229 if (tsc2101 == NULL) {
230 dev_err(&spi->dev, "out of mem\n");
234 spi_set_drvdata(spi, tsc2101);
235 tsc2101->enable_mclk = pdata->enable_mclk;
236 tsc2101->disable_mclk = pdata->disable_mclk;
238 mutex_init(&tsc2101->mutex);
240 spi->mode = SPI_MODE_0;
241 spi->bits_per_word = 16;
242 if ((r = spi_setup(spi)) < 0) {
243 dev_err(&spi->dev, "SPI setup failed\n");
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);
253 if (pdata->init != NULL) {
254 if ((r = pdata->init(spi)) < 0) {
255 dev_err(&spi->dev, "platform init failed\n");
260 dev_info(&spi->dev, "initialized\n");
268 static int tsc2101_remove(struct spi_device *spi)
270 struct tsc2101_platform_data *pdata;
271 struct tsc2101_device *tsc2101;
273 pdata = spi->dev.platform_data;
274 tsc2101 = spi_get_drvdata(spi);
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);
280 if (pdata->cleanup != NULL)
283 spi_set_drvdata(spi, NULL);
289 static struct spi_driver tsc2101_driver = {
290 .probe = tsc2101_probe,
291 .remove = tsc2101_remove,
292 .suspend = tsc2101_suspend,
293 .resume = tsc2101_resume,
296 .owner = THIS_MODULE,
300 static int tsc2101_init(void)
302 return spi_register_driver(&tsc2101_driver);
305 static void tsc2101_exit(void)
307 spi_unregister_driver(&tsc2101_driver);
310 module_init(tsc2101_init);
311 module_exit(tsc2101_exit);
313 MODULE_AUTHOR("Texas Instruments");
315 ("Glue audio driver for the TI OMAP1610/OMAP1710 TSC2101 codec.");
316 MODULE_LICENSE("GPL");