blob: cb6916e9b74ff00b7a0eebb56eef85519e551100 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * PMac Tumbler/Snapper lowlevel functions
3 *
4 * Copyright (c) by Takashi Iwai <tiwai@suse.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 * Rene Rebe <rene.rebe@gmx.net>:
21 * * update from shadow registers on wakeup and headphone plug
22 * * automatically toggle DRC on headphone plug
23 *
24 */
25
26
27#include <sound/driver.h>
28#include <linux/init.h>
29#include <linux/delay.h>
30#include <linux/i2c.h>
31#include <linux/i2c-dev.h>
32#include <linux/kmod.h>
33#include <linux/slab.h>
34#include <linux/interrupt.h>
35#include <sound/core.h>
36#include <asm/io.h>
37#include <asm/irq.h>
38#ifdef CONFIG_PPC_HAS_FEATURE_CALLS
39#include <asm/pmac_feature.h>
Benjamin Herrenschmidtb75550e2005-04-16 15:24:31 -070040#else
41#error old crap
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#endif
43#include "pmac.h"
44#include "tumbler_volume.h"
45
46/* i2c address for tumbler */
47#define TAS_I2C_ADDR 0x34
48
49/* registers */
50#define TAS_REG_MCS 0x01 /* main control */
51#define TAS_REG_DRC 0x02
52#define TAS_REG_VOL 0x04
53#define TAS_REG_TREBLE 0x05
54#define TAS_REG_BASS 0x06
55#define TAS_REG_INPUT1 0x07
56#define TAS_REG_INPUT2 0x08
57
58/* tas3001c */
59#define TAS_REG_PCM TAS_REG_INPUT1
60
61/* tas3004 */
62#define TAS_REG_LMIX TAS_REG_INPUT1
63#define TAS_REG_RMIX TAS_REG_INPUT2
64#define TAS_REG_MCS2 0x43 /* main control 2 */
65#define TAS_REG_ACS 0x40 /* analog control */
66
67/* mono volumes for tas3001c/tas3004 */
68enum {
69 VOL_IDX_PCM_MONO, /* tas3001c only */
70 VOL_IDX_BASS, VOL_IDX_TREBLE,
71 VOL_IDX_LAST_MONO
72};
73
74/* stereo volumes for tas3004 */
75enum {
76 VOL_IDX_PCM, VOL_IDX_PCM2, VOL_IDX_ADC,
77 VOL_IDX_LAST_MIX
78};
79
80typedef struct pmac_gpio {
81#ifdef CONFIG_PPC_HAS_FEATURE_CALLS
82 unsigned int addr;
83#else
84 void __iomem *addr;
85#endif
86 int active_state;
87} pmac_gpio_t;
88
89typedef struct pmac_tumbler_t {
90 pmac_keywest_t i2c;
91 pmac_gpio_t audio_reset;
92 pmac_gpio_t amp_mute;
93 pmac_gpio_t hp_mute;
94 pmac_gpio_t hp_detect;
95 int headphone_irq;
96 unsigned int master_vol[2];
Benjamin Herrenschmidtb20af5f2005-04-16 15:24:32 -070097 unsigned int save_master_switch[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -070098 unsigned int master_switch[2];
99 unsigned int mono_vol[VOL_IDX_LAST_MONO];
100 unsigned int mix_vol[VOL_IDX_LAST_MIX][2]; /* stereo volumes for tas3004 */
101 int drc_range;
102 int drc_enable;
103 int capture_source;
Benjamin Herrenschmidtb20af5f2005-04-16 15:24:32 -0700104 int anded_reset;
105 int auto_mute_notify;
106 int reset_on_sleep;
107 u8 acs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108} pmac_tumbler_t;
109
110
111/*
112 */
113
114static int send_init_client(pmac_keywest_t *i2c, unsigned int *regs)
115{
116 while (*regs > 0) {
117 int err, count = 10;
118 do {
119 err = i2c_smbus_write_byte_data(i2c->client,
120 regs[0], regs[1]);
121 if (err >= 0)
122 break;
123 mdelay(10);
124 } while (count--);
125 if (err < 0)
126 return -ENXIO;
127 regs += 2;
128 }
129 return 0;
130}
131
132
133static int tumbler_init_client(pmac_keywest_t *i2c)
134{
135 static unsigned int regs[] = {
136 /* normal operation, SCLK=64fps, i2s output, i2s input, 16bit width */
137 TAS_REG_MCS, (1<<6)|(2<<4)|(2<<2)|0,
138 0, /* terminator */
139 };
140 return send_init_client(i2c, regs);
141}
142
143static int snapper_init_client(pmac_keywest_t *i2c)
144{
145 static unsigned int regs[] = {
146 /* normal operation, SCLK=64fps, i2s output, 16bit width */
147 TAS_REG_MCS, (1<<6)|(2<<4)|0,
148 /* normal operation, all-pass mode */
149 TAS_REG_MCS2, (1<<1),
150 /* normal output, no deemphasis, A input, power-up, line-in */
151 TAS_REG_ACS, 0,
152 0, /* terminator */
153 };
154 return send_init_client(i2c, regs);
155}
156
157/*
158 * gpio access
159 */
160#ifdef CONFIG_PPC_HAS_FEATURE_CALLS
161#define do_gpio_write(gp, val) \
162 pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, (gp)->addr, val)
163#define do_gpio_read(gp) \
164 pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, (gp)->addr, 0)
165#define tumbler_gpio_free(gp) /* NOP */
166#else
167#define do_gpio_write(gp, val) writeb(val, (gp)->addr)
168#define do_gpio_read(gp) readb((gp)->addr)
169static inline void tumbler_gpio_free(pmac_gpio_t *gp)
170{
171 if (gp->addr) {
172 iounmap(gp->addr);
173 gp->addr = NULL;
174 }
175}
176#endif /* CONFIG_PPC_HAS_FEATURE_CALLS */
177
178static void write_audio_gpio(pmac_gpio_t *gp, int active)
179{
180 if (! gp->addr)
181 return;
182 active = active ? gp->active_state : !gp->active_state;
183 do_gpio_write(gp, active ? 0x05 : 0x04);
184}
185
186static int read_audio_gpio(pmac_gpio_t *gp)
187{
188 int ret;
189 if (! gp->addr)
190 return 0;
191 ret = ((do_gpio_read(gp) & 0x02) !=0);
192 return ret == gp->active_state;
193}
194
195/*
196 * update master volume
197 */
198static int tumbler_set_master_volume(pmac_tumbler_t *mix)
199{
200 unsigned char block[6];
201 unsigned int left_vol, right_vol;
202
203 if (! mix->i2c.client)
204 return -ENODEV;
205
206 if (! mix->master_switch[0])
207 left_vol = 0;
208 else {
209 left_vol = mix->master_vol[0];
210 if (left_vol >= ARRAY_SIZE(master_volume_table))
211 left_vol = ARRAY_SIZE(master_volume_table) - 1;
212 left_vol = master_volume_table[left_vol];
213 }
214 if (! mix->master_switch[1])
215 right_vol = 0;
216 else {
217 right_vol = mix->master_vol[1];
218 if (right_vol >= ARRAY_SIZE(master_volume_table))
219 right_vol = ARRAY_SIZE(master_volume_table) - 1;
220 right_vol = master_volume_table[right_vol];
221 }
222
223 block[0] = (left_vol >> 16) & 0xff;
224 block[1] = (left_vol >> 8) & 0xff;
225 block[2] = (left_vol >> 0) & 0xff;
226
227 block[3] = (right_vol >> 16) & 0xff;
228 block[4] = (right_vol >> 8) & 0xff;
229 block[5] = (right_vol >> 0) & 0xff;
230
231 if (i2c_smbus_write_block_data(mix->i2c.client, TAS_REG_VOL,
232 6, block) < 0) {
233 snd_printk("failed to set volume \n");
234 return -EINVAL;
235 }
236 return 0;
237}
238
239
240/* output volume */
241static int tumbler_info_master_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
242{
243 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
244 uinfo->count = 2;
245 uinfo->value.integer.min = 0;
246 uinfo->value.integer.max = ARRAY_SIZE(master_volume_table) - 1;
247 return 0;
248}
249
250static int tumbler_get_master_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
251{
252 pmac_t *chip = snd_kcontrol_chip(kcontrol);
253 pmac_tumbler_t *mix = chip->mixer_data;
254 snd_assert(mix, return -ENODEV);
255 ucontrol->value.integer.value[0] = mix->master_vol[0];
256 ucontrol->value.integer.value[1] = mix->master_vol[1];
257 return 0;
258}
259
260static int tumbler_put_master_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
261{
262 pmac_t *chip = snd_kcontrol_chip(kcontrol);
263 pmac_tumbler_t *mix = chip->mixer_data;
264 int change;
265
266 snd_assert(mix, return -ENODEV);
267 change = mix->master_vol[0] != ucontrol->value.integer.value[0] ||
268 mix->master_vol[1] != ucontrol->value.integer.value[1];
269 if (change) {
270 mix->master_vol[0] = ucontrol->value.integer.value[0];
271 mix->master_vol[1] = ucontrol->value.integer.value[1];
272 tumbler_set_master_volume(mix);
273 }
274 return change;
275}
276
277/* output switch */
278static int tumbler_get_master_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
279{
280 pmac_t *chip = snd_kcontrol_chip(kcontrol);
281 pmac_tumbler_t *mix = chip->mixer_data;
282 snd_assert(mix, return -ENODEV);
283 ucontrol->value.integer.value[0] = mix->master_switch[0];
284 ucontrol->value.integer.value[1] = mix->master_switch[1];
285 return 0;
286}
287
288static int tumbler_put_master_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
289{
290 pmac_t *chip = snd_kcontrol_chip(kcontrol);
291 pmac_tumbler_t *mix = chip->mixer_data;
292 int change;
293
294 snd_assert(mix, return -ENODEV);
295 change = mix->master_switch[0] != ucontrol->value.integer.value[0] ||
296 mix->master_switch[1] != ucontrol->value.integer.value[1];
297 if (change) {
298 mix->master_switch[0] = !!ucontrol->value.integer.value[0];
299 mix->master_switch[1] = !!ucontrol->value.integer.value[1];
300 tumbler_set_master_volume(mix);
301 }
302 return change;
303}
304
305
306/*
307 * TAS3001c dynamic range compression
308 */
309
310#define TAS3001_DRC_MAX 0x5f
311
312static int tumbler_set_drc(pmac_tumbler_t *mix)
313{
314 unsigned char val[2];
315
316 if (! mix->i2c.client)
317 return -ENODEV;
318
319 if (mix->drc_enable) {
320 val[0] = 0xc1; /* enable, 3:1 compression */
321 if (mix->drc_range > TAS3001_DRC_MAX)
322 val[1] = 0xf0;
323 else if (mix->drc_range < 0)
324 val[1] = 0x91;
325 else
326 val[1] = mix->drc_range + 0x91;
327 } else {
328 val[0] = 0;
329 val[1] = 0;
330 }
331
332 if (i2c_smbus_write_block_data(mix->i2c.client, TAS_REG_DRC,
333 2, val) < 0) {
334 snd_printk("failed to set DRC\n");
335 return -EINVAL;
336 }
337 return 0;
338}
339
340/*
341 * TAS3004
342 */
343
344#define TAS3004_DRC_MAX 0xef
345
346static int snapper_set_drc(pmac_tumbler_t *mix)
347{
348 unsigned char val[6];
349
350 if (! mix->i2c.client)
351 return -ENODEV;
352
353 if (mix->drc_enable)
354 val[0] = 0x50; /* 3:1 above threshold */
355 else
356 val[0] = 0x51; /* disabled */
357 val[1] = 0x02; /* 1:1 below threshold */
358 if (mix->drc_range > 0xef)
359 val[2] = 0xef;
360 else if (mix->drc_range < 0)
361 val[2] = 0x00;
362 else
363 val[2] = mix->drc_range;
364 val[3] = 0xb0;
365 val[4] = 0x60;
366 val[5] = 0xa0;
367
368 if (i2c_smbus_write_block_data(mix->i2c.client, TAS_REG_DRC,
369 6, val) < 0) {
370 snd_printk("failed to set DRC\n");
371 return -EINVAL;
372 }
373 return 0;
374}
375
376static int tumbler_info_drc_value(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
377{
378 pmac_t *chip = snd_kcontrol_chip(kcontrol);
379 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
380 uinfo->count = 1;
381 uinfo->value.integer.min = 0;
382 uinfo->value.integer.max =
383 chip->model == PMAC_TUMBLER ? TAS3001_DRC_MAX : TAS3004_DRC_MAX;
384 return 0;
385}
386
387static int tumbler_get_drc_value(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
388{
389 pmac_t *chip = snd_kcontrol_chip(kcontrol);
390 pmac_tumbler_t *mix;
391 if (! (mix = chip->mixer_data))
392 return -ENODEV;
393 ucontrol->value.integer.value[0] = mix->drc_range;
394 return 0;
395}
396
397static int tumbler_put_drc_value(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
398{
399 pmac_t *chip = snd_kcontrol_chip(kcontrol);
400 pmac_tumbler_t *mix;
401 int change;
402
403 if (! (mix = chip->mixer_data))
404 return -ENODEV;
405 change = mix->drc_range != ucontrol->value.integer.value[0];
406 if (change) {
407 mix->drc_range = ucontrol->value.integer.value[0];
408 if (chip->model == PMAC_TUMBLER)
409 tumbler_set_drc(mix);
410 else
411 snapper_set_drc(mix);
412 }
413 return change;
414}
415
416static int tumbler_get_drc_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
417{
418 pmac_t *chip = snd_kcontrol_chip(kcontrol);
419 pmac_tumbler_t *mix;
420 if (! (mix = chip->mixer_data))
421 return -ENODEV;
422 ucontrol->value.integer.value[0] = mix->drc_enable;
423 return 0;
424}
425
426static int tumbler_put_drc_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
427{
428 pmac_t *chip = snd_kcontrol_chip(kcontrol);
429 pmac_tumbler_t *mix;
430 int change;
431
432 if (! (mix = chip->mixer_data))
433 return -ENODEV;
434 change = mix->drc_enable != ucontrol->value.integer.value[0];
435 if (change) {
436 mix->drc_enable = !!ucontrol->value.integer.value[0];
437 if (chip->model == PMAC_TUMBLER)
438 tumbler_set_drc(mix);
439 else
440 snapper_set_drc(mix);
441 }
442 return change;
443}
444
445
446/*
447 * mono volumes
448 */
449
450struct tumbler_mono_vol {
451 int index;
452 int reg;
453 int bytes;
454 unsigned int max;
455 unsigned int *table;
456};
457
458static int tumbler_set_mono_volume(pmac_tumbler_t *mix, struct tumbler_mono_vol *info)
459{
460 unsigned char block[4];
461 unsigned int vol;
462 int i;
463
464 if (! mix->i2c.client)
465 return -ENODEV;
466
467 vol = mix->mono_vol[info->index];
468 if (vol >= info->max)
469 vol = info->max - 1;
470 vol = info->table[vol];
471 for (i = 0; i < info->bytes; i++)
472 block[i] = (vol >> ((info->bytes - i - 1) * 8)) & 0xff;
473 if (i2c_smbus_write_block_data(mix->i2c.client, info->reg,
474 info->bytes, block) < 0) {
475 snd_printk("failed to set mono volume %d\n", info->index);
476 return -EINVAL;
477 }
478 return 0;
479}
480
481static int tumbler_info_mono(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
482{
483 struct tumbler_mono_vol *info = (struct tumbler_mono_vol *)kcontrol->private_value;
484
485 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
486 uinfo->count = 1;
487 uinfo->value.integer.min = 0;
488 uinfo->value.integer.max = info->max - 1;
489 return 0;
490}
491
492static int tumbler_get_mono(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
493{
494 struct tumbler_mono_vol *info = (struct tumbler_mono_vol *)kcontrol->private_value;
495 pmac_t *chip = snd_kcontrol_chip(kcontrol);
496 pmac_tumbler_t *mix;
497 if (! (mix = chip->mixer_data))
498 return -ENODEV;
499 ucontrol->value.integer.value[0] = mix->mono_vol[info->index];
500 return 0;
501}
502
503static int tumbler_put_mono(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
504{
505 struct tumbler_mono_vol *info = (struct tumbler_mono_vol *)kcontrol->private_value;
506 pmac_t *chip = snd_kcontrol_chip(kcontrol);
507 pmac_tumbler_t *mix;
508 int change;
509
510 if (! (mix = chip->mixer_data))
511 return -ENODEV;
512 change = mix->mono_vol[info->index] != ucontrol->value.integer.value[0];
513 if (change) {
514 mix->mono_vol[info->index] = ucontrol->value.integer.value[0];
515 tumbler_set_mono_volume(mix, info);
516 }
517 return change;
518}
519
520/* TAS3001c mono volumes */
521static struct tumbler_mono_vol tumbler_pcm_vol_info = {
522 .index = VOL_IDX_PCM_MONO,
523 .reg = TAS_REG_PCM,
524 .bytes = 3,
525 .max = ARRAY_SIZE(mixer_volume_table),
526 .table = mixer_volume_table,
527};
528
529static struct tumbler_mono_vol tumbler_bass_vol_info = {
530 .index = VOL_IDX_BASS,
531 .reg = TAS_REG_BASS,
532 .bytes = 1,
533 .max = ARRAY_SIZE(bass_volume_table),
534 .table = bass_volume_table,
535};
536
537static struct tumbler_mono_vol tumbler_treble_vol_info = {
538 .index = VOL_IDX_TREBLE,
539 .reg = TAS_REG_TREBLE,
540 .bytes = 1,
541 .max = ARRAY_SIZE(treble_volume_table),
542 .table = treble_volume_table,
543};
544
545/* TAS3004 mono volumes */
546static struct tumbler_mono_vol snapper_bass_vol_info = {
547 .index = VOL_IDX_BASS,
548 .reg = TAS_REG_BASS,
549 .bytes = 1,
550 .max = ARRAY_SIZE(snapper_bass_volume_table),
551 .table = snapper_bass_volume_table,
552};
553
554static struct tumbler_mono_vol snapper_treble_vol_info = {
555 .index = VOL_IDX_TREBLE,
556 .reg = TAS_REG_TREBLE,
557 .bytes = 1,
558 .max = ARRAY_SIZE(snapper_treble_volume_table),
559 .table = snapper_treble_volume_table,
560};
561
562
563#define DEFINE_MONO(xname,type) { \
564 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,\
565 .name = xname, \
566 .info = tumbler_info_mono, \
567 .get = tumbler_get_mono, \
568 .put = tumbler_put_mono, \
569 .private_value = (unsigned long)(&tumbler_##type##_vol_info), \
570}
571
572#define DEFINE_SNAPPER_MONO(xname,type) { \
573 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,\
574 .name = xname, \
575 .info = tumbler_info_mono, \
576 .get = tumbler_get_mono, \
577 .put = tumbler_put_mono, \
578 .private_value = (unsigned long)(&snapper_##type##_vol_info), \
579}
580
581
582/*
583 * snapper mixer volumes
584 */
585
586static int snapper_set_mix_vol1(pmac_tumbler_t *mix, int idx, int ch, int reg)
587{
588 int i, j, vol;
589 unsigned char block[9];
590
591 vol = mix->mix_vol[idx][ch];
592 if (vol >= ARRAY_SIZE(mixer_volume_table)) {
593 vol = ARRAY_SIZE(mixer_volume_table) - 1;
594 mix->mix_vol[idx][ch] = vol;
595 }
596
597 for (i = 0; i < 3; i++) {
598 vol = mix->mix_vol[i][ch];
599 vol = mixer_volume_table[vol];
600 for (j = 0; j < 3; j++)
601 block[i * 3 + j] = (vol >> ((2 - j) * 8)) & 0xff;
602 }
603 if (i2c_smbus_write_block_data(mix->i2c.client, reg, 9, block) < 0) {
604 snd_printk("failed to set mono volume %d\n", reg);
605 return -EINVAL;
606 }
607 return 0;
608}
609
610static int snapper_set_mix_vol(pmac_tumbler_t *mix, int idx)
611{
612 if (! mix->i2c.client)
613 return -ENODEV;
614 if (snapper_set_mix_vol1(mix, idx, 0, TAS_REG_LMIX) < 0 ||
615 snapper_set_mix_vol1(mix, idx, 1, TAS_REG_RMIX) < 0)
616 return -EINVAL;
617 return 0;
618}
619
620static int snapper_info_mix(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
621{
622 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
623 uinfo->count = 2;
624 uinfo->value.integer.min = 0;
625 uinfo->value.integer.max = ARRAY_SIZE(mixer_volume_table) - 1;
626 return 0;
627}
628
629static int snapper_get_mix(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
630{
631 int idx = (int)kcontrol->private_value;
632 pmac_t *chip = snd_kcontrol_chip(kcontrol);
633 pmac_tumbler_t *mix;
634 if (! (mix = chip->mixer_data))
635 return -ENODEV;
636 ucontrol->value.integer.value[0] = mix->mix_vol[idx][0];
637 ucontrol->value.integer.value[1] = mix->mix_vol[idx][1];
638 return 0;
639}
640
641static int snapper_put_mix(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
642{
643 int idx = (int)kcontrol->private_value;
644 pmac_t *chip = snd_kcontrol_chip(kcontrol);
645 pmac_tumbler_t *mix;
646 int change;
647
648 if (! (mix = chip->mixer_data))
649 return -ENODEV;
650 change = mix->mix_vol[idx][0] != ucontrol->value.integer.value[0] ||
651 mix->mix_vol[idx][1] != ucontrol->value.integer.value[1];
652 if (change) {
653 mix->mix_vol[idx][0] = ucontrol->value.integer.value[0];
654 mix->mix_vol[idx][1] = ucontrol->value.integer.value[1];
655 snapper_set_mix_vol(mix, idx);
656 }
657 return change;
658}
659
660
661/*
Benjamin Herrenschmidtb20af5f2005-04-16 15:24:32 -0700662 * mute switches. FIXME: Turn that into software mute when both outputs are muted
663 * to avoid codec reset on ibook M7
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 */
665
666enum { TUMBLER_MUTE_HP, TUMBLER_MUTE_AMP };
667
668static int tumbler_get_mute_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
669{
670 pmac_t *chip = snd_kcontrol_chip(kcontrol);
671 pmac_tumbler_t *mix;
672 pmac_gpio_t *gp;
673 if (! (mix = chip->mixer_data))
674 return -ENODEV;
675 gp = (kcontrol->private_value == TUMBLER_MUTE_HP) ? &mix->hp_mute : &mix->amp_mute;
676 ucontrol->value.integer.value[0] = ! read_audio_gpio(gp);
677 return 0;
678}
679
680static int tumbler_put_mute_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
681{
682 pmac_t *chip = snd_kcontrol_chip(kcontrol);
683 pmac_tumbler_t *mix;
684 pmac_gpio_t *gp;
685 int val;
686#ifdef PMAC_SUPPORT_AUTOMUTE
687 if (chip->update_automute && chip->auto_mute)
688 return 0; /* don't touch in the auto-mute mode */
689#endif
690 if (! (mix = chip->mixer_data))
691 return -ENODEV;
692 gp = (kcontrol->private_value == TUMBLER_MUTE_HP) ? &mix->hp_mute : &mix->amp_mute;
693 val = ! read_audio_gpio(gp);
694 if (val != ucontrol->value.integer.value[0]) {
695 write_audio_gpio(gp, ! ucontrol->value.integer.value[0]);
696 return 1;
697 }
698 return 0;
699}
700
701static int snapper_set_capture_source(pmac_tumbler_t *mix)
702{
703 if (! mix->i2c.client)
704 return -ENODEV;
Benjamin Herrenschmidtb20af5f2005-04-16 15:24:32 -0700705 if (mix->capture_source)
706 mix->acs = mix->acs |= 2;
707 else
708 mix->acs &= ~2;
709 return i2c_smbus_write_byte_data(mix->i2c.client, TAS_REG_ACS, mix->acs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710}
711
712static int snapper_info_capture_source(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
713{
714 static char *texts[2] = {
715 "Line", "Mic"
716 };
717 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
718 uinfo->count = 1;
719 uinfo->value.enumerated.items = 2;
720 if (uinfo->value.enumerated.item > 1)
721 uinfo->value.enumerated.item = 1;
722 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
723 return 0;
724}
725
726static int snapper_get_capture_source(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
727{
728 pmac_t *chip = snd_kcontrol_chip(kcontrol);
729 pmac_tumbler_t *mix = chip->mixer_data;
730
731 snd_assert(mix, return -ENODEV);
732 ucontrol->value.integer.value[0] = mix->capture_source;
733 return 0;
734}
735
736static int snapper_put_capture_source(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
737{
738 pmac_t *chip = snd_kcontrol_chip(kcontrol);
739 pmac_tumbler_t *mix = chip->mixer_data;
740 int change;
741
742 snd_assert(mix, return -ENODEV);
743 change = ucontrol->value.integer.value[0] != mix->capture_source;
744 if (change) {
745 mix->capture_source = !!ucontrol->value.integer.value[0];
746 snapper_set_capture_source(mix);
747 }
748 return change;
749}
750
751#define DEFINE_SNAPPER_MIX(xname,idx,ofs) { \
752 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,\
753 .name = xname, \
754 .info = snapper_info_mix, \
755 .get = snapper_get_mix, \
756 .put = snapper_put_mix, \
757 .index = idx,\
758 .private_value = ofs, \
759}
760
761
762/*
763 */
764static snd_kcontrol_new_t tumbler_mixers[] __initdata = {
765 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
766 .name = "Master Playback Volume",
767 .info = tumbler_info_master_volume,
768 .get = tumbler_get_master_volume,
769 .put = tumbler_put_master_volume
770 },
771 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
772 .name = "Master Playback Switch",
773 .info = snd_pmac_boolean_stereo_info,
774 .get = tumbler_get_master_switch,
775 .put = tumbler_put_master_switch
776 },
777 DEFINE_MONO("Tone Control - Bass", bass),
778 DEFINE_MONO("Tone Control - Treble", treble),
779 DEFINE_MONO("PCM Playback Volume", pcm),
780 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
781 .name = "DRC Range",
782 .info = tumbler_info_drc_value,
783 .get = tumbler_get_drc_value,
784 .put = tumbler_put_drc_value
785 },
786};
787
788static snd_kcontrol_new_t snapper_mixers[] __initdata = {
789 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
790 .name = "Master Playback Volume",
791 .info = tumbler_info_master_volume,
792 .get = tumbler_get_master_volume,
793 .put = tumbler_put_master_volume
794 },
795 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
796 .name = "Master Playback Switch",
797 .info = snd_pmac_boolean_stereo_info,
798 .get = tumbler_get_master_switch,
799 .put = tumbler_put_master_switch
800 },
801 DEFINE_SNAPPER_MIX("PCM Playback Volume", 0, VOL_IDX_PCM),
802 DEFINE_SNAPPER_MIX("PCM Playback Volume", 1, VOL_IDX_PCM2),
803 DEFINE_SNAPPER_MIX("Monitor Mix Volume", 0, VOL_IDX_ADC),
804 DEFINE_SNAPPER_MONO("Tone Control - Bass", bass),
805 DEFINE_SNAPPER_MONO("Tone Control - Treble", treble),
806 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
807 .name = "DRC Range",
808 .info = tumbler_info_drc_value,
809 .get = tumbler_get_drc_value,
810 .put = tumbler_put_drc_value
811 },
812 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
813 .name = "Input Source", /* FIXME: "Capture Source" doesn't work properly */
814 .info = snapper_info_capture_source,
815 .get = snapper_get_capture_source,
816 .put = snapper_put_capture_source
817 },
818};
819
820static snd_kcontrol_new_t tumbler_hp_sw __initdata = {
821 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
822 .name = "Headphone Playback Switch",
823 .info = snd_pmac_boolean_mono_info,
824 .get = tumbler_get_mute_switch,
825 .put = tumbler_put_mute_switch,
826 .private_value = TUMBLER_MUTE_HP,
827};
828static snd_kcontrol_new_t tumbler_speaker_sw __initdata = {
829 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
830 .name = "PC Speaker Playback Switch",
831 .info = snd_pmac_boolean_mono_info,
832 .get = tumbler_get_mute_switch,
833 .put = tumbler_put_mute_switch,
834 .private_value = TUMBLER_MUTE_AMP,
835};
836static snd_kcontrol_new_t tumbler_drc_sw __initdata = {
837 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
838 .name = "DRC Switch",
839 .info = snd_pmac_boolean_mono_info,
840 .get = tumbler_get_drc_switch,
841 .put = tumbler_put_drc_switch
842};
843
844
845#ifdef PMAC_SUPPORT_AUTOMUTE
846/*
847 * auto-mute stuffs
848 */
849static int tumbler_detect_headphone(pmac_t *chip)
850{
851 pmac_tumbler_t *mix = chip->mixer_data;
852 return read_audio_gpio(&mix->hp_detect);
853}
854
855static void check_mute(pmac_t *chip, pmac_gpio_t *gp, int val, int do_notify, snd_kcontrol_t *sw)
856{
857 //pmac_tumbler_t *mix = chip->mixer_data;
858 if (val != read_audio_gpio(gp)) {
859 write_audio_gpio(gp, val);
860 if (do_notify)
861 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &sw->id);
862 }
863}
864
865static struct work_struct device_change;
866
Benjamin Herrenschmidtb20af5f2005-04-16 15:24:32 -0700867static void device_change_handler(void *self)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868{
869 pmac_t *chip = (pmac_t*) self;
870 pmac_tumbler_t *mix;
871
872 if (!chip)
873 return;
874
875 mix = chip->mixer_data;
Benjamin Herrenschmidtb20af5f2005-04-16 15:24:32 -0700876 snd_assert(mix, return);
877
878 if (tumbler_detect_headphone(chip)) {
879 /* mute speaker */
880 check_mute(chip, &mix->hp_mute, 0, mix->auto_mute_notify,
881 chip->master_sw_ctl);
882 if (mix->anded_reset)
883 big_mdelay(10);
884 check_mute(chip, &mix->amp_mute, 1, mix->auto_mute_notify,
885 chip->speaker_sw_ctl);
886 mix->drc_enable = 0;
887 } else {
888 /* unmute speaker */
889 check_mute(chip, &mix->amp_mute, 0, mix->auto_mute_notify,
890 chip->speaker_sw_ctl);
891 if (mix->anded_reset)
892 big_mdelay(10);
893 check_mute(chip, &mix->hp_mute, 1, mix->auto_mute_notify,
894 chip->master_sw_ctl);
895 mix->drc_enable = 1;
896 }
897 if (mix->auto_mute_notify) {
898 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
899 &chip->hp_detect_ctl->id);
900 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
901 &chip->drc_sw_ctl->id);
902 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903
904 /* first set the DRC so the speaker do not explode -ReneR */
905 if (chip->model == PMAC_TUMBLER)
906 tumbler_set_drc(mix);
907 else
908 snapper_set_drc(mix);
909
910 /* reset the master volume so the correct amplification is applied */
911 tumbler_set_master_volume(mix);
912}
913
914static void tumbler_update_automute(pmac_t *chip, int do_notify)
915{
916 if (chip->auto_mute) {
Benjamin Herrenschmidtb20af5f2005-04-16 15:24:32 -0700917 pmac_tumbler_t *mix;
918 mix = chip->mixer_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 snd_assert(mix, return);
Benjamin Herrenschmidtb20af5f2005-04-16 15:24:32 -0700920 mix->auto_mute_notify = do_notify;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 schedule_work(&device_change);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 }
923}
924#endif /* PMAC_SUPPORT_AUTOMUTE */
925
926
927/* interrupt - headphone plug changed */
928static irqreturn_t headphone_intr(int irq, void *devid, struct pt_regs *regs)
929{
930 pmac_t *chip = devid;
931 if (chip->update_automute && chip->initialized) {
932 chip->update_automute(chip, 1);
933 return IRQ_HANDLED;
934 }
935 return IRQ_NONE;
936}
937
938/* look for audio-gpio device */
939static struct device_node *find_audio_device(const char *name)
940{
941 struct device_node *np;
942
943 if (! (np = find_devices("gpio")))
944 return NULL;
945
946 for (np = np->child; np; np = np->sibling) {
947 char *property = get_property(np, "audio-gpio", NULL);
948 if (property && strcmp(property, name) == 0)
949 return np;
950 }
951 return NULL;
952}
953
954/* look for audio-gpio device */
955static struct device_node *find_compatible_audio_device(const char *name)
956{
957 struct device_node *np;
958
959 if (! (np = find_devices("gpio")))
960 return NULL;
961
962 for (np = np->child; np; np = np->sibling) {
963 if (device_is_compatible(np, name))
964 return np;
965 }
966 return NULL;
967}
968
969/* find an audio device and get its address */
Benjamin Herrenschmidtb75550e2005-04-16 15:24:31 -0700970static long tumbler_find_device(const char *device, pmac_gpio_t *gp, int is_compatible)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971{
972 struct device_node *node;
Benjamin Herrenschmidtb75550e2005-04-16 15:24:31 -0700973 u32 *base, addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974
975 if (is_compatible)
976 node = find_compatible_audio_device(device);
977 else
978 node = find_audio_device(device);
979 if (! node) {
980 snd_printdd("cannot find device %s\n", device);
981 return -ENODEV;
982 }
983
984 base = (u32 *)get_property(node, "AAPL,address", NULL);
985 if (! base) {
Benjamin Herrenschmidtb75550e2005-04-16 15:24:31 -0700986 base = (u32 *)get_property(node, "reg", NULL);
987 if (!base) {
988 snd_printd("cannot find address for device %s\n", device);
989 return -ENODEV;
990 }
991 /* this only work if PPC_HAS_FEATURE_CALLS is set as we
992 * are only getting the low part of the address
993 */
994 addr = *base;
995 if (addr < 0x50)
996 addr += 0x50;
997 } else
998 addr = *base;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999
1000#ifdef CONFIG_PPC_HAS_FEATURE_CALLS
Benjamin Herrenschmidtb75550e2005-04-16 15:24:31 -07001001 gp->addr = addr & 0x0000ffff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002#else
Benjamin Herrenschmidtb75550e2005-04-16 15:24:31 -07001003 gp->addr = ioremap((unsigned long)addr, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004#endif
Benjamin Herrenschmidtb75550e2005-04-16 15:24:31 -07001005 /* Try to find the active state, default to 0 ! */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 base = (u32 *)get_property(node, "audio-gpio-active-state", NULL);
1007 if (base)
1008 gp->active_state = *base;
1009 else
Benjamin Herrenschmidtb75550e2005-04-16 15:24:31 -07001010 gp->active_state = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011
1012 return (node->n_intrs > 0) ? node->intrs[0].line : 0;
1013}
1014
1015/* reset audio */
1016static void tumbler_reset_audio(pmac_t *chip)
1017{
1018 pmac_tumbler_t *mix = chip->mixer_data;
1019
Benjamin Herrenschmidtb20af5f2005-04-16 15:24:32 -07001020 if (mix->anded_reset) {
1021 write_audio_gpio(&mix->hp_mute, 0);
1022 write_audio_gpio(&mix->amp_mute, 0);
1023 big_mdelay(200);
1024 write_audio_gpio(&mix->hp_mute, 1);
1025 write_audio_gpio(&mix->amp_mute, 1);
1026 big_mdelay(100);
1027 write_audio_gpio(&mix->hp_mute, 0);
1028 write_audio_gpio(&mix->amp_mute, 0);
1029 big_mdelay(100);
1030 } else {
1031 write_audio_gpio(&mix->audio_reset, 0);
1032 big_mdelay(200);
1033 write_audio_gpio(&mix->audio_reset, 1);
1034 big_mdelay(100);
1035 write_audio_gpio(&mix->audio_reset, 0);
1036 big_mdelay(100);
1037 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038}
1039
1040#ifdef CONFIG_PMAC_PBOOK
Benjamin Herrenschmidtb20af5f2005-04-16 15:24:32 -07001041/* suspend mixer */
1042static void tumbler_suspend(pmac_t *chip)
1043{
1044 pmac_tumbler_t *mix = chip->mixer_data;
1045
1046 if (mix->headphone_irq >= 0)
1047 disable_irq(mix->headphone_irq);
1048 mix->save_master_switch[0] = mix->master_switch[0];
1049 mix->save_master_switch[1] = mix->master_switch[1];
1050 mix->master_switch[0] = mix->master_switch[1] = 0;
1051 tumbler_set_master_volume(mix);
1052 if (!mix->anded_reset) {
1053 write_audio_gpio(&mix->amp_mute, 1);
1054 write_audio_gpio(&mix->hp_mute, 1);
1055 }
1056 if (chip->model == PMAC_SNAPPER) {
1057 mix->acs |= 1;
1058 i2c_smbus_write_byte_data(mix->i2c.client, TAS_REG_ACS, mix->acs);
1059 }
1060 if (mix->anded_reset) {
1061 write_audio_gpio(&mix->amp_mute, 1);
1062 write_audio_gpio(&mix->hp_mute, 1);
1063 } else
1064 write_audio_gpio(&mix->audio_reset, 1);
1065}
1066
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067/* resume mixer */
1068static void tumbler_resume(pmac_t *chip)
1069{
1070 pmac_tumbler_t *mix = chip->mixer_data;
1071
1072 snd_assert(mix, return);
1073
Benjamin Herrenschmidtb20af5f2005-04-16 15:24:32 -07001074 mix->acs &= ~1;
1075 mix->master_switch[0] = mix->save_master_switch[0];
1076 mix->master_switch[1] = mix->save_master_switch[1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 tumbler_reset_audio(chip);
1078 if (mix->i2c.client && mix->i2c.init_client) {
1079 if (mix->i2c.init_client(&mix->i2c) < 0)
1080 printk(KERN_ERR "tumbler_init_client error\n");
1081 } else
1082 printk(KERN_ERR "tumbler: i2c is not initialized\n");
1083 if (chip->model == PMAC_TUMBLER) {
1084 tumbler_set_mono_volume(mix, &tumbler_pcm_vol_info);
1085 tumbler_set_mono_volume(mix, &tumbler_bass_vol_info);
1086 tumbler_set_mono_volume(mix, &tumbler_treble_vol_info);
1087 tumbler_set_drc(mix);
1088 } else {
1089 snapper_set_mix_vol(mix, VOL_IDX_PCM);
1090 snapper_set_mix_vol(mix, VOL_IDX_PCM2);
1091 snapper_set_mix_vol(mix, VOL_IDX_ADC);
1092 tumbler_set_mono_volume(mix, &snapper_bass_vol_info);
1093 tumbler_set_mono_volume(mix, &snapper_treble_vol_info);
1094 snapper_set_drc(mix);
1095 snapper_set_capture_source(mix);
1096 }
1097 tumbler_set_master_volume(mix);
1098 if (chip->update_automute)
1099 chip->update_automute(chip, 0);
Benjamin Herrenschmidtb20af5f2005-04-16 15:24:32 -07001100 if (mix->headphone_irq >= 0)
1101 enable_irq(mix->headphone_irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102}
1103#endif
1104
1105/* initialize tumbler */
1106static int __init tumbler_init(pmac_t *chip)
1107{
1108 int irq, err;
1109 pmac_tumbler_t *mix = chip->mixer_data;
1110 snd_assert(mix, return -EINVAL);
1111
Benjamin Herrenschmidtb75550e2005-04-16 15:24:31 -07001112 if (tumbler_find_device("audio-hw-reset", &mix->audio_reset, 0) < 0)
1113 tumbler_find_device("hw-reset", &mix->audio_reset, 1);
1114 if (tumbler_find_device("amp-mute", &mix->amp_mute, 0) < 0)
1115 tumbler_find_device("amp-mute", &mix->amp_mute, 1);
1116 if (tumbler_find_device("headphone-mute", &mix->hp_mute, 0) < 0)
1117 tumbler_find_device("headphone-mute", &mix->hp_mute, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 irq = tumbler_find_device("headphone-detect", &mix->hp_detect, 0);
1119 if (irq < 0)
Benjamin Herrenschmidtb75550e2005-04-16 15:24:31 -07001120 irq = tumbler_find_device("headphone-detect", &mix->hp_detect, 1);
1121 if (irq < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 irq = tumbler_find_device("keywest-gpio15", &mix->hp_detect, 1);
1123
1124 tumbler_reset_audio(chip);
1125
1126 /* activate headphone status interrupts */
1127 if (irq >= 0) {
1128 unsigned char val;
1129 if ((err = request_irq(irq, headphone_intr, 0,
1130 "Tumbler Headphone Detection", chip)) < 0)
1131 return err;
1132 /* activate headphone status interrupts */
1133 val = do_gpio_read(&mix->hp_detect);
1134 do_gpio_write(&mix->hp_detect, val | 0x80);
1135 }
1136 mix->headphone_irq = irq;
1137
1138 return 0;
1139}
1140
1141static void tumbler_cleanup(pmac_t *chip)
1142{
1143 pmac_tumbler_t *mix = chip->mixer_data;
1144 if (! mix)
1145 return;
1146
1147 if (mix->headphone_irq >= 0)
1148 free_irq(mix->headphone_irq, chip);
1149 tumbler_gpio_free(&mix->audio_reset);
1150 tumbler_gpio_free(&mix->amp_mute);
1151 tumbler_gpio_free(&mix->hp_mute);
1152 tumbler_gpio_free(&mix->hp_detect);
1153 snd_pmac_keywest_cleanup(&mix->i2c);
1154 kfree(mix);
1155 chip->mixer_data = NULL;
1156}
1157
1158/* exported */
1159int __init snd_pmac_tumbler_init(pmac_t *chip)
1160{
1161 int i, err;
1162 pmac_tumbler_t *mix;
1163 u32 *paddr;
Benjamin Herrenschmidtb20af5f2005-04-16 15:24:32 -07001164 struct device_node *tas_node, *np;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 char *chipname;
1166
1167#ifdef CONFIG_KMOD
1168 if (current->fs->root)
1169 request_module("i2c-keywest");
1170#endif /* CONFIG_KMOD */
1171
1172 mix = kmalloc(sizeof(*mix), GFP_KERNEL);
1173 if (! mix)
1174 return -ENOMEM;
1175 memset(mix, 0, sizeof(*mix));
1176 mix->headphone_irq = -1;
1177
1178 chip->mixer_data = mix;
1179 chip->mixer_free = tumbler_cleanup;
Benjamin Herrenschmidtb20af5f2005-04-16 15:24:32 -07001180 mix->anded_reset = 0;
1181 mix->reset_on_sleep = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182
Benjamin Herrenschmidtb20af5f2005-04-16 15:24:32 -07001183 for (np = chip->node->child; np; np = np->sibling) {
1184 if (!strcmp(np->name, "sound")) {
1185 if (get_property(np, "has-anded-reset", NULL))
1186 mix->anded_reset = 1;
1187 if (get_property(np, "layout-id", NULL))
1188 mix->reset_on_sleep = 0;
1189 break;
1190 }
1191 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 if ((err = tumbler_init(chip)) < 0)
1193 return err;
1194
1195 /* set up TAS */
1196 tas_node = find_devices("deq");
1197 if (tas_node == NULL)
Benjamin Herrenschmidtb75550e2005-04-16 15:24:31 -07001198 tas_node = find_devices("codec");
1199 if (tas_node == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 return -ENODEV;
1201
1202 paddr = (u32 *)get_property(tas_node, "i2c-address", NULL);
Benjamin Herrenschmidtb75550e2005-04-16 15:24:31 -07001203 if (paddr == NULL)
1204 paddr = (u32 *)get_property(tas_node, "reg", NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 if (paddr)
1206 mix->i2c.addr = (*paddr) >> 1;
1207 else
1208 mix->i2c.addr = TAS_I2C_ADDR;
1209
1210 if (chip->model == PMAC_TUMBLER) {
1211 mix->i2c.init_client = tumbler_init_client;
1212 mix->i2c.name = "TAS3001c";
1213 chipname = "Tumbler";
1214 } else {
1215 mix->i2c.init_client = snapper_init_client;
1216 mix->i2c.name = "TAS3004";
1217 chipname = "Snapper";
1218 }
1219
1220 if ((err = snd_pmac_keywest_init(&mix->i2c)) < 0)
1221 return err;
1222
1223 /*
1224 * build mixers
1225 */
1226 sprintf(chip->card->mixername, "PowerMac %s", chipname);
1227
1228 if (chip->model == PMAC_TUMBLER) {
1229 for (i = 0; i < ARRAY_SIZE(tumbler_mixers); i++) {
1230 if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&tumbler_mixers[i], chip))) < 0)
1231 return err;
1232 }
1233 } else {
1234 for (i = 0; i < ARRAY_SIZE(snapper_mixers); i++) {
1235 if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snapper_mixers[i], chip))) < 0)
1236 return err;
1237 }
1238 }
1239 chip->master_sw_ctl = snd_ctl_new1(&tumbler_hp_sw, chip);
1240 if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
1241 return err;
1242 chip->speaker_sw_ctl = snd_ctl_new1(&tumbler_speaker_sw, chip);
1243 if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
1244 return err;
1245 chip->drc_sw_ctl = snd_ctl_new1(&tumbler_drc_sw, chip);
1246 if ((err = snd_ctl_add(chip->card, chip->drc_sw_ctl)) < 0)
1247 return err;
1248
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249#ifdef CONFIG_PMAC_PBOOK
Benjamin Herrenschmidtb20af5f2005-04-16 15:24:32 -07001250 chip->suspend = tumbler_suspend;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 chip->resume = tumbler_resume;
1252#endif
1253
1254 INIT_WORK(&device_change, device_change_handler, (void *)chip);
1255
1256#ifdef PMAC_SUPPORT_AUTOMUTE
1257 if (mix->headphone_irq >=0 && (err = snd_pmac_add_automute(chip)) < 0)
1258 return err;
1259 chip->detect_headphone = tumbler_detect_headphone;
1260 chip->update_automute = tumbler_update_automute;
1261 tumbler_update_automute(chip, 0); /* update the status only */
1262#endif
1263
1264 return 0;
1265}