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");