diff options
Diffstat (limited to 'sound/pci/ice1712/revo.c')
-rw-r--r-- | sound/pci/ice1712/revo.c | 132 |
1 files changed, 122 insertions, 10 deletions
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 | |||
90 | static 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 | |||
96 | static 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 | |||
102 | static 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 | |||
119 | static 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 | |||
134 | static 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 | |||
145 | static 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 | |||
153 | static 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 | ||
304 | static struct snd_pt2258 ptc_revo51_volume; | ||
305 | |||
208 | static int __devinit revo_init(struct snd_ice1712 *ice) | 306 | static 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 | } |