aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/ice1712
diff options
context:
space:
mode:
authorJochen Voss <voss@seehuhn.de>2006-10-04 12:08:43 -0400
committerJaroslav Kysela <perex@suse.cz>2007-02-09 03:00:05 -0500
commitfeaa6a74d852be40c0e717471aa92eead012052c (patch)
tree9ad326bb90037ebc10375e75f6b86c6ab74a0d2c /sound/pci/ice1712
parenta58e7cb16dfae8a3c1c98a7ab7ca02a9e9b38921 (diff)
[ALSA] Enable the analog loopback of the Revolution 5.1
Enable the analog loopback of the Revolution 5.1 card. This patch adds support for the PT2258 volume controller and modifies the Revolution 5.1 driver to make use of this facility. This allows to control the analog loopback of the card. Signed-off-by: Jochen Voss <voss@seehuhn.de> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/pci/ice1712')
-rw-r--r--sound/pci/ice1712/ice1712.h14
-rw-r--r--sound/pci/ice1712/revo.c132
-rw-r--r--sound/pci/ice1712/revo.h6
3 files changed, 140 insertions, 12 deletions
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
index ce27eac40d4e..064542bf3af8 100644
--- a/sound/pci/ice1712/ice1712.h
+++ b/sound/pci/ice1712/ice1712.h
@@ -28,6 +28,7 @@
28#include <sound/i2c.h> 28#include <sound/i2c.h>
29#include <sound/ak4xxx-adda.h> 29#include <sound/ak4xxx-adda.h>
30#include <sound/ak4114.h> 30#include <sound/ak4114.h>
31#include <sound/pt2258.h>
31#include <sound/pcm.h> 32#include <sound/pcm.h>
32#include <sound/mpu401.h> 33#include <sound/mpu401.h>
33 34
@@ -381,6 +382,11 @@ struct snd_ice1712 {
381 unsigned short master[2]; 382 unsigned short master[2];
382 unsigned short vol[8]; 383 unsigned short vol[8];
383 } phase28; 384 } phase28;
385 /* a non-standard I2C device for revo51 */
386 struct revo51_spec {
387 struct snd_i2c_device *dev;
388 struct snd_pt2258 *pt2258;
389 } revo51;
384 /* Hoontech-specific setting */ 390 /* Hoontech-specific setting */
385 struct hoontech_spec { 391 struct hoontech_spec {
386 unsigned char boxbits[4]; 392 unsigned char boxbits[4];
@@ -462,6 +468,14 @@ static inline void snd_ice1712_gpio_write_bits(struct snd_ice1712 *ice,
462 snd_ice1712_gpio_write(ice, mask & bits); 468 snd_ice1712_gpio_write(ice, mask & bits);
463} 469}
464 470
471static inline int snd_ice1712_gpio_read_bits(struct snd_ice1712 *ice,
472 unsigned int mask)
473{
474 ice->gpio.direction &= ~mask;
475 snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
476 return (snd_ice1712_gpio_read(ice) & mask);
477}
478
465int snd_ice1712_spdif_build_controls(struct snd_ice1712 *ice); 479int snd_ice1712_spdif_build_controls(struct snd_ice1712 *ice);
466 480
467int snd_ice1712_akm4xxx_init(struct snd_akm4xxx *ak, const struct snd_akm4xxx *template, 481int snd_ice1712_akm4xxx_init(struct snd_akm4xxx *ak, const struct snd_akm4xxx *template,
diff --git a/sound/pci/ice1712/revo.c b/sound/pci/ice1712/revo.c
index d556de59b9ae..233e9a5a2e70 100644
--- a/sound/pci/ice1712/revo.c
+++ b/sound/pci/ice1712/revo.c
@@ -84,6 +84,102 @@ static void revo_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
84} 84}
85 85
86/* 86/*
87 * I2C access to the PT2258 volume controller on GPIO 6/7 (Revolution 5.1)
88 */
89
90static void revo_i2c_start(struct snd_i2c_bus *bus)
91{
92 struct snd_ice1712 *ice = bus->private_data;
93 snd_ice1712_save_gpio_status(ice);
94}
95
96static void revo_i2c_stop(struct snd_i2c_bus *bus)
97{
98 struct snd_ice1712 *ice = bus->private_data;
99 snd_ice1712_restore_gpio_status(ice);
100}
101
102static void revo_i2c_direction(struct snd_i2c_bus *bus, int clock, int data)
103{
104 struct snd_ice1712 *ice = bus->private_data;
105 unsigned int mask, val;
106
107 val = 0;
108 if (clock)
109 val |= VT1724_REVO_I2C_CLOCK; /* write SCL */
110 if (data)
111 val |= VT1724_REVO_I2C_DATA; /* write SDA */
112 mask = VT1724_REVO_I2C_CLOCK | VT1724_REVO_I2C_DATA;
113 ice->gpio.direction &= ~mask;
114 ice->gpio.direction |= val;
115 snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
116 snd_ice1712_gpio_set_mask(ice, ~mask);
117}
118
119static void revo_i2c_setlines(struct snd_i2c_bus *bus, int clk, int data)
120{
121 struct snd_ice1712 *ice = bus->private_data;
122 unsigned int val = 0;
123
124 if (clk)
125 val |= VT1724_REVO_I2C_CLOCK;
126 if (data)
127 val |= VT1724_REVO_I2C_DATA;
128 snd_ice1712_gpio_write_bits(ice,
129 VT1724_REVO_I2C_DATA |
130 VT1724_REVO_I2C_CLOCK, val);
131 udelay(5);
132}
133
134static int revo_i2c_getdata(struct snd_i2c_bus *bus, int ack)
135{
136 struct snd_ice1712 *ice = bus->private_data;
137 int bit;
138
139 if (ack)
140 udelay(5);
141 bit = snd_ice1712_gpio_read_bits(ice, VT1724_REVO_I2C_DATA) ? 1 : 0;
142 return bit;
143}
144
145static struct snd_i2c_bit_ops revo51_bit_ops = {
146 .start = revo_i2c_start,
147 .stop = revo_i2c_stop,
148 .direction = revo_i2c_direction,
149 .setlines = revo_i2c_setlines,
150 .getdata = revo_i2c_getdata,
151};
152
153static int revo51_i2c_init(struct snd_ice1712 *ice,
154 struct snd_pt2258 *pt)
155{
156 int err;
157
158 /* create the I2C bus */
159 err = snd_i2c_bus_create(ice->card, "ICE1724 GPIO6", NULL, &ice->i2c);
160 if (err < 0)
161 return err;
162
163 ice->i2c->private_data = ice;
164 ice->i2c->hw_ops.bit = &revo51_bit_ops;
165
166 /* create the I2C device */
167 err = snd_i2c_device_create(ice->i2c, "PT2258", 0x40,
168 &ice->spec.revo51.dev);
169 if (err < 0)
170 return err;
171
172 pt->card = ice->card;
173 pt->i2c_bus = ice->i2c;
174 pt->i2c_dev = ice->spec.revo51.dev;
175 ice->spec.revo51.pt2258 = pt;
176
177 snd_pt2258_reset(pt);
178
179 return 0;
180}
181
182/*
87 * initialize the chips on M-Audio Revolution cards 183 * initialize the chips on M-Audio Revolution cards
88 */ 184 */
89 185
@@ -180,9 +276,9 @@ static struct snd_ak4xxx_private akm_revo51_priv __devinitdata = {
180 .cif = 0, 276 .cif = 0,
181 .data_mask = VT1724_REVO_CDOUT, 277 .data_mask = VT1724_REVO_CDOUT,
182 .clk_mask = VT1724_REVO_CCLK, 278 .clk_mask = VT1724_REVO_CCLK,
183 .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2, 279 .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1,
184 .cs_addr = VT1724_REVO_CS1 | VT1724_REVO_CS2, 280 .cs_addr = VT1724_REVO_CS1,
185 .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2, 281 .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1,
186 .add_flags = VT1724_REVO_CCLK, /* high at init */ 282 .add_flags = VT1724_REVO_CCLK, /* high at init */
187 .mask_flags = 0, 283 .mask_flags = 0,
188}; 284};
@@ -198,13 +294,15 @@ static struct snd_ak4xxx_private akm_revo51_adc_priv __devinitdata = {
198 .cif = 0, 294 .cif = 0,
199 .data_mask = VT1724_REVO_CDOUT, 295 .data_mask = VT1724_REVO_CDOUT,
200 .clk_mask = VT1724_REVO_CCLK, 296 .clk_mask = VT1724_REVO_CCLK,
201 .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2, 297 .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1,
202 .cs_addr = VT1724_REVO_CS0 | VT1724_REVO_CS2, 298 .cs_addr = VT1724_REVO_CS0,
203 .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2, 299 .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1,
204 .add_flags = VT1724_REVO_CCLK, /* high at init */ 300 .add_flags = VT1724_REVO_CCLK, /* high at init */
205 .mask_flags = 0, 301 .mask_flags = 0,
206}; 302};
207 303
304static struct snd_pt2258 ptc_revo51_volume;
305
208static int __devinit revo_init(struct snd_ice1712 *ice) 306static int __devinit revo_init(struct snd_ice1712 *ice)
209{ 307{
210 struct snd_akm4xxx *ak; 308 struct snd_akm4xxx *ak;
@@ -243,14 +341,20 @@ static int __devinit revo_init(struct snd_ice1712 *ice)
243 break; 341 break;
244 case VT1724_SUBDEVICE_REVOLUTION51: 342 case VT1724_SUBDEVICE_REVOLUTION51:
245 ice->akm_codecs = 2; 343 ice->akm_codecs = 2;
246 if ((err = snd_ice1712_akm4xxx_init(ak, &akm_revo51, &akm_revo51_priv, ice)) < 0) 344 err = snd_ice1712_akm4xxx_init(ak, &akm_revo51,
345 &akm_revo51_priv, ice);
346 if (err < 0)
247 return err; 347 return err;
248 err = snd_ice1712_akm4xxx_init(ak + 1, &akm_revo51_adc, 348 err = snd_ice1712_akm4xxx_init(ak+1, &akm_revo51_adc,
249 &akm_revo51_adc_priv, ice); 349 &akm_revo51_adc_priv, ice);
250 if (err < 0) 350 if (err < 0)
251 return err; 351 return err;
252 /* unmute all codecs - needed! */ 352 err = revo51_i2c_init(ice, &ptc_revo51_volume);
253 snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE, VT1724_REVO_MUTE); 353 if (err < 0)
354 return err;
355 /* unmute all codecs */
356 snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE,
357 VT1724_REVO_MUTE);
254 break; 358 break;
255 } 359 }
256 360
@@ -264,10 +368,18 @@ static int __devinit revo_add_controls(struct snd_ice1712 *ice)
264 368
265 switch (ice->eeprom.subvendor) { 369 switch (ice->eeprom.subvendor) {
266 case VT1724_SUBDEVICE_REVOLUTION71: 370 case VT1724_SUBDEVICE_REVOLUTION71:
371 err = snd_ice1712_akm4xxx_build_controls(ice);
372 if (err < 0)
373 return err;
374 break;
267 case VT1724_SUBDEVICE_REVOLUTION51: 375 case VT1724_SUBDEVICE_REVOLUTION51:
268 err = snd_ice1712_akm4xxx_build_controls(ice); 376 err = snd_ice1712_akm4xxx_build_controls(ice);
269 if (err < 0) 377 if (err < 0)
270 return err; 378 return err;
379 err = snd_pt2258_build_controls(ice->spec.revo51.pt2258);
380 if (err < 0)
381 return err;
382 break;
271 } 383 }
272 return 0; 384 return 0;
273} 385}
diff --git a/sound/pci/ice1712/revo.h b/sound/pci/ice1712/revo.h
index efbb86ec3289..c70adaf017c1 100644
--- a/sound/pci/ice1712/revo.h
+++ b/sound/pci/ice1712/revo.h
@@ -42,9 +42,11 @@ extern struct snd_ice1712_card_info snd_vt1724_revo_cards[];
42#define VT1724_REVO_CCLK 0x02 42#define VT1724_REVO_CCLK 0x02
43#define VT1724_REVO_CDIN 0x04 /* not used */ 43#define VT1724_REVO_CDIN 0x04 /* not used */
44#define VT1724_REVO_CDOUT 0x08 44#define VT1724_REVO_CDOUT 0x08
45#define VT1724_REVO_CS0 0x10 /* AK5365 chipselect for Rev. 5.1 */ 45#define VT1724_REVO_CS0 0x10 /* AK5365 chipselect for (revo51) */
46#define VT1724_REVO_CS1 0x20 /* front AKM4381 chipselect */ 46#define VT1724_REVO_CS1 0x20 /* front AKM4381 chipselect */
47#define VT1724_REVO_CS2 0x40 /* surround AKM4355 chipselect */ 47#define VT1724_REVO_CS2 0x40 /* surround AKM4355 CS (revo71) */
48#define VT1724_REVO_I2C_DATA 0x40 /* I2C: PT 2258 SDA (on revo51) */
49#define VT1724_REVO_I2C_CLOCK 0x80 /* I2C: PT 2258 SCL (on revo51) */
48#define VT1724_REVO_MUTE (1<<22) /* 0 = all mute, 1 = normal operation */ 50#define VT1724_REVO_MUTE (1<<22) /* 0 = all mute, 1 = normal operation */
49 51
50#endif /* __SOUND_REVO_H */ 52#endif /* __SOUND_REVO_H */