Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 47
b: refs/heads/master
c: b20af5f
h: refs/heads/master
i:
  45: 20e5919
  43: 392d769
  39: 7b9e0aa
  31: decb105
v: v3
  • Loading branch information
Benjamin Herrenschmidt authored and Linus Torvalds committed Apr 16, 2005
1 parent db5979f commit d741651
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 37 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b75550e1bc6b3b2c80b628e68628fca015634071
refs/heads/master: b20af5f59797796d28b701f5d337e47c8a142eb2
142 changes: 106 additions & 36 deletions trunk/sound/ppc/tumbler.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,17 @@ typedef struct pmac_tumbler_t {
pmac_gpio_t hp_detect;
int headphone_irq;
unsigned int master_vol[2];
unsigned int save_master_switch[2];
unsigned int master_switch[2];
unsigned int mono_vol[VOL_IDX_LAST_MONO];
unsigned int mix_vol[VOL_IDX_LAST_MIX][2]; /* stereo volumes for tas3004 */
int drc_range;
int drc_enable;
int capture_source;
int anded_reset;
int auto_mute_notify;
int reset_on_sleep;
u8 acs;
} pmac_tumbler_t;


Expand Down Expand Up @@ -654,7 +659,8 @@ static int snapper_put_mix(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucont


/*
* mute switches
* mute switches. FIXME: Turn that into software mute when both outputs are muted
* to avoid codec reset on ibook M7
*/

enum { TUMBLER_MUTE_HP, TUMBLER_MUTE_AMP };
Expand Down Expand Up @@ -696,8 +702,11 @@ static int snapper_set_capture_source(pmac_tumbler_t *mix)
{
if (! mix->i2c.client)
return -ENODEV;
return i2c_smbus_write_byte_data(mix->i2c.client, TAS_REG_ACS,
mix->capture_source ? 2 : 0);
if (mix->capture_source)
mix->acs = mix->acs |= 2;
else
mix->acs &= ~2;
return i2c_smbus_write_byte_data(mix->i2c.client, TAS_REG_ACS, mix->acs);
}

static int snapper_info_capture_source(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
Expand Down Expand Up @@ -855,8 +864,7 @@ static void check_mute(pmac_t *chip, pmac_gpio_t *gp, int val, int do_notify, sn

static struct work_struct device_change;

static void
device_change_handler(void *self)
static void device_change_handler(void *self)
{
pmac_t *chip = (pmac_t*) self;
pmac_tumbler_t *mix;
Expand All @@ -865,6 +873,33 @@ device_change_handler(void *self)
return;

mix = chip->mixer_data;
snd_assert(mix, return);

if (tumbler_detect_headphone(chip)) {
/* mute speaker */
check_mute(chip, &mix->hp_mute, 0, mix->auto_mute_notify,
chip->master_sw_ctl);
if (mix->anded_reset)
big_mdelay(10);
check_mute(chip, &mix->amp_mute, 1, mix->auto_mute_notify,
chip->speaker_sw_ctl);
mix->drc_enable = 0;
} else {
/* unmute speaker */
check_mute(chip, &mix->amp_mute, 0, mix->auto_mute_notify,
chip->speaker_sw_ctl);
if (mix->anded_reset)
big_mdelay(10);
check_mute(chip, &mix->hp_mute, 1, mix->auto_mute_notify,
chip->master_sw_ctl);
mix->drc_enable = 1;
}
if (mix->auto_mute_notify) {
snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
&chip->hp_detect_ctl->id);
snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
&chip->drc_sw_ctl->id);
}

/* first set the DRC so the speaker do not explode -ReneR */
if (chip->model == PMAC_TUMBLER)
Expand All @@ -879,31 +914,11 @@ device_change_handler(void *self)
static void tumbler_update_automute(pmac_t *chip, int do_notify)
{
if (chip->auto_mute) {
pmac_tumbler_t *mix = chip->mixer_data;
pmac_tumbler_t *mix;
mix = chip->mixer_data;
snd_assert(mix, return);
if (tumbler_detect_headphone(chip)) {
/* mute speaker */
check_mute(chip, &mix->amp_mute, 1, do_notify, chip->speaker_sw_ctl);
check_mute(chip, &mix->hp_mute, 0, do_notify, chip->master_sw_ctl);
mix->drc_enable = 0;

} else {
/* unmute speaker */
check_mute(chip, &mix->amp_mute, 0, do_notify, chip->speaker_sw_ctl);
check_mute(chip, &mix->hp_mute, 1, do_notify, chip->master_sw_ctl);
mix->drc_enable = 1;
}
if (do_notify) {
snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
&chip->hp_detect_ctl->id);
snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
&chip->drc_sw_ctl->id);
}

/* finally we need to schedule an update of the mixer values
(master and DRC are enough for now) -ReneR */
mix->auto_mute_notify = do_notify;
schedule_work(&device_change);

}
}
#endif /* PMAC_SUPPORT_AUTOMUTE */
Expand Down Expand Up @@ -1002,22 +1017,63 @@ static void tumbler_reset_audio(pmac_t *chip)
{
pmac_tumbler_t *mix = chip->mixer_data;

write_audio_gpio(&mix->audio_reset, 0);
big_mdelay(200);
write_audio_gpio(&mix->audio_reset, 1);
big_mdelay(100);
write_audio_gpio(&mix->audio_reset, 0);
big_mdelay(100);
if (mix->anded_reset) {
write_audio_gpio(&mix->hp_mute, 0);
write_audio_gpio(&mix->amp_mute, 0);
big_mdelay(200);
write_audio_gpio(&mix->hp_mute, 1);
write_audio_gpio(&mix->amp_mute, 1);
big_mdelay(100);
write_audio_gpio(&mix->hp_mute, 0);
write_audio_gpio(&mix->amp_mute, 0);
big_mdelay(100);
} else {
write_audio_gpio(&mix->audio_reset, 0);
big_mdelay(200);
write_audio_gpio(&mix->audio_reset, 1);
big_mdelay(100);
write_audio_gpio(&mix->audio_reset, 0);
big_mdelay(100);
}
}

