Commit 80b8d5d6bc0000c6e499260883cfc95e645f49d1
Committed by
Jaroslav Kysela
1 parent
ac5d1a7d25
Exists in
master
and in
7 other branches
[ALSA] Enable stereo line input for TAS codec
Despite what the data sheet says in one place, to get stereo input from input A (line in), we have to clear the 'input B monaural' bit in the ACR. Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Showing 1 changed file with 9 additions and 4 deletions Inline Diff
sound/aoa/codecs/snd-aoa-codec-tas.c
1 | /* | 1 | /* |
2 | * Apple Onboard Audio driver for tas codec | 2 | * Apple Onboard Audio driver for tas codec |
3 | * | 3 | * |
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | 4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> |
5 | * | 5 | * |
6 | * GPL v2, can be found in COPYING. | 6 | * GPL v2, can be found in COPYING. |
7 | * | 7 | * |
8 | * Open questions: | 8 | * Open questions: |
9 | * - How to distinguish between 3004 and versions? | 9 | * - How to distinguish between 3004 and versions? |
10 | * | 10 | * |
11 | * FIXMEs: | 11 | * FIXMEs: |
12 | * - This codec driver doesn't honour the 'connected' | 12 | * - This codec driver doesn't honour the 'connected' |
13 | * property of the aoa_codec struct, hence if | 13 | * property of the aoa_codec struct, hence if |
14 | * it is used in machines where not everything is | 14 | * it is used in machines where not everything is |
15 | * connected it will display wrong mixer elements. | 15 | * connected it will display wrong mixer elements. |
16 | * - Driver assumes that the microphone is always | 16 | * - Driver assumes that the microphone is always |
17 | * monaureal and connected to the right channel of | 17 | * monaureal and connected to the right channel of |
18 | * the input. This should also be a codec-dependent | 18 | * the input. This should also be a codec-dependent |
19 | * flag, maybe the codec should have 3 different | 19 | * flag, maybe the codec should have 3 different |
20 | * bits for the three different possibilities how | 20 | * bits for the three different possibilities how |
21 | * it can be hooked up... | 21 | * it can be hooked up... |
22 | * But as long as I don't see any hardware hooked | 22 | * But as long as I don't see any hardware hooked |
23 | * up that way... | 23 | * up that way... |
24 | * - As Apple notes in their code, the tas3004 seems | 24 | * - As Apple notes in their code, the tas3004 seems |
25 | * to delay the right channel by one sample. You can | 25 | * to delay the right channel by one sample. You can |
26 | * see this when for example recording stereo in | 26 | * see this when for example recording stereo in |
27 | * audacity, or recording the tas output via cable | 27 | * audacity, or recording the tas output via cable |
28 | * on another machine (use a sinus generator or so). | 28 | * on another machine (use a sinus generator or so). |
29 | * I tried programming the BiQuads but couldn't | 29 | * I tried programming the BiQuads but couldn't |
30 | * make the delay work, maybe someone can read the | 30 | * make the delay work, maybe someone can read the |
31 | * datasheet and fix it. The relevant Apple comment | 31 | * datasheet and fix it. The relevant Apple comment |
32 | * is in AppleTAS3004Audio.cpp lines 1637 ff. Note | 32 | * is in AppleTAS3004Audio.cpp lines 1637 ff. Note |
33 | * that their comment describing how they program | 33 | * that their comment describing how they program |
34 | * the filters sucks... | 34 | * the filters sucks... |
35 | * | 35 | * |
36 | * Other things: | 36 | * Other things: |
37 | * - this should actually register *two* aoa_codec | 37 | * - this should actually register *two* aoa_codec |
38 | * structs since it has two inputs. Then it must | 38 | * structs since it has two inputs. Then it must |
39 | * use the prepare callback to forbid running the | 39 | * use the prepare callback to forbid running the |
40 | * secondary output on a different clock. | 40 | * secondary output on a different clock. |
41 | * Also, whatever bus knows how to do this must | 41 | * Also, whatever bus knows how to do this must |
42 | * provide two soundbus_dev devices and the fabric | 42 | * provide two soundbus_dev devices and the fabric |
43 | * must be able to link them correctly. | 43 | * must be able to link them correctly. |
44 | * | 44 | * |
45 | * I don't even know if Apple ever uses the second | 45 | * I don't even know if Apple ever uses the second |
46 | * port on the tas3004 though, I don't think their | 46 | * port on the tas3004 though, I don't think their |
47 | * i2s controllers can even do it. OTOH, they all | 47 | * i2s controllers can even do it. OTOH, they all |
48 | * derive the clocks from common clocks, so it | 48 | * derive the clocks from common clocks, so it |
49 | * might just be possible. The framework allows the | 49 | * might just be possible. The framework allows the |
50 | * codec to refine the transfer_info items in the | 50 | * codec to refine the transfer_info items in the |
51 | * usable callback, so we can simply remove the | 51 | * usable callback, so we can simply remove the |
52 | * rates the second instance is not using when it | 52 | * rates the second instance is not using when it |
53 | * actually is in use. | 53 | * actually is in use. |
54 | * Maybe we'll need to make the sound busses have | 54 | * Maybe we'll need to make the sound busses have |
55 | * a 'clock group id' value so the codec can | 55 | * a 'clock group id' value so the codec can |
56 | * determine if the two outputs can be driven at | 56 | * determine if the two outputs can be driven at |
57 | * the same time. But that is likely overkill, up | 57 | * the same time. But that is likely overkill, up |
58 | * to the fabric to not link them up incorrectly, | 58 | * to the fabric to not link them up incorrectly, |
59 | * and up to the hardware designer to not wire | 59 | * and up to the hardware designer to not wire |
60 | * them up in some weird unusable way. | 60 | * them up in some weird unusable way. |
61 | */ | 61 | */ |
62 | #include <stddef.h> | 62 | #include <stddef.h> |
63 | #include <linux/i2c.h> | 63 | #include <linux/i2c.h> |
64 | #include <linux/i2c-dev.h> | 64 | #include <linux/i2c-dev.h> |
65 | #include <asm/pmac_low_i2c.h> | 65 | #include <asm/pmac_low_i2c.h> |
66 | #include <asm/prom.h> | 66 | #include <asm/prom.h> |
67 | #include <linux/delay.h> | 67 | #include <linux/delay.h> |
68 | #include <linux/module.h> | 68 | #include <linux/module.h> |
69 | #include <linux/mutex.h> | 69 | #include <linux/mutex.h> |
70 | 70 | ||
71 | MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); | 71 | MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); |
72 | MODULE_LICENSE("GPL"); | 72 | MODULE_LICENSE("GPL"); |
73 | MODULE_DESCRIPTION("tas codec driver for snd-aoa"); | 73 | MODULE_DESCRIPTION("tas codec driver for snd-aoa"); |
74 | 74 | ||
75 | #include "snd-aoa-codec-tas.h" | 75 | #include "snd-aoa-codec-tas.h" |
76 | #include "snd-aoa-codec-tas-gain-table.h" | 76 | #include "snd-aoa-codec-tas-gain-table.h" |
77 | #include "snd-aoa-codec-tas-basstreble.h" | 77 | #include "snd-aoa-codec-tas-basstreble.h" |
78 | #include "../aoa.h" | 78 | #include "../aoa.h" |
79 | #include "../soundbus/soundbus.h" | 79 | #include "../soundbus/soundbus.h" |
80 | 80 | ||
81 | #define PFX "snd-aoa-codec-tas: " | 81 | #define PFX "snd-aoa-codec-tas: " |
82 | 82 | ||
83 | 83 | ||
84 | struct tas { | 84 | struct tas { |
85 | struct aoa_codec codec; | 85 | struct aoa_codec codec; |
86 | struct i2c_client i2c; | 86 | struct i2c_client i2c; |
87 | u32 mute_l:1, mute_r:1 , | 87 | u32 mute_l:1, mute_r:1 , |
88 | controls_created:1 , | 88 | controls_created:1 , |
89 | drc_enabled:1, | 89 | drc_enabled:1, |
90 | hw_enabled:1; | 90 | hw_enabled:1; |
91 | u8 cached_volume_l, cached_volume_r; | 91 | u8 cached_volume_l, cached_volume_r; |
92 | u8 mixer_l[3], mixer_r[3]; | 92 | u8 mixer_l[3], mixer_r[3]; |
93 | u8 bass, treble; | 93 | u8 bass, treble; |
94 | u8 acr; | 94 | u8 acr; |
95 | int drc_range; | 95 | int drc_range; |
96 | /* protects hardware access against concurrency from | 96 | /* protects hardware access against concurrency from |
97 | * userspace when hitting controls and during | 97 | * userspace when hitting controls and during |
98 | * codec init/suspend/resume */ | 98 | * codec init/suspend/resume */ |
99 | struct mutex mtx; | 99 | struct mutex mtx; |
100 | }; | 100 | }; |
101 | 101 | ||
102 | static int tas_reset_init(struct tas *tas); | 102 | static int tas_reset_init(struct tas *tas); |
103 | 103 | ||
104 | static struct tas *codec_to_tas(struct aoa_codec *codec) | 104 | static struct tas *codec_to_tas(struct aoa_codec *codec) |
105 | { | 105 | { |
106 | return container_of(codec, struct tas, codec); | 106 | return container_of(codec, struct tas, codec); |
107 | } | 107 | } |
108 | 108 | ||
109 | static inline int tas_write_reg(struct tas *tas, u8 reg, u8 len, u8 *data) | 109 | static inline int tas_write_reg(struct tas *tas, u8 reg, u8 len, u8 *data) |
110 | { | 110 | { |
111 | if (len == 1) | 111 | if (len == 1) |
112 | return i2c_smbus_write_byte_data(&tas->i2c, reg, *data); | 112 | return i2c_smbus_write_byte_data(&tas->i2c, reg, *data); |
113 | else | 113 | else |
114 | return i2c_smbus_write_i2c_block_data(&tas->i2c, reg, len, data); | 114 | return i2c_smbus_write_i2c_block_data(&tas->i2c, reg, len, data); |
115 | } | 115 | } |
116 | 116 | ||
117 | static void tas3004_set_drc(struct tas *tas) | 117 | static void tas3004_set_drc(struct tas *tas) |
118 | { | 118 | { |
119 | unsigned char val[6]; | 119 | unsigned char val[6]; |
120 | 120 | ||
121 | if (tas->drc_enabled) | 121 | if (tas->drc_enabled) |
122 | val[0] = 0x50; /* 3:1 above threshold */ | 122 | val[0] = 0x50; /* 3:1 above threshold */ |
123 | else | 123 | else |
124 | val[0] = 0x51; /* disabled */ | 124 | val[0] = 0x51; /* disabled */ |
125 | val[1] = 0x02; /* 1:1 below threshold */ | 125 | val[1] = 0x02; /* 1:1 below threshold */ |
126 | if (tas->drc_range > 0xef) | 126 | if (tas->drc_range > 0xef) |
127 | val[2] = 0xef; | 127 | val[2] = 0xef; |
128 | else if (tas->drc_range < 0) | 128 | else if (tas->drc_range < 0) |
129 | val[2] = 0x00; | 129 | val[2] = 0x00; |
130 | else | 130 | else |
131 | val[2] = tas->drc_range; | 131 | val[2] = tas->drc_range; |
132 | val[3] = 0xb0; | 132 | val[3] = 0xb0; |
133 | val[4] = 0x60; | 133 | val[4] = 0x60; |
134 | val[5] = 0xa0; | 134 | val[5] = 0xa0; |
135 | 135 | ||
136 | tas_write_reg(tas, TAS_REG_DRC, 6, val); | 136 | tas_write_reg(tas, TAS_REG_DRC, 6, val); |
137 | } | 137 | } |
138 | 138 | ||
139 | static void tas_set_treble(struct tas *tas) | 139 | static void tas_set_treble(struct tas *tas) |
140 | { | 140 | { |
141 | u8 tmp; | 141 | u8 tmp; |
142 | 142 | ||
143 | tmp = tas3004_treble(tas->treble); | 143 | tmp = tas3004_treble(tas->treble); |
144 | tas_write_reg(tas, TAS_REG_TREBLE, 1, &tmp); | 144 | tas_write_reg(tas, TAS_REG_TREBLE, 1, &tmp); |
145 | } | 145 | } |
146 | 146 | ||
147 | static void tas_set_bass(struct tas *tas) | 147 | static void tas_set_bass(struct tas *tas) |
148 | { | 148 | { |
149 | u8 tmp; | 149 | u8 tmp; |
150 | 150 | ||
151 | tmp = tas3004_bass(tas->bass); | 151 | tmp = tas3004_bass(tas->bass); |
152 | tas_write_reg(tas, TAS_REG_BASS, 1, &tmp); | 152 | tas_write_reg(tas, TAS_REG_BASS, 1, &tmp); |
153 | } | 153 | } |
154 | 154 | ||
155 | static void tas_set_volume(struct tas *tas) | 155 | static void tas_set_volume(struct tas *tas) |
156 | { | 156 | { |
157 | u8 block[6]; | 157 | u8 block[6]; |
158 | int tmp; | 158 | int tmp; |
159 | u8 left, right; | 159 | u8 left, right; |
160 | 160 | ||
161 | left = tas->cached_volume_l; | 161 | left = tas->cached_volume_l; |
162 | right = tas->cached_volume_r; | 162 | right = tas->cached_volume_r; |
163 | 163 | ||
164 | if (left > 177) left = 177; | 164 | if (left > 177) left = 177; |
165 | if (right > 177) right = 177; | 165 | if (right > 177) right = 177; |
166 | 166 | ||
167 | if (tas->mute_l) left = 0; | 167 | if (tas->mute_l) left = 0; |
168 | if (tas->mute_r) right = 0; | 168 | if (tas->mute_r) right = 0; |
169 | 169 | ||
170 | /* analysing the volume and mixer tables shows | 170 | /* analysing the volume and mixer tables shows |
171 | * that they are similar enough when we shift | 171 | * that they are similar enough when we shift |
172 | * the mixer table down by 4 bits. The error | 172 | * the mixer table down by 4 bits. The error |
173 | * is miniscule, in just one item the error | 173 | * is miniscule, in just one item the error |
174 | * is 1, at a value of 0x07f17b (mixer table | 174 | * is 1, at a value of 0x07f17b (mixer table |
175 | * value is 0x07f17a) */ | 175 | * value is 0x07f17a) */ |
176 | tmp = tas_gaintable[left]; | 176 | tmp = tas_gaintable[left]; |
177 | block[0] = tmp>>20; | 177 | block[0] = tmp>>20; |
178 | block[1] = tmp>>12; | 178 | block[1] = tmp>>12; |
179 | block[2] = tmp>>4; | 179 | block[2] = tmp>>4; |
180 | tmp = tas_gaintable[right]; | 180 | tmp = tas_gaintable[right]; |
181 | block[3] = tmp>>20; | 181 | block[3] = tmp>>20; |
182 | block[4] = tmp>>12; | 182 | block[4] = tmp>>12; |
183 | block[5] = tmp>>4; | 183 | block[5] = tmp>>4; |
184 | tas_write_reg(tas, TAS_REG_VOL, 6, block); | 184 | tas_write_reg(tas, TAS_REG_VOL, 6, block); |
185 | } | 185 | } |
186 | 186 | ||
187 | static void tas_set_mixer(struct tas *tas) | 187 | static void tas_set_mixer(struct tas *tas) |
188 | { | 188 | { |
189 | u8 block[9]; | 189 | u8 block[9]; |
190 | int tmp, i; | 190 | int tmp, i; |
191 | u8 val; | 191 | u8 val; |
192 | 192 | ||
193 | for (i=0;i<3;i++) { | 193 | for (i=0;i<3;i++) { |
194 | val = tas->mixer_l[i]; | 194 | val = tas->mixer_l[i]; |
195 | if (val > 177) val = 177; | 195 | if (val > 177) val = 177; |
196 | tmp = tas_gaintable[val]; | 196 | tmp = tas_gaintable[val]; |
197 | block[3*i+0] = tmp>>16; | 197 | block[3*i+0] = tmp>>16; |
198 | block[3*i+1] = tmp>>8; | 198 | block[3*i+1] = tmp>>8; |
199 | block[3*i+2] = tmp; | 199 | block[3*i+2] = tmp; |
200 | } | 200 | } |
201 | tas_write_reg(tas, TAS_REG_LMIX, 9, block); | 201 | tas_write_reg(tas, TAS_REG_LMIX, 9, block); |
202 | 202 | ||
203 | for (i=0;i<3;i++) { | 203 | for (i=0;i<3;i++) { |
204 | val = tas->mixer_r[i]; | 204 | val = tas->mixer_r[i]; |
205 | if (val > 177) val = 177; | 205 | if (val > 177) val = 177; |
206 | tmp = tas_gaintable[val]; | 206 | tmp = tas_gaintable[val]; |
207 | block[3*i+0] = tmp>>16; | 207 | block[3*i+0] = tmp>>16; |
208 | block[3*i+1] = tmp>>8; | 208 | block[3*i+1] = tmp>>8; |
209 | block[3*i+2] = tmp; | 209 | block[3*i+2] = tmp; |
210 | } | 210 | } |
211 | tas_write_reg(tas, TAS_REG_RMIX, 9, block); | 211 | tas_write_reg(tas, TAS_REG_RMIX, 9, block); |
212 | } | 212 | } |
213 | 213 | ||
214 | /* alsa stuff */ | 214 | /* alsa stuff */ |
215 | 215 | ||
216 | static int tas_dev_register(struct snd_device *dev) | 216 | static int tas_dev_register(struct snd_device *dev) |
217 | { | 217 | { |
218 | return 0; | 218 | return 0; |
219 | } | 219 | } |
220 | 220 | ||
221 | static struct snd_device_ops ops = { | 221 | static struct snd_device_ops ops = { |
222 | .dev_register = tas_dev_register, | 222 | .dev_register = tas_dev_register, |
223 | }; | 223 | }; |
224 | 224 | ||
225 | static int tas_snd_vol_info(struct snd_kcontrol *kcontrol, | 225 | static int tas_snd_vol_info(struct snd_kcontrol *kcontrol, |
226 | struct snd_ctl_elem_info *uinfo) | 226 | struct snd_ctl_elem_info *uinfo) |
227 | { | 227 | { |
228 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 228 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
229 | uinfo->count = 2; | 229 | uinfo->count = 2; |
230 | uinfo->value.integer.min = 0; | 230 | uinfo->value.integer.min = 0; |
231 | uinfo->value.integer.max = 177; | 231 | uinfo->value.integer.max = 177; |
232 | return 0; | 232 | return 0; |
233 | } | 233 | } |
234 | 234 | ||
235 | static int tas_snd_vol_get(struct snd_kcontrol *kcontrol, | 235 | static int tas_snd_vol_get(struct snd_kcontrol *kcontrol, |
236 | struct snd_ctl_elem_value *ucontrol) | 236 | struct snd_ctl_elem_value *ucontrol) |
237 | { | 237 | { |
238 | struct tas *tas = snd_kcontrol_chip(kcontrol); | 238 | struct tas *tas = snd_kcontrol_chip(kcontrol); |
239 | 239 | ||
240 | mutex_lock(&tas->mtx); | 240 | mutex_lock(&tas->mtx); |
241 | ucontrol->value.integer.value[0] = tas->cached_volume_l; | 241 | ucontrol->value.integer.value[0] = tas->cached_volume_l; |
242 | ucontrol->value.integer.value[1] = tas->cached_volume_r; | 242 | ucontrol->value.integer.value[1] = tas->cached_volume_r; |
243 | mutex_unlock(&tas->mtx); | 243 | mutex_unlock(&tas->mtx); |
244 | return 0; | 244 | return 0; |
245 | } | 245 | } |
246 | 246 | ||
247 | static int tas_snd_vol_put(struct snd_kcontrol *kcontrol, | 247 | static int tas_snd_vol_put(struct snd_kcontrol *kcontrol, |
248 | struct snd_ctl_elem_value *ucontrol) | 248 | struct snd_ctl_elem_value *ucontrol) |
249 | { | 249 | { |
250 | struct tas *tas = snd_kcontrol_chip(kcontrol); | 250 | struct tas *tas = snd_kcontrol_chip(kcontrol); |
251 | 251 | ||
252 | mutex_lock(&tas->mtx); | 252 | mutex_lock(&tas->mtx); |
253 | if (tas->cached_volume_l == ucontrol->value.integer.value[0] | 253 | if (tas->cached_volume_l == ucontrol->value.integer.value[0] |
254 | && tas->cached_volume_r == ucontrol->value.integer.value[1]) { | 254 | && tas->cached_volume_r == ucontrol->value.integer.value[1]) { |
255 | mutex_unlock(&tas->mtx); | 255 | mutex_unlock(&tas->mtx); |
256 | return 0; | 256 | return 0; |
257 | } | 257 | } |
258 | 258 | ||
259 | tas->cached_volume_l = ucontrol->value.integer.value[0]; | 259 | tas->cached_volume_l = ucontrol->value.integer.value[0]; |
260 | tas->cached_volume_r = ucontrol->value.integer.value[1]; | 260 | tas->cached_volume_r = ucontrol->value.integer.value[1]; |
261 | if (tas->hw_enabled) | 261 | if (tas->hw_enabled) |
262 | tas_set_volume(tas); | 262 | tas_set_volume(tas); |
263 | mutex_unlock(&tas->mtx); | 263 | mutex_unlock(&tas->mtx); |
264 | return 1; | 264 | return 1; |
265 | } | 265 | } |
266 | 266 | ||
267 | static struct snd_kcontrol_new volume_control = { | 267 | static struct snd_kcontrol_new volume_control = { |
268 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 268 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
269 | .name = "Master Playback Volume", | 269 | .name = "Master Playback Volume", |
270 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | 270 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, |
271 | .info = tas_snd_vol_info, | 271 | .info = tas_snd_vol_info, |
272 | .get = tas_snd_vol_get, | 272 | .get = tas_snd_vol_get, |
273 | .put = tas_snd_vol_put, | 273 | .put = tas_snd_vol_put, |
274 | }; | 274 | }; |
275 | 275 | ||
276 | static int tas_snd_mute_info(struct snd_kcontrol *kcontrol, | 276 | static int tas_snd_mute_info(struct snd_kcontrol *kcontrol, |
277 | struct snd_ctl_elem_info *uinfo) | 277 | struct snd_ctl_elem_info *uinfo) |
278 | { | 278 | { |
279 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | 279 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; |
280 | uinfo->count = 2; | 280 | uinfo->count = 2; |
281 | uinfo->value.integer.min = 0; | 281 | uinfo->value.integer.min = 0; |
282 | uinfo->value.integer.max = 1; | 282 | uinfo->value.integer.max = 1; |
283 | return 0; | 283 | return 0; |
284 | } | 284 | } |
285 | 285 | ||
286 | static int tas_snd_mute_get(struct snd_kcontrol *kcontrol, | 286 | static int tas_snd_mute_get(struct snd_kcontrol *kcontrol, |
287 | struct snd_ctl_elem_value *ucontrol) | 287 | struct snd_ctl_elem_value *ucontrol) |
288 | { | 288 | { |
289 | struct tas *tas = snd_kcontrol_chip(kcontrol); | 289 | struct tas *tas = snd_kcontrol_chip(kcontrol); |
290 | 290 | ||
291 | mutex_lock(&tas->mtx); | 291 | mutex_lock(&tas->mtx); |
292 | ucontrol->value.integer.value[0] = !tas->mute_l; | 292 | ucontrol->value.integer.value[0] = !tas->mute_l; |
293 | ucontrol->value.integer.value[1] = !tas->mute_r; | 293 | ucontrol->value.integer.value[1] = !tas->mute_r; |
294 | mutex_unlock(&tas->mtx); | 294 | mutex_unlock(&tas->mtx); |
295 | return 0; | 295 | return 0; |
296 | } | 296 | } |
297 | 297 | ||
298 | static int tas_snd_mute_put(struct snd_kcontrol *kcontrol, | 298 | static int tas_snd_mute_put(struct snd_kcontrol *kcontrol, |
299 | struct snd_ctl_elem_value *ucontrol) | 299 | struct snd_ctl_elem_value *ucontrol) |
300 | { | 300 | { |
301 | struct tas *tas = snd_kcontrol_chip(kcontrol); | 301 | struct tas *tas = snd_kcontrol_chip(kcontrol); |
302 | 302 | ||
303 | mutex_lock(&tas->mtx); | 303 | mutex_lock(&tas->mtx); |
304 | if (tas->mute_l == !ucontrol->value.integer.value[0] | 304 | if (tas->mute_l == !ucontrol->value.integer.value[0] |
305 | && tas->mute_r == !ucontrol->value.integer.value[1]) { | 305 | && tas->mute_r == !ucontrol->value.integer.value[1]) { |
306 | mutex_unlock(&tas->mtx); | 306 | mutex_unlock(&tas->mtx); |
307 | return 0; | 307 | return 0; |
308 | } | 308 | } |
309 | 309 | ||
310 | tas->mute_l = !ucontrol->value.integer.value[0]; | 310 | tas->mute_l = !ucontrol->value.integer.value[0]; |
311 | tas->mute_r = !ucontrol->value.integer.value[1]; | 311 | tas->mute_r = !ucontrol->value.integer.value[1]; |
312 | if (tas->hw_enabled) | 312 | if (tas->hw_enabled) |
313 | tas_set_volume(tas); | 313 | tas_set_volume(tas); |
314 | mutex_unlock(&tas->mtx); | 314 | mutex_unlock(&tas->mtx); |
315 | return 1; | 315 | return 1; |
316 | } | 316 | } |
317 | 317 | ||
318 | static struct snd_kcontrol_new mute_control = { | 318 | static struct snd_kcontrol_new mute_control = { |
319 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 319 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
320 | .name = "Master Playback Switch", | 320 | .name = "Master Playback Switch", |
321 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | 321 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, |
322 | .info = tas_snd_mute_info, | 322 | .info = tas_snd_mute_info, |
323 | .get = tas_snd_mute_get, | 323 | .get = tas_snd_mute_get, |
324 | .put = tas_snd_mute_put, | 324 | .put = tas_snd_mute_put, |
325 | }; | 325 | }; |
326 | 326 | ||
327 | static int tas_snd_mixer_info(struct snd_kcontrol *kcontrol, | 327 | static int tas_snd_mixer_info(struct snd_kcontrol *kcontrol, |
328 | struct snd_ctl_elem_info *uinfo) | 328 | struct snd_ctl_elem_info *uinfo) |
329 | { | 329 | { |
330 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 330 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
331 | uinfo->count = 2; | 331 | uinfo->count = 2; |
332 | uinfo->value.integer.min = 0; | 332 | uinfo->value.integer.min = 0; |
333 | uinfo->value.integer.max = 177; | 333 | uinfo->value.integer.max = 177; |
334 | return 0; | 334 | return 0; |
335 | } | 335 | } |
336 | 336 | ||
337 | static int tas_snd_mixer_get(struct snd_kcontrol *kcontrol, | 337 | static int tas_snd_mixer_get(struct snd_kcontrol *kcontrol, |
338 | struct snd_ctl_elem_value *ucontrol) | 338 | struct snd_ctl_elem_value *ucontrol) |
339 | { | 339 | { |
340 | struct tas *tas = snd_kcontrol_chip(kcontrol); | 340 | struct tas *tas = snd_kcontrol_chip(kcontrol); |
341 | int idx = kcontrol->private_value; | 341 | int idx = kcontrol->private_value; |
342 | 342 | ||
343 | mutex_lock(&tas->mtx); | 343 | mutex_lock(&tas->mtx); |
344 | ucontrol->value.integer.value[0] = tas->mixer_l[idx]; | 344 | ucontrol->value.integer.value[0] = tas->mixer_l[idx]; |
345 | ucontrol->value.integer.value[1] = tas->mixer_r[idx]; | 345 | ucontrol->value.integer.value[1] = tas->mixer_r[idx]; |
346 | mutex_unlock(&tas->mtx); | 346 | mutex_unlock(&tas->mtx); |
347 | 347 | ||
348 | return 0; | 348 | return 0; |
349 | } | 349 | } |
350 | 350 | ||
351 | static int tas_snd_mixer_put(struct snd_kcontrol *kcontrol, | 351 | static int tas_snd_mixer_put(struct snd_kcontrol *kcontrol, |
352 | struct snd_ctl_elem_value *ucontrol) | 352 | struct snd_ctl_elem_value *ucontrol) |
353 | { | 353 | { |
354 | struct tas *tas = snd_kcontrol_chip(kcontrol); | 354 | struct tas *tas = snd_kcontrol_chip(kcontrol); |
355 | int idx = kcontrol->private_value; | 355 | int idx = kcontrol->private_value; |
356 | 356 | ||
357 | mutex_lock(&tas->mtx); | 357 | mutex_lock(&tas->mtx); |
358 | if (tas->mixer_l[idx] == ucontrol->value.integer.value[0] | 358 | if (tas->mixer_l[idx] == ucontrol->value.integer.value[0] |
359 | && tas->mixer_r[idx] == ucontrol->value.integer.value[1]) { | 359 | && tas->mixer_r[idx] == ucontrol->value.integer.value[1]) { |
360 | mutex_unlock(&tas->mtx); | 360 | mutex_unlock(&tas->mtx); |
361 | return 0; | 361 | return 0; |
362 | } | 362 | } |
363 | 363 | ||
364 | tas->mixer_l[idx] = ucontrol->value.integer.value[0]; | 364 | tas->mixer_l[idx] = ucontrol->value.integer.value[0]; |
365 | tas->mixer_r[idx] = ucontrol->value.integer.value[1]; | 365 | tas->mixer_r[idx] = ucontrol->value.integer.value[1]; |
366 | 366 | ||
367 | if (tas->hw_enabled) | 367 | if (tas->hw_enabled) |
368 | tas_set_mixer(tas); | 368 | tas_set_mixer(tas); |
369 | mutex_unlock(&tas->mtx); | 369 | mutex_unlock(&tas->mtx); |
370 | return 1; | 370 | return 1; |
371 | } | 371 | } |
372 | 372 | ||
373 | #define MIXER_CONTROL(n,descr,idx) \ | 373 | #define MIXER_CONTROL(n,descr,idx) \ |
374 | static struct snd_kcontrol_new n##_control = { \ | 374 | static struct snd_kcontrol_new n##_control = { \ |
375 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 375 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
376 | .name = descr " Playback Volume", \ | 376 | .name = descr " Playback Volume", \ |
377 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ | 377 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ |
378 | .info = tas_snd_mixer_info, \ | 378 | .info = tas_snd_mixer_info, \ |
379 | .get = tas_snd_mixer_get, \ | 379 | .get = tas_snd_mixer_get, \ |
380 | .put = tas_snd_mixer_put, \ | 380 | .put = tas_snd_mixer_put, \ |
381 | .private_value = idx, \ | 381 | .private_value = idx, \ |
382 | } | 382 | } |
383 | 383 | ||
384 | MIXER_CONTROL(pcm1, "PCM", 0); | 384 | MIXER_CONTROL(pcm1, "PCM", 0); |
385 | MIXER_CONTROL(monitor, "Monitor", 2); | 385 | MIXER_CONTROL(monitor, "Monitor", 2); |
386 | 386 | ||
387 | static int tas_snd_drc_range_info(struct snd_kcontrol *kcontrol, | 387 | static int tas_snd_drc_range_info(struct snd_kcontrol *kcontrol, |
388 | struct snd_ctl_elem_info *uinfo) | 388 | struct snd_ctl_elem_info *uinfo) |
389 | { | 389 | { |
390 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 390 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
391 | uinfo->count = 1; | 391 | uinfo->count = 1; |
392 | uinfo->value.integer.min = 0; | 392 | uinfo->value.integer.min = 0; |
393 | uinfo->value.integer.max = TAS3004_DRC_MAX; | 393 | uinfo->value.integer.max = TAS3004_DRC_MAX; |
394 | return 0; | 394 | return 0; |
395 | } | 395 | } |
396 | 396 | ||
397 | static int tas_snd_drc_range_get(struct snd_kcontrol *kcontrol, | 397 | static int tas_snd_drc_range_get(struct snd_kcontrol *kcontrol, |
398 | struct snd_ctl_elem_value *ucontrol) | 398 | struct snd_ctl_elem_value *ucontrol) |
399 | { | 399 | { |
400 | struct tas *tas = snd_kcontrol_chip(kcontrol); | 400 | struct tas *tas = snd_kcontrol_chip(kcontrol); |
401 | 401 | ||
402 | mutex_lock(&tas->mtx); | 402 | mutex_lock(&tas->mtx); |
403 | ucontrol->value.integer.value[0] = tas->drc_range; | 403 | ucontrol->value.integer.value[0] = tas->drc_range; |
404 | mutex_unlock(&tas->mtx); | 404 | mutex_unlock(&tas->mtx); |
405 | return 0; | 405 | return 0; |
406 | } | 406 | } |
407 | 407 | ||
408 | static int tas_snd_drc_range_put(struct snd_kcontrol *kcontrol, | 408 | static int tas_snd_drc_range_put(struct snd_kcontrol *kcontrol, |
409 | struct snd_ctl_elem_value *ucontrol) | 409 | struct snd_ctl_elem_value *ucontrol) |
410 | { | 410 | { |
411 | struct tas *tas = snd_kcontrol_chip(kcontrol); | 411 | struct tas *tas = snd_kcontrol_chip(kcontrol); |
412 | 412 | ||
413 | mutex_lock(&tas->mtx); | 413 | mutex_lock(&tas->mtx); |
414 | if (tas->drc_range == ucontrol->value.integer.value[0]) { | 414 | if (tas->drc_range == ucontrol->value.integer.value[0]) { |
415 | mutex_unlock(&tas->mtx); | 415 | mutex_unlock(&tas->mtx); |
416 | return 0; | 416 | return 0; |
417 | } | 417 | } |
418 | 418 | ||
419 | tas->drc_range = ucontrol->value.integer.value[0]; | 419 | tas->drc_range = ucontrol->value.integer.value[0]; |
420 | if (tas->hw_enabled) | 420 | if (tas->hw_enabled) |
421 | tas3004_set_drc(tas); | 421 | tas3004_set_drc(tas); |
422 | mutex_unlock(&tas->mtx); | 422 | mutex_unlock(&tas->mtx); |
423 | return 1; | 423 | return 1; |
424 | } | 424 | } |
425 | 425 | ||
426 | static struct snd_kcontrol_new drc_range_control = { | 426 | static struct snd_kcontrol_new drc_range_control = { |
427 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 427 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
428 | .name = "DRC Range", | 428 | .name = "DRC Range", |
429 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | 429 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, |
430 | .info = tas_snd_drc_range_info, | 430 | .info = tas_snd_drc_range_info, |
431 | .get = tas_snd_drc_range_get, | 431 | .get = tas_snd_drc_range_get, |
432 | .put = tas_snd_drc_range_put, | 432 | .put = tas_snd_drc_range_put, |
433 | }; | 433 | }; |
434 | 434 | ||
435 | static int tas_snd_drc_switch_info(struct snd_kcontrol *kcontrol, | 435 | static int tas_snd_drc_switch_info(struct snd_kcontrol *kcontrol, |
436 | struct snd_ctl_elem_info *uinfo) | 436 | struct snd_ctl_elem_info *uinfo) |
437 | { | 437 | { |
438 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | 438 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; |
439 | uinfo->count = 1; | 439 | uinfo->count = 1; |
440 | uinfo->value.integer.min = 0; | 440 | uinfo->value.integer.min = 0; |
441 | uinfo->value.integer.max = 1; | 441 | uinfo->value.integer.max = 1; |
442 | return 0; | 442 | return 0; |
443 | } | 443 | } |
444 | 444 | ||
445 | static int tas_snd_drc_switch_get(struct snd_kcontrol *kcontrol, | 445 | static int tas_snd_drc_switch_get(struct snd_kcontrol *kcontrol, |
446 | struct snd_ctl_elem_value *ucontrol) | 446 | struct snd_ctl_elem_value *ucontrol) |
447 | { | 447 | { |
448 | struct tas *tas = snd_kcontrol_chip(kcontrol); | 448 | struct tas *tas = snd_kcontrol_chip(kcontrol); |
449 | 449 | ||
450 | mutex_lock(&tas->mtx); | 450 | mutex_lock(&tas->mtx); |
451 | ucontrol->value.integer.value[0] = tas->drc_enabled; | 451 | ucontrol->value.integer.value[0] = tas->drc_enabled; |
452 | mutex_unlock(&tas->mtx); | 452 | mutex_unlock(&tas->mtx); |
453 | return 0; | 453 | return 0; |
454 | } | 454 | } |
455 | 455 | ||
456 | static int tas_snd_drc_switch_put(struct snd_kcontrol *kcontrol, | 456 | static int tas_snd_drc_switch_put(struct snd_kcontrol *kcontrol, |
457 | struct snd_ctl_elem_value *ucontrol) | 457 | struct snd_ctl_elem_value *ucontrol) |
458 | { | 458 | { |
459 | struct tas *tas = snd_kcontrol_chip(kcontrol); | 459 | struct tas *tas = snd_kcontrol_chip(kcontrol); |
460 | 460 | ||
461 | mutex_lock(&tas->mtx); | 461 | mutex_lock(&tas->mtx); |
462 | if (tas->drc_enabled == ucontrol->value.integer.value[0]) { | 462 | if (tas->drc_enabled == ucontrol->value.integer.value[0]) { |
463 | mutex_unlock(&tas->mtx); | 463 | mutex_unlock(&tas->mtx); |
464 | return 0; | 464 | return 0; |
465 | } | 465 | } |
466 | 466 | ||
467 | tas->drc_enabled = ucontrol->value.integer.value[0]; | 467 | tas->drc_enabled = ucontrol->value.integer.value[0]; |
468 | if (tas->hw_enabled) | 468 | if (tas->hw_enabled) |
469 | tas3004_set_drc(tas); | 469 | tas3004_set_drc(tas); |
470 | mutex_unlock(&tas->mtx); | 470 | mutex_unlock(&tas->mtx); |
471 | return 1; | 471 | return 1; |
472 | } | 472 | } |
473 | 473 | ||
474 | static struct snd_kcontrol_new drc_switch_control = { | 474 | static struct snd_kcontrol_new drc_switch_control = { |
475 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 475 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
476 | .name = "DRC Range Switch", | 476 | .name = "DRC Range Switch", |
477 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | 477 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, |
478 | .info = tas_snd_drc_switch_info, | 478 | .info = tas_snd_drc_switch_info, |
479 | .get = tas_snd_drc_switch_get, | 479 | .get = tas_snd_drc_switch_get, |
480 | .put = tas_snd_drc_switch_put, | 480 | .put = tas_snd_drc_switch_put, |
481 | }; | 481 | }; |
482 | 482 | ||
483 | static int tas_snd_capture_source_info(struct snd_kcontrol *kcontrol, | 483 | static int tas_snd_capture_source_info(struct snd_kcontrol *kcontrol, |
484 | struct snd_ctl_elem_info *uinfo) | 484 | struct snd_ctl_elem_info *uinfo) |
485 | { | 485 | { |
486 | static char *texts[] = { "Line-In", "Microphone" }; | 486 | static char *texts[] = { "Line-In", "Microphone" }; |
487 | 487 | ||
488 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 488 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
489 | uinfo->count = 1; | 489 | uinfo->count = 1; |
490 | uinfo->value.enumerated.items = 2; | 490 | uinfo->value.enumerated.items = 2; |
491 | if (uinfo->value.enumerated.item > 1) | 491 | if (uinfo->value.enumerated.item > 1) |
492 | uinfo->value.enumerated.item = 1; | 492 | uinfo->value.enumerated.item = 1; |
493 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | 493 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); |
494 | return 0; | 494 | return 0; |
495 | } | 495 | } |
496 | 496 | ||
497 | static int tas_snd_capture_source_get(struct snd_kcontrol *kcontrol, | 497 | static int tas_snd_capture_source_get(struct snd_kcontrol *kcontrol, |
498 | struct snd_ctl_elem_value *ucontrol) | 498 | struct snd_ctl_elem_value *ucontrol) |
499 | { | 499 | { |
500 | struct tas *tas = snd_kcontrol_chip(kcontrol); | 500 | struct tas *tas = snd_kcontrol_chip(kcontrol); |
501 | 501 | ||
502 | mutex_lock(&tas->mtx); | 502 | mutex_lock(&tas->mtx); |
503 | ucontrol->value.enumerated.item[0] = !!(tas->acr & TAS_ACR_INPUT_B); | 503 | ucontrol->value.enumerated.item[0] = !!(tas->acr & TAS_ACR_INPUT_B); |
504 | mutex_unlock(&tas->mtx); | 504 | mutex_unlock(&tas->mtx); |
505 | return 0; | 505 | return 0; |
506 | } | 506 | } |
507 | 507 | ||
508 | static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol, | 508 | static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol, |
509 | struct snd_ctl_elem_value *ucontrol) | 509 | struct snd_ctl_elem_value *ucontrol) |
510 | { | 510 | { |
511 | struct tas *tas = snd_kcontrol_chip(kcontrol); | 511 | struct tas *tas = snd_kcontrol_chip(kcontrol); |
512 | int oldacr; | 512 | int oldacr; |
513 | 513 | ||
514 | mutex_lock(&tas->mtx); | 514 | mutex_lock(&tas->mtx); |
515 | oldacr = tas->acr; | 515 | oldacr = tas->acr; |
516 | 516 | ||
517 | tas->acr &= ~TAS_ACR_INPUT_B; | 517 | /* |
518 | * Despite what the data sheet says in one place, the | ||
519 | * TAS_ACR_B_MONAUREAL bit forces mono output even when | ||
520 | * input A (line in) is selected. | ||
521 | */ | ||
522 | tas->acr &= ~(TAS_ACR_INPUT_B | TAS_ACR_B_MONAUREAL); | ||
518 | if (ucontrol->value.enumerated.item[0]) | 523 | if (ucontrol->value.enumerated.item[0]) |
519 | tas->acr |= TAS_ACR_INPUT_B; | 524 | tas->acr |= TAS_ACR_INPUT_B | TAS_ACR_B_MONAUREAL | |
525 | TAS_ACR_B_MON_SEL_RIGHT; | ||
520 | if (oldacr == tas->acr) { | 526 | if (oldacr == tas->acr) { |
521 | mutex_unlock(&tas->mtx); | 527 | mutex_unlock(&tas->mtx); |
522 | return 0; | 528 | return 0; |
523 | } | 529 | } |
524 | if (tas->hw_enabled) | 530 | if (tas->hw_enabled) |
525 | tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); | 531 | tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); |
526 | mutex_unlock(&tas->mtx); | 532 | mutex_unlock(&tas->mtx); |
527 | return 1; | 533 | return 1; |
528 | } | 534 | } |
529 | 535 | ||
530 | static struct snd_kcontrol_new capture_source_control = { | 536 | static struct snd_kcontrol_new capture_source_control = { |
531 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 537 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
532 | /* If we name this 'Input Source', it properly shows up in | 538 | /* If we name this 'Input Source', it properly shows up in |
533 | * alsamixer as a selection, * but it's shown under the | 539 | * alsamixer as a selection, * but it's shown under the |
534 | * 'Playback' category. | 540 | * 'Playback' category. |
535 | * If I name it 'Capture Source', it shows up in strange | 541 | * If I name it 'Capture Source', it shows up in strange |
536 | * ways (two bools of which one can be selected at a | 542 | * ways (two bools of which one can be selected at a |
537 | * time) but at least it's shown in the 'Capture' | 543 | * time) but at least it's shown in the 'Capture' |
538 | * category. | 544 | * category. |
539 | * I was told that this was due to backward compatibility, | 545 | * I was told that this was due to backward compatibility, |
540 | * but I don't understand then why the mangling is *not* | 546 | * but I don't understand then why the mangling is *not* |
541 | * done when I name it "Input Source"..... | 547 | * done when I name it "Input Source"..... |
542 | */ | 548 | */ |
543 | .name = "Capture Source", | 549 | .name = "Capture Source", |
544 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | 550 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, |
545 | .info = tas_snd_capture_source_info, | 551 | .info = tas_snd_capture_source_info, |
546 | .get = tas_snd_capture_source_get, | 552 | .get = tas_snd_capture_source_get, |
547 | .put = tas_snd_capture_source_put, | 553 | .put = tas_snd_capture_source_put, |
548 | }; | 554 | }; |
549 | 555 | ||
550 | static int tas_snd_treble_info(struct snd_kcontrol *kcontrol, | 556 | static int tas_snd_treble_info(struct snd_kcontrol *kcontrol, |
551 | struct snd_ctl_elem_info *uinfo) | 557 | struct snd_ctl_elem_info *uinfo) |
552 | { | 558 | { |
553 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 559 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
554 | uinfo->count = 1; | 560 | uinfo->count = 1; |
555 | uinfo->value.integer.min = TAS3004_TREBLE_MIN; | 561 | uinfo->value.integer.min = TAS3004_TREBLE_MIN; |
556 | uinfo->value.integer.max = TAS3004_TREBLE_MAX; | 562 | uinfo->value.integer.max = TAS3004_TREBLE_MAX; |
557 | return 0; | 563 | return 0; |
558 | } | 564 | } |
559 | 565 | ||
560 | static int tas_snd_treble_get(struct snd_kcontrol *kcontrol, | 566 | static int tas_snd_treble_get(struct snd_kcontrol *kcontrol, |
561 | struct snd_ctl_elem_value *ucontrol) | 567 | struct snd_ctl_elem_value *ucontrol) |
562 | { | 568 | { |
563 | struct tas *tas = snd_kcontrol_chip(kcontrol); | 569 | struct tas *tas = snd_kcontrol_chip(kcontrol); |
564 | 570 | ||
565 | mutex_lock(&tas->mtx); | 571 | mutex_lock(&tas->mtx); |
566 | ucontrol->value.integer.value[0] = tas->treble; | 572 | ucontrol->value.integer.value[0] = tas->treble; |
567 | mutex_unlock(&tas->mtx); | 573 | mutex_unlock(&tas->mtx); |
568 | return 0; | 574 | return 0; |
569 | } | 575 | } |
570 | 576 | ||
571 | static int tas_snd_treble_put(struct snd_kcontrol *kcontrol, | 577 | static int tas_snd_treble_put(struct snd_kcontrol *kcontrol, |
572 | struct snd_ctl_elem_value *ucontrol) | 578 | struct snd_ctl_elem_value *ucontrol) |
573 | { | 579 | { |
574 | struct tas *tas = snd_kcontrol_chip(kcontrol); | 580 | struct tas *tas = snd_kcontrol_chip(kcontrol); |
575 | 581 | ||
576 | mutex_lock(&tas->mtx); | 582 | mutex_lock(&tas->mtx); |
577 | if (tas->treble == ucontrol->value.integer.value[0]) { | 583 | if (tas->treble == ucontrol->value.integer.value[0]) { |
578 | mutex_unlock(&tas->mtx); | 584 | mutex_unlock(&tas->mtx); |
579 | return 0; | 585 | return 0; |
580 | } | 586 | } |
581 | 587 | ||
582 | tas->treble = ucontrol->value.integer.value[0]; | 588 | tas->treble = ucontrol->value.integer.value[0]; |
583 | if (tas->hw_enabled) | 589 | if (tas->hw_enabled) |
584 | tas_set_treble(tas); | 590 | tas_set_treble(tas); |
585 | mutex_unlock(&tas->mtx); | 591 | mutex_unlock(&tas->mtx); |
586 | return 1; | 592 | return 1; |
587 | } | 593 | } |
588 | 594 | ||
589 | static struct snd_kcontrol_new treble_control = { | 595 | static struct snd_kcontrol_new treble_control = { |
590 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 596 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
591 | .name = "Treble", | 597 | .name = "Treble", |
592 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | 598 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, |
593 | .info = tas_snd_treble_info, | 599 | .info = tas_snd_treble_info, |
594 | .get = tas_snd_treble_get, | 600 | .get = tas_snd_treble_get, |
595 | .put = tas_snd_treble_put, | 601 | .put = tas_snd_treble_put, |
596 | }; | 602 | }; |
597 | 603 | ||
598 | static int tas_snd_bass_info(struct snd_kcontrol *kcontrol, | 604 | static int tas_snd_bass_info(struct snd_kcontrol *kcontrol, |
599 | struct snd_ctl_elem_info *uinfo) | 605 | struct snd_ctl_elem_info *uinfo) |
600 | { | 606 | { |
601 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 607 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
602 | uinfo->count = 1; | 608 | uinfo->count = 1; |
603 | uinfo->value.integer.min = TAS3004_BASS_MIN; | 609 | uinfo->value.integer.min = TAS3004_BASS_MIN; |
604 | uinfo->value.integer.max = TAS3004_BASS_MAX; | 610 | uinfo->value.integer.max = TAS3004_BASS_MAX; |
605 | return 0; | 611 | return 0; |
606 | } | 612 | } |
607 | 613 | ||
608 | static int tas_snd_bass_get(struct snd_kcontrol *kcontrol, | 614 | static int tas_snd_bass_get(struct snd_kcontrol *kcontrol, |
609 | struct snd_ctl_elem_value *ucontrol) | 615 | struct snd_ctl_elem_value *ucontrol) |
610 | { | 616 | { |
611 | struct tas *tas = snd_kcontrol_chip(kcontrol); | 617 | struct tas *tas = snd_kcontrol_chip(kcontrol); |
612 | 618 | ||
613 | mutex_lock(&tas->mtx); | 619 | mutex_lock(&tas->mtx); |
614 | ucontrol->value.integer.value[0] = tas->bass; | 620 | ucontrol->value.integer.value[0] = tas->bass; |
615 | mutex_unlock(&tas->mtx); | 621 | mutex_unlock(&tas->mtx); |
616 | return 0; | 622 | return 0; |
617 | } | 623 | } |
618 | 624 | ||
619 | static int tas_snd_bass_put(struct snd_kcontrol *kcontrol, | 625 | static int tas_snd_bass_put(struct snd_kcontrol *kcontrol, |
620 | struct snd_ctl_elem_value *ucontrol) | 626 | struct snd_ctl_elem_value *ucontrol) |
621 | { | 627 | { |
622 | struct tas *tas = snd_kcontrol_chip(kcontrol); | 628 | struct tas *tas = snd_kcontrol_chip(kcontrol); |
623 | 629 | ||
624 | mutex_lock(&tas->mtx); | 630 | mutex_lock(&tas->mtx); |
625 | if (tas->bass == ucontrol->value.integer.value[0]) { | 631 | if (tas->bass == ucontrol->value.integer.value[0]) { |
626 | mutex_unlock(&tas->mtx); | 632 | mutex_unlock(&tas->mtx); |
627 | return 0; | 633 | return 0; |
628 | } | 634 | } |
629 | 635 | ||
630 | tas->bass = ucontrol->value.integer.value[0]; | 636 | tas->bass = ucontrol->value.integer.value[0]; |
631 | if (tas->hw_enabled) | 637 | if (tas->hw_enabled) |
632 | tas_set_bass(tas); | 638 | tas_set_bass(tas); |
633 | mutex_unlock(&tas->mtx); | 639 | mutex_unlock(&tas->mtx); |
634 | return 1; | 640 | return 1; |
635 | } | 641 | } |
636 | 642 | ||
637 | static struct snd_kcontrol_new bass_control = { | 643 | static struct snd_kcontrol_new bass_control = { |
638 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 644 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
639 | .name = "Bass", | 645 | .name = "Bass", |
640 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | 646 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, |
641 | .info = tas_snd_bass_info, | 647 | .info = tas_snd_bass_info, |
642 | .get = tas_snd_bass_get, | 648 | .get = tas_snd_bass_get, |
643 | .put = tas_snd_bass_put, | 649 | .put = tas_snd_bass_put, |
644 | }; | 650 | }; |
645 | 651 | ||
646 | static struct transfer_info tas_transfers[] = { | 652 | static struct transfer_info tas_transfers[] = { |
647 | { | 653 | { |
648 | /* input */ | 654 | /* input */ |
649 | .formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S16_BE | | 655 | .formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S16_BE | |
650 | SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S24_BE, | 656 | SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S24_BE, |
651 | .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, | 657 | .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, |
652 | .transfer_in = 1, | 658 | .transfer_in = 1, |
653 | }, | 659 | }, |
654 | { | 660 | { |
655 | /* output */ | 661 | /* output */ |
656 | .formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S16_BE | | 662 | .formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S16_BE | |
657 | SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S24_BE, | 663 | SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S24_BE, |
658 | .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, | 664 | .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, |
659 | .transfer_in = 0, | 665 | .transfer_in = 0, |
660 | }, | 666 | }, |
661 | {} | 667 | {} |
662 | }; | 668 | }; |
663 | 669 | ||
664 | static int tas_usable(struct codec_info_item *cii, | 670 | static int tas_usable(struct codec_info_item *cii, |
665 | struct transfer_info *ti, | 671 | struct transfer_info *ti, |
666 | struct transfer_info *out) | 672 | struct transfer_info *out) |
667 | { | 673 | { |
668 | return 1; | 674 | return 1; |
669 | } | 675 | } |
670 | 676 | ||
671 | static int tas_reset_init(struct tas *tas) | 677 | static int tas_reset_init(struct tas *tas) |
672 | { | 678 | { |
673 | u8 tmp; | 679 | u8 tmp; |
674 | 680 | ||
675 | tas->codec.gpio->methods->all_amps_off(tas->codec.gpio); | 681 | tas->codec.gpio->methods->all_amps_off(tas->codec.gpio); |
676 | msleep(5); | 682 | msleep(5); |
677 | tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0); | 683 | tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0); |
678 | msleep(5); | 684 | msleep(5); |
679 | tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 1); | 685 | tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 1); |
680 | msleep(20); | 686 | msleep(20); |
681 | tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0); | 687 | tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0); |
682 | msleep(10); | 688 | msleep(10); |
683 | tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio); | 689 | tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio); |
684 | 690 | ||
685 | tmp = TAS_MCS_SCLK64 | TAS_MCS_SPORT_MODE_I2S | TAS_MCS_SPORT_WL_24BIT; | 691 | tmp = TAS_MCS_SCLK64 | TAS_MCS_SPORT_MODE_I2S | TAS_MCS_SPORT_WL_24BIT; |
686 | if (tas_write_reg(tas, TAS_REG_MCS, 1, &tmp)) | 692 | if (tas_write_reg(tas, TAS_REG_MCS, 1, &tmp)) |
687 | goto outerr; | 693 | goto outerr; |
688 | 694 | ||
689 | tas->acr |= TAS_ACR_ANALOG_PDOWN | TAS_ACR_B_MONAUREAL | | 695 | tas->acr |= TAS_ACR_ANALOG_PDOWN; |
690 | TAS_ACR_B_MON_SEL_RIGHT; | ||
691 | if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr)) | 696 | if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr)) |
692 | goto outerr; | 697 | goto outerr; |
693 | 698 | ||
694 | tmp = 0; | 699 | tmp = 0; |
695 | if (tas_write_reg(tas, TAS_REG_MCS2, 1, &tmp)) | 700 | if (tas_write_reg(tas, TAS_REG_MCS2, 1, &tmp)) |
696 | goto outerr; | 701 | goto outerr; |
697 | 702 | ||
698 | tas3004_set_drc(tas); | 703 | tas3004_set_drc(tas); |
699 | 704 | ||
700 | /* Set treble & bass to 0dB */ | 705 | /* Set treble & bass to 0dB */ |
701 | tas->treble = TAS3004_TREBLE_ZERO; | 706 | tas->treble = TAS3004_TREBLE_ZERO; |
702 | tas->bass = TAS3004_BASS_ZERO; | 707 | tas->bass = TAS3004_BASS_ZERO; |
703 | tas_set_treble(tas); | 708 | tas_set_treble(tas); |
704 | tas_set_bass(tas); | 709 | tas_set_bass(tas); |
705 | 710 | ||
706 | tas->acr &= ~TAS_ACR_ANALOG_PDOWN; | 711 | tas->acr &= ~TAS_ACR_ANALOG_PDOWN; |
707 | if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr)) | 712 | if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr)) |
708 | goto outerr; | 713 | goto outerr; |
709 | 714 | ||
710 | return 0; | 715 | return 0; |
711 | outerr: | 716 | outerr: |
712 | return -ENODEV; | 717 | return -ENODEV; |
713 | } | 718 | } |
714 | 719 | ||
715 | static int tas_switch_clock(struct codec_info_item *cii, enum clock_switch clock) | 720 | static int tas_switch_clock(struct codec_info_item *cii, enum clock_switch clock) |
716 | { | 721 | { |
717 | struct tas *tas = cii->codec_data; | 722 | struct tas *tas = cii->codec_data; |
718 | 723 | ||
719 | switch(clock) { | 724 | switch(clock) { |
720 | case CLOCK_SWITCH_PREPARE_SLAVE: | 725 | case CLOCK_SWITCH_PREPARE_SLAVE: |
721 | /* Clocks are going away, mute mute mute */ | 726 | /* Clocks are going away, mute mute mute */ |
722 | tas->codec.gpio->methods->all_amps_off(tas->codec.gpio); | 727 | tas->codec.gpio->methods->all_amps_off(tas->codec.gpio); |
723 | tas->hw_enabled = 0; | 728 | tas->hw_enabled = 0; |
724 | break; | 729 | break; |
725 | case CLOCK_SWITCH_SLAVE: | 730 | case CLOCK_SWITCH_SLAVE: |
726 | /* Clocks are back, re-init the codec */ | 731 | /* Clocks are back, re-init the codec */ |
727 | mutex_lock(&tas->mtx); | 732 | mutex_lock(&tas->mtx); |
728 | tas_reset_init(tas); | 733 | tas_reset_init(tas); |
729 | tas_set_volume(tas); | 734 | tas_set_volume(tas); |
730 | tas_set_mixer(tas); | 735 | tas_set_mixer(tas); |
731 | tas->hw_enabled = 1; | 736 | tas->hw_enabled = 1; |
732 | tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio); | 737 | tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio); |
733 | mutex_unlock(&tas->mtx); | 738 | mutex_unlock(&tas->mtx); |
734 | break; | 739 | break; |
735 | default: | 740 | default: |
736 | /* doesn't happen as of now */ | 741 | /* doesn't happen as of now */ |
737 | return -EINVAL; | 742 | return -EINVAL; |
738 | } | 743 | } |
739 | return 0; | 744 | return 0; |
740 | } | 745 | } |
741 | 746 | ||
742 | /* we are controlled via i2c and assume that is always up | 747 | /* we are controlled via i2c and assume that is always up |
743 | * If that wasn't the case, we'd have to suspend once | 748 | * If that wasn't the case, we'd have to suspend once |
744 | * our i2c device is suspended, and then take note of that! */ | 749 | * our i2c device is suspended, and then take note of that! */ |
745 | static int tas_suspend(struct tas *tas) | 750 | static int tas_suspend(struct tas *tas) |
746 | { | 751 | { |
747 | mutex_lock(&tas->mtx); | 752 | mutex_lock(&tas->mtx); |
748 | tas->hw_enabled = 0; | 753 | tas->hw_enabled = 0; |
749 | tas->acr |= TAS_ACR_ANALOG_PDOWN; | 754 | tas->acr |= TAS_ACR_ANALOG_PDOWN; |
750 | tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); | 755 | tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); |
751 | mutex_unlock(&tas->mtx); | 756 | mutex_unlock(&tas->mtx); |
752 | return 0; | 757 | return 0; |
753 | } | 758 | } |
754 | 759 | ||
755 | static int tas_resume(struct tas *tas) | 760 | static int tas_resume(struct tas *tas) |
756 | { | 761 | { |
757 | /* reset codec */ | 762 | /* reset codec */ |
758 | mutex_lock(&tas->mtx); | 763 | mutex_lock(&tas->mtx); |
759 | tas_reset_init(tas); | 764 | tas_reset_init(tas); |
760 | tas_set_volume(tas); | 765 | tas_set_volume(tas); |
761 | tas_set_mixer(tas); | 766 | tas_set_mixer(tas); |
762 | tas->hw_enabled = 1; | 767 | tas->hw_enabled = 1; |
763 | mutex_unlock(&tas->mtx); | 768 | mutex_unlock(&tas->mtx); |
764 | return 0; | 769 | return 0; |
765 | } | 770 | } |
766 | 771 | ||
767 | #ifdef CONFIG_PM | 772 | #ifdef CONFIG_PM |
768 | static int _tas_suspend(struct codec_info_item *cii, pm_message_t state) | 773 | static int _tas_suspend(struct codec_info_item *cii, pm_message_t state) |
769 | { | 774 | { |
770 | return tas_suspend(cii->codec_data); | 775 | return tas_suspend(cii->codec_data); |
771 | } | 776 | } |
772 | 777 | ||
773 | static int _tas_resume(struct codec_info_item *cii) | 778 | static int _tas_resume(struct codec_info_item *cii) |
774 | { | 779 | { |
775 | return tas_resume(cii->codec_data); | 780 | return tas_resume(cii->codec_data); |
776 | } | 781 | } |
777 | #endif | 782 | #endif |
778 | 783 | ||
779 | static struct codec_info tas_codec_info = { | 784 | static struct codec_info tas_codec_info = { |
780 | .transfers = tas_transfers, | 785 | .transfers = tas_transfers, |
781 | /* in theory, we can drive it at 512 too... | 786 | /* in theory, we can drive it at 512 too... |
782 | * but so far the framework doesn't allow | 787 | * but so far the framework doesn't allow |
783 | * for that and I don't see much point in it. */ | 788 | * for that and I don't see much point in it. */ |
784 | .sysclock_factor = 256, | 789 | .sysclock_factor = 256, |
785 | /* same here, could be 32 for just one 16 bit format */ | 790 | /* same here, could be 32 for just one 16 bit format */ |
786 | .bus_factor = 64, | 791 | .bus_factor = 64, |
787 | .owner = THIS_MODULE, | 792 | .owner = THIS_MODULE, |
788 | .usable = tas_usable, | 793 | .usable = tas_usable, |
789 | .switch_clock = tas_switch_clock, | 794 | .switch_clock = tas_switch_clock, |
790 | #ifdef CONFIG_PM | 795 | #ifdef CONFIG_PM |
791 | .suspend = _tas_suspend, | 796 | .suspend = _tas_suspend, |
792 | .resume = _tas_resume, | 797 | .resume = _tas_resume, |
793 | #endif | 798 | #endif |
794 | }; | 799 | }; |
795 | 800 | ||
796 | static int tas_init_codec(struct aoa_codec *codec) | 801 | static int tas_init_codec(struct aoa_codec *codec) |
797 | { | 802 | { |
798 | struct tas *tas = codec_to_tas(codec); | 803 | struct tas *tas = codec_to_tas(codec); |
799 | int err; | 804 | int err; |
800 | 805 | ||
801 | if (!tas->codec.gpio || !tas->codec.gpio->methods) { | 806 | if (!tas->codec.gpio || !tas->codec.gpio->methods) { |
802 | printk(KERN_ERR PFX "gpios not assigned!!\n"); | 807 | printk(KERN_ERR PFX "gpios not assigned!!\n"); |
803 | return -EINVAL; | 808 | return -EINVAL; |
804 | } | 809 | } |
805 | 810 | ||
806 | mutex_lock(&tas->mtx); | 811 | mutex_lock(&tas->mtx); |
807 | if (tas_reset_init(tas)) { | 812 | if (tas_reset_init(tas)) { |
808 | printk(KERN_ERR PFX "tas failed to initialise\n"); | 813 | printk(KERN_ERR PFX "tas failed to initialise\n"); |
809 | mutex_unlock(&tas->mtx); | 814 | mutex_unlock(&tas->mtx); |
810 | return -ENXIO; | 815 | return -ENXIO; |
811 | } | 816 | } |
812 | tas->hw_enabled = 1; | 817 | tas->hw_enabled = 1; |
813 | mutex_unlock(&tas->mtx); | 818 | mutex_unlock(&tas->mtx); |
814 | 819 | ||
815 | if (tas->codec.soundbus_dev->attach_codec(tas->codec.soundbus_dev, | 820 | if (tas->codec.soundbus_dev->attach_codec(tas->codec.soundbus_dev, |
816 | aoa_get_card(), | 821 | aoa_get_card(), |
817 | &tas_codec_info, tas)) { | 822 | &tas_codec_info, tas)) { |
818 | printk(KERN_ERR PFX "error attaching tas to soundbus\n"); | 823 | printk(KERN_ERR PFX "error attaching tas to soundbus\n"); |
819 | return -ENODEV; | 824 | return -ENODEV; |
820 | } | 825 | } |
821 | 826 | ||
822 | if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, tas, &ops)) { | 827 | if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, tas, &ops)) { |
823 | printk(KERN_ERR PFX "failed to create tas snd device!\n"); | 828 | printk(KERN_ERR PFX "failed to create tas snd device!\n"); |
824 | return -ENODEV; | 829 | return -ENODEV; |
825 | } | 830 | } |
826 | err = aoa_snd_ctl_add(snd_ctl_new1(&volume_control, tas)); | 831 | err = aoa_snd_ctl_add(snd_ctl_new1(&volume_control, tas)); |
827 | if (err) | 832 | if (err) |
828 | goto error; | 833 | goto error; |
829 | 834 | ||
830 | err = aoa_snd_ctl_add(snd_ctl_new1(&mute_control, tas)); | 835 | err = aoa_snd_ctl_add(snd_ctl_new1(&mute_control, tas)); |
831 | if (err) | 836 | if (err) |
832 | goto error; | 837 | goto error; |
833 | 838 | ||
834 | err = aoa_snd_ctl_add(snd_ctl_new1(&pcm1_control, tas)); | 839 | err = aoa_snd_ctl_add(snd_ctl_new1(&pcm1_control, tas)); |
835 | if (err) | 840 | if (err) |
836 | goto error; | 841 | goto error; |
837 | 842 | ||
838 | err = aoa_snd_ctl_add(snd_ctl_new1(&monitor_control, tas)); | 843 | err = aoa_snd_ctl_add(snd_ctl_new1(&monitor_control, tas)); |
839 | if (err) | 844 | if (err) |
840 | goto error; | 845 | goto error; |
841 | 846 | ||
842 | err = aoa_snd_ctl_add(snd_ctl_new1(&capture_source_control, tas)); | 847 | err = aoa_snd_ctl_add(snd_ctl_new1(&capture_source_control, tas)); |
843 | if (err) | 848 | if (err) |
844 | goto error; | 849 | goto error; |
845 | 850 | ||
846 | err = aoa_snd_ctl_add(snd_ctl_new1(&drc_range_control, tas)); | 851 | err = aoa_snd_ctl_add(snd_ctl_new1(&drc_range_control, tas)); |
847 | if (err) | 852 | if (err) |
848 | goto error; | 853 | goto error; |
849 | 854 | ||
850 | err = aoa_snd_ctl_add(snd_ctl_new1(&drc_switch_control, tas)); | 855 | err = aoa_snd_ctl_add(snd_ctl_new1(&drc_switch_control, tas)); |
851 | if (err) | 856 | if (err) |
852 | goto error; | 857 | goto error; |
853 | 858 | ||
854 | err = aoa_snd_ctl_add(snd_ctl_new1(&treble_control, tas)); | 859 | err = aoa_snd_ctl_add(snd_ctl_new1(&treble_control, tas)); |
855 | if (err) | 860 | if (err) |
856 | goto error; | 861 | goto error; |
857 | 862 | ||
858 | err = aoa_snd_ctl_add(snd_ctl_new1(&bass_control, tas)); | 863 | err = aoa_snd_ctl_add(snd_ctl_new1(&bass_control, tas)); |
859 | if (err) | 864 | if (err) |
860 | goto error; | 865 | goto error; |
861 | 866 | ||
862 | return 0; | 867 | return 0; |
863 | error: | 868 | error: |
864 | tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas); | 869 | tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas); |
865 | snd_device_free(aoa_get_card(), tas); | 870 | snd_device_free(aoa_get_card(), tas); |
866 | return err; | 871 | return err; |
867 | } | 872 | } |
868 | 873 | ||
869 | static void tas_exit_codec(struct aoa_codec *codec) | 874 | static void tas_exit_codec(struct aoa_codec *codec) |
870 | { | 875 | { |
871 | struct tas *tas = codec_to_tas(codec); | 876 | struct tas *tas = codec_to_tas(codec); |
872 | 877 | ||
873 | if (!tas->codec.soundbus_dev) | 878 | if (!tas->codec.soundbus_dev) |
874 | return; | 879 | return; |
875 | tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas); | 880 | tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas); |
876 | } | 881 | } |
877 | 882 | ||
878 | 883 | ||
879 | static struct i2c_driver tas_driver; | 884 | static struct i2c_driver tas_driver; |
880 | 885 | ||
881 | static int tas_create(struct i2c_adapter *adapter, | 886 | static int tas_create(struct i2c_adapter *adapter, |
882 | struct device_node *node, | 887 | struct device_node *node, |
883 | int addr) | 888 | int addr) |
884 | { | 889 | { |
885 | struct tas *tas; | 890 | struct tas *tas; |
886 | 891 | ||
887 | tas = kzalloc(sizeof(struct tas), GFP_KERNEL); | 892 | tas = kzalloc(sizeof(struct tas), GFP_KERNEL); |
888 | 893 | ||
889 | if (!tas) | 894 | if (!tas) |
890 | return -ENOMEM; | 895 | return -ENOMEM; |
891 | 896 | ||
892 | mutex_init(&tas->mtx); | 897 | mutex_init(&tas->mtx); |
893 | tas->i2c.driver = &tas_driver; | 898 | tas->i2c.driver = &tas_driver; |
894 | tas->i2c.adapter = adapter; | 899 | tas->i2c.adapter = adapter; |
895 | tas->i2c.addr = addr; | 900 | tas->i2c.addr = addr; |
896 | /* seems that half is a saner default */ | 901 | /* seems that half is a saner default */ |
897 | tas->drc_range = TAS3004_DRC_MAX / 2; | 902 | tas->drc_range = TAS3004_DRC_MAX / 2; |
898 | strlcpy(tas->i2c.name, "tas audio codec", I2C_NAME_SIZE-1); | 903 | strlcpy(tas->i2c.name, "tas audio codec", I2C_NAME_SIZE-1); |
899 | 904 | ||
900 | if (i2c_attach_client(&tas->i2c)) { | 905 | if (i2c_attach_client(&tas->i2c)) { |
901 | printk(KERN_ERR PFX "failed to attach to i2c\n"); | 906 | printk(KERN_ERR PFX "failed to attach to i2c\n"); |
902 | goto fail; | 907 | goto fail; |
903 | } | 908 | } |
904 | 909 | ||
905 | strlcpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN-1); | 910 | strlcpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN-1); |
906 | tas->codec.owner = THIS_MODULE; | 911 | tas->codec.owner = THIS_MODULE; |
907 | tas->codec.init = tas_init_codec; | 912 | tas->codec.init = tas_init_codec; |
908 | tas->codec.exit = tas_exit_codec; | 913 | tas->codec.exit = tas_exit_codec; |
909 | tas->codec.node = of_node_get(node); | 914 | tas->codec.node = of_node_get(node); |
910 | 915 | ||
911 | if (aoa_codec_register(&tas->codec)) { | 916 | if (aoa_codec_register(&tas->codec)) { |
912 | goto detach; | 917 | goto detach; |
913 | } | 918 | } |
914 | printk(KERN_DEBUG | 919 | printk(KERN_DEBUG |
915 | "snd-aoa-codec-tas: tas found, addr 0x%02x on %s\n", | 920 | "snd-aoa-codec-tas: tas found, addr 0x%02x on %s\n", |
916 | addr, node->full_name); | 921 | addr, node->full_name); |
917 | return 0; | 922 | return 0; |
918 | detach: | 923 | detach: |
919 | i2c_detach_client(&tas->i2c); | 924 | i2c_detach_client(&tas->i2c); |
920 | fail: | 925 | fail: |
921 | mutex_destroy(&tas->mtx); | 926 | mutex_destroy(&tas->mtx); |
922 | kfree(tas); | 927 | kfree(tas); |
923 | return -EINVAL; | 928 | return -EINVAL; |
924 | } | 929 | } |
925 | 930 | ||
926 | static int tas_i2c_attach(struct i2c_adapter *adapter) | 931 | static int tas_i2c_attach(struct i2c_adapter *adapter) |
927 | { | 932 | { |
928 | struct device_node *busnode, *dev = NULL; | 933 | struct device_node *busnode, *dev = NULL; |
929 | struct pmac_i2c_bus *bus; | 934 | struct pmac_i2c_bus *bus; |
930 | 935 | ||
931 | bus = pmac_i2c_adapter_to_bus(adapter); | 936 | bus = pmac_i2c_adapter_to_bus(adapter); |
932 | if (bus == NULL) | 937 | if (bus == NULL) |
933 | return -ENODEV; | 938 | return -ENODEV; |
934 | busnode = pmac_i2c_get_bus_node(bus); | 939 | busnode = pmac_i2c_get_bus_node(bus); |
935 | 940 | ||
936 | while ((dev = of_get_next_child(busnode, dev)) != NULL) { | 941 | while ((dev = of_get_next_child(busnode, dev)) != NULL) { |
937 | if (device_is_compatible(dev, "tas3004")) { | 942 | if (device_is_compatible(dev, "tas3004")) { |
938 | u32 *addr; | 943 | u32 *addr; |
939 | printk(KERN_DEBUG PFX "found tas3004\n"); | 944 | printk(KERN_DEBUG PFX "found tas3004\n"); |
940 | addr = (u32 *) get_property(dev, "reg", NULL); | 945 | addr = (u32 *) get_property(dev, "reg", NULL); |
941 | if (!addr) | 946 | if (!addr) |
942 | continue; | 947 | continue; |
943 | return tas_create(adapter, dev, ((*addr) >> 1) & 0x7f); | 948 | return tas_create(adapter, dev, ((*addr) >> 1) & 0x7f); |
944 | } | 949 | } |
945 | /* older machines have no 'codec' node with a 'compatible' | 950 | /* older machines have no 'codec' node with a 'compatible' |
946 | * property that says 'tas3004', they just have a 'deq' | 951 | * property that says 'tas3004', they just have a 'deq' |
947 | * node without any such property... */ | 952 | * node without any such property... */ |
948 | if (strcmp(dev->name, "deq") == 0) { | 953 | if (strcmp(dev->name, "deq") == 0) { |
949 | u32 *_addr, addr; | 954 | u32 *_addr, addr; |
950 | printk(KERN_DEBUG PFX "found 'deq' node\n"); | 955 | printk(KERN_DEBUG PFX "found 'deq' node\n"); |
951 | _addr = (u32 *) get_property(dev, "i2c-address", NULL); | 956 | _addr = (u32 *) get_property(dev, "i2c-address", NULL); |
952 | if (!_addr) | 957 | if (!_addr) |
953 | continue; | 958 | continue; |
954 | addr = ((*_addr) >> 1) & 0x7f; | 959 | addr = ((*_addr) >> 1) & 0x7f; |
955 | /* now, if the address doesn't match any of the two | 960 | /* now, if the address doesn't match any of the two |
956 | * that a tas3004 can have, we cannot handle this. | 961 | * that a tas3004 can have, we cannot handle this. |
957 | * I doubt it ever happens but hey. */ | 962 | * I doubt it ever happens but hey. */ |
958 | if (addr != 0x34 && addr != 0x35) | 963 | if (addr != 0x34 && addr != 0x35) |
959 | continue; | 964 | continue; |
960 | return tas_create(adapter, dev, addr); | 965 | return tas_create(adapter, dev, addr); |
961 | } | 966 | } |
962 | } | 967 | } |
963 | return -ENODEV; | 968 | return -ENODEV; |
964 | } | 969 | } |
965 | 970 | ||
966 | static int tas_i2c_detach(struct i2c_client *client) | 971 | static int tas_i2c_detach(struct i2c_client *client) |
967 | { | 972 | { |
968 | struct tas *tas = container_of(client, struct tas, i2c); | 973 | struct tas *tas = container_of(client, struct tas, i2c); |
969 | int err; | 974 | int err; |
970 | u8 tmp = TAS_ACR_ANALOG_PDOWN; | 975 | u8 tmp = TAS_ACR_ANALOG_PDOWN; |
971 | 976 | ||
972 | if ((err = i2c_detach_client(client))) | 977 | if ((err = i2c_detach_client(client))) |
973 | return err; | 978 | return err; |
974 | aoa_codec_unregister(&tas->codec); | 979 | aoa_codec_unregister(&tas->codec); |
975 | of_node_put(tas->codec.node); | 980 | of_node_put(tas->codec.node); |
976 | 981 | ||
977 | /* power down codec chip */ | 982 | /* power down codec chip */ |
978 | tas_write_reg(tas, TAS_REG_ACR, 1, &tmp); | 983 | tas_write_reg(tas, TAS_REG_ACR, 1, &tmp); |
979 | 984 | ||
980 | mutex_destroy(&tas->mtx); | 985 | mutex_destroy(&tas->mtx); |
981 | kfree(tas); | 986 | kfree(tas); |
982 | return 0; | 987 | return 0; |
983 | } | 988 | } |
984 | 989 | ||
985 | static struct i2c_driver tas_driver = { | 990 | static struct i2c_driver tas_driver = { |
986 | .driver = { | 991 | .driver = { |
987 | .name = "aoa_codec_tas", | 992 | .name = "aoa_codec_tas", |
988 | .owner = THIS_MODULE, | 993 | .owner = THIS_MODULE, |
989 | }, | 994 | }, |
990 | .attach_adapter = tas_i2c_attach, | 995 | .attach_adapter = tas_i2c_attach, |
991 | .detach_client = tas_i2c_detach, | 996 | .detach_client = tas_i2c_detach, |
992 | }; | 997 | }; |
993 | 998 | ||
994 | static int __init tas_init(void) | 999 | static int __init tas_init(void) |
995 | { | 1000 | { |
996 | return i2c_add_driver(&tas_driver); | 1001 | return i2c_add_driver(&tas_driver); |
997 | } | 1002 | } |
998 | 1003 | ||
999 | static void __exit tas_exit(void) | 1004 | static void __exit tas_exit(void) |
1000 | { | 1005 | { |
1001 | i2c_del_driver(&tas_driver); | 1006 | i2c_del_driver(&tas_driver); |
1002 | } | 1007 | } |
1003 | 1008 | ||
1004 | module_init(tas_init); | 1009 | module_init(tas_init); |
1005 | module_exit(tas_exit); | 1010 | module_exit(tas_exit); |