Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 193242
b: refs/heads/master
c: eb581ad
h: refs/heads/master
v: v3
  • Loading branch information
Hans de Goede authored and Takashi Iwai committed Apr 23, 2010
1 parent 2d77086 commit 65c56dc
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 3 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: 20133d4cd329af7a02ee5af36bba1796d5ff7b1d
refs/heads/master: eb581adf25fe9e42197e591926de85459e68b9fd
10 changes: 10 additions & 0 deletions trunk/sound/pci/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,16 @@ config SND_MAESTRO3
To compile this driver as a module, choose M here: the module
will be called snd-maestro3.

config SND_MAESTRO3_INPUT
bool "Enable input device for maestro3 volume buttons"
depends on SND_MAESTRO3
depends on INPUT=y || INPUT=SND_MAESTRO3
help
If you say Y here, you will get an input device which reports
keypresses for the volume buttons connected to the maestro3 chip.
If you say N the buttons will directly control the master volume.
It is recommended to say Y.

config SND_MIXART
tristate "Digigram miXart"
select SND_HWDEP
Expand Down
116 changes: 114 additions & 2 deletions trunk/sound/pci/maestro3.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include <linux/vmalloc.h>
#include <linux/moduleparam.h>
#include <linux/firmware.h>
#include <linux/input.h>
#include <sound/core.h>
#include <sound/info.h>
#include <sound/control.h>
Expand Down Expand Up @@ -844,11 +845,17 @@ struct snd_m3 {
struct m3_dma *substreams;

spinlock_t reg_lock;
spinlock_t ac97_lock;

#ifdef CONFIG_SND_MAESTRO3_INPUT
struct input_dev *input_dev;
char phys[64]; /* physical device path */
#else
spinlock_t ac97_lock;
struct snd_kcontrol *master_switch;
struct snd_kcontrol *master_volume;
struct tasklet_struct hwvol_tq;
#endif

unsigned int in_suspend;

#ifdef CONFIG_PM
Expand Down Expand Up @@ -1606,7 +1613,9 @@ static void snd_m3_update_hw_volume(unsigned long private_data)
{
struct snd_m3 *chip = (struct snd_m3 *) private_data;
int x, val;
#ifndef CONFIG_SND_MAESTRO3_INPUT
unsigned long flags;
#endif

/* Figure out which volume control button was pushed,
based on differences from the default register
Expand All @@ -1632,6 +1641,7 @@ static void snd_m3_update_hw_volume(unsigned long private_data)
if (chip->in_suspend)
return;

#ifndef CONFIG_SND_MAESTRO3_INPUT
if (!chip->master_switch || !chip->master_volume)
return;

Expand Down Expand Up @@ -1677,6 +1687,35 @@ static void snd_m3_update_hw_volume(unsigned long private_data)
break;
}
spin_unlock_irqrestore(&chip->ac97_lock, flags);
#else
if (!chip->input_dev)
return;

val = 0;
switch (x) {
case 0x88:
/* The counters have not changed, yet we've received a HV
interrupt. According to tests run by various people this
happens when pressing the mute button. */
val = KEY_MUTE;
break;
case 0xaa:
/* counters increased by 1 -> volume up */
val = KEY_VOLUMEUP;
break;
case 0x66:
/* counters decreased by 1 -> volume down */
val = KEY_VOLUMEDOWN;
break;
}

if (val) {
input_report_key(chip->input_dev, val, 1);
input_sync(chip->input_dev);
input_report_key(chip->input_dev, val, 0);
input_sync(chip->input_dev);
}
#endif
}

static irqreturn_t snd_m3_interrupt(int irq, void *dev_id)
Expand All @@ -1691,7 +1730,11 @@ static irqreturn_t snd_m3_interrupt(int irq, void *dev_id)
return IRQ_NONE;

if (status & HV_INT_PENDING)
#ifdef CONFIG_SND_MAESTRO3_INPUT
snd_m3_update_hw_volume((unsigned long)chip);
#else
tasklet_schedule(&chip->hwvol_tq);
#endif

