aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--include/sound/pt2258.h37
-rw-r--r--sound/i2c/Makefile1
-rw-r--r--sound/i2c/other/Makefile4
-rw-r--r--sound/i2c/other/pt2258.c233
-rw-r--r--sound/pci/ice1712/ice1712.h14
-rw-r--r--sound/pci/ice1712/revo.c132
-rw-r--r--sound/pci/ice1712/revo.h6
7 files changed, 413 insertions, 14 deletions
diff --git a/include/sound/pt2258.h b/include/sound/pt2258.h
new file mode 100644
index 000000000000..160f812faa42
--- /dev/null
+++ b/include/sound/pt2258.h
@@ -0,0 +1,37 @@
1/*
2 * ALSA Driver for the PT2258 volume controller.
3 *
4 * Copyright (c) 2006 Jochen Voss <voss@seehuhn.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#ifndef __SOUND_PT2258_H
23#define __SOUND_PT2258_H
24
25struct snd_pt2258 {
26 struct snd_card *card;
27 struct snd_i2c_bus *i2c_bus;
28 struct snd_i2c_device *i2c_dev;
29
30 unsigned char volume[6];
31 int mute;
32};
33
34extern int snd_pt2258_reset(struct snd_pt2258 *pt);
35extern int snd_pt2258_build_controls(struct snd_pt2258 *pt);
36
37#endif /* __SOUND_PT2258_H */
diff --git a/sound/i2c/Makefile b/sound/i2c/Makefile
index 816a2e7c88ca..45902d48c89c 100644
--- a/sound/i2c/Makefile
+++ b/sound/i2c/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_SND) += other/
16# Toplevel Module Dependency 16# Toplevel Module Dependency
17obj-$(CONFIG_SND_INTERWAVE_STB) += snd-tea6330t.o snd-i2c.o 17obj-$(CONFIG_SND_INTERWAVE_STB) += snd-tea6330t.o snd-i2c.o
18obj-$(CONFIG_SND_ICE1712) += snd-cs8427.o snd-i2c.o 18obj-$(CONFIG_SND_ICE1712) += snd-cs8427.o snd-i2c.o
19obj-$(CONFIG_SND_ICE1724) += snd-i2c.o
diff --git a/sound/i2c/other/Makefile b/sound/i2c/other/Makefile
index 2fe023ef00a7..77a8a7c75dd9 100644
--- a/sound/i2c/other/Makefile
+++ b/sound/i2c/other/Makefile
@@ -6,11 +6,11 @@
6snd-ak4114-objs := ak4114.o 6snd-ak4114-objs := ak4114.o
7snd-ak4117-objs := ak4117.o 7snd-ak4117-objs := ak4117.o
8snd-ak4xxx-adda-objs := ak4xxx-adda.o 8snd-ak4xxx-adda-objs := ak4xxx-adda.o
9snd-pt2258-objs := pt2258.o
9snd-tea575x-tuner-objs := tea575x-tuner.o 10snd-tea575x-tuner-objs := tea575x-tuner.o
10 11
11# Module Dependency 12# Module Dependency
12obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o 13obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o
13obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o 14obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o
14obj-$(CONFIG_SND_ICE1724) += snd-ak4xxx-adda.o 15obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4xxx-adda.o snd-pt2258.o
15obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o
16obj-$(CONFIG_SND_FM801_TEA575X) += snd-tea575x-tuner.o 16obj-$(CONFIG_SND_FM801_TEA575X) += snd-tea575x-tuner.o
diff --git a/sound/i2c/other/pt2258.c b/sound/i2c/other/pt2258.c
new file mode 100644
index 000000000000..50df1df2f2b9
--- /dev/null
+++ b/sound/i2c/other/pt2258.c
@@ -0,0 +1,233 @@
1/*
2 * ALSA Driver for the PT2258 volume controller.
3 *
4 * Copyright (c) 2006 Jochen Voss <voss@seehuhn.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/driver.h>
23#include <sound/core.h>
24#include <sound/control.h>
25#include <sound/tlv.h>
26#include <sound/i2c.h>
27#include <sound/pt2258.h>
28
29MODULE_AUTHOR("Jochen Voss <voss@seehuhn.de>");
30MODULE_DESCRIPTION("PT2258 volume controller (Princeton Technology Corp.)");
31MODULE_LICENSE("GPL");
32
33#define PT2258_CMD_RESET 0xc0
34#define PT2258_CMD_UNMUTE 0xf8
35#define PT2258_CMD_MUTE 0xf9
36
37static const unsigned char pt2258_channel_code[12] = {
38 0x80, 0x90, /* channel 1: -10dB, -1dB */
39 0x40, 0x50, /* channel 2: -10dB, -1dB */
40 0x00, 0x10, /* channel 3: -10dB, -1dB */
41 0x20, 0x30, /* channel 4: -10dB, -1dB */
42 0x60, 0x70, /* channel 5: -10dB, -1dB */
43 0xa0, 0xb0 /* channel 6: -10dB, -1dB */
44};
45
46int snd_pt2258_reset(struct snd_pt2258 *pt)
47{
48 unsigned char bytes[2];
49 int i;
50
51 /* reset chip */
52 bytes[0] = PT2258_CMD_RESET;
53 snd_i2c_lock(pt->i2c_bus);
54 if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 1) != 1)
55 goto __error;
56 snd_i2c_unlock(pt->i2c_bus);
57
58 /* mute all channels */
59 pt->mute = 1;
60 bytes[0] = PT2258_CMD_MUTE;
61 snd_i2c_lock(pt->i2c_bus);
62 if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 1) != 1)
63 goto __error;
64 snd_i2c_unlock(pt->i2c_bus);
65
66 /* set all channels to 0dB */
67 for (i = 0; i < 6; ++i)
68 pt->volume[i] = 0;
69 bytes[0] = 0xd0;
70 bytes[1] = 0xe0;
71 snd_i2c_lock(pt->i2c_bus);
72 if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 2) != 2)
73 goto __error;
74 snd_i2c_unlock(pt->i2c_bus);
75
76 return 0;
77
78 __error:
79 snd_i2c_unlock(pt->i2c_bus);
80 snd_printk(KERN_ERR "PT2258 reset failed\n");
81 return -EIO;
82}
83
84static int pt2258_stereo_volume_info(struct snd_kcontrol *kcontrol,
85 struct snd_ctl_elem_info *uinfo)
86{
87 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
88 uinfo->count = 2;
89 uinfo->value.integer.min = 0;
90 uinfo->value.integer.max = 79;
91 return 0;
92}
93
94static int pt2258_stereo_volume_get(struct snd_kcontrol *kcontrol,
95 struct snd_ctl_elem_value *ucontrol)
96{
97 struct snd_pt2258 *pt = kcontrol->private_data;
98 int base = kcontrol->private_value;
99
100 /* chip does not support register reads */
101 ucontrol->value.integer.value[0] = 79 - pt->volume[base];
102 ucontrol->value.integer.value[1] = 79 - pt->volume[base + 1];
103 return 0;
104}
105
106static int pt2258_stereo_volume_put(struct snd_kcontrol *kcontrol,
107 struct snd_ctl_elem_value *ucontrol)
108{
109 struct snd_pt2258 *pt = kcontrol->private_data;
110 int base = kcontrol->private_value;
111 unsigned char bytes[2];
112 int val0, val1;
113
114 val0 = 79 - ucontrol->value.integer.value[0];
115 val1 = 79 - ucontrol->value.integer.value[1];
116 if (val0 == pt->volume[base] && val1 == pt->volume[base + 1])
117 return 0;
118
119 pt->volume[base] = val0;
120 bytes[0] = pt2258_channel_code[2 * base] | (val0 / 10);
121 bytes[1] = pt2258_channel_code[2 * base + 1] | (val0 % 10);
122 snd_i2c_lock(pt->i2c_bus);
123 if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 2) != 2)
124 goto __error;
125 snd_i2c_unlock(pt->i2c_bus);
126
127 pt->volume[base + 1] = val1;
128 bytes[0] = pt2258_channel_code[2 * base + 2] | (val1 / 10);
129 bytes[1] = pt2258_channel_code[2 * base + 3] | (val1 % 10);
130 snd_i2c_lock(pt->i2c_bus);
131 if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 2) != 2)
132 goto __error;
133 snd_i2c_unlock(pt->i2c_bus);
134
135 return 1;
136
137 __error:
138 snd_i2c_unlock(pt->i2c_bus);
139 snd_printk(KERN_ERR "PT2258 access failed\n");
140 return -EIO;
141}
142
143static int pt2258_switch_info(struct snd_kcontrol *kcontrol,
144 struct snd_ctl_elem_info *uinfo)
145{
146 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
147 uinfo->count = 1;
148 uinfo->value.integer.min = 0;
149 uinfo->value.integer.max = 1;
150 return 0;
151}
152
153static int pt2258_switch_get(struct snd_kcontrol *kcontrol,
154 struct snd_ctl_elem_value *ucontrol)
155{
156 struct snd_pt2258 *pt = kcontrol->private_data;
157
158 ucontrol->value.integer.value[0] = !pt->mute;
159 return 0;
160}
161
162static int pt2258_switch_put(struct snd_kcontrol *kcontrol,
163 struct snd_ctl_elem_value *ucontrol)
164{
165 struct snd_pt2258 *pt = kcontrol->private_data;
166 unsigned char bytes[2];
167 int val;
168
169 val = !ucontrol->value.integer.value[0];
170 if (pt->mute == val)
171 return 0;
172
173 pt->mute = val;
174 bytes[0] = val ? PT2258_CMD_MUTE : PT2258_CMD_UNMUTE;
175 snd_i2c_lock(pt->i2c_bus);
176 if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 1) != 1)
177 goto __error;
178 snd_i2c_unlock(pt->i2c_bus);
179
180 return 1;
181
182 __error:
183 snd_i2c_unlock(pt->i2c_bus);
184 snd_printk(KERN_ERR "PT2258 access failed 2\n");
185 return -EIO;
186}
187
188static DECLARE_TLV_DB_SCALE(pt2258_db_scale, -7900, 100, 0);
189
190int snd_pt2258_build_controls(struct snd_pt2258 *pt)
191{
192 struct snd_kcontrol_new knew;
193 char *names[3] = {
194 "Mic Loopback Playback Volume",
195 "Line Loopback Playback Volume",
196 "CD Loopback Playback Volume"
197 };
198 int i, err;
199
200 for (i = 0; i < 3; ++i) {
201 memset(&knew, 0, sizeof(knew));
202 knew.name = names[i];
203 knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
204 knew.count = 1;
205 knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
206 SNDRV_CTL_ELEM_ACCESS_TLV_READ;
207 knew.private_value = 2 * i;
208 knew.info = pt2258_stereo_volume_info;
209 knew.get = pt2258_stereo_volume_get;
210 knew.put = pt2258_stereo_volume_put;
211 knew.tlv.p = pt2258_db_scale;
212
213 err = snd_ctl_add(pt->card, snd_ctl_new1(&knew, pt));
214 if (err < 0)
215 return err;
216 }
217
218 memset(&knew, 0, sizeof(knew));
219 knew.name = "Loopback Switch";
220 knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
221 knew.info = pt2258_switch_info;
222 knew.get = pt2258_switch_get;
223 knew.put = pt2258_switch_put;
224 knew.access = 0;
225 err = snd_ctl_add(pt->card, snd_ctl_new1(&knew, pt));
226 if (err < 0)
227 return err;
228
229 return 0;
230}
231
232EXPORT_SYMBOL(snd_pt2258_reset);
233EXPORT_SYMBOL(snd_pt2258_build_controls);
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 */