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
pci
cs5535audio
cs5535audio_olpc.c
Go to the documentation of this file.
1
/*
2
* OLPC XO-1 additional sound features
3
*
4
* Copyright © 2006 Jaya Kumar <
[email protected]
>
5
* Copyright © 2007-2008 Andres Salomon <
[email protected]
>
6
*
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
11
*/
12
#include <
sound/core.h
>
13
#include <
sound/info.h
>
14
#include <
sound/control.h
>
15
#include <
sound/ac97_codec.h
>
16
#include <
linux/gpio.h
>
17
18
#include <
asm/olpc.h
>
19
#include "
cs5535audio.h
"
20
21
#define DRV_NAME "cs5535audio-olpc"
22
23
/*
24
* OLPC has an additional feature on top of the regular AD1888 codec features.
25
* It has an Analog Input mode that is switched into (after disabling the
26
* High Pass Filter) via GPIO. It is supported on B2 and later models.
27
*/
28
void
olpc_analog_input
(
struct
snd_ac97
*ac97,
int
on)
29
{
30
int
err
;
31
32
if
(!machine_is_olpc())
33
return
;
34
35
/* update the High Pass Filter (via AC97_AD_TEST2) */
36
err =
snd_ac97_update_bits
(ac97,
AC97_AD_TEST2
,
37
1 <<
AC97_AD_HPFD_SHIFT
, on <<
AC97_AD_HPFD_SHIFT
);
38
if
(err < 0) {
39
snd_printk
(
KERN_ERR
"setting High Pass Filter - %d\n"
, err);
40
return
;
41
}
42
43
/* set Analog Input through GPIO */
44
gpio_set_value
(
OLPC_GPIO_MIC_AC
, on);
45
}
46
47
/*
48
* OLPC XO-1's V_REFOUT is a mic bias enable.
49
*/
50
void
olpc_mic_bias
(
struct
snd_ac97
*ac97,
int
on)
51
{
52
int
err
;
53
54
if
(!machine_is_olpc())
55
return
;
56
57
on = on ? 0 : 1;
58
err =
snd_ac97_update_bits
(ac97,
AC97_AD_MISC
,
59
1 <<
AC97_AD_VREFD_SHIFT
, on <<
AC97_AD_VREFD_SHIFT
);
60
if
(err < 0)
61
snd_printk
(
KERN_ERR
"setting MIC Bias - %d\n"
, err);
62
}
63
64
static
int
olpc_dc_info(
struct
snd_kcontrol
*kctl,
65
struct
snd_ctl_elem_info
*uinfo)
66
{
67
uinfo->
type
=
SNDRV_CTL_ELEM_TYPE_BOOLEAN
;
68
uinfo->
count
= 1;
69
uinfo->
value
.
integer
.min = 0;
70
uinfo->
value
.
integer
.max = 1;
71
return
0;
72
}
73
74
static
int
olpc_dc_get(
struct
snd_kcontrol
*kctl,
struct
snd_ctl_elem_value
*
v
)
75
{
76
v->
value
.integer.value[0] =
gpio_get_value
(
OLPC_GPIO_MIC_AC
);
77
return
0;
78
}
79
80
static
int
olpc_dc_put(
struct
snd_kcontrol
*kctl,
struct
snd_ctl_elem_value
*
v
)
81
{
82
struct
cs5535audio
*cs5535au =
snd_kcontrol_chip
(kctl);
83
84
olpc_analog_input
(cs5535au->
ac97
, v->
value
.integer.value[0]);
85
return
1;
86
}
87
88
static
int
olpc_mic_info(
struct
snd_kcontrol
*kctl,
89
struct
snd_ctl_elem_info
*uinfo)
90
{
91
uinfo->
type
=
SNDRV_CTL_ELEM_TYPE_BOOLEAN
;
92
uinfo->
count
= 1;
93
uinfo->
value
.
integer
.min = 0;
94
uinfo->
value
.
integer
.max = 1;
95
return
0;
96
}
97
98
static
int
olpc_mic_get(
struct
snd_kcontrol
*kctl,
struct
snd_ctl_elem_value
*
v
)
99
{
100
struct
cs5535audio
*cs5535au =
snd_kcontrol_chip
(kctl);
101
struct
snd_ac97
*
ac97
= cs5535au->
ac97
;
102
int
i
;
103
104
i = (
snd_ac97_read
(ac97,
AC97_AD_MISC
) >>
AC97_AD_VREFD_SHIFT
) & 0x1;
105
v->
value
.integer.value[0] = i ? 0 : 1;
106
return
0;
107
}
108
109
static
int
olpc_mic_put(
struct
snd_kcontrol
*kctl,
struct
snd_ctl_elem_value
*
v
)
110
{
111
struct
cs5535audio
*cs5535au =
snd_kcontrol_chip
(kctl);
112
113
olpc_mic_bias
(cs5535au->
ac97
, v->
value
.integer.value[0]);
114
return
1;
115
}
116
117
static
struct
snd_kcontrol_new
olpc_cs5535audio_ctls[]
__devinitdata
= {
118
{
119
.iface =
SNDRV_CTL_ELEM_IFACE_MIXER
,
120
.name =
"DC Mode Enable"
,
121
.info = olpc_dc_info,
122
.get = olpc_dc_get,
123
.put = olpc_dc_put,
124
.private_value = 0,
125
},
126
{
127
.iface =
SNDRV_CTL_ELEM_IFACE_MIXER
,
128
.name =
"MIC Bias Enable"
,
129
.info = olpc_mic_info,
130
.get = olpc_mic_get,
131
.put = olpc_mic_put,
132
.private_value = 0,
133
},
134
};
135
136
void
__devinit
olpc_prequirks
(
struct
snd_card
*
card
,
137
struct
snd_ac97_template
*ac97)
138
{
139
if
(!machine_is_olpc())
140
return
;
141
142
/* invert EAPD if on an OLPC B3 or higher */
143
if
(olpc_board_at_least(olpc_board_pre(0xb3)))
144
ac97->
scaps
|=
AC97_SCAP_INV_EAPD
;
145
}
146
147
int
__devinit
olpc_quirks
(
struct
snd_card
*
card
,
struct
snd_ac97
*ac97)
148
{
149
struct
snd_ctl_elem_id
elem;
150
int
i
,
err
;
151
152
if
(!machine_is_olpc())
153
return
0;
154
155
if
(
gpio_request
(
OLPC_GPIO_MIC_AC
,
DRV_NAME
)) {
156
printk
(
KERN_ERR
DRV_NAME
": unable to allocate MIC GPIO\n"
);
157
return
-
EIO
;
158
}
159
gpio_direction_output
(
OLPC_GPIO_MIC_AC
, 0);
160
161
/* drop the original AD1888 HPF control */
162
memset
(&elem, 0,
sizeof
(elem));
163
elem.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
;
164
strncpy
(elem.
name
,
"High Pass Filter Enable"
,
sizeof
(elem.
name
));
165
snd_ctl_remove_id
(card, &elem);
166
167
/* drop the original V_REFOUT control */
168
memset
(&elem, 0,
sizeof
(elem));
169
elem.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
;
170
strncpy
(elem.
name
,
"V_REFOUT Enable"
,
sizeof
(elem.
name
));
171
snd_ctl_remove_id
(card, &elem);
172
173
/* add the OLPC-specific controls */
174
for
(i = 0; i <
ARRAY_SIZE
(olpc_cs5535audio_ctls); i++) {
175
err =
snd_ctl_add
(card,
snd_ctl_new1
(&olpc_cs5535audio_ctls[i],
176
ac97->
private_data
));
177
if
(err < 0) {
178
gpio_free
(
OLPC_GPIO_MIC_AC
);
179
return
err
;
180
}
181
}
182
183
/* turn off the mic by default */
184
olpc_mic_bias
(ac97, 0);
185
return
0;
186
}
187
188
void
__devexit
olpc_quirks_cleanup
(
void
)
189
{
190
gpio_free
(
OLPC_GPIO_MIC_AC
);
191
}
Generated on Thu Jan 10 2013 15:06:01 for Linux Kernel by
1.8.2