summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/arm/aaci.c1
-rw-r--r--sound/arm/pxa2xx-ac97.c8
-rw-r--r--sound/core/init.c14
-rw-r--r--sound/core/sound.c2
-rw-r--r--sound/oss/soundcard.c4
-rw-r--r--sound/parisc/harmony.c116
-rw-r--r--sound/parisc/harmony.h17
-rw-r--r--sound/pci/ac97/ac97_bus.c6
-rw-r--r--sound/ppc/beep.c66
-rw-r--r--sound/sound_core.c2
10 files changed, 162 insertions, 74 deletions
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
index b2d5db20ec8c..559ead6367da 100644
--- a/sound/arm/aaci.c
+++ b/sound/arm/aaci.c
@@ -20,6 +20,7 @@
#include <asm/io.h>
#include <asm/irq.h>
+#include <asm/sizes.h>
#include <asm/hardware/amba.h>
#include <sound/driver.h>
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index 38b20efc9c0b..877bb00d3295 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -275,23 +275,23 @@ static int pxa2xx_ac97_do_resume(snd_card_t *card)
return 0;
}
-static int pxa2xx_ac97_suspend(struct device *_dev, pm_message_t state, u32 level)
+static int pxa2xx_ac97_suspend(struct device *_dev, pm_message_t state)
{
snd_card_t *card = dev_get_drvdata(_dev);
int ret = 0;
- if (card && level == SUSPEND_DISABLE)
+ if (card)
ret = pxa2xx_ac97_do_suspend(card, PMSG_SUSPEND);
return ret;
}
-static int pxa2xx_ac97_resume(struct device *_dev, u32 level)
+static int pxa2xx_ac97_resume(struct device *_dev)
{
snd_card_t *card = dev_get_drvdata(_dev);
int ret = 0;
- if (card && level == RESUME_ENABLE)
+ if (card)
ret = pxa2xx_ac97_do_resume(card);
return ret;
diff --git a/sound/core/init.c b/sound/core/init.c
index c72a79115cca..59202de1d2ce 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -676,8 +676,8 @@ struct snd_generic_device {
#define SND_GENERIC_NAME "snd_generic"
#ifdef CONFIG_PM
-static int snd_generic_suspend(struct device *dev, pm_message_t state, u32 level);
-static int snd_generic_resume(struct device *dev, u32 level);
+static int snd_generic_suspend(struct device *dev, pm_message_t state);
+static int snd_generic_resume(struct device *dev);
#endif
/* initialized in sound.c */
@@ -818,13 +818,10 @@ int snd_card_set_pm_callback(snd_card_t *card,
#ifdef CONFIG_SND_GENERIC_DRIVER
/* suspend/resume callbacks for snd_generic platform device */
-static int snd_generic_suspend(struct device *dev, pm_message_t state, u32 level)
+static int snd_generic_suspend(struct device *dev, pm_message_t state)
{
snd_card_t *card;
- if (level != SUSPEND_DISABLE)
- return 0;
-
card = get_snd_generic_card(dev);
if (card->power_state == SNDRV_CTL_POWER_D3hot)
return 0;
@@ -834,13 +831,10 @@ static int snd_generic_suspend(struct device *dev, pm_message_t state, u32 level
return 0;
}
-static int snd_generic_resume(struct device *dev, u32 level)
+static int snd_generic_resume(struct device *dev)
{
snd_card_t *card;
- if (level != RESUME_ENABLE)
- return 0;
-
card = get_snd_generic_card(dev);
if (card->power_state == SNDRV_CTL_POWER_D0)
return 0;
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 9e76bddb2c0b..b57519a3e3d9 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -231,7 +231,7 @@ int snd_register_device(int type, snd_card_t * card, int dev, snd_minor_t * reg,
devfs_mk_cdev(MKDEV(major, minor), S_IFCHR | device_mode, "snd/%s", name);
if (card)
device = card->dev;
- class_device_create(sound_class, MKDEV(major, minor), device, "%s", name);
+ class_device_create(sound_class, NULL, MKDEV(major, minor), device, "%s", name);
up(&sound_mutex);
return 0;
diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c
index 95fa81e26de2..d33bb464f70e 100644
--- a/sound/oss/soundcard.c
+++ b/sound/oss/soundcard.c
@@ -567,7 +567,7 @@ static int __init oss_init(void)
devfs_mk_cdev(MKDEV(SOUND_MAJOR, dev_list[i].minor),
S_IFCHR | dev_list[i].mode,
"sound/%s", dev_list[i].name);
- class_device_create(sound_class,
+ class_device_create(sound_class, NULL,
MKDEV(SOUND_MAJOR, dev_list[i].minor),
NULL, "%s", dev_list[i].name);
@@ -579,7 +579,7 @@ static int __init oss_init(void)
dev_list[i].minor + (j*0x10)),
S_IFCHR | dev_list[i].mode,
"sound/%s%d", dev_list[i].name, j);
- class_device_create(sound_class,
+ class_device_create(sound_class, NULL,
MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)),
NULL, "%s%d", dev_list[i].name, j);
}
diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c
index f560dd8cdb90..d833349ed518 100644
--- a/sound/parisc/harmony.c
+++ b/sound/parisc/harmony.c
@@ -197,7 +197,7 @@ snd_harmony_interrupt(int irq, void *dev, struct pt_regs *regs)
spin_unlock(&h->lock);
if (dstatus & HARMONY_DSTATUS_PN) {
- if (h->psubs) {
+ if (h->psubs && h->st.playing) {
spin_lock(&h->lock);
h->pbuf.buf += h->pbuf.count; /* PAGE_SIZE */
h->pbuf.buf %= h->pbuf.size; /* MAX_BUFS*PAGE_SIZE */
@@ -216,7 +216,7 @@ snd_harmony_interrupt(int irq, void *dev, struct pt_regs *regs)
}
if (dstatus & HARMONY_DSTATUS_RN) {
- if (h->csubs) {
+ if (h->csubs && h->st.capturing) {
spin_lock(&h->lock);
h->cbuf.buf += h->cbuf.count;
h->cbuf.buf %= h->cbuf.size;
@@ -316,6 +316,7 @@ snd_harmony_playback_trigger(snd_pcm_substream_t *ss, int cmd)
case SNDRV_PCM_TRIGGER_STOP:
h->st.playing = 0;
harmony_mute(h);
+ harmony_write(h, HARMONY_PNXTADD, h->sdma.addr);
harmony_disable_interrupts(h);
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
@@ -351,8 +352,9 @@ snd_harmony_capture_trigger(snd_pcm_substream_t *ss, int cmd)
break;
case SNDRV_PCM_TRIGGER_STOP:
h->st.capturing = 0;
- harmony_mute(h);
- harmony_disable_interrupts(h);
+ harmony_mute(h);
+ harmony_write(h, HARMONY_RNXTADD, h->gdma.addr);
+ harmony_disable_interrupts(h);
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
@@ -408,7 +410,8 @@ snd_harmony_playback_prepare(snd_pcm_substream_t *ss)
h->pbuf.size = snd_pcm_lib_buffer_bytes(ss);
h->pbuf.count = snd_pcm_lib_period_bytes(ss);
- h->pbuf.buf = 0;
+ if (h->pbuf.buf >= h->pbuf.size)
+ h->pbuf.buf = 0;
h->st.playing = 0;
h->st.rate = snd_harmony_rate_bits(rt->rate);
@@ -437,7 +440,8 @@ snd_harmony_capture_prepare(snd_pcm_substream_t *ss)
h->cbuf.size = snd_pcm_lib_buffer_bytes(ss);
h->cbuf.count = snd_pcm_lib_period_bytes(ss);
- h->cbuf.buf = 0;
+ if (h->cbuf.buf >= h->cbuf.size)
+ h->cbuf.buf = 0;
h->st.capturing = 0;
h->st.rate = snd_harmony_rate_bits(rt->rate);
@@ -712,13 +716,14 @@ snd_harmony_volume_get(snd_kcontrol_t *kc,
left = (h->st.gain >> shift_left) & mask;
right = (h->st.gain >> shift_right) & mask;
-
if (invert) {
left = mask - left;
right = mask - right;
}
+
ucontrol->value.integer.value[0] = left;
- ucontrol->value.integer.value[1] = right;
+ if (shift_left != shift_right)
+ ucontrol->value.integer.value[1] = right;
spin_unlock_irqrestore(&h->mixer_lock, flags);
@@ -738,22 +743,82 @@ snd_harmony_volume_put(snd_kcontrol_t *kc,
int old_gain = h->st.gain;
unsigned long flags;
+ spin_lock_irqsave(&h->mixer_lock, flags);
+
left = ucontrol->value.integer.value[0] & mask;
- right = ucontrol->value.integer.value[1] & mask;
- if (invert) {
+ if (invert)
left = mask - left;
- right = mask - right;
+ h->st.gain &= ~( (mask << shift_left ) );
+ h->st.gain |= (left << shift_left);
+
+ if (shift_left != shift_right) {
+ right = ucontrol->value.integer.value[1] & mask;
+ if (invert)
+ right = mask - right;
+ h->st.gain &= ~( (mask << shift_right) );
+ h->st.gain |= (right << shift_right);
}
+
+ snd_harmony_set_new_gain(h);
+
+ spin_unlock_irqrestore(&h->mixer_lock, flags);
+
+ return h->st.gain != old_gain;
+}
+
+static int
+snd_harmony_captureroute_info(snd_kcontrol_t *kc,
+ snd_ctl_elem_info_t *uinfo)
+{
+ static char *texts[2] = { "Line", "Mic" };
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 2;
+ if (uinfo->value.enumerated.item > 1)
+ uinfo->value.enumerated.item = 1;
+ strcpy(uinfo->value.enumerated.name,
+ texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int
+snd_harmony_captureroute_get(snd_kcontrol_t *kc,
+ snd_ctl_elem_value_t *ucontrol)
+{
+ harmony_t *h = snd_kcontrol_chip(kc);
+ int value;
+ unsigned long flags;
+
+ spin_lock_irqsave(&h->mixer_lock, flags);
+
+ value = (h->st.gain >> HARMONY_GAIN_IS_SHIFT) & 1;
+ ucontrol->value.enumerated.item[0] = value;
+
+ spin_unlock_irqrestore(&h->mixer_lock, flags);
+
+ return 0;
+}
+
+static int
+snd_harmony_captureroute_put(snd_kcontrol_t *kc,
+ snd_ctl_elem_value_t *ucontrol)
+{
+ harmony_t *h = snd_kcontrol_chip(kc);
+ int value;
+ int old_gain = h->st.gain;
+ unsigned long flags;
spin_lock_irqsave(&h->mixer_lock, flags);
- h->st.gain &= ~( (mask << shift_right) | (mask << shift_left) );
- h->st.gain |= ( (left << shift_left) | (right << shift_right) );
+ value = ucontrol->value.enumerated.item[0] & 1;
+ h->st.gain &= ~HARMONY_GAIN_IS_MASK;
+ h->st.gain |= value << HARMONY_GAIN_IS_SHIFT;
+
snd_harmony_set_new_gain(h);
spin_unlock_irqrestore(&h->mixer_lock, flags);
- return (old_gain - h->st.gain);
+ return h->st.gain != old_gain;
}
#define HARMONY_CONTROLS (sizeof(snd_harmony_controls)/ \
@@ -767,10 +832,25 @@ snd_harmony_volume_put(snd_kcontrol_t *kc,
((mask) << 16) | ((invert) << 24)) }
static snd_kcontrol_new_t snd_harmony_controls[] = {
- HARMONY_VOLUME("Playback Volume", HARMONY_GAIN_LO_SHIFT,
+ HARMONY_VOLUME("Master Playback Volume", HARMONY_GAIN_LO_SHIFT,
HARMONY_GAIN_RO_SHIFT, HARMONY_GAIN_OUT, 1),
HARMONY_VOLUME("Capture Volume", HARMONY_GAIN_LI_SHIFT,
HARMONY_GAIN_RI_SHIFT, HARMONY_GAIN_IN, 0),
+ HARMONY_VOLUME("Monitor Volume", HARMONY_GAIN_MA_SHIFT,
+ HARMONY_GAIN_MA_SHIFT, HARMONY_GAIN_MA, 1),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Input Route",
+ .info = snd_harmony_captureroute_info,
+ .get = snd_harmony_captureroute_get,
+ .put = snd_harmony_captureroute_put
+ },
+ HARMONY_VOLUME("Internal Speaker Switch", HARMONY_GAIN_SE_SHIFT,
+ HARMONY_GAIN_SE_SHIFT, 1, 0),
+ HARMONY_VOLUME("Line-Out Switch", HARMONY_GAIN_LE_SHIFT,
+ HARMONY_GAIN_LE_SHIFT, 1, 0),
+ HARMONY_VOLUME("Headphones Switch", HARMONY_GAIN_HE_SHIFT,
+ HARMONY_GAIN_HE_SHIFT, 1, 0),
};
static void __init
@@ -852,14 +932,14 @@ snd_harmony_create(snd_card_t *card,
memset(&h->pbuf, 0, sizeof(h->pbuf));
memset(&h->cbuf, 0, sizeof(h->cbuf));
- h->hpa = padev->hpa;
+ h->hpa = padev->hpa.start;
h->card = card;
h->dev = padev;
h->irq = padev->irq;
- h->iobase = ioremap_nocache(padev->hpa, HARMONY_SIZE);
+ h->iobase = ioremap_nocache(padev->hpa.start, HARMONY_SIZE);
if (h->iobase == NULL) {
printk(KERN_ERR PFX "unable to remap hpa 0x%lx\n",
- padev->hpa);
+ padev->hpa.start);
err = -EBUSY;
goto free_and_ret;
}
diff --git a/sound/parisc/harmony.h b/sound/parisc/harmony.h
index ef77f9a577d5..526c52389de2 100644
--- a/sound/parisc/harmony.h
+++ b/sound/parisc/harmony.h
@@ -61,7 +61,7 @@ typedef struct snd_card_harmony {
#define HARMONY_SIZE 64
#define BUF_SIZE PAGE_SIZE
-#define MAX_BUFS 10
+#define MAX_BUFS 16
#define MAX_BUF_SIZE (MAX_BUFS * BUF_SIZE)
#define PLAYBACK_BUFS MAX_BUFS
@@ -101,28 +101,31 @@ typedef struct snd_card_harmony {
#define HARMONY_SS_MONO 0x00000000
#define HARMONY_SS_STEREO 0x00000001
-#define HARMONY_GAIN_SILENCE 0x00F00FFF
-#define HARMONY_GAIN_DEFAULT 0x0FF00000
+#define HARMONY_GAIN_SILENCE 0x01F00FFF
+#define HARMONY_GAIN_DEFAULT 0x01F00FFF
-#define HARMONY_GAIN_HE_SHIFT 27
+#define HARMONY_GAIN_HE_SHIFT 27 /* headphones enabled */
#define HARMONY_GAIN_HE_MASK (1 << HARMONY_GAIN_HE_SHIFT)
-#define HARMONY_GAIN_LE_SHIFT 26
+#define HARMONY_GAIN_LE_SHIFT 26 /* line-out enabled */
#define HARMONY_GAIN_LE_MASK (1 << HARMONY_GAIN_LE_SHIFT)
-#define HARMONY_GAIN_SE_SHIFT 25
+#define HARMONY_GAIN_SE_SHIFT 25 /* internal-speaker enabled */
#define HARMONY_GAIN_SE_MASK (1 << HARMONY_GAIN_SE_SHIFT)
-#define HARMONY_GAIN_IS_SHIFT 24
+#define HARMONY_GAIN_IS_SHIFT 24 /* input select - 0 for line, 1 for mic */
#define HARMONY_GAIN_IS_MASK (1 << HARMONY_GAIN_IS_SHIFT)
+/* monitor attenuation */
#define HARMONY_GAIN_MA 0x0f
#define HARMONY_GAIN_MA_SHIFT 20
#define HARMONY_GAIN_MA_MASK (HARMONY_GAIN_MA << HARMONY_GAIN_MA_SHIFT)
+/* input gain */
#define HARMONY_GAIN_IN 0x0f
#define HARMONY_GAIN_LI_SHIFT 16
#define HARMONY_GAIN_LI_MASK (HARMONY_GAIN_IN << HARMONY_GAIN_LI_SHIFT)
#define HARMONY_GAIN_RI_SHIFT 12
#define HARMONY_GAIN_RI_MASK (HARMONY_GAIN_IN << HARMONY_GAIN_RI_SHIFT)
+/* output gain (master volume) */
#define HARMONY_GAIN_OUT 0x3f
#define HARMONY_GAIN_LO_SHIFT 6
#define HARMONY_GAIN_LO_MASK (HARMONY_GAIN_OUT << HARMONY_GAIN_LO_SHIFT)
diff --git a/sound/pci/ac97/ac97_bus.c b/sound/pci/ac97/ac97_bus.c
index becbc420ba41..ec70fadde7d9 100644
--- a/sound/pci/ac97/ac97_bus.c
+++ b/sound/pci/ac97/ac97_bus.c
@@ -31,7 +31,8 @@ static int ac97_bus_suspend(struct device *dev, pm_message_t state)
int ret = 0;
if (dev->driver && dev->driver->suspend)
- ret = dev->driver->suspend(dev, state, SUSPEND_POWER_DOWN);
+ ret = dev->driver->suspend(dev, state);
+
return ret;
}
@@ -40,7 +41,8 @@ static int ac97_bus_resume(struct device *dev)
int ret = 0;
if (dev->driver && dev->driver->resume)
- ret = dev->driver->resume(dev, RESUME_POWER_ON);
+ ret = dev->driver->resume(dev);
+
return ret;
}
diff --git a/sound/ppc/beep.c b/sound/ppc/beep.c
index 31ea7a4c069f..1681ee13efbb 100644
--- a/sound/ppc/beep.c
+++ b/sound/ppc/beep.c
@@ -31,14 +31,14 @@
#include "pmac.h"
struct snd_pmac_beep {
- int running; /* boolean */
- int volume; /* mixer volume: 0-100 */
+ int running; /* boolean */
+ int volume; /* mixer volume: 0-100 */
int volume_play; /* currently playing volume */
int hz;
int nsamples;
short *buf; /* allocated wave buffer */
dma_addr_t addr; /* physical address of buffer */
- struct input_dev dev;
+ struct input_dev *dev;
};
/*
@@ -212,47 +212,55 @@ static snd_kcontrol_new_t snd_pmac_beep_mixer = {
int __init snd_pmac_attach_beep(pmac_t *chip)
{
pmac_beep_t *beep;
- int err;
+ struct input_dev *input_dev;
+ void *dmabuf;
+ int err = -ENOMEM;
- beep = kmalloc(sizeof(*beep), GFP_KERNEL);
- if (! beep)
- return -ENOMEM;
-
- memset(beep, 0, sizeof(*beep));
- beep->buf = dma_alloc_coherent(&chip->pdev->dev, BEEP_BUFLEN * 4,
- &beep->addr, GFP_KERNEL);
-
- beep->dev.evbit[0] = BIT(EV_SND);
- beep->dev.sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
- beep->dev.event = snd_pmac_beep_event;
- beep->dev.private = chip;
+ beep = kzalloc(sizeof(*beep), GFP_KERNEL);
+ dmabuf = dma_alloc_coherent(&chip->pdev->dev, BEEP_BUFLEN * 4,
+ &beep->addr, GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!beep || !dmabuf || !input_dev)
+ goto fail;
/* FIXME: set more better values */
- beep->dev.name = "PowerMac Beep";
- beep->dev.phys = "powermac/beep";
- beep->dev.id.bustype = BUS_ADB;
- beep->dev.id.vendor = 0x001f;
- beep->dev.id.product = 0x0001;
- beep->dev.id.version = 0x0100;
+ input_dev->name = "PowerMac Beep";
+ input_dev->phys = "powermac/beep";
+ input_dev->id.bustype = BUS_ADB;
+ input_dev->id.vendor = 0x001f;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0100;
+
+ input_dev->evbit[0] = BIT(EV_SND);
+ input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
+ input_dev->event = snd_pmac_beep_event;
+ input_dev->private = chip;
+ input_dev->cdev.dev = &chip->pdev->dev;
+ beep->dev = input_dev;
+ beep->buf = dmabuf;
beep->volume = BEEP_VOLUME;
beep->running = 0;
- if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_pmac_beep_mixer, chip))) < 0) {
- kfree(beep->buf);
- kfree(beep);
- return err;
- }
+
+ err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_pmac_beep_mixer, chip));
+ if (err < 0)
+ goto fail;
chip->beep = beep;
- input_register_device(&beep->dev);
+ input_register_device(beep->dev);
return 0;
+
+ fail: input_free_device(input_dev);
+ kfree(dmabuf);
+ kfree(beep);
+ return err;
}
void snd_pmac_detach_beep(pmac_t *chip)
{
if (chip->beep) {
- input_unregister_device(&chip->beep->dev);
+ input_unregister_device(chip->beep->dev);
dma_free_coherent(&chip->pdev->dev, BEEP_BUFLEN * 4,
chip->beep->buf, chip->beep->addr);
kfree(chip->beep);
diff --git a/sound/sound_core.c b/sound/sound_core.c
index 954f994592ab..394b53e20cb8 100644
--- a/sound/sound_core.c
+++ b/sound/sound_core.c
@@ -174,7 +174,7 @@ static int sound_insert_unit(struct sound_unit **list, struct file_operations *f
devfs_mk_cdev(MKDEV(SOUND_MAJOR, s->unit_minor),
S_IFCHR | mode, s->name);
- class_device_create(sound_class, MKDEV(SOUND_MAJOR, s->unit_minor),
+ class_device_create(sound_class, NULL, MKDEV(SOUND_MAJOR, s->unit_minor),
dev, s->name+6);
return r;
OpenPOWER on IntegriCloud