Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
sound
arm
pxa2xx-ac97-lib.c
Go to the documentation of this file.
1
/*
2
* Based on sound/arm/pxa2xx-ac97.c and sound/soc/pxa/pxa2xx-ac97.c
3
* which contain:
4
*
5
* Author: Nicolas Pitre
6
* Created: Dec 02, 2004
7
* Copyright: MontaVista Software Inc.
8
*
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License version 2 as
11
* published by the Free Software Foundation.
12
*/
13
14
#include <linux/kernel.h>
15
#include <
linux/platform_device.h
>
16
#include <
linux/interrupt.h
>
17
#include <
linux/clk.h
>
18
#include <
linux/delay.h
>
19
#include <linux/module.h>
20
#include <
linux/io.h
>
21
22
#include <
sound/ac97_codec.h
>
23
#include <
sound/pxa2xx-lib.h
>
24
25
#include <mach/irqs.h>
26
#include <mach/regs-ac97.h>
27
#include <
mach/audio.h
>
28
29
static
DEFINE_MUTEX
(car_mutex);
30
static
DECLARE_WAIT_QUEUE_HEAD
(gsr_wq);
31
static
volatile
long
gsr_bits;
32
static
struct
clk
*ac97_clk;
33
static
struct
clk
*ac97conf_clk;
34
static
int
reset_gpio;
35
36
extern
void
pxa27x_assert_ac97reset
(
int
reset_gpio,
int
on);
37
38
/*
39
* Beware PXA27x bugs:
40
*
41
* o Slot 12 read from modem space will hang controller.
42
* o CDONE, SDONE interrupt fails after any slot 12 IO.
43
*
44
* We therefore have an hybrid approach for waiting on SDONE (interrupt or
45
* 1 jiffy timeout if interrupt never comes).
46
*/
47
48
unsigned
short
pxa2xx_ac97_read
(
struct
snd_ac97
*ac97,
unsigned
short
reg
)
49
{
50
unsigned
short
val
= -1;
51
volatile
u32
*
reg_addr
;
52
53
mutex_lock
(&car_mutex);
54
55
/* set up primary or secondary codec space */
56
if
(
cpu_is_pxa25x
() && reg ==
AC97_GPIO_STATUS
)
57
reg_addr = ac97->
num
? &
SMC_REG_BASE
: &
PMC_REG_BASE
;
58
else
59
reg_addr = ac97->
num
? &
SAC_REG_BASE
: &
PAC_REG_BASE
;
60
reg_addr += (reg >> 1);
61
62
/* start read access across the ac97 link */
63
GSR
=
GSR_CDONE
|
GSR_SDONE
;
64
gsr_bits = 0;
65
val = *
reg_addr
;
66
if
(reg ==
AC97_GPIO_STATUS
)
67
goto
out
;
68
if
(
wait_event_timeout
(gsr_wq, (
GSR
| gsr_bits) &
GSR_SDONE
, 1) <= 0 &&
69
!((
GSR
| gsr_bits) & GSR_SDONE)) {
70
printk
(
KERN_ERR
"%s: read error (ac97_reg=%d GSR=%#lx)\n"
,
71
__func__, reg,
GSR
| gsr_bits);
72
val = -1;
73
goto
out
;
74
}
75
76
/* valid data now */
77
GSR
=
GSR_CDONE
|
GSR_SDONE
;
78
gsr_bits = 0;
79
val = *
reg_addr
;
80
/* but we've just started another cycle... */
81
wait_event_timeout
(gsr_wq, (
GSR
| gsr_bits) & GSR_SDONE, 1);
82
83
out
:
mutex_unlock
(&car_mutex);
84
return
val
;
85
}
86
EXPORT_SYMBOL_GPL
(
pxa2xx_ac97_read
);
87
88
void
pxa2xx_ac97_write
(
struct
snd_ac97
*ac97,
unsigned
short
reg
,
89
unsigned
short
val
)
90
{
91
volatile
u32
*
reg_addr
;
92
93
mutex_lock
(&car_mutex);
94
95
/* set up primary or secondary codec space */
96
if
(
cpu_is_pxa25x
() && reg ==
AC97_GPIO_STATUS
)
97
reg_addr = ac97->
num
? &
SMC_REG_BASE
: &
PMC_REG_BASE
;
98
else
99
reg_addr = ac97->
num
? &
SAC_REG_BASE
: &
PAC_REG_BASE
;
100
reg_addr += (reg >> 1);
101
102
GSR
=
GSR_CDONE
|
GSR_SDONE
;
103
gsr_bits = 0;
104
*reg_addr =
val
;
105
if
(
wait_event_timeout
(gsr_wq, (
GSR
| gsr_bits) &
GSR_CDONE
, 1) <= 0 &&
106
!((
GSR
| gsr_bits) & GSR_CDONE))
107
printk
(
KERN_ERR
"%s: write error (ac97_reg=%d GSR=%#lx)\n"
,
108
__func__, reg,
GSR
| gsr_bits);
109
110
mutex_unlock
(&car_mutex);
111
}
112
EXPORT_SYMBOL_GPL
(
pxa2xx_ac97_write
);
113
114
#ifdef CONFIG_PXA25x
115
static
inline
void
pxa_ac97_warm_pxa25x(
void
)
116
{
117
gsr_bits = 0;
118
119
GCR
|=
GCR_WARM_RST
|
GCR_PRIRDY_IEN
|
GCR_SECRDY_IEN
;
120
wait_event_timeout
(gsr_wq, gsr_bits & (
GSR_PCR
|
GSR_SCR
), 1);
121
}
122
123
static
inline
void
pxa_ac97_cold_pxa25x(
void
)
124
{
125
GCR
&=
GCR_COLD_RST
;
/* clear everything but nCRST */
126
GCR
&= ~
GCR_COLD_RST
;
/* then assert nCRST */
127
128
gsr_bits = 0;
129
130
GCR
=
GCR_COLD_RST
;
131
GCR
|=
GCR_CDONE_IE
|
GCR_SDONE_IE
;
132
wait_event_timeout
(gsr_wq, gsr_bits & (
GSR_PCR
|
GSR_SCR
), 1);
133
}
134
#endif
135
136
#ifdef CONFIG_PXA27x
137
static
inline
void
pxa_ac97_warm_pxa27x(
void
)
138
{
139
gsr_bits = 0;
140
141
/* warm reset broken on Bulverde, so manually keep AC97 reset high */
142
pxa27x_assert_ac97reset
(reset_gpio, 1);
143
udelay
(10);
144
GCR
|=
GCR_WARM_RST
;
145
pxa27x_assert_ac97reset
(reset_gpio, 0);
146
udelay
(500);
147
}
148
149
static
inline
void
pxa_ac97_cold_pxa27x(
void
)
150
{
151
GCR
&=
GCR_COLD_RST
;
/* clear everything but nCRST */
152
GCR
&= ~
GCR_COLD_RST
;
/* then assert nCRST */
153
154
gsr_bits = 0;
155
156
/* PXA27x Developers Manual section 13.5.2.2.1 */
157
clk_enable
(ac97conf_clk);
158
udelay
(5);
159
clk_disable
(ac97conf_clk);
160
GCR
=
GCR_COLD_RST
;
161
udelay
(50);
162
}
163
#endif
164
165
#ifdef CONFIG_PXA3xx
166
static
inline
void
pxa_ac97_warm_pxa3xx(
void
)
167
{
168
int
timeout
= 100;
169
170
gsr_bits = 0;
171
172
/* Can't use interrupts */
173
GCR
|=
GCR_WARM_RST
;
174
while
(!((
GSR
| gsr_bits) & (
GSR_PCR
|
GSR_SCR
)) && timeout--)
175
mdelay
(1);
176
}
177
178
static
inline
void
pxa_ac97_cold_pxa3xx(
void
)
179
{
180
int
timeout = 1000;
181
182
/* Hold CLKBPB for 100us */
183
GCR
= 0;
184
GCR
= GCR_CLKBPB;
185
udelay
(100);
186
GCR
= 0;
187
188
GCR
&=
GCR_COLD_RST
;
/* clear everything but nCRST */
189
GCR
&= ~
GCR_COLD_RST
;
/* then assert nCRST */
190
191
gsr_bits = 0;
192
193
/* Can't use interrupts on PXA3xx */
194
GCR
&= ~(
GCR_PRIRDY_IEN
|
GCR_SECRDY_IEN
);
195
196
GCR
=
GCR_WARM_RST
|
GCR_COLD_RST
;
197
while
(!(
GSR
& (
GSR_PCR
|
GSR_SCR
)) && timeout--)
198
mdelay
(10);
199
}
200
#endif
201
202
bool
pxa2xx_ac97_try_warm_reset
(
struct
snd_ac97
*ac97)
203
{
204
unsigned
long
gsr;
205
206
#ifdef CONFIG_PXA25x
207
if
(
cpu_is_pxa25x
())
208
pxa_ac97_warm_pxa25x();
209
else
210
#endif
211
#ifdef CONFIG_PXA27x
212
if
(
cpu_is_pxa27x
())
213
pxa_ac97_warm_pxa27x();
214
else
215
#endif
216
#ifdef CONFIG_PXA3xx
217
if
(
cpu_is_pxa3xx
())
218
pxa_ac97_warm_pxa3xx();
219
else
220
#endif
221
BUG
();
222
gsr =
GSR
| gsr_bits;
223
if
(!(gsr & (
GSR_PCR
|
GSR_SCR
))) {
224
printk
(
KERN_INFO
"%s: warm reset timeout (GSR=%#lx)\n"
,
225
__func__, gsr);
226
227
return
false
;
228
}
229
230
return
true
;
231
}
232
EXPORT_SYMBOL_GPL
(
pxa2xx_ac97_try_warm_reset
);
233
234
bool
pxa2xx_ac97_try_cold_reset
(
struct
snd_ac97
*ac97)
235
{
236
unsigned
long
gsr;
237
238
#ifdef CONFIG_PXA25x
239
if
(
cpu_is_pxa25x
())
240
pxa_ac97_cold_pxa25x();
241
else
242
#endif
243
#ifdef CONFIG_PXA27x
244
if
(
cpu_is_pxa27x
())
245
pxa_ac97_cold_pxa27x();
246
else
247
#endif
248
#ifdef CONFIG_PXA3xx
249
if
(
cpu_is_pxa3xx
())
250
pxa_ac97_cold_pxa3xx();
251
else
252
#endif
253
BUG
();
254
255
gsr =
GSR
| gsr_bits;
256
if
(!(gsr & (
GSR_PCR
|
GSR_SCR
))) {
257
printk
(
KERN_INFO
"%s: cold reset timeout (GSR=%#lx)\n"
,
258
__func__, gsr);
259
260
return
false
;
261
}
262
263
return
true
;
264
}
265
EXPORT_SYMBOL_GPL
(
pxa2xx_ac97_try_cold_reset
);
266
267
268
void
pxa2xx_ac97_finish_reset
(
struct
snd_ac97
*ac97)
269
{
270
GCR
&= ~(
GCR_PRIRDY_IEN
|
GCR_SECRDY_IEN
);
271
GCR
|=
GCR_SDONE_IE
|
GCR_CDONE_IE
;
272
}
273
EXPORT_SYMBOL_GPL
(
pxa2xx_ac97_finish_reset
);
274
275
static
irqreturn_t
pxa2xx_ac97_irq(
int
irq,
void
*
dev_id
)
276
{
277
long
status
;
278
279
status =
GSR
;
280
if
(status) {
281
GSR
=
status
;
282
gsr_bits |=
status
;
283
wake_up
(&gsr_wq);
284
285
/* Although we don't use those we still need to clear them
286
since they tend to spuriously trigger when MMC is used
287
(hardware bug? go figure)... */
288
if
(
cpu_is_pxa27x
()) {
289
MISR
=
MISR_EOC
;
290
PISR
=
PISR_EOC
;
291
MCSR
=
MCSR_EOC
;
292
}
293
294
return
IRQ_HANDLED
;
295
}
296
297
return
IRQ_NONE
;
298
}
299
300
#ifdef CONFIG_PM
301
int
pxa2xx_ac97_hw_suspend
(
void
)
302
{
303
GCR
|=
GCR_ACLINK_OFF
;
304
clk_disable
(ac97_clk);
305
return
0;
306
}
307
EXPORT_SYMBOL_GPL
(
pxa2xx_ac97_hw_suspend
);
308
309
int
pxa2xx_ac97_hw_resume
(
void
)
310
{
311
clk_enable
(ac97_clk);
312
return
0;
313
}
314
EXPORT_SYMBOL_GPL
(
pxa2xx_ac97_hw_resume
);
315
#endif
316
317
int
__devinit
pxa2xx_ac97_hw_probe
(
struct
platform_device
*
dev
)
318
{
319
int
ret
;
320
pxa2xx_audio_ops_t
*
pdata
= dev->
dev
.platform_data;
321
322
if
(pdata) {
323
switch
(pdata->
reset_gpio
) {
324
case
95:
325
case
113:
326
reset_gpio = pdata->
reset_gpio
;
327
break
;
328
case
0:
329
reset_gpio = 113;
330
break
;
331
case
-1:
332
break
;
333
default
:
334
dev_err
(&dev->
dev
,
"Invalid reset GPIO %d\n"
,
335
pdata->
reset_gpio
);
336
}
337
}
else
{
338
if
(
cpu_is_pxa27x
())
339
reset_gpio = 113;
340
}
341
342
if
(
cpu_is_pxa27x
()) {
343
/* Use GPIO 113 as AC97 Reset on Bulverde */
344
pxa27x_assert_ac97reset
(reset_gpio, 0);
345
ac97conf_clk =
clk_get
(&dev->
dev
,
"AC97CONFCLK"
);
346
if
(IS_ERR(ac97conf_clk)) {
347
ret = PTR_ERR(ac97conf_clk);
348
ac97conf_clk =
NULL
;
349
goto
err_conf;
350
}
351
}
352
353
ac97_clk =
clk_get
(&dev->
dev
,
"AC97CLK"
);
354
if
(IS_ERR(ac97_clk)) {
355
ret = PTR_ERR(ac97_clk);
356
ac97_clk =
NULL
;
357
goto
err_clk;
358
}
359
360
ret =
clk_enable
(ac97_clk);
361
if
(ret)
362
goto
err_clk2;
363
364
ret =
request_irq
(
IRQ_AC97
, pxa2xx_ac97_irq, 0,
"AC97"
,
NULL
);
365
if
(ret < 0)
366
goto
err_irq;
367
368
return
0;
369
370
err_irq:
371
GCR
|=
GCR_ACLINK_OFF
;
372
err_clk2:
373
clk_put
(ac97_clk);
374
ac97_clk =
NULL
;
375
err_clk:
376
if
(ac97conf_clk) {
377
clk_put
(ac97conf_clk);
378
ac97conf_clk =
NULL
;
379
}
380
err_conf:
381
return
ret
;
382
}
383
EXPORT_SYMBOL_GPL
(
pxa2xx_ac97_hw_probe
);
384
385
void
pxa2xx_ac97_hw_remove
(
struct
platform_device
*
dev
)
386
{
387
GCR
|=
GCR_ACLINK_OFF
;
388
free_irq
(
IRQ_AC97
,
NULL
);
389
if
(ac97conf_clk) {
390
clk_put
(ac97conf_clk);
391
ac97conf_clk =
NULL
;
392
}
393
clk_disable
(ac97_clk);
394
clk_put
(ac97_clk);
395
ac97_clk =
NULL
;
396
}
397
EXPORT_SYMBOL_GPL
(
pxa2xx_ac97_hw_remove
);
398
399
MODULE_AUTHOR
(
"Nicolas Pitre"
);
400
MODULE_DESCRIPTION
(
"Intel/Marvell PXA sound library"
);
401
MODULE_LICENSE
(
"GPL"
);
402
Generated on Thu Jan 10 2013 15:03:35 for Linux Kernel by
1.8.2