| changeset 5876: | 2d6164f0bf0e |
| parent: | d773ad622068 |
| author: | tiwai |
| date: | Tue Feb 19 11:56:06 2008 +0100 (4 years ago) |
| permissions: | -rw-r--r-- |
| description: | Dont touch fs_struct in drivers The sound drivers and the pnpbios core test for current->root != NULL. This test seems to be unnecessary since we always have rootfs mounted before initializing the drivers. Patch-level: Merged Signed-off-by: Jan Blunck <jblunck@suse.de> Acked-by: Christoph Hellwig <hch@lst.de> Cc: Bjorn Helgaas <bjorn.helgaas@hp.com> Cc: Jaroslav Kysela <perex@suse.cz> Acked-by: Takashi Iwai <tiwai@suse.de> Cc: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
1/*2 * PMac Tumbler/Snapper lowlevel functions3 *4 * Copyright (c) by Takashi Iwai <tiwai@suse.de>5 *6 * This program is free software; you can redistribute it and/or modify7 * it under the terms of the GNU General Public License as published by8 * the Free Software Foundation; either version 2 of the License, or9 * (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 of13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the14 * GNU General Public License for more details.15 *16 * You should have received a copy of the GNU General Public License17 * along with this program; if not, write to the Free Software18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA19 *20 * Rene Rebe <rene.rebe@gmx.net>:21 * * update from shadow registers on wakeup and headphone plug22 * * automatically toggle DRC on headphone plug23 *24 */252627#include <linux/init.h>28#include <linux/delay.h>29#include <linux/i2c.h>30#include <linux/kmod.h>31#include <linux/slab.h>32#include <linux/interrupt.h>33#include <sound/core.h>34#include <asm/io.h>35#include <asm/irq.h>36#include <asm/machdep.h>37#include <asm/pmac_feature.h>38#include "pmac.h"39#include "tumbler_volume.h"4041#undef DEBUG4243#ifdef DEBUG44#define DBG(fmt...) printk(fmt)45#else46#define DBG(fmt...)47#endif4849/* i2c address for tumbler */50#define TAS_I2C_ADDR 0x345152/* registers */53#define TAS_REG_MCS 0x01 /* main control */54#define TAS_REG_DRC 0x0255#define TAS_REG_VOL 0x0456#define TAS_REG_TREBLE 0x0557#define TAS_REG_BASS 0x0658#define TAS_REG_INPUT1 0x0759#define TAS_REG_INPUT2 0x086061/* tas3001c */62#define TAS_REG_PCM TAS_REG_INPUT16364/* tas3004 */65#define TAS_REG_LMIX TAS_REG_INPUT166#define TAS_REG_RMIX TAS_REG_INPUT267#define TAS_REG_MCS2 0x43 /* main control 2 */68#define TAS_REG_ACS 0x40 /* analog control */6970/* mono volumes for tas3001c/tas3004 */71enum {72 VOL_IDX_PCM_MONO, /* tas3001c only */73 VOL_IDX_BASS, VOL_IDX_TREBLE,74 VOL_IDX_LAST_MONO75};7677/* stereo volumes for tas3004 */78enum {79 VOL_IDX_PCM, VOL_IDX_PCM2, VOL_IDX_ADC,80 VOL_IDX_LAST_MIX81};8283struct pmac_gpio {84 unsigned int addr;85 u8 active_val;86 u8 inactive_val;87 u8 active_state;88};8990struct pmac_tumbler {91 struct pmac_keywest i2c;92 struct pmac_gpio audio_reset;93 struct pmac_gpio amp_mute;94 struct pmac_gpio line_mute;95 struct pmac_gpio line_detect;96 struct pmac_gpio hp_mute;97 struct pmac_gpio hp_detect;98 int headphone_irq;99 int lineout_irq;100 unsigned int save_master_vol[2];101 unsigned int master_vol[2];102 unsigned int save_master_switch[2];103 unsigned int master_switch[2];104 unsigned int mono_vol[VOL_IDX_LAST_MONO];105 unsigned int mix_vol[VOL_IDX_LAST_MIX][2]; /* stereo volumes for tas3004 */106 int drc_range;107 int drc_enable;108 int capture_source;109 int anded_reset;110 int auto_mute_notify;111 int reset_on_sleep;112 u8 acs;113};114115116/*117 */118119static int send_init_client(struct pmac_keywest *i2c, unsigned int *regs)120{121 while (*regs > 0) {122 int err, count = 10;123 do {124 err = i2c_smbus_write_byte_data(i2c->client,125 regs[0], regs[1]);126 if (err >= 0)127 break;128 DBG("(W) i2c error %d\n", err);129 mdelay(10);130 } while (count--);131 if (err < 0)132 return -ENXIO;133 regs += 2;134 }135 return 0;136}137138139static int tumbler_init_client(struct pmac_keywest *i2c)140{141 static unsigned int regs[] = {142 /* normal operation, SCLK=64fps, i2s output, i2s input, 16bit width */143 TAS_REG_MCS, (1<<6)|(2<<4)|(2<<2)|0,144 0, /* terminator */145 };146 DBG("(I) tumbler init client\n");147 return send_init_client(i2c, regs);148}149150static int snapper_init_client(struct pmac_keywest *i2c)151{152 static unsigned int regs[] = {153 /* normal operation, SCLK=64fps, i2s output, 16bit width */154 TAS_REG_MCS, (1<<6)|(2<<4)|0,155 /* normal operation, all-pass mode */156 TAS_REG_MCS2, (1<<1),157 /* normal output, no deemphasis, A input, power-up, line-in */158 TAS_REG_ACS, 0,159 0, /* terminator */160 };161 DBG("(I) snapper init client\n");162 return send_init_client(i2c, regs);163}164165/*166 * gpio access167 */168#define do_gpio_write(gp, val) \169 pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, (gp)->addr, val)170#define do_gpio_read(gp) \171 pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, (gp)->addr, 0)172#define tumbler_gpio_free(gp) /* NOP */173174static void write_audio_gpio(struct pmac_gpio *gp, int active)175{176 if (! gp->addr)177 return;178 active = active ? gp->active_val : gp->inactive_val;179 do_gpio_write(gp, active);180 DBG("(I) gpio %x write %d\n", gp->addr, active);181}182183static int check_audio_gpio(struct pmac_gpio *gp)184{185 int ret;186187 if (! gp->addr)188 return 0;189190 ret = do_gpio_read(gp);191192 return (ret & 0x1) == (gp->active_val & 0x1);193}194195static int read_audio_gpio(struct pmac_gpio *gp)196{197 int ret;198 if (! gp->addr)199 return 0;200 ret = do_gpio_read(gp);201 ret = (ret & 0x02) !=0;202 return ret == gp->active_state;203}204205/*206 * update master volume207 */208static int tumbler_set_master_volume(struct pmac_tumbler *mix)209{210 unsigned char block[6];211 unsigned int left_vol, right_vol;212213 if (! mix->i2c.client)214 return -ENODEV;215216 if (! mix->master_switch[0])217 left_vol = 0;218 else {219 left_vol = mix->master_vol[0];220 if (left_vol >= ARRAY_SIZE(master_volume_table))221 left_vol = ARRAY_SIZE(master_volume_table) - 1;222 left_vol = master_volume_table[left_vol];223 }224 if (! mix->master_switch[1])225 right_vol = 0;226 else {227 right_vol = mix->master_vol[1];228 if (right_vol >= ARRAY_SIZE(master_volume_table))229 right_vol = ARRAY_SIZE(master_volume_table) - 1;230 right_vol = master_volume_table[right_vol];231 }232233 block[0] = (left_vol >> 16) & 0xff;234 block[1] = (left_vol >> 8) & 0xff;235 block[2] = (left_vol >> 0) & 0xff;236237 block[3] = (right_vol >> 16) & 0xff;238 block[4] = (right_vol >> 8) & 0xff;239 block[5] = (right_vol >> 0) & 0xff;240241 if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_VOL, 6,242 block) < 0) {243 snd_printk("failed to set volume \n");244 return -EINVAL;245 }246 return 0;247}248249250/* output volume */251static int tumbler_info_master_volume(struct snd_kcontrol *kcontrol,252 struct snd_ctl_elem_info *uinfo)253{254 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;255 uinfo->count = 2;256 uinfo->value.integer.min = 0;257 uinfo->value.integer.max = ARRAY_SIZE(master_volume_table) - 1;258 return 0;259}260261static int tumbler_get_master_volume(struct snd_kcontrol *kcontrol,262 struct snd_ctl_elem_value *ucontrol)263{264 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);265 struct pmac_tumbler *mix = chip->mixer_data;266 snd_assert(mix, return -ENODEV);267 ucontrol->value.integer.value[0] = mix->master_vol[0];268 ucontrol->value.integer.value[1] = mix->master_vol[1];269 return 0;270}271272static int tumbler_put_master_volume(struct snd_kcontrol *kcontrol,273 struct snd_ctl_elem_value *ucontrol)274{275 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);276 struct pmac_tumbler *mix = chip->mixer_data;277 unsigned int vol[2];278 int change;279280 snd_assert(mix, return -ENODEV);281 vol[0] = ucontrol->value.integer.value[0];282 vol[1] = ucontrol->value.integer.value[1];283 if (vol[0] >= ARRAY_SIZE(master_volume_table) ||284 vol[1] >= ARRAY_SIZE(master_volume_table))285 return -EINVAL;286 change = mix->master_vol[0] != vol[0] ||287 mix->master_vol[1] != vol[1];288 if (change) {289 mix->master_vol[0] = vol[0];290 mix->master_vol[1] = vol[1];291 tumbler_set_master_volume(mix);292 }293 return change;294}295296/* output switch */297static int tumbler_get_master_switch(struct snd_kcontrol *kcontrol,298 struct snd_ctl_elem_value *ucontrol)299{300 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);301 struct pmac_tumbler *mix = chip->mixer_data;302 snd_assert(mix, return -ENODEV);303 ucontrol->value.integer.value[0] = mix->master_switch[0];304 ucontrol->value.integer.value[1] = mix->master_switch[1];305 return 0;306}307308static int tumbler_put_master_switch(struct snd_kcontrol *kcontrol,309 struct snd_ctl_elem_value *ucontrol)310{311 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);312 struct pmac_tumbler *mix = chip->mixer_data;313 int change;314315 snd_assert(mix, return -ENODEV);316 change = mix->master_switch[0] != ucontrol->value.integer.value[0] ||317 mix->master_switch[1] != ucontrol->value.integer.value[1];318 if (change) {319 mix->master_switch[0] = !!ucontrol->value.integer.value[0];320 mix->master_switch[1] = !!ucontrol->value.integer.value[1];321 tumbler_set_master_volume(mix);322 }323 return change;324}325326327/*328 * TAS3001c dynamic range compression329 */330331#define TAS3001_DRC_MAX 0x5f332333static int tumbler_set_drc(struct pmac_tumbler *mix)334{335 unsigned char val[2];336337 if (! mix->i2c.client)338 return -ENODEV;339340 if (mix->drc_enable) {341 val[0] = 0xc1; /* enable, 3:1 compression */342 if (mix->drc_range > TAS3001_DRC_MAX)343 val[1] = 0xf0;344 else if (mix->drc_range < 0)345 val[1] = 0x91;346 else347 val[1] = mix->drc_range + 0x91;348 } else {349 val[0] = 0;350 val[1] = 0;351 }352353 if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_DRC,354 2, val) < 0) {355 snd_printk("failed to set DRC\n");356 return -EINVAL;357 }358 return 0;359}360361/*362 * TAS3004363 */364365#define TAS3004_DRC_MAX 0xef366367static int snapper_set_drc(struct pmac_tumbler *mix)368{369 unsigned char val[6];370371 if (! mix->i2c.client)372 return -ENODEV;373374 if (mix->drc_enable)375 val[0] = 0x50; /* 3:1 above threshold */376 else377 val[0] = 0x51; /* disabled */378 val[1] = 0x02; /* 1:1 below threshold */379 if (mix->drc_range > 0xef)380 val[2] = 0xef;381 else if (mix->drc_range < 0)382 val[2] = 0x00;383 else384 val[2] = mix->drc_range;385 val[3] = 0xb0;386 val[4] = 0x60;387 val[5] = 0xa0;388389 if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_DRC,390 6, val) < 0) {391 snd_printk("failed to set DRC\n");392 return -EINVAL;393 }394 return 0;395}396397static int tumbler_info_drc_value(struct snd_kcontrol *kcontrol,398 struct snd_ctl_elem_info *uinfo)399{400 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);401 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;402 uinfo->count = 1;403 uinfo->value.integer.min = 0;404 uinfo->value.integer.max =405 chip->model == PMAC_TUMBLER ? TAS3001_DRC_MAX : TAS3004_DRC_MAX;406 return 0;407}408409static int tumbler_get_drc_value(struct snd_kcontrol *kcontrol,410 struct snd_ctl_elem_value *ucontrol)411{412 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);413 struct pmac_tumbler *mix;414 if (! (mix = chip->mixer_data))415 return -ENODEV;416 ucontrol->value.integer.value[0] = mix->drc_range;417 return 0;418}419420static int tumbler_put_drc_value(struct snd_kcontrol *kcontrol,421 struct snd_ctl_elem_value *ucontrol)422{423 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);424 struct pmac_tumbler *mix;425 unsigned int val;426 int change;427428 if (! (mix = chip->mixer_data))429 return -ENODEV;430 val = ucontrol->value.integer.value[0];431 if (chip->model == PMAC_TUMBLER) {432 if (val > TAS3001_DRC_MAX)433 return -EINVAL;434 } else {435 if (val > TAS3004_DRC_MAX)436 return -EINVAL;437 }438 change = mix->drc_range != val;439 if (change) {440 mix->drc_range = val;441 if (chip->model == PMAC_TUMBLER)442 tumbler_set_drc(mix);443 else444 snapper_set_drc(mix);445 }446 return change;447}448449static int tumbler_get_drc_switch(struct snd_kcontrol *kcontrol,450 struct snd_ctl_elem_value *ucontrol)451{452 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);453 struct pmac_tumbler *mix;454 if (! (mix = chip->mixer_data))455 return -ENODEV;456 ucontrol->value.integer.value[0] = mix->drc_enable;457 return 0;458}459460static int tumbler_put_drc_switch(struct snd_kcontrol *kcontrol,461 struct snd_ctl_elem_value *ucontrol)462{463 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);464 struct pmac_tumbler *mix;465 int change;466467 if (! (mix = chip->mixer_data))468 return -ENODEV;469 change = mix->drc_enable != ucontrol->value.integer.value[0];470 if (change) {471 mix->drc_enable = !!ucontrol->value.integer.value[0];472 if (chip->model == PMAC_TUMBLER)473 tumbler_set_drc(mix);474 else475 snapper_set_drc(mix);476 }477 return change;478}479480481/*482 * mono volumes483 */484485struct tumbler_mono_vol {486 int index;487 int reg;488 int bytes;489 unsigned int max;490 unsigned int *table;491};492493static int tumbler_set_mono_volume(struct pmac_tumbler *mix,494 struct tumbler_mono_vol *info)495{496 unsigned char block[4];497 unsigned int vol;498 int i;499500 if (! mix->i2c.client)501 return -ENODEV;502503 vol = mix->mono_vol[info->index];504 if (vol >= info->max)505 vol = info->max - 1;506 vol = info->table[vol];507 for (i = 0; i < info->bytes; i++)508 block[i] = (vol >> ((info->bytes - i - 1) * 8)) & 0xff;509 if (i2c_smbus_write_i2c_block_data(mix->i2c.client, info->reg,510 info->bytes, block) < 0) {511 snd_printk("failed to set mono volume %d\n", info->index);512 return -EINVAL;513 }514 return 0;515}516517static int tumbler_info_mono(struct snd_kcontrol *kcontrol,518 struct snd_ctl_elem_info *uinfo)519{520 struct tumbler_mono_vol *info = (struct tumbler_mono_vol *)kcontrol->private_value;521522 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;523 uinfo->count = 1;524 uinfo->value.integer.min = 0;525 uinfo->value.integer.max = info->max - 1;526 return 0;527}528529static int tumbler_get_mono(struct snd_kcontrol *kcontrol,530 struct snd_ctl_elem_value *ucontrol)531{532 struct tumbler_mono_vol *info = (struct tumbler_mono_vol *)kcontrol->private_value;533 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);534 struct pmac_tumbler *mix;535 if (! (mix = chip->mixer_data))536 return -ENODEV;537 ucontrol->value.integer.value[0] = mix->mono_vol[info->index];538 return 0;539}540541static int tumbler_put_mono(struct snd_kcontrol *kcontrol,542 struct snd_ctl_elem_value *ucontrol)543{544 struct tumbler_mono_vol *info = (struct tumbler_mono_vol *)kcontrol->private_value;545 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);546 struct pmac_tumbler *mix;547 unsigned int vol;548 int change;549550 if (! (mix = chip->mixer_data))551 return -ENODEV;552 vol = ucontrol->value.integer.value[0];553 if (vol >= info->max)554 return -EINVAL;555 change = mix->mono_vol[info->index] != vol;556 if (change) {557 mix->mono_vol[info->index] = vol;558 tumbler_set_mono_volume(mix, info);559 }560 return change;561}562563/* TAS3001c mono volumes */564static struct tumbler_mono_vol tumbler_pcm_vol_info = {565 .index = VOL_IDX_PCM_MONO,566 .reg = TAS_REG_PCM,567 .bytes = 3,568 .max = ARRAY_SIZE(mixer_volume_table),569 .table = mixer_volume_table,570};571572static struct tumbler_mono_vol tumbler_bass_vol_info = {573 .index = VOL_IDX_BASS,574 .reg = TAS_REG_BASS,575 .bytes = 1,576 .max = ARRAY_SIZE(bass_volume_table),577 .table = bass_volume_table,578};579580static struct tumbler_mono_vol tumbler_treble_vol_info = {581 .index = VOL_IDX_TREBLE,582 .reg = TAS_REG_TREBLE,583 .bytes = 1,584 .max = ARRAY_SIZE(treble_volume_table),585 .table = treble_volume_table,586};587588/* TAS3004 mono volumes */589static struct tumbler_mono_vol snapper_bass_vol_info = {590 .index = VOL_IDX_BASS,591 .reg = TAS_REG_BASS,592 .bytes = 1,593 .max = ARRAY_SIZE(snapper_bass_volume_table),594 .table = snapper_bass_volume_table,595};596597static struct tumbler_mono_vol snapper_treble_vol_info = {598 .index = VOL_IDX_TREBLE,599 .reg = TAS_REG_TREBLE,600 .bytes = 1,601 .max = ARRAY_SIZE(snapper_treble_volume_table),602 .table = snapper_treble_volume_table,603};604605606#define DEFINE_MONO(xname,type) { \607 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,\608 .name = xname, \609 .info = tumbler_info_mono, \610 .get = tumbler_get_mono, \611 .put = tumbler_put_mono, \612 .private_value = (unsigned long)(&tumbler_##type##_vol_info), \613}614615#define DEFINE_SNAPPER_MONO(xname,type) { \616 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,\617 .name = xname, \618 .info = tumbler_info_mono, \619 .get = tumbler_get_mono, \620 .put = tumbler_put_mono, \621 .private_value = (unsigned long)(&snapper_##type##_vol_info), \622}623624625/*626 * snapper mixer volumes627 */628629static int snapper_set_mix_vol1(struct pmac_tumbler *mix, int idx, int ch, int reg)630{631 int i, j, vol;632 unsigned char block[9];633634 vol = mix->mix_vol[idx][ch];635 if (vol >= ARRAY_SIZE(mixer_volume_table)) {636 vol = ARRAY_SIZE(mixer_volume_table) - 1;637 mix->mix_vol[idx][ch] = vol;638 }639640 for (i = 0; i < 3; i++) {641 vol = mix->mix_vol[i][ch];642 vol = mixer_volume_table[vol];643 for (j = 0; j < 3; j++)644 block[i * 3 + j] = (vol >> ((2 - j) * 8)) & 0xff;645 }646 if (i2c_smbus_write_i2c_block_data(mix->i2c.client, reg,647 9, block) < 0) {648 snd_printk("failed to set mono volume %d\n", reg);649 return -EINVAL;650 }651 return 0;652}653654static int snapper_set_mix_vol(struct pmac_tumbler *mix, int idx)655{656 if (! mix->i2c.client)657 return -ENODEV;658 if (snapper_set_mix_vol1(mix, idx, 0, TAS_REG_LMIX) < 0 ||659 snapper_set_mix_vol1(mix, idx, 1, TAS_REG_RMIX) < 0)660 return -EINVAL;661 return 0;662}663664static int snapper_info_mix(struct snd_kcontrol *kcontrol,665 struct snd_ctl_elem_info *uinfo)666{667 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;668 uinfo->count = 2;669 uinfo->value.integer.min = 0;670 uinfo->value.integer.max = ARRAY_SIZE(mixer_volume_table) - 1;671 return 0;672}673674static int snapper_get_mix(struct snd_kcontrol *kcontrol,675 struct snd_ctl_elem_value *ucontrol)676{677 int idx = (int)kcontrol->private_value;678 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);679 struct pmac_tumbler *mix;680 if (! (mix = chip->mixer_data))681 return -ENODEV;682 ucontrol->value.integer.value[0] = mix->mix_vol[idx][0];683 ucontrol->value.integer.value[1] = mix->mix_vol[idx][1];684 return 0;685}686687static int snapper_put_mix(struct snd_kcontrol *kcontrol,688 struct snd_ctl_elem_value *ucontrol)689{690 int idx = (int)kcontrol->private_value;691 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);692 struct pmac_tumbler *mix;693 unsigned int vol[2];694 int change;695696 if (! (mix = chip->mixer_data))697 return -ENODEV;698 vol[0] = ucontrol->value.integer.value[0];699 vol[1] = ucontrol->value.integer.value[1];700 if (vol[0] >= ARRAY_SIZE(mixer_volume_table) ||701 vol[1] >= ARRAY_SIZE(mixer_volume_table))702 return -EINVAL;703 change = mix->mix_vol[idx][0] != vol[0] ||704 mix->mix_vol[idx][1] != vol[1];705 if (change) {706 mix->mix_vol[idx][0] = vol[0];707 mix->mix_vol[idx][1] = vol[1];708 snapper_set_mix_vol(mix, idx);709 }710 return change;711}712713714/*715 * mute switches. FIXME: Turn that into software mute when both outputs are muted716 * to avoid codec reset on ibook M7717 */718719enum { TUMBLER_MUTE_HP, TUMBLER_MUTE_AMP, TUMBLER_MUTE_LINE };720721static int tumbler_get_mute_switch(struct snd_kcontrol *kcontrol,722 struct snd_ctl_elem_value *ucontrol)723{724 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);725 struct pmac_tumbler *mix;726 struct pmac_gpio *gp;727 if (! (mix = chip->mixer_data))728 return -ENODEV;729 switch(kcontrol->private_value) {730 case TUMBLER_MUTE_HP:731 gp = &mix->hp_mute; break;732 case TUMBLER_MUTE_AMP:733 gp = &mix->amp_mute; break;734 case TUMBLER_MUTE_LINE:735 gp = &mix->line_mute; break;736 default:737 gp = NULL;738 }739 if (gp == NULL)740 return -EINVAL;741 ucontrol->value.integer.value[0] = !check_audio_gpio(gp);742 return 0;743}744745static int tumbler_put_mute_switch(struct snd_kcontrol *kcontrol,746 struct snd_ctl_elem_value *ucontrol)747{748 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);749 struct pmac_tumbler *mix;750 struct pmac_gpio *gp;751 int val;752#ifdef PMAC_SUPPORT_AUTOMUTE753 if (chip->update_automute && chip->auto_mute)754 return 0; /* don't touch in the auto-mute mode */755#endif756 if (! (mix = chip->mixer_data))757 return -ENODEV;758 switch(kcontrol->private_value) {759 case TUMBLER_MUTE_HP:760 gp = &mix->hp_mute; break;761 case TUMBLER_MUTE_AMP:762 gp = &mix->amp_mute; break;763 case TUMBLER_MUTE_LINE:764 gp = &mix->line_mute; break;765 default:766 gp = NULL;767 }768 if (gp == NULL)769 return -EINVAL;770 val = ! check_audio_gpio(gp);771 if (val != ucontrol->value.integer.value[0]) {772 write_audio_gpio(gp, ! ucontrol->value.integer.value[0]);773 return 1;774 }775 return 0;776}777778static int snapper_set_capture_source(struct pmac_tumbler *mix)779{780 if (! mix->i2c.client)781 return -ENODEV;782 if (mix->capture_source)783 mix->acs = mix->acs |= 2;784 else785 mix->acs &= ~2;786 return i2c_smbus_write_byte_data(mix->i2c.client, TAS_REG_ACS, mix->acs);787}788789static int snapper_info_capture_source(struct snd_kcontrol *kcontrol,790 struct snd_ctl_elem_info *uinfo)791{792 static char *texts[2] = {793 "Line", "Mic"794 };795 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;796 uinfo->count = 1;797 uinfo->value.enumerated.items = 2;798 if (uinfo->value.enumerated.item > 1)799 uinfo->value.enumerated.item = 1;800 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);801 return 0;802}803804static int snapper_get_capture_source(struct snd_kcontrol *kcontrol,805 struct snd_ctl_elem_value *ucontrol)806{807 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);808 struct pmac_tumbler *mix = chip->mixer_data;809810 snd_assert(mix, return -ENODEV);811 ucontrol->value.enumerated.item[0] = mix->capture_source;812 return 0;813}814815static int snapper_put_capture_source(struct snd_kcontrol *kcontrol,816 struct snd_ctl_elem_value *ucontrol)817{818 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);819 struct pmac_tumbler *mix = chip->mixer_data;820 int change;821822 snd_assert(mix, return -ENODEV);823 change = ucontrol->value.enumerated.item[0] != mix->capture_source;824 if (change) {825 mix->capture_source = !!ucontrol->value.enumerated.item[0];826 snapper_set_capture_source(mix);827 }828 return change;829}830831#define DEFINE_SNAPPER_MIX(xname,idx,ofs) { \832 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,\833 .name = xname, \834 .info = snapper_info_mix, \835 .get = snapper_get_mix, \836 .put = snapper_put_mix, \837 .index = idx,\838 .private_value = ofs, \839}840841842/*843 */844static struct snd_kcontrol_new tumbler_mixers[] __initdata = {845 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,846 .name = "Master Playback Volume",847 .info = tumbler_info_master_volume,848 .get = tumbler_get_master_volume,849 .put = tumbler_put_master_volume850 },851 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,852 .name = "Master Playback Switch",853 .info = snd_pmac_boolean_stereo_info,854 .get = tumbler_get_master_switch,855 .put = tumbler_put_master_switch856 },857 DEFINE_MONO("Tone Control - Bass", bass),858 DEFINE_MONO("Tone Control - Treble", treble),859 DEFINE_MONO("PCM Playback Volume", pcm),860 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,861 .name = "DRC Range",862 .info = tumbler_info_drc_value,863 .get = tumbler_get_drc_value,864 .put = tumbler_put_drc_value865 },866};867868static struct snd_kcontrol_new snapper_mixers[] __initdata = {869 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,870 .name = "Master Playback Volume",871 .info = tumbler_info_master_volume,872 .get = tumbler_get_master_volume,873 .put = tumbler_put_master_volume874 },875 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,876 .name = "Master Playback Switch",877 .info = snd_pmac_boolean_stereo_info,878 .get = tumbler_get_master_switch,879 .put = tumbler_put_master_switch880 },881 DEFINE_SNAPPER_MIX("PCM Playback Volume", 0, VOL_IDX_PCM),882 DEFINE_SNAPPER_MIX("PCM Playback Volume", 1, VOL_IDX_PCM2),883 DEFINE_SNAPPER_MIX("Monitor Mix Volume", 0, VOL_IDX_ADC),884 DEFINE_SNAPPER_MONO("Tone Control - Bass", bass),885 DEFINE_SNAPPER_MONO("Tone Control - Treble", treble),886 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,887 .name = "DRC Range",888 .info = tumbler_info_drc_value,889 .get = tumbler_get_drc_value,890 .put = tumbler_put_drc_value891 },892 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,893 .name = "Input Source", /* FIXME: "Capture Source" doesn't work properly */894 .info = snapper_info_capture_source,895 .get = snapper_get_capture_source,896 .put = snapper_put_capture_source897 },898};899900static struct snd_kcontrol_new tumbler_hp_sw __initdata = {901 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,902 .name = "Headphone Playback Switch",903 .info = snd_pmac_boolean_mono_info,904 .get = tumbler_get_mute_switch,905 .put = tumbler_put_mute_switch,906 .private_value = TUMBLER_MUTE_HP,907};908static struct snd_kcontrol_new tumbler_speaker_sw __initdata = {909 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,910 .name = "PC Speaker Playback Switch",911 .info = snd_pmac_boolean_mono_info,912 .get = tumbler_get_mute_switch,913 .put = tumbler_put_mute_switch,914 .private_value = TUMBLER_MUTE_AMP,915};916static struct snd_kcontrol_new tumbler_lineout_sw __initdata = {917 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,918 .name = "Line Out Playback Switch",919 .info = snd_pmac_boolean_mono_info,920 .get = tumbler_get_mute_switch,921 .put = tumbler_put_mute_switch,922 .private_value = TUMBLER_MUTE_LINE,923};924static struct snd_kcontrol_new tumbler_drc_sw __initdata = {925 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,926 .name = "DRC Switch",927 .info = snd_pmac_boolean_mono_info,928 .get = tumbler_get_drc_switch,929 .put = tumbler_put_drc_switch930};931932933#ifdef PMAC_SUPPORT_AUTOMUTE934/*935 * auto-mute stuffs936 */937static int tumbler_detect_headphone(struct snd_pmac *chip)938{939 struct pmac_tumbler *mix = chip->mixer_data;940 int detect = 0;941942 if (mix->hp_detect.addr)943 detect |= read_audio_gpio(&mix->hp_detect);944 return detect;945}946947static int tumbler_detect_lineout(struct snd_pmac *chip)948{949 struct pmac_tumbler *mix = chip->mixer_data;950 int detect = 0;951952 if (mix->line_detect.addr)953 detect |= read_audio_gpio(&mix->line_detect);954 return detect;955}956957static void check_mute(struct snd_pmac *chip, struct pmac_gpio *gp, int val, int do_notify,958 struct snd_kcontrol *sw)959{960 if (check_audio_gpio(gp) != val) {961 write_audio_gpio(gp, val);962 if (do_notify)963 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,964 &sw->id);965 }966}967968static struct work_struct device_change;969static struct snd_pmac *device_change_chip;970971static void device_change_handler(struct work_struct *work)972{973 struct snd_pmac *chip = device_change_chip;974 struct pmac_tumbler *mix;975 int headphone, lineout;976977 if (!chip)978 return;979980 mix = chip->mixer_data;981 snd_assert(mix, return);982983 headphone = tumbler_detect_headphone(chip);984 lineout = tumbler_detect_lineout(chip);985986 DBG("headphone: %d, lineout: %d\n", headphone, lineout);987988 if (headphone || lineout) {989 /* unmute headphone/lineout & mute speaker */990 if (headphone)991 check_mute(chip, &mix->hp_mute, 0, mix->auto_mute_notify,992 chip->master_sw_ctl);993 if (lineout && mix->line_mute.addr != 0)994 check_mute(chip, &mix->line_mute, 0, mix->auto_mute_notify,995 chip->lineout_sw_ctl);996 if (mix->anded_reset)997 msleep(10);998 check_mute(chip, &mix->amp_mute, 1, mix->auto_mute_notify,999 chip->speaker_sw_ctl);1000 } else {1001 /* unmute speaker, mute others */1002 check_mute(chip, &mix->amp_mute, 0, mix->auto_mute_notify,1003 chip->speaker_sw_ctl);1004 if (mix->anded_reset)1005 msleep(10);1006 check_mute(chip, &mix->hp_mute, 1, mix->auto_mute_notify,1007 chip->master_sw_ctl);1008 if (mix->line_mute.addr != 0)1009 check_mute(chip, &mix->line_mute, 1, mix->auto_mute_notify,1010 chip->lineout_sw_ctl);1011 }1012 if (mix->auto_mute_notify)1013 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,1014 &chip->hp_detect_ctl->id);10151016#ifdef CONFIG_SND_POWERMAC_AUTO_DRC1017 mix->drc_enable = ! (headphone || lineout);1018 if (mix->auto_mute_notify)1019 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,1020 &chip->drc_sw_ctl->id);1021 if (chip->model == PMAC_TUMBLER)1022 tumbler_set_drc(mix);1023 else1024 snapper_set_drc(mix);1025#endif10261027 /* reset the master volume so the correct amplification is applied */1028 tumbler_set_master_volume(mix);1029}10301031static void tumbler_update_automute(struct snd_pmac *chip, int do_notify)1032{1033 if (chip->auto_mute) {1034 struct pmac_tumbler *mix;1035 mix = chip->mixer_data;1036 snd_assert(mix, return);1037 mix->auto_mute_notify = do_notify;1038 schedule_work(&device_change);1039 }1040}1041#endif /* PMAC_SUPPORT_AUTOMUTE */104210431044/* interrupt - headphone plug changed */1045static irqreturn_t headphone_intr(int irq, void *devid)1046{1047 struct snd_pmac *chip = devid;1048 if (chip->update_automute && chip->initialized) {1049 chip->update_automute(chip, 1);1050 return IRQ_HANDLED;1051 }1052 return IRQ_NONE;1053}10541055/* look for audio-gpio device */1056static struct device_node *find_audio_device(const char *name)1057{1058 struct device_node *gpiop;1059 struct device_node *np;10601061 gpiop = of_find_node_by_name(NULL, "gpio");1062 if (! gpiop)1063 return NULL;10641065 for (np = of_get_next_child(gpiop, NULL); np;1066 np = of_get_next_child(gpiop, np)) {1067 const char *property = of_get_property(np, "audio-gpio", NULL);1068 if (property && strcmp(property, name) == 0)1069 break;1070 }1071 of_node_put(gpiop);1072 return np;1073}10741075/* look for audio-gpio device */1076static struct device_node *find_compatible_audio_device(const char *name)1077{1078 struct device_node *gpiop;1079 struct device_node *np;10801081 gpiop = of_find_node_by_name(NULL, "gpio");1082 if (!gpiop)1083 return NULL;10841085 for (np = of_get_next_child(gpiop, NULL); np;1086 np = of_get_next_child(gpiop, np)) {1087 if (of_device_is_compatible(np, name))1088 break;1089 }1090 of_node_put(gpiop);1091 return np;1092}10931094/* find an audio device and get its address */1095static long tumbler_find_device(const char *device, const char *platform,1096 struct pmac_gpio *gp, int is_compatible)1097{1098 struct device_node *node;1099 const u32 *base;1100 u32 addr;1101 long ret;11021103 if (is_compatible)1104 node = find_compatible_audio_device(device);1105 else1106 node = find_audio_device(device);1107 if (! node) {1108 DBG("(W) cannot find audio device %s !\n", device);1109 snd_printdd("cannot find device %s\n", device);1110 return -ENODEV;1111 }11121113 base = of_get_property(node, "AAPL,address", NULL);1114 if (! base) {1115 base = of_get_property(node, "reg", NULL);1116 if (!base) {1117 DBG("(E) cannot find address for device %s !\n", device);1118 snd_printd("cannot find address for device %s\n", device);1119 of_node_put(node);1120 return -ENODEV;1121 }1122 addr = *base;1123 if (addr < 0x50)1124 addr += 0x50;1125 } else1126 addr = *base;11271128 gp->addr = addr & 0x0000ffff;1129 /* Try to find the active state, default to 0 ! */1130 base = of_get_property(node, "audio-gpio-active-state", NULL);1131 if (base) {1132 gp->active_state = *base;1133 gp->active_val = (*base) ? 0x5 : 0x4;1134 gp->inactive_val = (*base) ? 0x4 : 0x5;1135 } else {1136 const u32 *prop = NULL;1137 gp->active_state = 0;1138 gp->active_val = 0x4;1139 gp->inactive_val = 0x5;1140 /* Here are some crude hacks to extract the GPIO polarity and1141 * open collector informations out of the do-platform script1142 * as we don't yet have an interpreter for these things1143 */1144 if (platform)1145 prop = of_get_property(node, platform, NULL);1146 if (prop) {1147 if (prop[3] == 0x9 && prop[4] == 0x9) {1148 gp->active_val = 0xd;1149 gp->inactive_val = 0xc;1150 }1151 if (prop[3] == 0x1 && prop[4] == 0x1) {1152 gp->active_val = 0x5;1153 gp->inactive_val = 0x4;1154 }1155 }1156 }11571158 DBG("(I) GPIO device %s found, offset: %x, active state: %d !\n",1159 device, gp->addr, gp->active_state);11601161 ret = irq_of_parse_and_map(node, 0);1162 of_node_put(node);1163 return ret;1164}11651166/* reset audio */1167static void tumbler_reset_audio(struct snd_pmac *chip)1168{1169 struct pmac_tumbler *mix = chip->mixer_data;11701171 if (mix->anded_reset) {1172 DBG("(I) codec anded reset !\n");1173 write_audio_gpio(&mix->hp_mute, 0);1174 write_audio_gpio(&mix->amp_mute, 0);1175 msleep(200);1176 write_audio_gpio(&mix->hp_mute, 1);1177 write_audio_gpio(&mix->amp_mute, 1);1178 msleep(100);1179 write_audio_gpio(&mix->hp_mute, 0);1180 write_audio_gpio(&mix->amp_mute, 0);1181 msleep(100);1182 } else {1183 DBG("(I) codec normal reset !\n");11841185 write_audio_gpio(&mix->audio_reset, 0);1186 msleep(200);1187 write_audio_gpio(&mix->audio_reset, 1);1188 msleep(100);1189 write_audio_gpio(&mix->audio_reset, 0);1190 msleep(100);1191 }1192}11931194#ifdef CONFIG_PM1195/* suspend mixer */1196static void tumbler_suspend(struct snd_pmac *chip)1197{1198 struct pmac_tumbler *mix = chip->mixer_data;11991200 if (mix->headphone_irq >= 0)1201 disable_irq(mix->headphone_irq);1202 if (mix->lineout_irq >= 0)1203 disable_irq(mix->lineout_irq);1204 mix->save_master_switch[0] = mix->master_switch[0];1205 mix->save_master_switch[1] = mix->master_switch[1];1206 mix->save_master_vol[0] = mix->master_vol[0];1207 mix->save_master_vol[1] = mix->master_vol[1];1208 mix->master_switch[0] = mix->master_switch[1] = 0;1209 tumbler_set_master_volume(mix);1210 if (!mix->anded_reset) {1211 write_audio_gpio(&mix->amp_mute, 1);1212 write_audio_gpio(&mix->hp_mute, 1);1213 }1214 if (chip->model == PMAC_SNAPPER) {1215 mix->acs |= 1;1216 i2c_smbus_write_byte_data(mix->i2c.client, TAS_REG_ACS, mix->acs);1217 }1218 if (mix->anded_reset) {1219 write_audio_gpio(&mix->amp_mute, 1);1220 write_audio_gpio(&mix->hp_mute, 1);1221 } else1222 write_audio_gpio(&mix->audio_reset, 1);1223}12241225/* resume mixer */1226static void tumbler_resume(struct snd_pmac *chip)1227{1228 struct pmac_tumbler *mix = chip->mixer_data;12291230 snd_assert(mix, return);12311232 mix->acs &= ~1;1233 mix->master_switch[0] = mix->save_master_switch[0];1234 mix->master_switch[1] = mix->save_master_switch[1];1235 mix->master_vol[0] = mix->save_master_vol[0];1236 mix->master_vol[1] = mix->save_master_vol[1];1237 tumbler_reset_audio(chip);1238 if (mix->i2c.client && mix->i2c.init_client) {1239 if (mix->i2c.init_client(&mix->i2c) < 0)1240 printk(KERN_ERR "tumbler_init_client error\n");1241 } else1242 printk(KERN_ERR "tumbler: i2c is not initialized\n");1243 if (chip->model == PMAC_TUMBLER) {1244 tumbler_set_mono_volume(mix, &tumbler_pcm_vol_info);1245 tumbler_set_mono_volume(mix, &tumbler_bass_vol_info);1246 tumbler_set_mono_volume(mix, &tumbler_treble_vol_info);1247 tumbler_set_drc(mix);1248 } else {1249 snapper_set_mix_vol(mix, VOL_IDX_PCM);1250 snapper_set_mix_vol(mix, VOL_IDX_PCM2);1251 snapper_set_mix_vol(mix, VOL_IDX_ADC);1252 tumbler_set_mono_volume(mix, &snapper_bass_vol_info);1253 tumbler_set_mono_volume(mix, &snapper_treble_vol_info);1254 snapper_set_drc(mix);1255 snapper_set_capture_source(mix);1256 }1257 tumbler_set_master_volume(mix);1258 if (chip->update_automute)1259 chip->update_automute(chip, 0);1260 if (mix->headphone_irq >= 0) {1261 unsigned char val;12621263 enable_irq(mix->headphone_irq);1264 /* activate headphone status interrupts */1265 val = do_gpio_read(&mix->hp_detect);1266 do_gpio_write(&mix->hp_detect, val | 0x80);1267 }1268 if (mix->lineout_irq >= 0)1269 enable_irq(mix->lineout_irq);1270}1271#endif12721273/* initialize tumbler */1274static int __init tumbler_init(struct snd_pmac *chip)1275{1276 int irq;1277 struct pmac_tumbler *mix = chip->mixer_data;1278 snd_assert(mix, return -EINVAL);12791280 if (tumbler_find_device("audio-hw-reset",1281 "platform-do-hw-reset",1282 &mix->audio_reset, 0) < 0)1283 tumbler_find_device("hw-reset",1284 "platform-do-hw-reset",1285 &mix->audio_reset, 1);1286 if (tumbler_find_device("amp-mute",1287 "platform-do-amp-mute",1288 &mix->amp_mute, 0) < 0)1289 tumbler_find_device("amp-mute",1290 "platform-do-amp-mute",1291 &mix->amp_mute, 1);1292 if (tumbler_find_device("headphone-mute",1293 "platform-do-headphone-mute",1294 &mix->hp_mute, 0) < 0)1295 tumbler_find_device("headphone-mute",1296 "platform-do-headphone-mute",1297 &mix->hp_mute, 1);1298 if (tumbler_find_device("line-output-mute",1299 "platform-do-lineout-mute",1300 &mix->line_mute, 0) < 0)1301 tumbler_find_device("line-output-mute",1302 "platform-do-lineout-mute",1303 &mix->line_mute, 1);1304 irq = tumbler_find_device("headphone-detect",1305 NULL, &mix->hp_detect, 0);1306 if (irq <= NO_IRQ)1307 irq = tumbler_find_device("headphone-detect",1308 NULL, &mix->hp_detect, 1);1309 if (irq <= NO_IRQ)1310 irq = tumbler_find_device("keywest-gpio15",1311 NULL, &mix->hp_detect, 1);1312 mix->headphone_irq = irq;1313 irq = tumbler_find_device("line-output-detect",1314 NULL, &mix->line_detect, 0);1315 if (irq <= NO_IRQ)1316 irq = tumbler_find_device("line-output-detect",1317 NULL, &mix->line_detect, 1);1318 mix->lineout_irq = irq;13191320 tumbler_reset_audio(chip);13211322 return 0;1323}13241325static void tumbler_cleanup(struct snd_pmac *chip)1326{1327 struct pmac_tumbler *mix = chip->mixer_data;1328 if (! mix)1329 return;13301331 if (mix->headphone_irq >= 0)1332 free_irq(mix->headphone_irq, chip);1333 if (mix->lineout_irq >= 0)1334 free_irq(mix->lineout_irq, chip);1335 tumbler_gpio_free(&mix->audio_reset);1336 tumbler_gpio_free(&mix->amp_mute);1337 tumbler_gpio_free(&mix->hp_mute);1338 tumbler_gpio_free(&mix->hp_detect);1339 snd_pmac_keywest_cleanup(&mix->i2c);1340 kfree(mix);1341 chip->mixer_data = NULL;1342}13431344/* exported */1345int __init snd_pmac_tumbler_init(struct snd_pmac *chip)1346{1347 int i, err;1348 struct pmac_tumbler *mix;1349 const u32 *paddr;1350 struct device_node *tas_node, *np;1351 char *chipname;13521353#ifdef CONFIG_KMOD1354 request_module("i2c-powermac");1355#endif /* CONFIG_KMOD */13561357 mix = kzalloc(sizeof(*mix), GFP_KERNEL);1358 if (! mix)1359 return -ENOMEM;1360 mix->headphone_irq = -1;13611362 chip->mixer_data = mix;1363 chip->mixer_free = tumbler_cleanup;1364 mix->anded_reset = 0;1365 mix->reset_on_sleep = 1;13661367 for (np = chip->node->child; np; np = np->sibling) {1368 if (!strcmp(np->name, "sound")) {1369 if (of_get_property(np, "has-anded-reset", NULL))1370 mix->anded_reset = 1;1371 if (of_get_property(np, "layout-id", NULL))1372 mix->reset_on_sleep = 0;1373 break;1374 }1375 }1376 if ((err = tumbler_init(chip)) < 0)1377 return err;13781379 /* set up TAS */1380 tas_node = of_find_node_by_name(NULL, "deq");1381 if (tas_node == NULL)1382 tas_node = of_find_node_by_name(NULL, "codec");1383 if (tas_node == NULL)1384 return -ENODEV;13851386 paddr = of_get_property(tas_node, "i2c-address", NULL);1387 if (paddr == NULL)1388 paddr = of_get_property(tas_node, "reg", NULL);1389 if (paddr)1390 mix->i2c.addr = (*paddr) >> 1;1391 else1392 mix->i2c.addr = TAS_I2C_ADDR;1393 of_node_put(tas_node);13941395 DBG("(I) TAS i2c address is: %x\n", mix->i2c.addr);13961397 if (chip->model == PMAC_TUMBLER) {1398 mix->i2c.init_client = tumbler_init_client;1399 mix->i2c.name = "TAS3001c";1400 chipname = "Tumbler";1401 } else {1402 mix->i2c.init_client = snapper_init_client;1403 mix->i2c.name = "TAS3004";1404 chipname = "Snapper";1405 }14061407 if ((err = snd_pmac_keywest_init(&mix->i2c)) < 0)1408 return err;14091410 /*1411 * build mixers1412 */1413 sprintf(chip->card->mixername, "PowerMac %s", chipname);14141415 if (chip->model == PMAC_TUMBLER) {1416 for (i = 0; i < ARRAY_SIZE(tumbler_mixers); i++) {1417 if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&tumbler_mixers[i], chip))) < 0)1418 return err;1419 }1420 } else {1421 for (i = 0; i < ARRAY_SIZE(snapper_mixers); i++) {1422 if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snapper_mixers[i], chip))) < 0)1423 return err;1424 }1425 }1426 chip->master_sw_ctl = snd_ctl_new1(&tumbler_hp_sw, chip);1427 if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)1428 return err;1429 chip->speaker_sw_ctl = snd_ctl_new1(&tumbler_speaker_sw, chip);1430 if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)1431 return err;1432 if (mix->line_mute.addr != 0) {1433 chip->lineout_sw_ctl = snd_ctl_new1(&tumbler_lineout_sw, chip);1434 if ((err = snd_ctl_add(chip->card, chip->lineout_sw_ctl)) < 0)1435 return err;1436 }1437 chip->drc_sw_ctl = snd_ctl_new1(&tumbler_drc_sw, chip);1438 if ((err = snd_ctl_add(chip->card, chip->drc_sw_ctl)) < 0)1439 return err;14401441 /* set initial DRC range to 60% */1442 if (chip->model == PMAC_TUMBLER)1443 mix->drc_range = (TAS3001_DRC_MAX * 6) / 10;1444 else1445 mix->drc_range = (TAS3004_DRC_MAX * 6) / 10;1446 mix->drc_enable = 1; /* will be changed later if AUTO_DRC is set */1447 if (chip->model == PMAC_TUMBLER)1448 tumbler_set_drc(mix);1449 else1450 snapper_set_drc(mix);14511452#ifdef CONFIG_PM1453 chip->suspend = tumbler_suspend;1454 chip->resume = tumbler_resume;1455#endif14561457 INIT_WORK(&device_change, device_change_handler);1458 device_change_chip = chip;14591460#ifdef PMAC_SUPPORT_AUTOMUTE1461 if ((mix->headphone_irq >=0 || mix->lineout_irq >= 0)1462 && (err = snd_pmac_add_automute(chip)) < 0)1463 return err;1464 chip->detect_headphone = tumbler_detect_headphone;1465 chip->update_automute = tumbler_update_automute;1466 tumbler_update_automute(chip, 0); /* update the status only */14671468 /* activate headphone status interrupts */1469 if (mix->headphone_irq >= 0) {1470 unsigned char val;1471 if ((err = request_irq(mix->headphone_irq, headphone_intr, 0,1472 "Sound Headphone Detection", chip)) < 0)1473 return 0;1474 /* activate headphone status interrupts */1475 val = do_gpio_read(&mix->hp_detect);1476 do_gpio_write(&mix->hp_detect, val | 0x80);1477 }1478 if (mix->lineout_irq >= 0) {1479 unsigned char val;1480 if ((err = request_irq(mix->lineout_irq, headphone_intr, 0,1481 "Sound Lineout Detection", chip)) < 0)1482 return 0;1483 /* activate headphone status interrupts */1484 val = do_gpio_read(&mix->line_detect);1485 do_gpio_write(&mix->line_detect, val | 0x80);1486 }1487#endif14881489 return 0;1490}