#ifdef CONFIG_PMAC_PBOOK
/* suspend mixer */
static void tumbler_suspend(pmac_t *chip)
{
pmac_tumbler_t *mix = chip->mixer_data;

if (mix->headphone_irq >= 0)
disable_irq(mix->headphone_irq);
mix->save_master_switch[0] = mix->master_switch[0];
mix->save_master_switch[1] = mix->master_switch[1];
mix->master_switch[0] = mix->master_switch[1] = 0;
tumbler_set_master_volume(mix);
if (!mix->anded_reset) {
write_audio_gpio(&mix->amp_mute, 1);
write_audio_gpio(&mix->hp_mute, 1);
}
if (chip->model == PMAC_SNAPPER) {
mix->acs |= 1;
i2c_smbus_write_byte_data(mix->i2c.client, TAS_REG_ACS, mix->acs);
}
if (mix->anded_reset) {
write_audio_gpio(&mix->amp_mute, 1);
write_audio_gpio(&mix->hp_mute, 1);
} else
write_audio_gpio(&mix->audio_reset, 1);
}

/* resume mixer */
static void tumbler_resume(pmac_t *chip)
{
pmac_tumbler_t *mix = chip->mixer_data;

snd_assert(mix, return);

mix->acs &= ~1;
mix->master_switch[0] = mix->save_master_switch[0];
mix->master_switch[1] = mix->save_master_switch[1];
tumbler_reset_audio(chip);
if (mix->i2c.client && mix->i2c.init_client) {
if (mix->i2c.init_client(&mix->i2c) < 0)
Expand All @@ -1041,6 +1097,8 @@ static void tumbler_resume(pmac_t *chip)
tumbler_set_master_volume(mix);
if (chip->update_automute)
chip->update_automute(chip, 0);
if (mix->headphone_irq >= 0)
enable_irq(mix->headphone_irq);
}
#endif

Expand Down Expand Up @@ -1103,7 +1161,7 @@ int __init snd_pmac_tumbler_init(pmac_t *chip)
int i, err;
pmac_tumbler_t *mix;
u32 *paddr;
struct device_node *tas_node;
struct device_node *tas_node, *np;
char *chipname;

#ifdef CONFIG_KMOD
Expand All @@ -1119,7 +1177,18 @@ int __init snd_pmac_tumbler_init(pmac_t *chip)

chip->mixer_data = mix;
chip->mixer_free = tumbler_cleanup;

mix->anded_reset = 0;
mix->reset_on_sleep = 1;

for (np = chip->node->child; np; np = np->sibling) {
if (!strcmp(np->name, "sound")) {
if (get_property(np, "has-anded-reset", NULL))
mix->anded_reset = 1;
if (get_property(np, "layout-id", NULL))
mix->reset_on_sleep = 0;
break;
}
}
if ((err = tumbler_init(chip)) < 0)
return err;

Expand Down Expand Up @@ -1178,6 +1247,7 @@ int __init snd_pmac_tumbler_init(pmac_t *chip)
return err;

#ifdef CONFIG_PMAC_PBOOK
chip->suspend = tumbler_suspend;
chip->resume = tumbler_resume;
#endif

Expand Down

0 comments on commit d741651

Please sign in to comment.