/*
* ack an assp int if its running
Expand Down Expand Up @@ -1957,18 +2000,24 @@ static unsigned short
snd_m3_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
{
struct snd_m3 *chip = ac97->private_data;
#ifndef CONFIG_SND_MAESTRO3_INPUT
unsigned long flags;
#endif
unsigned short data = 0xffff;

if (snd_m3_ac97_wait(chip))
goto fail;
#ifndef CONFIG_SND_MAESTRO3_INPUT
spin_lock_irqsave(&chip->ac97_lock, flags);
#endif
snd_m3_outb(chip, 0x80 | (reg & 0x7f), CODEC_COMMAND);
if (snd_m3_ac97_wait(chip))
goto fail_unlock;
data = snd_m3_inw(chip, CODEC_DATA);
fail_unlock:
#ifndef CONFIG_SND_MAESTRO3_INPUT
spin_unlock_irqrestore(&chip->ac97_lock, flags);
#endif
fail:
return data;
}
Expand All @@ -1977,14 +2026,20 @@ static void
snd_m3_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val)
{
struct snd_m3 *chip = ac97->private_data;
#ifndef CONFIG_SND_MAESTRO3_INPUT
unsigned long flags;
#endif

if (snd_m3_ac97_wait(chip))
return;
#ifndef CONFIG_SND_MAESTRO3_INPUT
spin_lock_irqsave(&chip->ac97_lock, flags);
#endif
snd_m3_outw(chip, val, CODEC_DATA);
snd_m3_outb(chip, reg & 0x7f, CODEC_COMMAND);
#ifndef CONFIG_SND_MAESTRO3_INPUT
spin_unlock_irqrestore(&chip->ac97_lock, flags);
#endif
}


Expand Down Expand Up @@ -2091,7 +2146,9 @@ static int __devinit snd_m3_mixer(struct snd_m3 *chip)
{
struct snd_ac97_bus *pbus;
struct snd_ac97_template ac97;
#ifndef CONFIG_SND_MAESTRO3_INPUT
struct snd_ctl_elem_id elem_id;
#endif
int err;
static struct snd_ac97_bus_ops ops = {
.write = snd_m3_ac97_write,
Expand All @@ -2111,6 +2168,7 @@ static int __devinit snd_m3_mixer(struct snd_m3 *chip)
schedule_timeout_uninterruptible(msecs_to_jiffies(100));
snd_ac97_write(chip->ac97, AC97_PCM, 0);

#ifndef CONFIG_SND_MAESTRO3_INPUT
memset(&elem_id, 0, sizeof(elem_id));
elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
strcpy(elem_id.name, "Master Playback Switch");
Expand All @@ -2119,6 +2177,7 @@ static int __devinit snd_m3_mixer(struct snd_m3 *chip)
elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
strcpy(elem_id.name, "Master Playback Volume");
chip->master_volume = snd_ctl_find_id(chip->card, &elem_id);
#endif

return 0;
}
Expand Down Expand Up @@ -2398,6 +2457,11 @@ static int snd_m3_free(struct snd_m3 *chip)
struct m3_dma *s;
int i;

#ifdef CONFIG_SND_MAESTRO3_INPUT
if (chip->input_dev)
input_unregister_device(chip->input_dev);
#endif

if (chip->substreams) {
spin_lock_irq(&chip->reg_lock);
for (i = 0; i < chip->num_substreams; i++) {
Expand Down Expand Up @@ -2524,6 +2588,41 @@ static int m3_resume(struct pci_dev *pci)
}
#endif /* CONFIG_PM */

#ifdef CONFIG_SND_MAESTRO3_INPUT
static int __devinit snd_m3_input_register(struct snd_m3 *chip)
{
struct input_dev *input_dev;
int err;

input_dev = input_allocate_device();
if (!input_dev)
return -ENOMEM;

snprintf(chip->phys, sizeof(chip->phys), "pci-%s/input0",
pci_name(chip->pci));

input_dev->name = chip->card->driver;
input_dev->phys = chip->phys;
input_dev->id.bustype = BUS_PCI;
input_dev->id.vendor = chip->pci->vendor;
input_dev->id.product = chip->pci->device;
input_dev->dev.parent = &chip->pci->dev;

__set_bit(EV_KEY, input_dev->evbit);
__set_bit(KEY_MUTE, input_dev->keybit);
__set_bit(KEY_VOLUMEDOWN, input_dev->keybit);
__set_bit(KEY_VOLUMEUP, input_dev->keybit);

err = input_register_device(input_dev);
if (err) {
input_free_device(input_dev);
return err;
}

chip->input_dev = input_dev;
return 0;
}
#endif /* CONFIG_INPUT */

/*
*/
Expand Down Expand Up @@ -2567,7 +2666,9 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
}

spin_lock_init(&chip->reg_lock);
#ifndef CONFIG_SND_MAESTRO3_INPUT
spin_lock_init(&chip->ac97_lock);
#endif

switch (pci->device) {
case PCI_DEVICE_ID_ESS_ALLEGRO:
Expand Down Expand Up @@ -2650,7 +2751,9 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,

snd_m3_hv_init(chip);

#ifndef CONFIG_SND_MAESTRO3_INPUT
tasklet_init(&chip->hwvol_tq, snd_m3_update_hw_volume, (unsigned long)chip);
#endif

if (request_irq(pci->irq, snd_m3_interrupt, IRQF_SHARED,
card->driver, chip)) {
Expand Down Expand Up @@ -2682,7 +2785,16 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,

if ((err = snd_m3_pcm(chip, 0)) < 0)
return err;


#ifdef CONFIG_SND_MAESTRO3_INPUT
if (chip->hv_config & HV_CTRL_ENABLE) {
err = snd_m3_input_register(chip);
if (err)
snd_printk(KERN_WARNING "Input device registration "
"failed with error %i", err);
}
#endif

snd_m3_enable_ints(chip);
snd_m3_assp_continue(chip);

Expand Down

0 comments on commit 65c56dc

Please sign in to comment.